branches/new_menus/src/emu/cpu/sh2/sh2drc.c
| r29568 | r29569 | |
| 12 | 12 | #include "sh2.h" |
| 13 | 13 | #include "sh2comn.h" |
| 14 | 14 | |
| 15 | | CPU_DISASSEMBLE( sh2 ); |
| 16 | 15 | extern unsigned DasmSH2(char *buffer, unsigned pc, UINT16 opcode); |
| 17 | 16 | |
| 18 | 17 | using namespace uml; |
| r29568 | r29569 | |
| 21 | 20 | DEBUGGING |
| 22 | 21 | ***************************************************************************/ |
| 23 | 22 | |
| 24 | | #define LOG_UML (0) // log UML assembly |
| 25 | | #define LOG_NATIVE (0) // log native assembly |
| 26 | | |
| 27 | 23 | #define SET_EA (0) // makes slower but "shows work" in the EA fake register like the interpreter |
| 28 | 24 | |
| 29 | | #define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching |
| 30 | | #define SINGLE_INSTRUCTION_MODE (0) |
| 31 | | |
| 32 | 25 | #define ADDSUBV_DIRECT (0) |
| 33 | 26 | |
| 34 | | #define VERBOSE 0 |
| 35 | | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
| 36 | | |
| 37 | 27 | #if SET_EA |
| 38 | | #define SETEA(x) UML_MOV(block, mem(&sh2->ea), ireg(x)) |
| 28 | #define SETEA(x) UML_MOV(block, mem(&m_sh2_state->ea), ireg(x)) |
| 39 | 29 | #else |
| 40 | 30 | #define SETEA(x) |
| 41 | 31 | #endif |
| r29568 | r29569 | |
| 48 | 38 | #define MAPVAR_PC M0 |
| 49 | 39 | #define MAPVAR_CYCLES M1 |
| 50 | 40 | |
| 51 | | /* size of the execution code cache */ |
| 52 | | #define CACHE_SIZE (32 * 1024 * 1024) |
| 53 | | |
| 54 | | /* compilation boundaries -- how far back/forward does the analysis extend? */ |
| 55 | | #define COMPILE_BACKWARDS_BYTES 64 |
| 56 | | #define COMPILE_FORWARDS_BYTES 256 |
| 57 | | #define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/2) + (COMPILE_FORWARDS_BYTES/2)) |
| 58 | | #define COMPILE_MAX_SEQUENCE 64 |
| 59 | | |
| 60 | 41 | /* exit codes */ |
| 61 | 42 | #define EXECUTE_OUT_OF_CYCLES 0 |
| 62 | 43 | #define EXECUTE_MISSING_CODE 1 |
| r29568 | r29569 | |
| 65 | 46 | |
| 66 | 47 | #define PROBE_ADDRESS ~0 |
| 67 | 48 | |
| 68 | | extern int sh2_describe(void *param, opcode_desc *desc, const opcode_desc *prev); |
| 69 | 49 | |
| 70 | 50 | /*************************************************************************** |
| 71 | 51 | MACROS |
| 72 | 52 | ***************************************************************************/ |
| 73 | 53 | |
| 74 | | #define R32(reg) sh2->regmap[reg] |
| 54 | #define R32(reg) m_regmap[reg] |
| 75 | 55 | |
| 76 | 56 | /*************************************************************************** |
| 77 | | STRUCTURES & TYPEDEFS |
| 78 | | ***************************************************************************/ |
| 79 | | |
| 80 | | /* internal compiler state */ |
| 81 | | struct compiler_state |
| 82 | | { |
| 83 | | UINT32 cycles; /* accumulated cycles */ |
| 84 | | UINT8 checkints; /* need to check interrupts before next instruction */ |
| 85 | | code_label labelnum; /* index for local labels */ |
| 86 | | }; |
| 87 | | |
| 88 | | /*************************************************************************** |
| 89 | | FUNCTION PROTOTYPES |
| 90 | | ***************************************************************************/ |
| 91 | | |
| 92 | | static void static_generate_entry_point(sh2_state *sh2); |
| 93 | | static void static_generate_nocode_handler(sh2_state *sh2); |
| 94 | | static void static_generate_out_of_cycles(sh2_state *sh2); |
| 95 | | static void static_generate_memory_accessor(sh2_state *sh2, int size, int iswrite, const char *name, code_handle **handleptr); |
| 96 | | |
| 97 | | static void generate_update_cycles(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception); |
| 98 | | static void generate_checksum_block(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); |
| 99 | | static void generate_sequence_instruction(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc); |
| 100 | | static void generate_delay_slot(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc); |
| 101 | | |
| 102 | | static int generate_opcode(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc); |
| 103 | | static int generate_group_0(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc); |
| 104 | | static int generate_group_2(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc); |
| 105 | | static int generate_group_3(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, UINT32 ovrpc); |
| 106 | | static int generate_group_4(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc); |
| 107 | | static int generate_group_6(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc); |
| 108 | | static int generate_group_8(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc); |
| 109 | | static int generate_group_12(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc); |
| 110 | | |
| 111 | | static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc); |
| 112 | | |
| 113 | | static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent); |
| 114 | | static void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist); |
| 115 | | static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op); |
| 116 | | static const char *log_desc_flags_to_string(UINT32 flags); |
| 117 | | |
| 118 | | static void cfunc_printf_probe(void *param); |
| 119 | | static void cfunc_unimplemented(void *param); |
| 120 | | static void cfunc_fastirq(void *param); |
| 121 | | static void cfunc_MAC_W(void *param); |
| 122 | | static void cfunc_MAC_L(void *param); |
| 123 | | static void cfunc_DIV1(void *param); |
| 124 | | |
| 125 | | /*************************************************************************** |
| 126 | 57 | INLINE FUNCTIONS |
| 127 | 58 | ***************************************************************************/ |
| 128 | 59 | |
| 129 | | INLINE sh2_state *get_safe_token(device_t *device) |
| 130 | | { |
| 131 | | assert(device != NULL); |
| 132 | | assert(device->type() == SH1_DRC || |
| 133 | | device->type() == SH2_DRC); |
| 134 | | return *(sh2_state **)downcast<legacy_cpu_device *>(device)->token(); |
| 135 | | } |
| 136 | | |
| 137 | | INLINE UINT16 RW(sh2_state *sh2, offs_t A) |
| 138 | | { |
| 139 | | if (A >= 0xe0000000) |
| 140 | | return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8); |
| 141 | | |
| 142 | | if (A >= 0xc0000000) |
| 143 | | return sh2->program->read_word(A); |
| 144 | | |
| 145 | | return sh2->program->read_word(A & AM); |
| 146 | | } |
| 147 | | |
| 148 | | INLINE UINT32 RL(sh2_state *sh2, offs_t A) |
| 149 | | { |
| 150 | | if (A >= 0xe0000000) |
| 151 | | return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffffffff); |
| 152 | | |
| 153 | | if (A >= 0xc0000000) |
| 154 | | return sh2->program->read_dword(A); |
| 155 | | |
| 156 | | return sh2->program->read_dword(A & AM); |
| 157 | | } |
| 158 | | |
| 159 | 60 | /*------------------------------------------------- |
| 160 | 61 | epc - compute the exception PC from a |
| 161 | 62 | descriptor |
| 162 | 63 | -------------------------------------------------*/ |
| 163 | 64 | |
| 164 | | INLINE UINT32 epc(const opcode_desc *desc) |
| 65 | UINT32 sh2_device::epc(const opcode_desc *desc) |
| 165 | 66 | { |
| 166 | 67 | return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 1) : desc->pc; |
| 167 | 68 | } |
| r29568 | r29569 | |
| 171 | 72 | already allocated |
| 172 | 73 | -------------------------------------------------*/ |
| 173 | 74 | |
| 174 | | INLINE void alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name) |
| 75 | void sh2_device::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name) |
| 175 | 76 | { |
| 176 | 77 | if (*handleptr == NULL) |
| 177 | 78 | *handleptr = drcuml->handle_alloc(name); |
| r29568 | r29569 | |
| 182 | 83 | registers |
| 183 | 84 | -------------------------------------------------*/ |
| 184 | 85 | |
| 185 | | INLINE void load_fast_iregs(sh2_state *sh2, drcuml_block *block) |
| 86 | void sh2_device::load_fast_iregs(drcuml_block *block) |
| 186 | 87 | { |
| 187 | 88 | int regnum; |
| 188 | 89 | |
| 189 | | for (regnum = 0; regnum < ARRAY_LENGTH(sh2->regmap); regnum++) |
| 90 | for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) |
| 190 | 91 | { |
| 191 | | if (sh2->regmap[regnum].is_int_register()) |
| 92 | if (m_regmap[regnum].is_int_register()) |
| 192 | 93 | { |
| 193 | | UML_MOV(block, parameter::make_ireg(sh2->regmap[regnum].ireg()), mem(&sh2->r[regnum])); |
| 94 | UML_MOV(block, parameter::make_ireg(m_regmap[regnum].ireg()), mem(&m_sh2_state->r[regnum])); |
| 194 | 95 | } |
| 195 | 96 | } |
| 196 | 97 | } |
| r29568 | r29569 | |
| 201 | 102 | registers |
| 202 | 103 | -------------------------------------------------*/ |
| 203 | 104 | |
| 204 | | INLINE void save_fast_iregs(sh2_state *sh2, drcuml_block *block) |
| 105 | void sh2_device::save_fast_iregs(drcuml_block *block) |
| 205 | 106 | { |
| 206 | 107 | int regnum; |
| 207 | 108 | |
| 208 | | for (regnum = 0; regnum < ARRAY_LENGTH(sh2->regmap); regnum++) |
| 109 | for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) |
| 209 | 110 | { |
| 210 | | if (sh2->regmap[regnum].is_int_register()) |
| 111 | if (m_regmap[regnum].is_int_register()) |
| 211 | 112 | { |
| 212 | | UML_MOV(block, mem(&sh2->r[regnum]), parameter::make_ireg(sh2->regmap[regnum].ireg())); |
| 113 | UML_MOV(block, mem(&m_sh2_state->r[regnum]), parameter::make_ireg(m_regmap[regnum].ireg())); |
| 213 | 114 | } |
| 214 | 115 | } |
| 215 | 116 | } |
| r29568 | r29569 | |
| 221 | 122 | |
| 222 | 123 | static void cfunc_printf_probe(void *param) |
| 223 | 124 | { |
| 224 | | sh2_state *sh2 = (sh2_state *)param; |
| 225 | | UINT32 pc = sh2->pc; |
| 125 | ((sh2_device *)param)->func_printf_probe(); |
| 126 | } |
| 226 | 127 | |
| 128 | void sh2_device::func_printf_probe() |
| 129 | { |
| 130 | UINT32 pc = m_sh2_state->pc; |
| 131 | |
| 227 | 132 | printf(" PC=%08X r0=%08X r1=%08X r2=%08X\n", |
| 228 | 133 | pc, |
| 229 | | (UINT32)sh2->r[0], |
| 230 | | (UINT32)sh2->r[1], |
| 231 | | (UINT32)sh2->r[2]); |
| 134 | (UINT32)m_sh2_state->r[0], |
| 135 | (UINT32)m_sh2_state->r[1], |
| 136 | (UINT32)m_sh2_state->r[2]); |
| 232 | 137 | printf(" r3=%08X r4=%08X r5=%08X r6=%08X\n", |
| 233 | | (UINT32)sh2->r[3], |
| 234 | | (UINT32)sh2->r[4], |
| 235 | | (UINT32)sh2->r[5], |
| 236 | | (UINT32)sh2->r[6]); |
| 138 | (UINT32)m_sh2_state->r[3], |
| 139 | (UINT32)m_sh2_state->r[4], |
| 140 | (UINT32)m_sh2_state->r[5], |
| 141 | (UINT32)m_sh2_state->r[6]); |
| 237 | 142 | printf(" r7=%08X r8=%08X r9=%08X r10=%08X\n", |
| 238 | | (UINT32)sh2->r[7], |
| 239 | | (UINT32)sh2->r[8], |
| 240 | | (UINT32)sh2->r[9], |
| 241 | | (UINT32)sh2->r[10]); |
| 143 | (UINT32)m_sh2_state->r[7], |
| 144 | (UINT32)m_sh2_state->r[8], |
| 145 | (UINT32)m_sh2_state->r[9], |
| 146 | (UINT32)m_sh2_state->r[10]); |
| 242 | 147 | printf(" r11=%08X r12=%08X r13=%08X r14=%08X\n", |
| 243 | | (UINT32)sh2->r[11], |
| 244 | | (UINT32)sh2->r[12], |
| 245 | | (UINT32)sh2->r[13], |
| 246 | | (UINT32)sh2->r[14]); |
| 148 | (UINT32)m_sh2_state->r[11], |
| 149 | (UINT32)m_sh2_state->r[12], |
| 150 | (UINT32)m_sh2_state->r[13], |
| 151 | (UINT32)m_sh2_state->r[14]); |
| 247 | 152 | printf(" r15=%08X macl=%08X mach=%08X gbr=%08X\n", |
| 248 | | (UINT32)sh2->r[15], |
| 249 | | (UINT32)sh2->macl, |
| 250 | | (UINT32)sh2->mach, |
| 251 | | (UINT32)sh2->gbr); |
| 153 | (UINT32)m_sh2_state->r[15], |
| 154 | (UINT32)m_sh2_state->macl, |
| 155 | (UINT32)m_sh2_state->mach, |
| 156 | (UINT32)m_sh2_state->gbr); |
| 252 | 157 | printf(" evec %x irqsr %x pc=%08x\n", |
| 253 | | (UINT32)sh2->evec, |
| 254 | | (UINT32)sh2->irqsr, (UINT32)sh2->pc); |
| 158 | (UINT32)m_sh2_state->evec, |
| 159 | (UINT32)m_sh2_state->irqsr, (UINT32)m_sh2_state->pc); |
| 255 | 160 | } |
| 256 | 161 | |
| 257 | 162 | /*------------------------------------------------- |
| r29568 | r29569 | |
| 261 | 166 | |
| 262 | 167 | static void cfunc_unimplemented(void *param) |
| 263 | 168 | { |
| 264 | | sh2_state *sh2 = (sh2_state *)param; |
| 169 | ((sh2_device *)param)->func_unimplemented(); |
| 170 | } |
| 265 | 171 | |
| 172 | void sh2_device::func_unimplemented() |
| 173 | { |
| 266 | 174 | // set up an invalid opcode exception |
| 267 | | sh2->evec = RL( sh2, sh2->vbr + 4 * 4 ); |
| 268 | | sh2->evec &= AM; |
| 269 | | sh2->irqsr = sh2->sr; |
| 175 | m_sh2_state->evec = RL( m_sh2_state->vbr + 4 * 4 ); |
| 176 | m_sh2_state->evec &= AM; |
| 177 | m_sh2_state->irqsr = m_sh2_state->sr; |
| 270 | 178 | // claim it's an NMI, because it pretty much is |
| 271 | | sh2->pending_nmi = 1; |
| 179 | m_sh2_state->pending_nmi = 1; |
| 272 | 180 | } |
| 273 | 181 | |
| 274 | 182 | /*------------------------------------------------- |
| r29568 | r29569 | |
| 276 | 184 | -------------------------------------------------*/ |
| 277 | 185 | static void cfunc_fastirq(void *param) |
| 278 | 186 | { |
| 279 | | sh2_state *sh2 = (sh2_state *)param; |
| 280 | | sh2_exception(sh2, "fastirq",sh2->irqline); |
| 187 | ((sh2_device *)param)->func_fastirq(); |
| 281 | 188 | } |
| 282 | 189 | |
| 190 | void sh2_device::func_fastirq() |
| 191 | { |
| 192 | sh2_exception("fastirq",m_sh2_state->irqline); |
| 193 | } |
| 194 | |
| 283 | 195 | /*------------------------------------------------- |
| 284 | 196 | cfunc_MAC_W - implementation of MAC_W Rm,Rn |
| 285 | 197 | -------------------------------------------------*/ |
| 286 | 198 | static void cfunc_MAC_W(void *param) |
| 287 | 199 | { |
| 288 | | sh2_state *sh2 = (sh2_state *)param; |
| 200 | ((sh2_device *)param)->func_MAC_W(); |
| 201 | } |
| 202 | |
| 203 | void sh2_device::func_MAC_W() |
| 204 | { |
| 289 | 205 | INT32 tempm, tempn, dest, src, ans; |
| 290 | 206 | UINT32 templ; |
| 291 | 207 | UINT16 opcode; |
| 292 | 208 | int n, m; |
| 293 | 209 | |
| 294 | 210 | // recover the opcode |
| 295 | | opcode = sh2->arg0; |
| 211 | opcode = m_sh2_state->arg0; |
| 296 | 212 | |
| 297 | 213 | // extract the operands |
| 298 | 214 | n = Rn; |
| 299 | 215 | m = Rm; |
| 300 | 216 | |
| 301 | | tempn = (INT32) RW( sh2, sh2->r[n] ); |
| 302 | | sh2->r[n] += 2; |
| 303 | | tempm = (INT32) RW( sh2, sh2->r[m] ); |
| 304 | | sh2->r[m] += 2; |
| 305 | | templ = sh2->macl; |
| 217 | tempn = (INT32) RW( m_sh2_state->r[n] ); |
| 218 | m_sh2_state->r[n] += 2; |
| 219 | tempm = (INT32) RW( m_sh2_state->r[m] ); |
| 220 | m_sh2_state->r[m] += 2; |
| 221 | templ = m_sh2_state->macl; |
| 306 | 222 | tempm = ((INT32) (short) tempn * (INT32) (short) tempm); |
| 307 | | if ((INT32) sh2->macl >= 0) |
| 223 | if ((INT32) m_sh2_state->macl >= 0) |
| 308 | 224 | dest = 0; |
| 309 | 225 | else |
| 310 | 226 | dest = 1; |
| r29568 | r29569 | |
| 319 | 235 | tempn = 0xffffffff; |
| 320 | 236 | } |
| 321 | 237 | src += dest; |
| 322 | | sh2->macl += tempm; |
| 323 | | if ((INT32) sh2->macl >= 0) |
| 238 | m_sh2_state->macl += tempm; |
| 239 | if ((INT32) m_sh2_state->macl >= 0) |
| 324 | 240 | ans = 0; |
| 325 | 241 | else |
| 326 | 242 | ans = 1; |
| 327 | 243 | ans += dest; |
| 328 | | if (sh2->sr & S) |
| 244 | if (m_sh2_state->sr & S) |
| 329 | 245 | { |
| 330 | 246 | if (ans == 1) |
| 331 | 247 | { |
| 332 | | if ((sh2->cpu_type == CPU_TYPE_SH1) && ((src == 0) || (src == 2))) |
| 248 | if ((m_cpu_type == CPU_TYPE_SH1) && ((src == 0) || (src == 2))) |
| 333 | 249 | { |
| 334 | | sh2->mach |= 0x00000001; |
| 250 | m_sh2_state->mach |= 0x00000001; |
| 335 | 251 | } |
| 336 | 252 | |
| 337 | 253 | if (src == 0) |
| 338 | | sh2->macl = 0x7fffffff; |
| 254 | m_sh2_state->macl = 0x7fffffff; |
| 339 | 255 | if (src == 2) |
| 340 | | sh2->macl = 0x80000000; |
| 256 | m_sh2_state->macl = 0x80000000; |
| 341 | 257 | } |
| 342 | 258 | } |
| 343 | 259 | else |
| 344 | 260 | { |
| 345 | | sh2->mach += tempn; |
| 346 | | if (templ > sh2->macl) |
| 347 | | sh2->mach += 1; |
| 261 | m_sh2_state->mach += tempn; |
| 262 | if (templ > m_sh2_state->macl) |
| 263 | m_sh2_state->mach += 1; |
| 348 | 264 | |
| 349 | 265 | // SH-1 has limited precision |
| 350 | | if (sh2->cpu_type == CPU_TYPE_SH1) |
| 266 | if (m_cpu_type == CPU_TYPE_SH1) |
| 351 | 267 | { |
| 352 | | if ((sh2->mach & 0x200) == 0) |
| 268 | if ((m_sh2_state->mach & 0x200) == 0) |
| 353 | 269 | { |
| 354 | | sh2->mach &= 0x3ff; |
| 270 | m_sh2_state->mach &= 0x3ff; |
| 355 | 271 | } |
| 356 | 272 | else |
| 357 | 273 | { |
| 358 | | sh2->mach |= 0xfffffc00; |
| 274 | m_sh2_state->mach |= 0xfffffc00; |
| 359 | 275 | } |
| 360 | 276 | } |
| 361 | 277 | |
| r29568 | r29569 | |
| 368 | 284 | -------------------------------------------------*/ |
| 369 | 285 | static void cfunc_MAC_L(void *param) |
| 370 | 286 | { |
| 371 | | sh2_state *sh2 = (sh2_state *)param; |
| 287 | ((sh2_device *)param)->func_MAC_L(); |
| 288 | } |
| 289 | |
| 290 | void sh2_device::func_MAC_L() |
| 291 | { |
| 372 | 292 | UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; |
| 373 | 293 | UINT32 temp0, temp1, temp2, temp3; |
| 374 | 294 | INT32 tempm, tempn, fnLmL; |
| r29568 | r29569 | |
| 376 | 296 | int n, m; |
| 377 | 297 | |
| 378 | 298 | // recover the opcode |
| 379 | | opcode = sh2->arg0; |
| 299 | opcode = m_sh2_state->arg0; |
| 380 | 300 | |
| 381 | 301 | // extract the operands |
| 382 | 302 | n = Rn; |
| 383 | 303 | m = Rm; |
| 384 | 304 | |
| 385 | | tempn = (INT32) RL( sh2, sh2->r[n] ); |
| 386 | | sh2->r[n] += 4; |
| 387 | | tempm = (INT32) RL( sh2, sh2->r[m] ); |
| 388 | | sh2->r[m] += 4; |
| 305 | tempn = (INT32) RL( m_sh2_state->r[n] ); |
| 306 | m_sh2_state->r[n] += 4; |
| 307 | tempm = (INT32) RL( m_sh2_state->r[m] ); |
| 308 | m_sh2_state->r[m] += 4; |
| 389 | 309 | if ((INT32) (tempn ^ tempm) < 0) |
| 390 | 310 | fnLmL = -1; |
| 391 | 311 | else |
| r29568 | r29569 | |
| 421 | 341 | else |
| 422 | 342 | Res0 = (~Res0) + 1; |
| 423 | 343 | } |
| 424 | | if (sh2->sr & S) |
| 344 | if (m_sh2_state->sr & S) |
| 425 | 345 | { |
| 426 | | Res0 = sh2->macl + Res0; |
| 427 | | if (sh2->macl > Res0) |
| 346 | Res0 = m_sh2_state->macl + Res0; |
| 347 | if (m_sh2_state->macl > Res0) |
| 428 | 348 | Res2++; |
| 429 | | Res2 += (sh2->mach & 0x0000ffff); |
| 349 | Res2 += (m_sh2_state->mach & 0x0000ffff); |
| 430 | 350 | if (((INT32) Res2 < 0) && (Res2 < 0xffff8000)) |
| 431 | 351 | { |
| 432 | 352 | Res2 = 0x00008000; |
| r29568 | r29569 | |
| 437 | 357 | Res2 = 0x00007fff; |
| 438 | 358 | Res0 = 0xffffffff; |
| 439 | 359 | } |
| 440 | | sh2->mach = Res2; |
| 441 | | sh2->macl = Res0; |
| 360 | m_sh2_state->mach = Res2; |
| 361 | m_sh2_state->macl = Res0; |
| 442 | 362 | } |
| 443 | 363 | else |
| 444 | 364 | { |
| 445 | | Res0 = sh2->macl + Res0; |
| 446 | | if (sh2->macl > Res0) |
| 365 | Res0 = m_sh2_state->macl + Res0; |
| 366 | if (m_sh2_state->macl > Res0) |
| 447 | 367 | Res2++; |
| 448 | | Res2 += sh2->mach; |
| 449 | | sh2->mach = Res2; |
| 450 | | sh2->macl = Res0; |
| 368 | Res2 += m_sh2_state->mach; |
| 369 | m_sh2_state->mach = Res2; |
| 370 | m_sh2_state->macl = Res0; |
| 451 | 371 | } |
| 452 | 372 | } |
| 453 | 373 | |
| r29568 | r29569 | |
| 456 | 376 | -------------------------------------------------*/ |
| 457 | 377 | static void cfunc_DIV1(void *param) |
| 458 | 378 | { |
| 459 | | sh2_state *sh2 = (sh2_state *)param; |
| 379 | ((sh2_device *)param)->func_DIV1(); |
| 380 | } |
| 381 | |
| 382 | void sh2_device::func_DIV1() |
| 383 | { |
| 460 | 384 | UINT32 tmp0; |
| 461 | 385 | UINT32 old_q; |
| 462 | 386 | UINT16 opcode; |
| 463 | 387 | int n, m; |
| 464 | 388 | |
| 465 | 389 | // recover the opcode |
| 466 | | opcode = sh2->arg0; |
| 390 | opcode = m_sh2_state->arg0; |
| 467 | 391 | |
| 468 | 392 | // extract the operands |
| 469 | 393 | n = Rn; |
| 470 | 394 | m = Rm; |
| 471 | 395 | |
| 472 | | old_q = sh2->sr & Q; |
| 473 | | if (0x80000000 & sh2->r[n]) |
| 474 | | sh2->sr |= Q; |
| 396 | old_q = m_sh2_state->sr & Q; |
| 397 | if (0x80000000 & m_sh2_state->r[n]) |
| 398 | m_sh2_state->sr |= Q; |
| 475 | 399 | else |
| 476 | | sh2->sr &= ~Q; |
| 400 | m_sh2_state->sr &= ~Q; |
| 477 | 401 | |
| 478 | | sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T); |
| 402 | m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); |
| 479 | 403 | |
| 480 | 404 | if (!old_q) |
| 481 | 405 | { |
| 482 | | if (!(sh2->sr & M)) |
| 406 | if (!(m_sh2_state->sr & M)) |
| 483 | 407 | { |
| 484 | | tmp0 = sh2->r[n]; |
| 485 | | sh2->r[n] -= sh2->r[m]; |
| 486 | | if(!(sh2->sr & Q)) |
| 487 | | if(sh2->r[n] > tmp0) |
| 488 | | sh2->sr |= Q; |
| 408 | tmp0 = m_sh2_state->r[n]; |
| 409 | m_sh2_state->r[n] -= m_sh2_state->r[m]; |
| 410 | if(!(m_sh2_state->sr & Q)) |
| 411 | if(m_sh2_state->r[n] > tmp0) |
| 412 | m_sh2_state->sr |= Q; |
| 489 | 413 | else |
| 490 | | sh2->sr &= ~Q; |
| 414 | m_sh2_state->sr &= ~Q; |
| 491 | 415 | else |
| 492 | | if(sh2->r[n] > tmp0) |
| 493 | | sh2->sr &= ~Q; |
| 416 | if(m_sh2_state->r[n] > tmp0) |
| 417 | m_sh2_state->sr &= ~Q; |
| 494 | 418 | else |
| 495 | | sh2->sr |= Q; |
| 419 | m_sh2_state->sr |= Q; |
| 496 | 420 | } |
| 497 | 421 | else |
| 498 | 422 | { |
| 499 | | tmp0 = sh2->r[n]; |
| 500 | | sh2->r[n] += sh2->r[m]; |
| 501 | | if(!(sh2->sr & Q)) |
| 423 | tmp0 = m_sh2_state->r[n]; |
| 424 | m_sh2_state->r[n] += m_sh2_state->r[m]; |
| 425 | if(!(m_sh2_state->sr & Q)) |
| 502 | 426 | { |
| 503 | | if(sh2->r[n] < tmp0) |
| 504 | | sh2->sr &= ~Q; |
| 427 | if(m_sh2_state->r[n] < tmp0) |
| 428 | m_sh2_state->sr &= ~Q; |
| 505 | 429 | else |
| 506 | | sh2->sr |= Q; |
| 430 | m_sh2_state->sr |= Q; |
| 507 | 431 | } |
| 508 | 432 | else |
| 509 | 433 | { |
| 510 | | if(sh2->r[n] < tmp0) |
| 511 | | sh2->sr |= Q; |
| 434 | if(m_sh2_state->r[n] < tmp0) |
| 435 | m_sh2_state->sr |= Q; |
| 512 | 436 | else |
| 513 | | sh2->sr &= ~Q; |
| 437 | m_sh2_state->sr &= ~Q; |
| 514 | 438 | } |
| 515 | 439 | } |
| 516 | 440 | } |
| 517 | 441 | else |
| 518 | 442 | { |
| 519 | | if (!(sh2->sr & M)) |
| 443 | if (!(m_sh2_state->sr & M)) |
| 520 | 444 | { |
| 521 | | tmp0 = sh2->r[n]; |
| 522 | | sh2->r[n] += sh2->r[m]; |
| 523 | | if(!(sh2->sr & Q)) |
| 524 | | if(sh2->r[n] < tmp0) |
| 525 | | sh2->sr |= Q; |
| 445 | tmp0 = m_sh2_state->r[n]; |
| 446 | m_sh2_state->r[n] += m_sh2_state->r[m]; |
| 447 | if(!(m_sh2_state->sr & Q)) |
| 448 | if(m_sh2_state->r[n] < tmp0) |
| 449 | m_sh2_state->sr |= Q; |
| 526 | 450 | else |
| 527 | | sh2->sr &= ~Q; |
| 451 | m_sh2_state->sr &= ~Q; |
| 528 | 452 | else |
| 529 | | if(sh2->r[n] < tmp0) |
| 530 | | sh2->sr &= ~Q; |
| 453 | if(m_sh2_state->r[n] < tmp0) |
| 454 | m_sh2_state->sr &= ~Q; |
| 531 | 455 | else |
| 532 | | sh2->sr |= Q; |
| 456 | m_sh2_state->sr |= Q; |
| 533 | 457 | } |
| 534 | 458 | else |
| 535 | 459 | { |
| 536 | | tmp0 = sh2->r[n]; |
| 537 | | sh2->r[n] -= sh2->r[m]; |
| 538 | | if(!(sh2->sr & Q)) |
| 539 | | if(sh2->r[n] > tmp0) |
| 540 | | sh2->sr &= ~Q; |
| 460 | tmp0 = m_sh2_state->r[n]; |
| 461 | m_sh2_state->r[n] -= m_sh2_state->r[m]; |
| 462 | if(!(m_sh2_state->sr & Q)) |
| 463 | if(m_sh2_state->r[n] > tmp0) |
| 464 | m_sh2_state->sr &= ~Q; |
| 541 | 465 | else |
| 542 | | sh2->sr |= Q; |
| 466 | m_sh2_state->sr |= Q; |
| 543 | 467 | else |
| 544 | | if(sh2->r[n] > tmp0) |
| 545 | | sh2->sr |= Q; |
| 468 | if(m_sh2_state->r[n] > tmp0) |
| 469 | m_sh2_state->sr |= Q; |
| 546 | 470 | else |
| 547 | | sh2->sr &= ~Q; |
| 471 | m_sh2_state->sr &= ~Q; |
| 548 | 472 | } |
| 549 | 473 | } |
| 550 | 474 | |
| 551 | | tmp0 = (sh2->sr & (Q | M)); |
| 475 | tmp0 = (m_sh2_state->sr & (Q | M)); |
| 552 | 476 | if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ |
| 553 | | sh2->sr |= T; |
| 477 | m_sh2_state->sr |= T; |
| 554 | 478 | else |
| 555 | | sh2->sr &= ~T; |
| 479 | m_sh2_state->sr &= ~T; |
| 556 | 480 | } |
| 557 | 481 | |
| 558 | 482 | #if (!ADDSUBV_DIRECT) |
| r29568 | r29569 | |
| 561 | 485 | -------------------------------------------------*/ |
| 562 | 486 | static void cfunc_ADDV(void *param) |
| 563 | 487 | { |
| 564 | | sh2_state *sh2 = (sh2_state *)param; |
| 488 | ((sh2_device *)param)->func_ADDV(); |
| 489 | } |
| 490 | |
| 491 | void sh2_device::func_ADDV() |
| 492 | { |
| 565 | 493 | INT32 dest, src, ans; |
| 566 | 494 | UINT16 opcode; |
| 567 | 495 | int n, m; |
| 568 | 496 | |
| 569 | 497 | // recover the opcode |
| 570 | | opcode = sh2->arg0; |
| 498 | opcode = m_sh2_state->arg0; |
| 571 | 499 | |
| 572 | 500 | // extract the operands |
| 573 | 501 | n = Rn; |
| 574 | 502 | m = Rm; |
| 575 | 503 | |
| 576 | | if ((INT32) sh2->r[n] >= 0) |
| 504 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 577 | 505 | dest = 0; |
| 578 | 506 | else |
| 579 | 507 | dest = 1; |
| 580 | | if ((INT32) sh2->r[m] >= 0) |
| 508 | if ((INT32) m_sh2_state->r[m] >= 0) |
| 581 | 509 | src = 0; |
| 582 | 510 | else |
| 583 | 511 | src = 1; |
| 584 | 512 | src += dest; |
| 585 | | sh2->r[n] += sh2->r[m]; |
| 586 | | if ((INT32) sh2->r[n] >= 0) |
| 513 | m_sh2_state->r[n] += m_sh2_state->r[m]; |
| 514 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 587 | 515 | ans = 0; |
| 588 | 516 | else |
| 589 | 517 | ans = 1; |
| r29568 | r29569 | |
| 591 | 519 | if (src == 0 || src == 2) |
| 592 | 520 | { |
| 593 | 521 | if (ans == 1) |
| 594 | | sh2->sr |= T; |
| 522 | m_sh2_state->sr |= T; |
| 595 | 523 | else |
| 596 | | sh2->sr &= ~T; |
| 524 | m_sh2_state->sr &= ~T; |
| 597 | 525 | } |
| 598 | 526 | else |
| 599 | | sh2->sr &= ~T; |
| 527 | m_sh2_state->sr &= ~T; |
| 600 | 528 | } |
| 601 | 529 | |
| 602 | 530 | /*------------------------------------------------- |
| r29568 | r29569 | |
| 604 | 532 | -------------------------------------------------*/ |
| 605 | 533 | static void cfunc_SUBV(void *param) |
| 606 | 534 | { |
| 607 | | sh2_state *sh2 = (sh2_state *)param; |
| 535 | ((sh2_device *)param)->func_SUBV(); |
| 536 | } |
| 537 | |
| 538 | void sh2_device::func_SUBV() |
| 539 | { |
| 608 | 540 | INT32 dest, src, ans; |
| 609 | 541 | UINT16 opcode; |
| 610 | 542 | int n, m; |
| 611 | 543 | |
| 612 | 544 | // recover the opcode |
| 613 | | opcode = sh2->arg0; |
| 545 | opcode = m_sh2_state->arg0; |
| 614 | 546 | |
| 615 | 547 | // extract the operands |
| 616 | 548 | n = Rn; |
| 617 | 549 | m = Rm; |
| 618 | 550 | |
| 619 | | if ((INT32) sh2->r[n] >= 0) |
| 551 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 620 | 552 | dest = 0; |
| 621 | 553 | else |
| 622 | 554 | dest = 1; |
| 623 | | if ((INT32) sh2->r[m] >= 0) |
| 555 | if ((INT32) m_sh2_state->r[m] >= 0) |
| 624 | 556 | src = 0; |
| 625 | 557 | else |
| 626 | 558 | src = 1; |
| 627 | 559 | src += dest; |
| 628 | | sh2->r[n] -= sh2->r[m]; |
| 629 | | if ((INT32) sh2->r[n] >= 0) |
| 560 | m_sh2_state->r[n] -= m_sh2_state->r[m]; |
| 561 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 630 | 562 | ans = 0; |
| 631 | 563 | else |
| 632 | 564 | ans = 1; |
| r29568 | r29569 | |
| 634 | 566 | if (src == 1) |
| 635 | 567 | { |
| 636 | 568 | if (ans == 1) |
| 637 | | sh2->sr |= T; |
| 569 | m_sh2_state->sr |= T; |
| 638 | 570 | else |
| 639 | | sh2->sr &= ~T; |
| 571 | m_sh2_state->sr &= ~T; |
| 640 | 572 | } |
| 641 | 573 | else |
| 642 | | sh2->sr &= ~T; |
| 574 | m_sh2_state->sr &= ~T; |
| 643 | 575 | } |
| 576 | #else |
| 577 | void sh2_device::func_ADDV() {} |
| 578 | void sh2_device::func_SUBV() {} |
| 644 | 579 | #endif |
| 645 | 580 | |
| 646 | 581 | /*------------------------------------------------- |
| 647 | | sh2_init - initialize the processor |
| 648 | | -------------------------------------------------*/ |
| 649 | | |
| 650 | | static CPU_INIT( sh2 ) |
| 651 | | { |
| 652 | | sh2_state *sh2 = get_safe_token(device); |
| 653 | | drc_cache *cache; |
| 654 | | drcbe_info beinfo; |
| 655 | | UINT32 flags = 0; |
| 656 | | int regnum; |
| 657 | | |
| 658 | | /* allocate enough space for the cache and the core */ |
| 659 | | cache = auto_alloc(device->machine(), drc_cache(CACHE_SIZE + sizeof(sh2_state))); |
| 660 | | |
| 661 | | /* allocate the core memory */ |
| 662 | | *(sh2_state **)device->token() = sh2 = (sh2_state *)cache->alloc_near(sizeof(sh2_state)); |
| 663 | | memset(sh2, 0, sizeof(sh2_state)); |
| 664 | | |
| 665 | | /* initialize the common core parts */ |
| 666 | | sh2_common_init(sh2, device, irqcallback,true); |
| 667 | | |
| 668 | | /* allocate the implementation-specific state from the full cache */ |
| 669 | | sh2->cache = cache; |
| 670 | | |
| 671 | | /* reset per-driver pcflushes */ |
| 672 | | sh2->pcfsel = 0; |
| 673 | | |
| 674 | | /* initialize the UML generator */ |
| 675 | | if (LOG_UML) |
| 676 | | flags |= DRCUML_OPTION_LOG_UML; |
| 677 | | if (LOG_NATIVE) |
| 678 | | flags |= DRCUML_OPTION_LOG_NATIVE; |
| 679 | | sh2->drcuml = auto_alloc(device->machine(), drcuml_state(*device, *cache, flags, 1, 32, 1)); |
| 680 | | |
| 681 | | /* add symbols for our stuff */ |
| 682 | | sh2->drcuml->symbol_add(&sh2->pc, sizeof(sh2->pc), "pc"); |
| 683 | | sh2->drcuml->symbol_add(&sh2->icount, sizeof(sh2->icount), "icount"); |
| 684 | | for (regnum = 0; regnum < 16; regnum++) |
| 685 | | { |
| 686 | | char buf[10]; |
| 687 | | sprintf(buf, "r%d", regnum); |
| 688 | | sh2->drcuml->symbol_add(&sh2->r[regnum], sizeof(sh2->r[regnum]), buf); |
| 689 | | } |
| 690 | | sh2->drcuml->symbol_add(&sh2->pr, sizeof(sh2->pr), "pr"); |
| 691 | | sh2->drcuml->symbol_add(&sh2->sr, sizeof(sh2->sr), "sr"); |
| 692 | | sh2->drcuml->symbol_add(&sh2->gbr, sizeof(sh2->gbr), "gbr"); |
| 693 | | sh2->drcuml->symbol_add(&sh2->vbr, sizeof(sh2->vbr), "vbr"); |
| 694 | | sh2->drcuml->symbol_add(&sh2->macl, sizeof(sh2->macl), "macl"); |
| 695 | | sh2->drcuml->symbol_add(&sh2->mach, sizeof(sh2->macl), "mach"); |
| 696 | | |
| 697 | | /* initialize the front-end helper */ |
| 698 | | sh2->drcfe = auto_alloc(device->machine(), sh2_frontend(*sh2, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE)); |
| 699 | | |
| 700 | | /* compute the register parameters */ |
| 701 | | for (regnum = 0; regnum < 16; regnum++) |
| 702 | | { |
| 703 | | sh2->regmap[regnum] = mem(&sh2->r[regnum]); |
| 704 | | } |
| 705 | | |
| 706 | | /* if we have registers to spare, assign r0, r1, r2 to leftovers */ |
| 707 | | /* WARNING: do not use synthetic registers that are mapped here! */ |
| 708 | | if (!DISABLE_FAST_REGISTERS) |
| 709 | | { |
| 710 | | sh2->drcuml->get_backend_info(beinfo); |
| 711 | | if (beinfo.direct_iregs > 4) |
| 712 | | { |
| 713 | | sh2->regmap[0] = I4; |
| 714 | | } |
| 715 | | if (beinfo.direct_iregs > 5) |
| 716 | | { |
| 717 | | sh2->regmap[1] = I5; |
| 718 | | } |
| 719 | | if (beinfo.direct_iregs > 6) |
| 720 | | { |
| 721 | | sh2->regmap[2] = I6; |
| 722 | | } |
| 723 | | } |
| 724 | | |
| 725 | | /* mark the cache dirty so it is updated on next execute */ |
| 726 | | sh2->cache_dirty = TRUE; |
| 727 | | } |
| 728 | | |
| 729 | | /*------------------------------------------------- |
| 730 | | sh2_exit - cleanup from execution |
| 731 | | -------------------------------------------------*/ |
| 732 | | |
| 733 | | static CPU_EXIT( sh2 ) |
| 734 | | { |
| 735 | | sh2_state *sh2 = get_safe_token(device); |
| 736 | | |
| 737 | | /* clean up the DRC */ |
| 738 | | auto_free(device->machine(), sh2->drcfe); |
| 739 | | auto_free(device->machine(), sh2->drcuml); |
| 740 | | auto_free(device->machine(), sh2->cache); |
| 741 | | } |
| 742 | | |
| 743 | | |
| 744 | | /*------------------------------------------------- |
| 745 | | sh2_reset - reset the processor |
| 746 | | -------------------------------------------------*/ |
| 747 | | |
| 748 | | static CPU_RESET( sh2 ) |
| 749 | | { |
| 750 | | sh2_state *sh2 = get_safe_token(device); |
| 751 | | |
| 752 | | void (*f)(UINT32 data); |
| 753 | | device_irq_acknowledge_callback save_irqcallback; |
| 754 | | |
| 755 | | f = sh2->ftcsr_read_callback; |
| 756 | | save_irqcallback = sh2->irq_callback; |
| 757 | | |
| 758 | | sh2->ppc = sh2->pc = sh2->pr = sh2->sr = sh2->gbr = sh2->vbr = sh2->mach = sh2->macl = 0; |
| 759 | | sh2->evec = sh2->irqsr = 0; |
| 760 | | memset(&sh2->r[0], 0, sizeof(sh2->r[0])*16); |
| 761 | | sh2->ea = sh2->delay = sh2->cpu_off = sh2->dvsr = sh2->dvdnth = sh2->dvdntl = sh2->dvcr = 0; |
| 762 | | sh2->pending_irq = sh2->test_irq = 0; |
| 763 | | memset(&sh2->irq_queue[0], 0, sizeof(sh2->irq_queue[0])*16); |
| 764 | | memset(&sh2->irq_line_state[0], 0, sizeof(sh2->irq_line_state[0])*17); |
| 765 | | sh2->frc = sh2->ocra = sh2->ocrb = sh2->icr = 0; |
| 766 | | sh2->frc_base = 0; |
| 767 | | sh2->frt_input = sh2->internal_irq_level = sh2->internal_irq_vector = 0; |
| 768 | | sh2->dma_timer_active[0] = sh2->dma_timer_active[1] = 0; |
| 769 | | sh2->dma_irq[0] = sh2->dma_irq[1] = 0; |
| 770 | | |
| 771 | | sh2->ftcsr_read_callback = f; |
| 772 | | sh2->irq_callback = save_irqcallback; |
| 773 | | sh2->device = device; |
| 774 | | |
| 775 | | memset(sh2->m, 0, 0x200); |
| 776 | | |
| 777 | | sh2->pc = sh2->program->read_dword(0); |
| 778 | | sh2->r[15] = sh2->program->read_dword(4); |
| 779 | | sh2->sr = I; |
| 780 | | |
| 781 | | sh2->internal_irq_level = -1; |
| 782 | | |
| 783 | | sh2->cache_dirty = TRUE; |
| 784 | | |
| 785 | | sh2->cpu_type = CPU_TYPE_SH2; |
| 786 | | } |
| 787 | | |
| 788 | | /*------------------------------------------------- |
| 789 | | sh1_reset - reset the processor |
| 790 | | -------------------------------------------------*/ |
| 791 | | |
| 792 | | static CPU_RESET( sh1 ) |
| 793 | | { |
| 794 | | sh2_state *sh2 = get_safe_token(device); |
| 795 | | CPU_RESET_CALL(sh2); |
| 796 | | sh2->cpu_type = CPU_TYPE_SH1; |
| 797 | | } |
| 798 | | |
| 799 | | /*------------------------------------------------- |
| 800 | 582 | code_flush_cache - flush the cache and |
| 801 | 583 | regenerate static code |
| 802 | 584 | -------------------------------------------------*/ |
| 803 | 585 | |
| 804 | | static void code_flush_cache(sh2_state *sh2) |
| 586 | void sh2_device::code_flush_cache() |
| 805 | 587 | { |
| 806 | | drcuml_state *drcuml = sh2->drcuml; |
| 588 | drcuml_state *drcuml = m_drcuml; |
| 807 | 589 | |
| 808 | 590 | /* empty the transient cache contents */ |
| 809 | 591 | drcuml->reset(); |
| r29568 | r29569 | |
| 811 | 593 | try |
| 812 | 594 | { |
| 813 | 595 | /* generate the entry point and out-of-cycles handlers */ |
| 814 | | static_generate_nocode_handler(sh2); |
| 815 | | static_generate_out_of_cycles(sh2); |
| 816 | | static_generate_entry_point(sh2); |
| 596 | static_generate_nocode_handler(); |
| 597 | static_generate_out_of_cycles(); |
| 598 | static_generate_entry_point(); |
| 817 | 599 | |
| 818 | 600 | /* add subroutines for memory accesses */ |
| 819 | | static_generate_memory_accessor(sh2, 1, FALSE, "read8", &sh2->read8); |
| 820 | | static_generate_memory_accessor(sh2, 1, TRUE, "write8", &sh2->write8); |
| 821 | | static_generate_memory_accessor(sh2, 2, FALSE, "read16", &sh2->read16); |
| 822 | | static_generate_memory_accessor(sh2, 2, TRUE, "write16", &sh2->write16); |
| 823 | | static_generate_memory_accessor(sh2, 4, FALSE, "read32", &sh2->read32); |
| 824 | | static_generate_memory_accessor(sh2, 4, TRUE, "write32", &sh2->write32); |
| 601 | static_generate_memory_accessor(1, FALSE, "read8", &m_read8); |
| 602 | static_generate_memory_accessor(1, TRUE, "write8", &m_write8); |
| 603 | static_generate_memory_accessor(2, FALSE, "read16", &m_read16); |
| 604 | static_generate_memory_accessor(2, TRUE, "write16", &m_write16); |
| 605 | static_generate_memory_accessor(4, FALSE, "read32", &m_read32); |
| 606 | static_generate_memory_accessor(4, TRUE, "write32", &m_write32); |
| 825 | 607 | } |
| 826 | 608 | catch (drcuml_block::abort_compilation &) |
| 827 | 609 | { |
| 828 | 610 | fatalerror("Unable to generate SH2 static code\n"); |
| 829 | 611 | } |
| 830 | 612 | |
| 831 | | sh2->cache_dirty = FALSE; |
| 613 | m_cache_dirty = FALSE; |
| 832 | 614 | } |
| 833 | 615 | |
| 834 | 616 | /* Execute cycles - returns number of cycles actually run */ |
| 835 | | static CPU_EXECUTE( sh2 ) |
| 617 | void sh2_device::execute_run_drc() |
| 836 | 618 | { |
| 837 | | sh2_state *sh2 = get_safe_token(device); |
| 838 | | drcuml_state *drcuml = sh2->drcuml; |
| 619 | drcuml_state *drcuml = m_drcuml; |
| 839 | 620 | int execute_result; |
| 840 | 621 | |
| 841 | 622 | // run any active DMAs now |
| 842 | 623 | #ifndef USE_TIMER_FOR_DMA |
| 843 | | for ( int i = 0; i < sh2->icount ; i++) |
| 624 | for ( int i = 0; i < m_sh2_state->icount ; i++) |
| 844 | 625 | { |
| 845 | 626 | for( int dma=0;dma<1;dma++) |
| 846 | 627 | { |
| 847 | | if (sh2->dma_timer_active[dma]) |
| 848 | | sh2_do_dma(sh2, dma); |
| 628 | if (m_dma_timer_active[dma]) |
| 629 | sh2_do_dma(dma); |
| 849 | 630 | } |
| 850 | 631 | } |
| 851 | 632 | #endif |
| 852 | 633 | |
| 853 | 634 | /* reset the cache if dirty */ |
| 854 | | if (sh2->cache_dirty) |
| 855 | | code_flush_cache(sh2); |
| 635 | if (m_cache_dirty) |
| 636 | code_flush_cache(); |
| 856 | 637 | |
| 857 | 638 | /* execute */ |
| 858 | 639 | do |
| 859 | 640 | { |
| 860 | 641 | /* run as much as we can */ |
| 861 | | execute_result = drcuml->execute(*sh2->entry); |
| 642 | execute_result = drcuml->execute(*m_entry); |
| 862 | 643 | |
| 863 | 644 | /* if we need to recompile, do it */ |
| 864 | 645 | if (execute_result == EXECUTE_MISSING_CODE) |
| 865 | 646 | { |
| 866 | | code_compile_block(sh2, 0, sh2->pc); |
| 647 | code_compile_block(0, m_sh2_state->pc); |
| 867 | 648 | } |
| 868 | 649 | else if (execute_result == EXECUTE_UNMAPPED_CODE) |
| 869 | 650 | { |
| 870 | | fatalerror("Attempted to execute unmapped code at PC=%08X\n", sh2->pc); |
| 651 | fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_sh2_state->pc); |
| 871 | 652 | } |
| 872 | 653 | else if (execute_result == EXECUTE_RESET_CACHE) |
| 873 | 654 | { |
| 874 | | code_flush_cache(sh2); |
| 655 | code_flush_cache(); |
| 875 | 656 | } |
| 876 | 657 | } while (execute_result != EXECUTE_OUT_OF_CYCLES); |
| 877 | 658 | } |
| r29568 | r29569 | |
| 881 | 662 | given mode at the specified pc |
| 882 | 663 | -------------------------------------------------*/ |
| 883 | 664 | |
| 884 | | static void code_compile_block(sh2_state *sh2, UINT8 mode, offs_t pc) |
| 665 | void sh2_device::code_compile_block(UINT8 mode, offs_t pc) |
| 885 | 666 | { |
| 886 | | drcuml_state *drcuml = sh2->drcuml; |
| 667 | drcuml_state *drcuml = m_drcuml; |
| 887 | 668 | compiler_state compiler = { 0 }; |
| 888 | 669 | const opcode_desc *seqhead, *seqlast; |
| 889 | 670 | const opcode_desc *desclist; |
| r29568 | r29569 | |
| 893 | 674 | g_profiler.start(PROFILER_DRC_COMPILE); |
| 894 | 675 | |
| 895 | 676 | /* get a description of this sequence */ |
| 896 | | desclist = sh2->drcfe->describe_code(pc); |
| 677 | desclist = m_drcfe->describe_code(pc); |
| 897 | 678 | if (LOG_UML || LOG_NATIVE) |
| 898 | 679 | log_opcode_desc(drcuml, desclist, 0); |
| 899 | 680 | |
| r29568 | r29569 | |
| 937 | 718 | else |
| 938 | 719 | { |
| 939 | 720 | UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 |
| 940 | | UML_HASHJMP(block, 0, seqhead->pc, *sh2->nocode); |
| 721 | UML_HASHJMP(block, 0, seqhead->pc, *m_nocode); |
| 941 | 722 | // hashjmp <mode>,seqhead->pc,nocode |
| 942 | 723 | continue; |
| 943 | 724 | } |
| 944 | 725 | |
| 945 | 726 | /* validate this code block if we're not pointing into ROM */ |
| 946 | | if (sh2->program->get_write_ptr(seqhead->physpc) != NULL) |
| 947 | | generate_checksum_block(sh2, block, &compiler, seqhead, seqlast); |
| 727 | if (m_program->get_write_ptr(seqhead->physpc) != NULL) |
| 728 | generate_checksum_block(block, &compiler, seqhead, seqlast); |
| 948 | 729 | |
| 949 | 730 | /* label this instruction, if it may be jumped to locally */ |
| 950 | 731 | if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) |
| r29568 | r29569 | |
| 955 | 736 | /* iterate over instructions in the sequence and compile them */ |
| 956 | 737 | for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) |
| 957 | 738 | { |
| 958 | | generate_sequence_instruction(sh2, block, &compiler, curdesc, 0xffffffff); |
| 739 | generate_sequence_instruction(block, &compiler, curdesc, 0xffffffff); |
| 959 | 740 | } |
| 960 | 741 | |
| 961 | 742 | /* if we need to return to the start, do it */ |
| r29568 | r29569 | |
| 970 | 751 | } |
| 971 | 752 | |
| 972 | 753 | /* count off cycles and go there */ |
| 973 | | generate_update_cycles(sh2, block, &compiler, nextpc, TRUE); // <subtract cycles> |
| 754 | generate_update_cycles(block, &compiler, nextpc, TRUE); // <subtract cycles> |
| 974 | 755 | |
| 975 | 756 | /* SH2 has no modes */ |
| 976 | 757 | if (seqlast->next() == NULL || seqlast->next()->pc != nextpc) |
| 977 | 758 | { |
| 978 | | UML_HASHJMP(block, 0, nextpc, *sh2->nocode); |
| 759 | UML_HASHJMP(block, 0, nextpc, *m_nocode); |
| 979 | 760 | } |
| 980 | 761 | // hashjmp <mode>,nextpc,nocode |
| 981 | 762 | } |
| r29568 | r29569 | |
| 987 | 768 | } |
| 988 | 769 | catch (drcuml_block::abort_compilation &) |
| 989 | 770 | { |
| 990 | | code_flush_cache(sh2); |
| 771 | code_flush_cache(); |
| 991 | 772 | } |
| 992 | 773 | } |
| 993 | 774 | } |
| r29568 | r29569 | |
| 997 | 778 | static entry point |
| 998 | 779 | -------------------------------------------------*/ |
| 999 | 780 | |
| 1000 | | static void static_generate_entry_point(sh2_state *sh2) |
| 781 | void sh2_device::static_generate_entry_point() |
| 1001 | 782 | { |
| 1002 | | drcuml_state *drcuml = sh2->drcuml; |
| 783 | drcuml_state *drcuml = m_drcuml; |
| 1003 | 784 | code_label skip = 1; |
| 1004 | 785 | drcuml_block *block; |
| 1005 | 786 | |
| r29568 | r29569 | |
| 1007 | 788 | block = drcuml->begin_block(200); |
| 1008 | 789 | |
| 1009 | 790 | /* forward references */ |
| 1010 | | alloc_handle(drcuml, &sh2->nocode, "nocode"); |
| 1011 | | alloc_handle(drcuml, &sh2->write32, "write32"); // necessary? |
| 1012 | | alloc_handle(drcuml, &sh2->entry, "entry"); |
| 1013 | | UML_HANDLE(block, *sh2->entry); // handle entry |
| 791 | alloc_handle(drcuml, &m_nocode, "nocode"); |
| 792 | alloc_handle(drcuml, &m_write32, "write32"); // necessary? |
| 793 | alloc_handle(drcuml, &m_entry, "entry"); |
| 794 | UML_HANDLE(block, *m_entry); // handle entry |
| 1014 | 795 | |
| 1015 | 796 | /* load fast integer registers */ |
| 1016 | | load_fast_iregs(sh2, block); |
| 797 | load_fast_iregs(block); |
| 1017 | 798 | |
| 1018 | 799 | /* check for interrupts */ |
| 1019 | | UML_MOV(block, mem(&sh2->irqline), 0xffffffff); // mov irqline, #-1 |
| 1020 | | UML_CMP(block, mem(&sh2->pending_nmi), 0); // cmp pending_nmi, #0 |
| 800 | UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 |
| 801 | UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 |
| 1021 | 802 | UML_JMPc(block, COND_Z, skip+2); // jz skip+2 |
| 1022 | 803 | |
| 1023 | | UML_MOV(block, mem(&sh2->pending_nmi), 0); // zap pending_nmi |
| 804 | UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi |
| 1024 | 805 | UML_JMP(block, skip+1); // and then go take it (evec is already set) |
| 1025 | 806 | |
| 1026 | 807 | UML_LABEL(block, skip+2); // skip+2: |
| 1027 | | UML_MOV(block, mem(&sh2->evec), 0xffffffff); // mov evec, -1 |
| 808 | UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 |
| 1028 | 809 | UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) |
| 1029 | 810 | UML_AND(block, I1, I0, 0xffff); // and r1, 0xffff |
| 1030 | 811 | |
| 1031 | | UML_LZCNT(block, I1, mem(&sh2->pending_irq)); // lzcnt r1, r1 |
| 812 | UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, r1 |
| 1032 | 813 | UML_CMP(block, I1, 32); // cmp r1, #32 |
| 1033 | 814 | UML_JMPc(block, COND_Z, skip+4); // jz skip+4 |
| 1034 | 815 | |
| 1035 | | UML_SUB(block, mem(&sh2->irqline), 31, I1); // sub irqline, #31, r1 |
| 816 | UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 |
| 1036 | 817 | |
| 1037 | 818 | UML_LABEL(block, skip+4); // skip+4: |
| 1038 | | UML_CMP(block, mem(&sh2->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 |
| 819 | UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 |
| 1039 | 820 | UML_JMPc(block, COND_Z, skip+3); // jz skip+3 |
| 1040 | | UML_CMP(block, mem(&sh2->internal_irq_level), mem(&sh2->irqline)); // cmp internal_irq_level, irqline |
| 821 | UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline |
| 1041 | 822 | UML_JMPc(block, COND_LE, skip+3); // jle skip+3 |
| 1042 | 823 | |
| 1043 | | UML_MOV(block, mem(&sh2->irqline), mem(&sh2->internal_irq_level)); // mov r0, internal_irq_level |
| 824 | UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level |
| 1044 | 825 | |
| 1045 | 826 | UML_LABEL(block, skip+3); // skip+3: |
| 1046 | | UML_CMP(block, mem(&sh2->irqline), 0xffffffff); // cmp irqline, #-1 |
| 827 | UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 |
| 1047 | 828 | UML_JMPc(block, COND_Z, skip+1); // jz skip+1 |
| 1048 | | UML_CALLC(block, cfunc_fastirq, sh2); // callc fastirq |
| 829 | UML_CALLC(block, cfunc_fastirq, this); // callc fastirq |
| 1049 | 830 | |
| 1050 | 831 | UML_LABEL(block, skip+1); // skip+1: |
| 1051 | 832 | |
| 1052 | | UML_CMP(block, mem(&sh2->evec), 0xffffffff); // cmp evec, 0xffffffff |
| 833 | UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff |
| 1053 | 834 | UML_JMPc(block, COND_Z, skip); // jz skip |
| 1054 | 835 | |
| 1055 | 836 | UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 |
| 1056 | 837 | UML_MOV(block, I0, R32(15)); // mov r0, R15 |
| 1057 | | UML_MOV(block, I1, mem(&sh2->irqsr)); // mov r1, irqsr |
| 1058 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 838 | UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr |
| 839 | UML_CALLH(block, *m_write32); // call write32 |
| 1059 | 840 | |
| 1060 | 841 | UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 |
| 1061 | 842 | UML_MOV(block, I0, R32(15)); // mov r0, R15 |
| 1062 | | UML_MOV(block, I1, mem(&sh2->pc)); // mov r1, pc |
| 1063 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 843 | UML_MOV(block, I1, mem(&m_sh2_state->pc)); // mov r1, pc |
| 844 | UML_CALLH(block, *m_write32); // call write32 |
| 1064 | 845 | |
| 1065 | | UML_MOV(block, mem(&sh2->pc), mem(&sh2->evec)); // mov pc, evec |
| 846 | UML_MOV(block, mem(&m_sh2_state->pc), mem(&m_sh2_state->evec)); // mov pc, evec |
| 1066 | 847 | |
| 1067 | 848 | UML_LABEL(block, skip); // skip: |
| 1068 | 849 | |
| 1069 | 850 | /* generate a hash jump via the current mode and PC */ |
| 1070 | | UML_HASHJMP(block, 0, mem(&sh2->pc), *sh2->nocode); // hashjmp <mode>,<pc>,nocode |
| 851 | UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // hashjmp <mode>,<pc>,nocode |
| 1071 | 852 | |
| 1072 | 853 | block->end(); |
| 1073 | 854 | } |
| r29568 | r29569 | |
| 1077 | 858 | exception handler for "out of code" |
| 1078 | 859 | -------------------------------------------------*/ |
| 1079 | 860 | |
| 1080 | | static void static_generate_nocode_handler(sh2_state *sh2) |
| 861 | void sh2_device::static_generate_nocode_handler() |
| 1081 | 862 | { |
| 1082 | | drcuml_state *drcuml = sh2->drcuml; |
| 863 | drcuml_state *drcuml = m_drcuml; |
| 1083 | 864 | drcuml_block *block; |
| 1084 | 865 | |
| 1085 | 866 | /* begin generating */ |
| 1086 | 867 | block = drcuml->begin_block(10); |
| 1087 | 868 | |
| 1088 | 869 | /* generate a hash jump via the current mode and PC */ |
| 1089 | | alloc_handle(drcuml, &sh2->nocode, "nocode"); |
| 1090 | | UML_HANDLE(block, *sh2->nocode); // handle nocode |
| 870 | alloc_handle(drcuml, &m_nocode, "nocode"); |
| 871 | UML_HANDLE(block, *m_nocode); // handle nocode |
| 1091 | 872 | UML_GETEXP(block, I0); // getexp i0 |
| 1092 | | UML_MOV(block, mem(&sh2->pc), I0); // mov [pc],i0 |
| 1093 | | save_fast_iregs(sh2, block); |
| 873 | UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov [pc],i0 |
| 874 | save_fast_iregs(block); |
| 1094 | 875 | UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE |
| 1095 | 876 | |
| 1096 | 877 | block->end(); |
| r29568 | r29569 | |
| 1102 | 883 | out of cycles exception handler |
| 1103 | 884 | -------------------------------------------------*/ |
| 1104 | 885 | |
| 1105 | | static void static_generate_out_of_cycles(sh2_state *sh2) |
| 886 | void sh2_device::static_generate_out_of_cycles() |
| 1106 | 887 | { |
| 1107 | | drcuml_state *drcuml = sh2->drcuml; |
| 888 | drcuml_state *drcuml = m_drcuml; |
| 1108 | 889 | drcuml_block *block; |
| 1109 | 890 | |
| 1110 | 891 | /* begin generating */ |
| 1111 | 892 | block = drcuml->begin_block(10); |
| 1112 | 893 | |
| 1113 | 894 | /* generate a hash jump via the current mode and PC */ |
| 1114 | | alloc_handle(drcuml, &sh2->out_of_cycles, "out_of_cycles"); |
| 1115 | | UML_HANDLE(block, *sh2->out_of_cycles); // handle out_of_cycles |
| 895 | alloc_handle(drcuml, &m_out_of_cycles, "out_of_cycles"); |
| 896 | UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles |
| 1116 | 897 | UML_GETEXP(block, I0); // getexp i0 |
| 1117 | | UML_MOV(block, mem(&sh2->pc), I0); // mov <pc>,i0 |
| 1118 | | save_fast_iregs(sh2,block); |
| 898 | UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov <pc>,i0 |
| 899 | save_fast_iregs(block); |
| 1119 | 900 | UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES |
| 1120 | 901 | |
| 1121 | 902 | block->end(); |
| r29568 | r29569 | |
| 1125 | 906 | static_generate_memory_accessor |
| 1126 | 907 | ------------------------------------------------------------------*/ |
| 1127 | 908 | |
| 1128 | | static void static_generate_memory_accessor(sh2_state *sh2, int size, int iswrite, const char *name, code_handle **handleptr) |
| 909 | void sh2_device::static_generate_memory_accessor(int size, int iswrite, const char *name, code_handle **handleptr) |
| 1129 | 910 | { |
| 1130 | 911 | /* on entry, address is in I0; data for writes is in I1 */ |
| 1131 | 912 | /* on exit, read result is in I0 */ |
| 1132 | 913 | /* routine trashes I0 */ |
| 1133 | | drcuml_state *drcuml = sh2->drcuml; |
| 914 | drcuml_state *drcuml = m_drcuml; |
| 1134 | 915 | drcuml_block *block; |
| 1135 | 916 | int label = 1; |
| 1136 | 917 | |
| r29568 | r29569 | |
| 1156 | 937 | #if 0 // DO NOT ENABLE - SEVERE AARON DAMAGE |
| 1157 | 938 | for (int ramnum = 0; ramnum < SH2_MAX_FASTRAM; ramnum++) |
| 1158 | 939 | { |
| 1159 | | if (sh2->fastram[ramnum].base != NULL && (!iswrite || !sh2->fastram[ramnum].readonly)) |
| 940 | if (m_fastram[ramnum].base != NULL && (!iswrite || !m_fastram[ramnum].readonly)) |
| 1160 | 941 | { |
| 1161 | | void *fastbase = (UINT8 *)sh2->fastram[ramnum].base - sh2->fastram[ramnum].start; |
| 942 | void *fastbase = (UINT8 *)m_fastram[ramnum].base - m_fastram[ramnum].start; |
| 1162 | 943 | UINT32 skip = label++; |
| 1163 | | if (sh2->fastram[ramnum].end != 0xffffffff) |
| 944 | if (m_fastram[ramnum].end != 0xffffffff) |
| 1164 | 945 | { |
| 1165 | | UML_CMP(block, I0, sh2->fastram[ramnum].end); // cmp i0,end |
| 946 | UML_CMP(block, I0, m_fastram[ramnum].end); // cmp i0,end |
| 1166 | 947 | UML_JMPc(block, COND_A, skip); // ja skip |
| 1167 | 948 | } |
| 1168 | | if (sh2->fastram[ramnum].start != 0x00000000) |
| 949 | if (m_fastram[ramnum].start != 0x00000000) |
| 1169 | 950 | { |
| 1170 | | UML_CMP(block, I0, sh2->fastram[ramnum].start);// cmp i0,fastram_start |
| 951 | UML_CMP(block, I0, m_fastram[ramnum].start);// cmp i0,fastram_start |
| 1171 | 952 | UML_JMPc(block, COND_B, skip); // jb skip |
| 1172 | 953 | } |
| 1173 | 954 | |
| r29568 | r29569 | |
| 1259 | 1040 | flags |
| 1260 | 1041 | -------------------------------------------------*/ |
| 1261 | 1042 | |
| 1262 | | static const char *log_desc_flags_to_string(UINT32 flags) |
| 1043 | const char *sh2_device::log_desc_flags_to_string(UINT32 flags) |
| 1263 | 1044 | { |
| 1264 | 1045 | static char tempbuf[30]; |
| 1265 | 1046 | char *dest = tempbuf; |
| r29568 | r29569 | |
| 1313 | 1094 | log_register_list - log a list of GPR registers |
| 1314 | 1095 | -------------------------------------------------*/ |
| 1315 | 1096 | |
| 1316 | | static void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist) |
| 1097 | void sh2_device::log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist) |
| 1317 | 1098 | { |
| 1318 | 1099 | int count = 0; |
| 1319 | 1100 | int regnum; |
| r29568 | r29569 | |
| 1383 | 1164 | log_opcode_desc - log a list of descriptions |
| 1384 | 1165 | -------------------------------------------------*/ |
| 1385 | 1166 | |
| 1386 | | static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent) |
| 1167 | void sh2_device::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent) |
| 1387 | 1168 | { |
| 1388 | 1169 | /* open the file, creating it if necessary */ |
| 1389 | 1170 | if (indent == 0) |
| r29568 | r29569 | |
| 1425 | 1206 | including disassembly of an SH2 instruction |
| 1426 | 1207 | -------------------------------------------------*/ |
| 1427 | 1208 | |
| 1428 | | static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op) |
| 1209 | void sh2_device::log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op) |
| 1429 | 1210 | { |
| 1430 | 1211 | #if (LOG_UML) |
| 1431 | 1212 | char buffer[100]; |
| r29568 | r29569 | |
| 1439 | 1220 | subtract cycles from the icount and generate |
| 1440 | 1221 | an exception if out |
| 1441 | 1222 | -------------------------------------------------*/ |
| 1442 | | static void generate_update_cycles(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception) |
| 1223 | void sh2_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception) |
| 1443 | 1224 | { |
| 1444 | 1225 | /* check full interrupts if pending */ |
| 1445 | 1226 | if (compiler->checkints) |
| r29568 | r29569 | |
| 1450 | 1231 | compiler->labelnum += 4; |
| 1451 | 1232 | |
| 1452 | 1233 | /* check for interrupts */ |
| 1453 | | UML_MOV(block, mem(&sh2->irqline), 0xffffffff); // mov irqline, #-1 |
| 1454 | | UML_CMP(block, mem(&sh2->pending_nmi), 0); // cmp pending_nmi, #0 |
| 1234 | UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 |
| 1235 | UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 |
| 1455 | 1236 | UML_JMPc(block, COND_Z, skip+2); // jz skip+2 |
| 1456 | 1237 | |
| 1457 | | UML_MOV(block, mem(&sh2->pending_nmi), 0); // zap pending_nmi |
| 1238 | UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi |
| 1458 | 1239 | UML_JMP(block, skip+1); // and then go take it (evec is already set) |
| 1459 | 1240 | |
| 1460 | 1241 | UML_LABEL(block, skip+2); // skip+2: |
| 1461 | | UML_MOV(block, mem(&sh2->evec), 0xffffffff); // mov evec, -1 |
| 1242 | UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 |
| 1462 | 1243 | UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) |
| 1463 | 1244 | UML_AND(block, I1, I0, 0xffff); // and r1, r0, 0xffff |
| 1464 | 1245 | |
| 1465 | | UML_LZCNT(block, I1, mem(&sh2->pending_irq)); // lzcnt r1, pending_irq |
| 1246 | UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, pending_irq |
| 1466 | 1247 | UML_CMP(block, I1, 32); // cmp r1, #32 |
| 1467 | 1248 | UML_JMPc(block, COND_Z, skip+4); // jz skip+4 |
| 1468 | 1249 | |
| 1469 | | UML_SUB(block, mem(&sh2->irqline), 31, I1); // sub irqline, #31, r1 |
| 1250 | UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 |
| 1470 | 1251 | |
| 1471 | 1252 | UML_LABEL(block, skip+4); // skip+4: |
| 1472 | | UML_CMP(block, mem(&sh2->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 |
| 1253 | UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 |
| 1473 | 1254 | UML_JMPc(block, COND_Z, skip+3); // jz skip+3 |
| 1474 | | UML_CMP(block, mem(&sh2->internal_irq_level), mem(&sh2->irqline)); // cmp internal_irq_level, irqline |
| 1255 | UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline |
| 1475 | 1256 | UML_JMPc(block, COND_LE, skip+3); // jle skip+3 |
| 1476 | 1257 | |
| 1477 | | UML_MOV(block, mem(&sh2->irqline), mem(&sh2->internal_irq_level)); // mov r0, internal_irq_level |
| 1258 | UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level |
| 1478 | 1259 | |
| 1479 | 1260 | UML_LABEL(block, skip+3); // skip+3: |
| 1480 | | UML_CMP(block, mem(&sh2->irqline), 0xffffffff); // cmp irqline, #-1 |
| 1261 | UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 |
| 1481 | 1262 | UML_JMPc(block, COND_Z, skip+1); // jz skip+1 |
| 1482 | | UML_CALLC(block, cfunc_fastirq, sh2); // callc fastirq |
| 1263 | UML_CALLC(block, cfunc_fastirq, this); // callc fastirq |
| 1483 | 1264 | |
| 1484 | 1265 | UML_LABEL(block, skip+1); // skip+1: |
| 1485 | | UML_CMP(block, mem(&sh2->evec), 0xffffffff); // cmp evec, 0xffffffff |
| 1266 | UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff |
| 1486 | 1267 | UML_JMPc(block, COND_Z, skip); // jz skip |
| 1487 | 1268 | |
| 1488 | 1269 | UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 |
| 1489 | 1270 | UML_MOV(block, I0, R32(15)); // mov r0, R15 |
| 1490 | | UML_MOV(block, I1, mem(&sh2->irqsr)); // mov r1, irqsr |
| 1491 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 1271 | UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr |
| 1272 | UML_CALLH(block, *m_write32); // call write32 |
| 1492 | 1273 | |
| 1493 | 1274 | UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 |
| 1494 | 1275 | UML_MOV(block, I0, R32(15)); // mov r0, R15 |
| 1495 | 1276 | UML_MOV(block, I1, param); // mov r1, nextpc |
| 1496 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 1277 | UML_CALLH(block, *m_write32); // call write32 |
| 1497 | 1278 | |
| 1498 | | UML_HASHJMP(block, 0, mem(&sh2->evec), *sh2->nocode); // hashjmp sh2->evec |
| 1279 | UML_HASHJMP(block, 0, mem(&m_sh2_state->evec), *m_nocode); // hashjmp m_sh2_state->evec |
| 1499 | 1280 | |
| 1500 | 1281 | UML_LABEL(block, skip); // skip: |
| 1501 | 1282 | } |
| r29568 | r29569 | |
| 1503 | 1284 | /* account for cycles */ |
| 1504 | 1285 | if (compiler->cycles > 0) |
| 1505 | 1286 | { |
| 1506 | | UML_SUB(block, mem(&sh2->icount), mem(&sh2->icount), MAPVAR_CYCLES); // sub icount,icount,cycles |
| 1287 | UML_SUB(block, mem(&m_sh2_state->icount), mem(&m_sh2_state->icount), MAPVAR_CYCLES); // sub icount,icount,cycles |
| 1507 | 1288 | UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 |
| 1508 | 1289 | if (allow_exception) |
| 1509 | | UML_EXHc(block, COND_S, *sh2->out_of_cycles, param); |
| 1290 | UML_EXHc(block, COND_S, *m_out_of_cycles, param); |
| 1510 | 1291 | // exh out_of_cycles,nextpc |
| 1511 | 1292 | } |
| 1512 | 1293 | compiler->cycles = 0; |
| r29568 | r29569 | |
| 1517 | 1298 | validate a sequence of opcodes |
| 1518 | 1299 | -------------------------------------------------*/ |
| 1519 | 1300 | |
| 1520 | | static void generate_checksum_block(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast) |
| 1301 | void sh2_device::generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast) |
| 1521 | 1302 | { |
| 1522 | 1303 | const opcode_desc *curdesc; |
| 1523 | 1304 | if (LOG_UML) |
| 1524 | 1305 | block->append_comment("[Validation for %08X]", seqhead->pc); // comment |
| 1525 | 1306 | |
| 1526 | 1307 | /* loose verify or single instruction: just compare and fail */ |
| 1527 | | if (!(sh2->drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == NULL) |
| 1308 | if (!(m_drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == NULL) |
| 1528 | 1309 | { |
| 1529 | 1310 | if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) |
| 1530 | 1311 | { |
| 1531 | | void *base = sh2->direct->read_decrypted_ptr(seqhead->physpc, SH2_CODE_XOR(0)); |
| 1312 | void *base = m_direct->read_decrypted_ptr(seqhead->physpc, SH2_CODE_XOR(0)); |
| 1532 | 1313 | UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,word |
| 1533 | 1314 | UML_CMP(block, I0, seqhead->opptr.w[0]); // cmp i0,*opptr |
| 1534 | | UML_EXHc(block, COND_NE, *sh2->nocode, epc(seqhead)); // exne nocode,seqhead->pc |
| 1315 | UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc |
| 1535 | 1316 | } |
| 1536 | 1317 | } |
| 1537 | 1318 | |
| r29568 | r29569 | |
| 1542 | 1323 | for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) |
| 1543 | 1324 | if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) |
| 1544 | 1325 | { |
| 1545 | | base = sh2->direct->read_decrypted_ptr(curdesc->physpc, SH2_CODE_XOR(0)); |
| 1326 | base = m_direct->read_decrypted_ptr(curdesc->physpc, SH2_CODE_XOR(0)); |
| 1546 | 1327 | UML_LOAD(block, I0, curdesc->opptr.w, 0, SIZE_WORD, SCALE_x2); // load i0,*opptr,0,word |
| 1547 | 1328 | UML_CMP(block, I0, curdesc->opptr.w[0]); // cmp i0,*opptr |
| 1548 | | UML_EXHc(block, COND_NE, *sh2->nocode, epc(seqhead)); // exne nocode,seqhead->pc |
| 1329 | UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc |
| 1549 | 1330 | } |
| 1550 | 1331 | #else |
| 1551 | 1332 | UINT32 sum = 0; |
| 1552 | | void *base = sh2->direct->read_decrypted_ptr(seqhead->physpc, SH2_CODE_XOR(0)); |
| 1333 | void *base = m_direct->read_decrypted_ptr(seqhead->physpc, SH2_CODE_XOR(0)); |
| 1553 | 1334 | UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x4); // load i0,base,word |
| 1554 | 1335 | sum += seqhead->opptr.w[0]; |
| 1555 | 1336 | for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) |
| 1556 | 1337 | if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) |
| 1557 | 1338 | { |
| 1558 | | base = sh2->direct->read_decrypted_ptr(curdesc->physpc, SH2_CODE_XOR(0)); |
| 1339 | base = m_direct->read_decrypted_ptr(curdesc->physpc, SH2_CODE_XOR(0)); |
| 1559 | 1340 | UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,*opptr,word |
| 1560 | 1341 | UML_ADD(block, I0, I0, I1); // add i0,i0,i1 |
| 1561 | 1342 | sum += curdesc->opptr.w[0]; |
| 1562 | 1343 | } |
| 1563 | 1344 | UML_CMP(block, I0, sum); // cmp i0,sum |
| 1564 | | UML_EXHc(block, COND_NE, *sh2->nocode, epc(seqhead)); // exne nocode,seqhead->pc |
| 1345 | UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc |
| 1565 | 1346 | #endif |
| 1566 | 1347 | } |
| 1567 | 1348 | } |
| r29568 | r29569 | |
| 1572 | 1353 | for a single instruction in a sequence |
| 1573 | 1354 | -------------------------------------------------*/ |
| 1574 | 1355 | |
| 1575 | | static void generate_sequence_instruction(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc) |
| 1356 | void sh2_device::generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc) |
| 1576 | 1357 | { |
| 1577 | 1358 | offs_t expc; |
| 1578 | 1359 | |
| r29568 | r29569 | |
| 1593 | 1374 | /* if we want a probe, add it here */ |
| 1594 | 1375 | if (desc->pc == PROBE_ADDRESS) |
| 1595 | 1376 | { |
| 1596 | | UML_MOV(block, mem(&sh2->pc), desc->pc); // mov [pc],desc->pc |
| 1597 | | UML_CALLC(block, cfunc_printf_probe, sh2); // callc cfunc_printf_probe,sh2 |
| 1377 | UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc |
| 1378 | UML_CALLC(block, cfunc_printf_probe, this); // callc cfunc_printf_probe,sh2 |
| 1598 | 1379 | } |
| 1599 | 1380 | |
| 1600 | 1381 | /* if we are debugging, call the debugger */ |
| 1601 | | if ((sh2->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 1382 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 1602 | 1383 | { |
| 1603 | | UML_MOV(block, mem(&sh2->pc), desc->pc); // mov [pc],desc->pc |
| 1604 | | save_fast_iregs(sh2, block); |
| 1384 | UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc |
| 1385 | save_fast_iregs(block); |
| 1605 | 1386 | UML_DEBUG(block, desc->pc); // debug desc->pc |
| 1606 | 1387 | } |
| 1607 | 1388 | else // not debug, see what other reasons there are for flushing the PC |
| 1608 | 1389 | { |
| 1609 | | if (sh2->drcoptions & SH2DRC_FLUSH_PC) // always flush? |
| 1390 | if (m_drcoptions & SH2DRC_FLUSH_PC) // always flush? |
| 1610 | 1391 | { |
| 1611 | | UML_MOV(block, mem(&sh2->pc), desc->pc); // mov sh2->pc, desc->pc |
| 1392 | UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc |
| 1612 | 1393 | } |
| 1613 | 1394 | else // check for driver-selected flushes |
| 1614 | 1395 | { |
| 1615 | 1396 | int pcflush; |
| 1616 | 1397 | |
| 1617 | | for (pcflush = 0; pcflush < sh2->pcfsel; pcflush++) |
| 1398 | for (pcflush = 0; pcflush < m_pcfsel; pcflush++) |
| 1618 | 1399 | { |
| 1619 | | if (desc->pc == sh2->pcflushes[pcflush]) |
| 1400 | if (desc->pc == m_pcflushes[pcflush]) |
| 1620 | 1401 | { |
| 1621 | | UML_MOV(block, mem(&sh2->pc), desc->pc); // mov sh2->pc, desc->pc |
| 1402 | UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc |
| 1622 | 1403 | } |
| 1623 | 1404 | } |
| 1624 | 1405 | } |
| r29568 | r29569 | |
| 1628 | 1409 | /* if we hit an unmapped address, fatal error */ |
| 1629 | 1410 | if (desc->flags & OPFLAG_COMPILER_UNMAPPED) |
| 1630 | 1411 | { |
| 1631 | | UML_MOV(block, mem(&sh2->pc), desc->pc); // mov [pc],desc->pc |
| 1632 | | save_fast_iregs(sh2, block); |
| 1412 | UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc |
| 1413 | save_fast_iregs(block); |
| 1633 | 1414 | UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE |
| 1634 | 1415 | } |
| 1635 | 1416 | |
| r29568 | r29569 | |
| 1643 | 1424 | else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) |
| 1644 | 1425 | { |
| 1645 | 1426 | /* compile the instruction */ |
| 1646 | | if (!generate_opcode(sh2, block, compiler, desc, ovrpc)) |
| 1427 | if (!generate_opcode(block, compiler, desc, ovrpc)) |
| 1647 | 1428 | { |
| 1648 | 1429 | // handle an illegal op |
| 1649 | | UML_MOV(block, mem(&sh2->pc), desc->pc); // mov [pc],desc->pc |
| 1650 | | UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]); // mov [arg0],opcode |
| 1651 | | UML_CALLC(block, cfunc_unimplemented, sh2); // callc cfunc_unimplemented |
| 1430 | UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc |
| 1431 | UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); // mov [arg0],opcode |
| 1432 | UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented |
| 1652 | 1433 | } |
| 1653 | 1434 | } |
| 1654 | 1435 | } |
| r29568 | r29569 | |
| 1657 | 1438 | generate_delay_slot |
| 1658 | 1439 | ------------------------------------------------------------------*/ |
| 1659 | 1440 | |
| 1660 | | static void generate_delay_slot(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc) |
| 1441 | void sh2_device::generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc) |
| 1661 | 1442 | { |
| 1662 | 1443 | compiler_state compiler_temp = *compiler; |
| 1663 | 1444 | |
| 1664 | 1445 | /* compile the delay slot using temporary compiler state */ |
| 1665 | 1446 | assert(desc->delay.first() != NULL); |
| 1666 | | generate_sequence_instruction(sh2, block, &compiler_temp, desc->delay.first(), ovrpc); // <next instruction> |
| 1447 | generate_sequence_instruction(block, &compiler_temp, desc->delay.first(), ovrpc); // <next instruction> |
| 1667 | 1448 | |
| 1668 | 1449 | /* update the label */ |
| 1669 | 1450 | compiler->labelnum = compiler_temp.labelnum; |
| r29568 | r29569 | |
| 1674 | 1455 | opcode |
| 1675 | 1456 | -------------------------------------------------*/ |
| 1676 | 1457 | |
| 1677 | | static int generate_opcode(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc) |
| 1458 | int sh2_device::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 ovrpc) |
| 1678 | 1459 | { |
| 1679 | 1460 | UINT32 scratch, scratch2; |
| 1680 | 1461 | INT32 disp; |
| r29568 | r29569 | |
| 1685 | 1466 | switch (opswitch) |
| 1686 | 1467 | { |
| 1687 | 1468 | case 0: |
| 1688 | | return generate_group_0(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1469 | return generate_group_0(block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1689 | 1470 | |
| 1690 | 1471 | case 1: // MOVLS4 |
| 1691 | 1472 | scratch = (opcode & 0x0f) * 4; |
| 1692 | 1473 | UML_ADD(block, I0, R32(Rn), scratch); // add r0, Rn, scratch |
| 1693 | 1474 | UML_MOV(block, I1, R32(Rm)); // mov r1, Rm |
| 1694 | 1475 | SETEA(0); // set ea for debug |
| 1695 | | UML_CALLH(block, *sh2->write32); |
| 1476 | UML_CALLH(block, *m_write32); |
| 1696 | 1477 | |
| 1697 | 1478 | if (!in_delay_slot) |
| 1698 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1479 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1699 | 1480 | return TRUE; |
| 1700 | 1481 | |
| 1701 | 1482 | case 2: |
| 1702 | | return generate_group_2(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1483 | return generate_group_2(block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1703 | 1484 | case 3: |
| 1704 | | return generate_group_3(sh2, block, compiler, desc, opcode, ovrpc); |
| 1485 | return generate_group_3(block, compiler, desc, opcode, ovrpc); |
| 1705 | 1486 | case 4: |
| 1706 | | return generate_group_4(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1487 | return generate_group_4(block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1707 | 1488 | |
| 1708 | 1489 | case 5: // MOVLL4 |
| 1709 | 1490 | scratch = (opcode & 0x0f) * 4; |
| 1710 | 1491 | UML_ADD(block, I0, R32(Rm), scratch); // add r0, Rm, scratch |
| 1711 | 1492 | SETEA(0); // set ea for debug |
| 1712 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 1493 | UML_CALLH(block, *m_read32); // call read32 |
| 1713 | 1494 | UML_MOV(block, R32(Rn), I0); // mov Rn, r0 |
| 1714 | 1495 | |
| 1715 | 1496 | if (!in_delay_slot) |
| 1716 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1497 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1717 | 1498 | return TRUE; |
| 1718 | 1499 | |
| 1719 | 1500 | case 6: |
| 1720 | | return generate_group_6(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1501 | return generate_group_6(block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1721 | 1502 | |
| 1722 | 1503 | case 7: // ADDI |
| 1723 | 1504 | scratch = opcode & 0xff; |
| r29568 | r29569 | |
| 1726 | 1507 | return TRUE; |
| 1727 | 1508 | |
| 1728 | 1509 | case 8: |
| 1729 | | return generate_group_8(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1510 | return generate_group_8(block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1730 | 1511 | |
| 1731 | 1512 | case 9: // MOVWI |
| 1732 | 1513 | if (ovrpc == 0xffffffff) |
| r29568 | r29569 | |
| 1738 | 1519 | scratch = (ovrpc + 2) + ((opcode & 0xff) * 2) + 2; |
| 1739 | 1520 | } |
| 1740 | 1521 | |
| 1741 | | if (sh2->drcoptions & SH2DRC_STRICT_PCREL) |
| 1522 | if (m_drcoptions & SH2DRC_STRICT_PCREL) |
| 1742 | 1523 | { |
| 1743 | 1524 | UML_MOV(block, I0, scratch); // mov r0, scratch |
| 1744 | 1525 | SETEA(0); // set ea for debug |
| 1745 | | UML_CALLH(block, *sh2->read16); // read16(r0, r1) |
| 1526 | UML_CALLH(block, *m_read16); // read16(r0, r1) |
| 1746 | 1527 | UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD |
| 1747 | 1528 | } |
| 1748 | 1529 | else |
| 1749 | 1530 | { |
| 1750 | | scratch2 = (UINT32)(INT32)(INT16) RW(sh2, scratch); |
| 1531 | scratch2 = (UINT32)(INT32)(INT16) RW(scratch); |
| 1751 | 1532 | UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 |
| 1752 | 1533 | } |
| 1753 | 1534 | |
| 1754 | 1535 | if (!in_delay_slot) |
| 1755 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1536 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1756 | 1537 | return TRUE; |
| 1757 | 1538 | |
| 1758 | 1539 | case 10: // BRA |
| 1759 | 1540 | disp = ((INT32)opcode << 20) >> 20; |
| 1760 | | sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = pc+4 + disp*2 + 2 |
| 1541 | m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = pc+4 + disp*2 + 2 |
| 1761 | 1542 | |
| 1762 | | generate_delay_slot(sh2, block, compiler, desc, sh2->ea-2); |
| 1543 | generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); |
| 1763 | 1544 | |
| 1764 | | generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles> |
| 1765 | | UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // hashjmp sh2->ea |
| 1545 | generate_update_cycles(block, compiler, m_sh2_state->ea, TRUE); // <subtract cycles> |
| 1546 | UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea |
| 1766 | 1547 | return TRUE; |
| 1767 | 1548 | |
| 1768 | 1549 | case 11: // BSR |
| 1769 | 1550 | // panicstr @ 403da22 relies on the delay slot clobbering the PR set by a BSR, so |
| 1770 | 1551 | // do this before running the delay slot |
| 1771 | | UML_ADD(block, mem(&sh2->pr), desc->pc, 4); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot) |
| 1552 | UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) |
| 1772 | 1553 | |
| 1773 | 1554 | disp = ((INT32)opcode << 20) >> 20; |
| 1774 | | sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = pc+4 + disp*2 + 2 |
| 1555 | m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = pc+4 + disp*2 + 2 |
| 1775 | 1556 | |
| 1776 | | generate_delay_slot(sh2, block, compiler, desc, sh2->ea-2); |
| 1557 | generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); |
| 1777 | 1558 | |
| 1778 | | generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles> |
| 1779 | | UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // hashjmp sh2->ea |
| 1559 | generate_update_cycles(block, compiler, m_sh2_state->ea, TRUE); // <subtract cycles> |
| 1560 | UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea |
| 1780 | 1561 | return TRUE; |
| 1781 | 1562 | |
| 1782 | 1563 | case 12: |
| 1783 | | return generate_group_12(sh2, block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1564 | return generate_group_12(block, compiler, desc, opcode, in_delay_slot, ovrpc); |
| 1784 | 1565 | |
| 1785 | 1566 | case 13: // MOVLI |
| 1786 | 1567 | if (ovrpc == 0xffffffff) |
| r29568 | r29569 | |
| 1792 | 1573 | scratch = ((ovrpc + 4) & ~3) + ((opcode & 0xff) * 4); |
| 1793 | 1574 | } |
| 1794 | 1575 | |
| 1795 | | if (sh2->drcoptions & SH2DRC_STRICT_PCREL) |
| 1576 | if (m_drcoptions & SH2DRC_STRICT_PCREL) |
| 1796 | 1577 | { |
| 1797 | 1578 | UML_MOV(block, I0, scratch); // mov r0, scratch |
| 1798 | | UML_CALLH(block, *sh2->read32); // read32(r0, r1) |
| 1579 | UML_CALLH(block, *m_read32); // read32(r0, r1) |
| 1799 | 1580 | UML_MOV(block, R32(Rn), I0); // mov Rn, r0 |
| 1800 | 1581 | } |
| 1801 | 1582 | else |
| 1802 | 1583 | { |
| 1803 | | scratch2 = RL(sh2, scratch); |
| 1584 | scratch2 = RL(scratch); |
| 1804 | 1585 | UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 |
| 1805 | 1586 | } |
| 1806 | 1587 | |
| 1807 | 1588 | if (!in_delay_slot) |
| 1808 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1589 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1809 | 1590 | return TRUE; |
| 1810 | 1591 | |
| 1811 | 1592 | case 14: // MOVI |
| r29568 | r29569 | |
| 1821 | 1602 | return FALSE; |
| 1822 | 1603 | } |
| 1823 | 1604 | |
| 1824 | | static int generate_group_0(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 1605 | int sh2_device::generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 1825 | 1606 | { |
| 1826 | 1607 | switch (opcode & 0x3F) |
| 1827 | 1608 | { |
| r29568 | r29569 | |
| 1846 | 1627 | return TRUE; |
| 1847 | 1628 | |
| 1848 | 1629 | case 0x02: // STCSR(Rn); |
| 1849 | | UML_MOV(block, R32(Rn), mem(&sh2->sr)); |
| 1630 | UML_MOV(block, R32(Rn), mem(&m_sh2_state->sr)); |
| 1850 | 1631 | return TRUE; |
| 1851 | 1632 | |
| 1852 | 1633 | case 0x03: // BSRF(Rn); |
| 1853 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 1634 | if (m_cpu_type > CPU_TYPE_SH1) |
| 1854 | 1635 | { |
| 1855 | | UML_ADD(block, mem(&sh2->target), R32(Rn), 4); // add target, Rm, #4 |
| 1856 | | UML_ADD(block, mem(&sh2->target), mem(&sh2->target), desc->pc); // add target, target, pc |
| 1636 | UML_ADD(block, mem(&m_sh2_state->target), R32(Rn), 4); // add target, Rm, #4 |
| 1637 | UML_ADD(block, mem(&m_sh2_state->target), mem(&m_sh2_state->target), desc->pc); // add target, target, pc |
| 1857 | 1638 | |
| 1858 | 1639 | // 32x Cosmic Carnage @ 6002cb0 relies on the delay slot |
| 1859 | 1640 | // clobbering the calculated PR, so do it first |
| 1860 | | UML_ADD(block, mem(&sh2->pr), desc->pc, 4); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot) |
| 1641 | UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) |
| 1861 | 1642 | |
| 1862 | | generate_delay_slot(sh2, block, compiler, desc, sh2->target); |
| 1643 | generate_delay_slot(block, compiler, desc, m_sh2_state->target); |
| 1863 | 1644 | |
| 1864 | | generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles> |
| 1865 | | UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); // jmp target |
| 1645 | generate_update_cycles(block, compiler, mem(&m_sh2_state->target), TRUE); // <subtract cycles> |
| 1646 | UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target |
| 1866 | 1647 | return TRUE; |
| 1867 | 1648 | } |
| 1868 | 1649 | break; |
| r29568 | r29569 | |
| 1873 | 1654 | case 0x34: // MOVBS0(Rm, Rn); |
| 1874 | 1655 | UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn |
| 1875 | 1656 | UML_AND(block, I1, R32(Rm), 0x000000ff); // and r1, Rm, 0xff |
| 1876 | | UML_CALLH(block, *sh2->write8); // call write8 |
| 1657 | UML_CALLH(block, *m_write8); // call write8 |
| 1877 | 1658 | |
| 1878 | 1659 | if (!in_delay_slot) |
| 1879 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1660 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1880 | 1661 | return TRUE; |
| 1881 | 1662 | |
| 1882 | 1663 | case 0x05: // MOVWS0(Rm, Rn); |
| r29568 | r29569 | |
| 1885 | 1666 | case 0x35: // MOVWS0(Rm, Rn); |
| 1886 | 1667 | UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn |
| 1887 | 1668 | UML_AND(block, I1, R32(Rm), 0x0000ffff); // and r1, Rm, 0xffff |
| 1888 | | UML_CALLH(block, *sh2->write16); // call write16 |
| 1669 | UML_CALLH(block, *m_write16); // call write16 |
| 1889 | 1670 | |
| 1890 | 1671 | if (!in_delay_slot) |
| 1891 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1672 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1892 | 1673 | return TRUE; |
| 1893 | 1674 | |
| 1894 | 1675 | case 0x06: // MOVLS0(Rm, Rn); |
| r29568 | r29569 | |
| 1897 | 1678 | case 0x36: // MOVLS0(Rm, Rn); |
| 1898 | 1679 | UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn |
| 1899 | 1680 | UML_MOV(block, I1, R32(Rm)); // mov r1, Rm |
| 1900 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 1681 | UML_CALLH(block, *m_write32); // call write32 |
| 1901 | 1682 | |
| 1902 | 1683 | if (!in_delay_slot) |
| 1903 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1684 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1904 | 1685 | return TRUE; |
| 1905 | 1686 | |
| 1906 | 1687 | case 0x07: // MULL(Rm, Rn); |
| 1907 | 1688 | case 0x17: // MULL(Rm, Rn); |
| 1908 | 1689 | case 0x27: // MULL(Rm, Rn); |
| 1909 | 1690 | case 0x37: // MULL(Rm, Rn); |
| 1910 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 1691 | if (m_cpu_type > CPU_TYPE_SH1) |
| 1911 | 1692 | { |
| 1912 | | UML_MULU(block, mem(&sh2->macl), mem(&sh2->ea), R32(Rn), R32(Rm)); // mulu macl, ea, Rn, Rm |
| 1693 | UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), R32(Rn), R32(Rm)); // mulu macl, ea, Rn, Rm |
| 1913 | 1694 | return TRUE; |
| 1914 | 1695 | } |
| 1915 | 1696 | break; |
| 1916 | 1697 | |
| 1917 | 1698 | case 0x08: // CLRT(); |
| 1918 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 1699 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 1919 | 1700 | return TRUE; |
| 1920 | 1701 | |
| 1921 | 1702 | case 0x0a: // STSMACH(Rn); |
| 1922 | | UML_MOV(block, R32(Rn), mem(&sh2->mach)); // mov Rn, mach |
| 1703 | UML_MOV(block, R32(Rn), mem(&m_sh2_state->mach)); // mov Rn, mach |
| 1923 | 1704 | return TRUE; |
| 1924 | 1705 | |
| 1925 | 1706 | case 0x0b: // RTS(); |
| 1926 | | UML_MOV(block, mem(&sh2->target), mem(&sh2->pr)); // mov target, pr (in case of d-slot shenanigans) |
| 1707 | UML_MOV(block, mem(&m_sh2_state->target), mem(&m_sh2_state->pr)); // mov target, pr (in case of d-slot shenanigans) |
| 1927 | 1708 | |
| 1928 | | generate_delay_slot(sh2, block, compiler, desc, sh2->target); |
| 1709 | generate_delay_slot(block, compiler, desc, m_sh2_state->target); |
| 1929 | 1710 | |
| 1930 | | generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles> |
| 1931 | | UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); |
| 1711 | generate_update_cycles(block, compiler, mem(&m_sh2_state->target), TRUE); // <subtract cycles> |
| 1712 | UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); |
| 1932 | 1713 | return TRUE; |
| 1933 | 1714 | |
| 1934 | 1715 | case 0x0c: // MOVBL0(Rm, Rn); |
| r29568 | r29569 | |
| 1936 | 1717 | case 0x2c: // MOVBL0(Rm, Rn); |
| 1937 | 1718 | case 0x3c: // MOVBL0(Rm, Rn); |
| 1938 | 1719 | UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm |
| 1939 | | UML_CALLH(block, *sh2->read8); // call read8 |
| 1720 | UML_CALLH(block, *m_read8); // call read8 |
| 1940 | 1721 | UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE |
| 1941 | 1722 | |
| 1942 | 1723 | if (!in_delay_slot) |
| 1943 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1724 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1944 | 1725 | return TRUE; |
| 1945 | 1726 | |
| 1946 | 1727 | case 0x0d: // MOVWL0(Rm, Rn); |
| r29568 | r29569 | |
| 1948 | 1729 | case 0x2d: // MOVWL0(Rm, Rn); |
| 1949 | 1730 | case 0x3d: // MOVWL0(Rm, Rn); |
| 1950 | 1731 | UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm |
| 1951 | | UML_CALLH(block, *sh2->read16); // call read16 |
| 1732 | UML_CALLH(block, *m_read16); // call read16 |
| 1952 | 1733 | UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD |
| 1953 | 1734 | |
| 1954 | 1735 | if (!in_delay_slot) |
| 1955 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1736 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1956 | 1737 | return TRUE; |
| 1957 | 1738 | |
| 1958 | 1739 | case 0x0e: // MOVLL0(Rm, Rn); |
| r29568 | r29569 | |
| 1960 | 1741 | case 0x2e: // MOVLL0(Rm, Rn); |
| 1961 | 1742 | case 0x3e: // MOVLL0(Rm, Rn); |
| 1962 | 1743 | UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm |
| 1963 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 1744 | UML_CALLH(block, *m_read32); // call read32 |
| 1964 | 1745 | UML_MOV(block, R32(Rn), I0); // mov Rn, r0 |
| 1965 | 1746 | |
| 1966 | 1747 | if (!in_delay_slot) |
| 1967 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1748 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 1968 | 1749 | return TRUE; |
| 1969 | 1750 | |
| 1970 | 1751 | case 0x0f: // MAC_L(Rm, Rn); |
| 1971 | 1752 | case 0x1f: // MAC_L(Rm, Rn); |
| 1972 | 1753 | case 0x2f: // MAC_L(Rm, Rn); |
| 1973 | 1754 | case 0x3f: // MAC_L(Rm, Rn); |
| 1974 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 1755 | if (m_cpu_type > CPU_TYPE_SH1) |
| 1975 | 1756 | { |
| 1976 | | save_fast_iregs(sh2, block); |
| 1977 | | UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]); |
| 1978 | | UML_CALLC(block, cfunc_MAC_L, sh2); |
| 1979 | | load_fast_iregs(sh2, block); |
| 1757 | save_fast_iregs(block); |
| 1758 | UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); |
| 1759 | UML_CALLC(block, cfunc_MAC_L, this); |
| 1760 | load_fast_iregs(block); |
| 1980 | 1761 | return TRUE; |
| 1981 | 1762 | } |
| 1982 | 1763 | break; |
| 1983 | 1764 | |
| 1984 | 1765 | case 0x12: // STCGBR(Rn); |
| 1985 | | UML_MOV(block, R32(Rn), mem(&sh2->gbr)); // mov Rn, gbr |
| 1766 | UML_MOV(block, R32(Rn), mem(&m_sh2_state->gbr)); // mov Rn, gbr |
| 1986 | 1767 | return TRUE; |
| 1987 | 1768 | |
| 1988 | 1769 | case 0x18: // SETT(); |
| 1989 | | UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T |
| 1770 | UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T |
| 1990 | 1771 | return TRUE; |
| 1991 | 1772 | |
| 1992 | 1773 | case 0x19: // DIV0U(); |
| 1993 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~(M|Q|T)); // and sr, sr, ~(M|Q|T) |
| 1774 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~(M|Q|T)); // and sr, sr, ~(M|Q|T) |
| 1994 | 1775 | return TRUE; |
| 1995 | 1776 | |
| 1996 | 1777 | case 0x1a: // STSMACL(Rn); |
| 1997 | | UML_MOV(block, R32(Rn), mem(&sh2->macl)); // mov Rn, macl |
| 1778 | UML_MOV(block, R32(Rn), mem(&m_sh2_state->macl)); // mov Rn, macl |
| 1998 | 1779 | return TRUE; |
| 1999 | 1780 | |
| 2000 | 1781 | case 0x1b: // SLEEP(); |
| 2001 | | UML_MOV(block, I0, mem(&sh2->sleep_mode)); // mov i0, sleep_mode |
| 1782 | UML_MOV(block, I0, mem(&m_sh2_state->sleep_mode)); // mov i0, sleep_mode |
| 2002 | 1783 | UML_CMP(block, I0, 0x2); // cmp i0, #2 |
| 2003 | 1784 | UML_JMPc(block, COND_E, compiler->labelnum); // beq labelnum |
| 2004 | 1785 | // sleep mode != 2 |
| 2005 | | UML_MOV(block, mem(&sh2->sleep_mode), 0x1); // mov sleep_mode, #1 |
| 2006 | | generate_update_cycles(sh2, block, compiler, desc->pc, TRUE); // repeat this insn |
| 1786 | UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x1); // mov sleep_mode, #1 |
| 1787 | generate_update_cycles(block, compiler, desc->pc, TRUE); // repeat this insn |
| 2007 | 1788 | UML_JMP(block, compiler->labelnum+1); // jmp labelnum+1 |
| 2008 | 1789 | |
| 2009 | 1790 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 2010 | 1791 | // sleep_mode == 2 |
| 2011 | | UML_MOV(block, mem(&sh2->sleep_mode), 0x0); // sleep_mode = 0 |
| 2012 | | generate_update_cycles(sh2, block, compiler, desc->pc+2, TRUE); // go to next insn |
| 1792 | UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x0); // sleep_mode = 0 |
| 1793 | generate_update_cycles(block, compiler, desc->pc+2, TRUE); // go to next insn |
| 2013 | 1794 | |
| 2014 | 1795 | UML_LABEL(block, compiler->labelnum++); // labelnum+1: |
| 2015 | 1796 | return TRUE; |
| 2016 | 1797 | |
| 2017 | 1798 | case 0x22: // STCVBR(Rn); |
| 2018 | | UML_MOV(block, R32(Rn), mem(&sh2->vbr)); // mov Rn, vbr |
| 1799 | UML_MOV(block, R32(Rn), mem(&m_sh2_state->vbr)); // mov Rn, vbr |
| 2019 | 1800 | return TRUE; |
| 2020 | 1801 | |
| 2021 | 1802 | case 0x23: // BRAF(Rn); |
| 2022 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 1803 | if (m_cpu_type > CPU_TYPE_SH1) |
| 2023 | 1804 | { |
| 2024 | | UML_ADD(block, mem(&sh2->target), R32(Rn), desc->pc+4); // add target, Rn, pc+4 |
| 1805 | UML_ADD(block, mem(&m_sh2_state->target), R32(Rn), desc->pc+4); // add target, Rn, pc+4 |
| 2025 | 1806 | |
| 2026 | | generate_delay_slot(sh2, block, compiler, desc, sh2->target); |
| 1807 | generate_delay_slot(block, compiler, desc, m_sh2_state->target); |
| 2027 | 1808 | |
| 2028 | | generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles> |
| 2029 | | UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); // jmp target |
| 1809 | generate_update_cycles(block, compiler, mem(&m_sh2_state->target), TRUE); // <subtract cycles> |
| 1810 | UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target |
| 2030 | 1811 | return TRUE; |
| 2031 | 1812 | } |
| 2032 | 1813 | break; |
| 2033 | 1814 | |
| 2034 | 1815 | case 0x28: // CLRMAC(); |
| 2035 | | UML_MOV(block, mem(&sh2->macl), 0); // mov macl, #0 |
| 2036 | | UML_MOV(block, mem(&sh2->mach), 0); // mov mach, #0 |
| 1816 | UML_MOV(block, mem(&m_sh2_state->macl), 0); // mov macl, #0 |
| 1817 | UML_MOV(block, mem(&m_sh2_state->mach), 0); // mov mach, #0 |
| 2037 | 1818 | return TRUE; |
| 2038 | 1819 | |
| 2039 | 1820 | case 0x29: // MOVT(Rn); |
| 2040 | | UML_AND(block, R32(Rn), mem(&sh2->sr), T); // and Rn, sr, T |
| 1821 | UML_AND(block, R32(Rn), mem(&m_sh2_state->sr), T); // and Rn, sr, T |
| 2041 | 1822 | return TRUE; |
| 2042 | 1823 | |
| 2043 | 1824 | case 0x2a: // STSPR(Rn); |
| 2044 | | UML_MOV(block, R32(Rn), mem(&sh2->pr)); // mov Rn, pr |
| 1825 | UML_MOV(block, R32(Rn), mem(&m_sh2_state->pr)); // mov Rn, pr |
| 2045 | 1826 | return TRUE; |
| 2046 | 1827 | |
| 2047 | 1828 | case 0x2b: // RTE(); |
| 2048 | | generate_delay_slot(sh2, block, compiler, desc, 0xffffffff); |
| 1829 | generate_delay_slot(block, compiler, desc, 0xffffffff); |
| 2049 | 1830 | |
| 2050 | 1831 | UML_MOV(block, I0, R32(15)); // mov r0, R15 |
| 2051 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2052 | | UML_MOV(block, mem(&sh2->pc), I0); // mov pc, r0 |
| 1832 | UML_CALLH(block, *m_read32); // call read32 |
| 1833 | UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov pc, r0 |
| 2053 | 1834 | UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 |
| 2054 | 1835 | |
| 2055 | 1836 | UML_MOV(block, I0, R32(15)); // mov r0, R15 |
| 2056 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2057 | | UML_MOV(block, mem(&sh2->sr), I0); // mov sr, r0 |
| 1837 | UML_CALLH(block, *m_read32); // call read32 |
| 1838 | UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 |
| 2058 | 1839 | UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 |
| 2059 | 1840 | |
| 2060 | 1841 | compiler->checkints = TRUE; |
| 2061 | | UML_MOV(block, mem(&sh2->ea), mem(&sh2->pc)); // mov ea, pc |
| 2062 | | generate_update_cycles(sh2, block, compiler, mem(&sh2->ea), TRUE); // <subtract cycles> |
| 2063 | | UML_HASHJMP(block, 0, mem(&sh2->pc), *sh2->nocode); // and jump to the "resume PC" |
| 1842 | UML_MOV(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->pc)); // mov ea, pc |
| 1843 | generate_update_cycles(block, compiler, mem(&m_sh2_state->ea), TRUE); // <subtract cycles> |
| 1844 | UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // and jump to the "resume PC" |
| 2064 | 1845 | |
| 2065 | 1846 | return TRUE; |
| 2066 | 1847 | } |
| r29568 | r29569 | |
| 2068 | 1849 | return FALSE; |
| 2069 | 1850 | } |
| 2070 | 1851 | |
| 2071 | | static int generate_group_2(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 1852 | int sh2_device::generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2072 | 1853 | { |
| 2073 | 1854 | switch (opcode & 15) |
| 2074 | 1855 | { |
| 2075 | 1856 | case 0: // MOVBS(Rm, Rn); |
| 2076 | 1857 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2077 | 1858 | UML_AND(block, I1, R32(Rm), 0xff); // and r1, Rm, 0xff |
| 2078 | | UML_CALLH(block, *sh2->write8); |
| 1859 | UML_CALLH(block, *m_write8); |
| 2079 | 1860 | |
| 2080 | 1861 | if (!in_delay_slot) |
| 2081 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1862 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2082 | 1863 | return TRUE; |
| 2083 | 1864 | |
| 2084 | 1865 | case 1: // MOVWS(Rm, Rn); |
| 2085 | 1866 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2086 | 1867 | UML_AND(block, I1, R32(Rm), 0xffff); // and r1, Rm, 0xffff |
| 2087 | | UML_CALLH(block, *sh2->write16); |
| 1868 | UML_CALLH(block, *m_write16); |
| 2088 | 1869 | |
| 2089 | 1870 | if (!in_delay_slot) |
| 2090 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1871 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2091 | 1872 | return TRUE; |
| 2092 | 1873 | |
| 2093 | 1874 | case 2: // MOVLS(Rm, Rn); |
| 2094 | 1875 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2095 | 1876 | UML_MOV(block, I1, R32(Rm)); // mov r1, Rm |
| 2096 | | UML_CALLH(block, *sh2->write32); |
| 1877 | UML_CALLH(block, *m_write32); |
| 2097 | 1878 | |
| 2098 | 1879 | if (!in_delay_slot) |
| 2099 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1880 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2100 | 1881 | return TRUE; |
| 2101 | 1882 | |
| 2102 | 1883 | case 3: |
| r29568 | r29569 | |
| 2106 | 1887 | UML_MOV(block, I1, R32(Rm)); // mov r1, Rm |
| 2107 | 1888 | UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1 |
| 2108 | 1889 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2109 | | UML_CALLH(block, *sh2->write8); // call write8 |
| 1890 | UML_CALLH(block, *m_write8); // call write8 |
| 2110 | 1891 | |
| 2111 | 1892 | if (!in_delay_slot) |
| 2112 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1893 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2113 | 1894 | return TRUE; |
| 2114 | 1895 | |
| 2115 | 1896 | case 5: // MOVWM(Rm, Rn); |
| 2116 | 1897 | UML_MOV(block, I1, R32(Rm)); // mov r1, Rm |
| 2117 | 1898 | UML_SUB(block, R32(Rn), R32(Rn), 2); // sub Rn, Rn, 2 |
| 2118 | 1899 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2119 | | UML_CALLH(block, *sh2->write16); // call write16 |
| 1900 | UML_CALLH(block, *m_write16); // call write16 |
| 2120 | 1901 | |
| 2121 | 1902 | if (!in_delay_slot) |
| 2122 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1903 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2123 | 1904 | return TRUE; |
| 2124 | 1905 | |
| 2125 | 1906 | case 6: // MOVLM(Rm, Rn); |
| 2126 | 1907 | UML_MOV(block, I1, R32(Rm)); // mov r1, Rm |
| 2127 | 1908 | UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 |
| 2128 | 1909 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2129 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 1910 | UML_CALLH(block, *m_write32); // call write32 |
| 2130 | 1911 | |
| 2131 | 1912 | if (!in_delay_slot) |
| 2132 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 1913 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2133 | 1914 | return TRUE; |
| 2134 | 1915 | |
| 2135 | 1916 | case 13: // XTRCT(Rm, Rn); |
| r29568 | r29569 | |
| 2143 | 1924 | return TRUE; |
| 2144 | 1925 | |
| 2145 | 1926 | case 7: // DIV0S(Rm, Rn); |
| 2146 | | UML_MOV(block, I0, mem(&sh2->sr)); // move r0, sr |
| 1927 | UML_MOV(block, I0, mem(&m_sh2_state->sr)); // move r0, sr |
| 2147 | 1928 | UML_AND(block, I0, I0, ~(Q|M|T)); // and r0, r0, ~(Q|M|T) (clear the Q,M, and T bits) |
| 2148 | 1929 | |
| 2149 | 1930 | UML_TEST(block, R32(Rn), 0x80000000); // test Rn, #0x80000000 |
| r29568 | r29569 | |
| 2164 | 1945 | |
| 2165 | 1946 | UML_OR(block, I0, I0, T); // or r0, r0, T |
| 2166 | 1947 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 2167 | | UML_MOV(block, mem(&sh2->sr), I0); // mov sr, r0 |
| 1948 | UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 |
| 2168 | 1949 | return TRUE; |
| 2169 | 1950 | |
| 2170 | 1951 | case 8: // TST(Rm, Rn); |
| 2171 | | UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 1952 | UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2172 | 1953 | UML_TEST(block, R32(Rm), R32(Rn)); // test Rm, Rn |
| 2173 | 1954 | UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum |
| 2174 | 1955 | |
| 2175 | 1956 | UML_OR(block, I0, I0, T); // or r0, r0, T |
| 2176 | 1957 | UML_LABEL(block, compiler->labelnum++); // desc->pc: |
| 2177 | 1958 | |
| 2178 | | UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0 |
| 1959 | UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 |
| 2179 | 1960 | return TRUE; |
| 2180 | 1961 | |
| 2181 | 1962 | case 12: // CMPSTR(Rm, Rn); |
| r29568 | r29569 | |
| 2192 | 1973 | |
| 2193 | 1974 | UML_AND(block, I7, I0, 0xff); // and r7, r0, #0xff (LL) |
| 2194 | 1975 | |
| 2195 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T (clear the T bit) |
| 1976 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) |
| 2196 | 1977 | |
| 2197 | 1978 | UML_CMP(block, I1, 0); // cmp r1, #0 |
| 2198 | 1979 | UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum |
| r29568 | r29569 | |
| 2204 | 1985 | UML_JMPc(block, COND_NZ, compiler->labelnum+1); // jnz labelnum |
| 2205 | 1986 | |
| 2206 | 1987 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 2207 | | UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T |
| 1988 | UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T |
| 2208 | 1989 | |
| 2209 | 1990 | UML_LABEL(block, compiler->labelnum++); // labelnum+1: |
| 2210 | 1991 | return TRUE; |
| r29568 | r29569 | |
| 2224 | 2005 | case 14: // MULU(Rm, Rn); |
| 2225 | 2006 | UML_AND(block, I0, R32(Rm), 0xffff); // and r0, Rm, 0xffff |
| 2226 | 2007 | UML_AND(block, I1, R32(Rn), 0xffff); // and r1, Rn, 0xffff |
| 2227 | | UML_MULU(block, mem(&sh2->macl), mem(&sh2->ea), I0, I1); // mulu macl, ea, r0, r1 |
| 2008 | UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // mulu macl, ea, r0, r1 |
| 2228 | 2009 | return TRUE; |
| 2229 | 2010 | |
| 2230 | 2011 | case 15: // MULS(Rm, Rn); |
| 2231 | 2012 | UML_SEXT(block, I0, R32(Rm), SIZE_WORD); // sext r0, Rm |
| 2232 | 2013 | UML_SEXT(block, I1, R32(Rn), SIZE_WORD); // sext r1, Rn |
| 2233 | | UML_MULS(block, mem(&sh2->macl), mem(&sh2->ea), I0, I1); // muls macl, ea, r0, r1 |
| 2014 | UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // muls macl, ea, r0, r1 |
| 2234 | 2015 | return TRUE; |
| 2235 | 2016 | } |
| 2236 | 2017 | |
| 2237 | 2018 | return FALSE; |
| 2238 | 2019 | } |
| 2239 | 2020 | |
| 2240 | | static int generate_group_3(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, UINT32 ovrpc) |
| 2021 | int sh2_device::generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, UINT32 ovrpc) |
| 2241 | 2022 | { |
| 2242 | 2023 | switch (opcode & 15) |
| 2243 | 2024 | { |
| 2244 | 2025 | case 0: // CMPEQ(Rm, Rn); (equality) |
| 2245 | 2026 | UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm |
| 2246 | 2027 | UML_SETc(block, COND_E, I0); // set E, r0 |
| 2247 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2028 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2248 | 2029 | return TRUE; |
| 2249 | 2030 | |
| 2250 | 2031 | case 2: // CMPHS(Rm, Rn); (unsigned greater than or equal) |
| 2251 | 2032 | UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm |
| 2252 | 2033 | UML_SETc(block, COND_AE, I0); // set AE, r0 |
| 2253 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2034 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2254 | 2035 | return TRUE; |
| 2255 | 2036 | |
| 2256 | 2037 | case 3: // CMPGE(Rm, Rn); (signed greater than or equal) |
| 2257 | 2038 | UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm |
| 2258 | 2039 | UML_SETc(block, COND_GE, I0); // set GE, r0 |
| 2259 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2040 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2260 | 2041 | return TRUE; |
| 2261 | 2042 | |
| 2262 | 2043 | case 6: // CMPHI(Rm, Rn); (unsigned greater than) |
| 2263 | 2044 | UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm |
| 2264 | 2045 | UML_SETc(block, COND_A, I0); // set A, r0 |
| 2265 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2046 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2266 | 2047 | return TRUE; |
| 2267 | 2048 | |
| 2268 | 2049 | case 7: // CMPGT(Rm, Rn); (signed greater than) |
| 2269 | 2050 | UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm |
| 2270 | 2051 | UML_SETc(block, COND_G, I0); // set G, r0 |
| 2271 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2052 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1 |
| 2272 | 2053 | return TRUE; |
| 2273 | 2054 | |
| 2274 | 2055 | case 1: |
| r29568 | r29569 | |
| 2276 | 2057 | return FALSE; |
| 2277 | 2058 | |
| 2278 | 2059 | case 4: // DIV1(Rm, Rn); |
| 2279 | | save_fast_iregs(sh2, block); |
| 2280 | | UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]); |
| 2281 | | UML_CALLC(block, cfunc_DIV1, sh2); |
| 2282 | | load_fast_iregs(sh2, block); |
| 2060 | save_fast_iregs(block); |
| 2061 | UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); |
| 2062 | UML_CALLC(block, cfunc_DIV1, this); |
| 2063 | load_fast_iregs(block); |
| 2283 | 2064 | return TRUE; |
| 2284 | 2065 | |
| 2285 | 2066 | case 5: // DMULU(Rm, Rn); |
| 2286 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 2067 | if (m_cpu_type > CPU_TYPE_SH1) |
| 2287 | 2068 | { |
| 2288 | | UML_MULU(block, mem(&sh2->macl), mem(&sh2->mach), R32(Rn), R32(Rm)); |
| 2069 | UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(Rn), R32(Rm)); |
| 2289 | 2070 | return TRUE; |
| 2290 | 2071 | } |
| 2291 | 2072 | break; |
| 2292 | 2073 | |
| 2293 | 2074 | case 13: // DMULS(Rm, Rn); |
| 2294 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 2075 | if (m_cpu_type > CPU_TYPE_SH1) |
| 2295 | 2076 | { |
| 2296 | | UML_MULS(block, mem(&sh2->macl), mem(&sh2->mach), R32(Rn), R32(Rm)); |
| 2077 | UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(Rn), R32(Rm)); |
| 2297 | 2078 | return TRUE; |
| 2298 | 2079 | } |
| 2299 | 2080 | break; |
| r29568 | r29569 | |
| 2307 | 2088 | return TRUE; |
| 2308 | 2089 | |
| 2309 | 2090 | case 10: // SUBC(Rm, Rn); |
| 2310 | | UML_CARRY(block, mem(&sh2->sr), 0); // carry = T (T is bit 0 of SR) |
| 2091 | UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry = T (T is bit 0 of SR) |
| 2311 | 2092 | UML_SUBB(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm |
| 2312 | 2093 | UML_SETc(block, COND_C, I0); // setc i0, C |
| 2313 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins sr,i0,0,T |
| 2094 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T |
| 2314 | 2095 | return TRUE; |
| 2315 | 2096 | |
| 2316 | 2097 | case 11: // SUBV(Rm, Rn); |
| 2317 | 2098 | #if ADDSUBV_DIRECT |
| 2318 | 2099 | UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm |
| 2319 | 2100 | UML_SETc(block, COND_V, I0); // setc i0, V |
| 2320 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2101 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2321 | 2102 | #else |
| 2322 | | save_fast_iregs(sh2, block); |
| 2323 | | UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]); |
| 2324 | | UML_CALLC(block, cfunc_SUBV, sh2); |
| 2325 | | load_fast_iregs(sh2, block); |
| 2103 | save_fast_iregs(block); |
| 2104 | UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); |
| 2105 | UML_CALLC(block, cfunc_SUBV, this); |
| 2106 | load_fast_iregs(block); |
| 2326 | 2107 | #endif |
| 2327 | 2108 | return TRUE; |
| 2328 | 2109 | |
| 2329 | 2110 | case 14: // ADDC(Rm, Rn); |
| 2330 | | UML_CARRY(block, mem(&sh2->sr), 0); // carry = T (T is bit 0 of SR) |
| 2111 | UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry = T (T is bit 0 of SR) |
| 2331 | 2112 | UML_ADDC(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm |
| 2332 | 2113 | UML_SETc(block, COND_C, I0); // setc i0, C |
| 2333 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins sr,i0,0,T |
| 2114 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T |
| 2334 | 2115 | return TRUE; |
| 2335 | 2116 | |
| 2336 | 2117 | case 15: // ADDV(Rm, Rn); |
| 2337 | 2118 | #if ADDSUBV_DIRECT |
| 2338 | 2119 | UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm |
| 2339 | 2120 | UML_SETc(block, COND_V, I0); // setc i0, V |
| 2340 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2121 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2341 | 2122 | #else |
| 2342 | | save_fast_iregs(sh2, block); |
| 2343 | | UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]); |
| 2344 | | UML_CALLC(block, cfunc_ADDV, sh2); |
| 2345 | | load_fast_iregs(sh2, block); |
| 2123 | save_fast_iregs(block); |
| 2124 | UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); |
| 2125 | UML_CALLC(block, cfunc_ADDV, this); |
| 2126 | load_fast_iregs(block); |
| 2346 | 2127 | #endif |
| 2347 | 2128 | return TRUE; |
| 2348 | 2129 | } |
| 2349 | 2130 | return FALSE; |
| 2350 | 2131 | } |
| 2351 | 2132 | |
| 2352 | | static int generate_group_4(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2133 | int sh2_device::generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2353 | 2134 | { |
| 2354 | 2135 | switch (opcode & 0x3F) |
| 2355 | 2136 | { |
| 2356 | 2137 | case 0x00: // SHLL(Rn); |
| 2357 | 2138 | UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1 |
| 2358 | 2139 | UML_SETc(block, COND_C, I0); // set i0,C |
| 2359 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2140 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2360 | 2141 | return TRUE; |
| 2361 | 2142 | |
| 2362 | 2143 | case 0x01: // SHLR(Rn); |
| 2363 | 2144 | UML_SHR(block, R32(Rn), R32(Rn), 1); // shr Rn, Rn, 1 |
| 2364 | 2145 | UML_SETc(block, COND_C, I0); // set i0,C |
| 2365 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2146 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2366 | 2147 | return TRUE; |
| 2367 | 2148 | |
| 2368 | 2149 | case 0x04: // ROTL(Rn); |
| 2369 | 2150 | UML_ROL(block, R32(Rn), R32(Rn), 1); // rol Rn, Rn, 1 |
| 2370 | 2151 | UML_SETc(block, COND_C, I0); // set i0,C |
| 2371 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2152 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2372 | 2153 | return TRUE; |
| 2373 | 2154 | |
| 2374 | 2155 | case 0x05: // ROTR(Rn); |
| 2375 | 2156 | UML_ROR(block, R32(Rn), R32(Rn), 1); // ror Rn, Rn, 1 |
| 2376 | 2157 | UML_SETc(block, COND_C, I0); // set i0,C |
| 2377 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2158 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T |
| 2378 | 2159 | return TRUE; |
| 2379 | 2160 | |
| 2380 | 2161 | case 0x02: // STSMMACH(Rn); |
| 2381 | 2162 | UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 |
| 2382 | 2163 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2383 | | UML_MOV(block, I1, mem(&sh2->mach)); // mov r1, mach |
| 2164 | UML_MOV(block, I1, mem(&m_sh2_state->mach)); // mov r1, mach |
| 2384 | 2165 | SETEA(0); // set ea for debug |
| 2385 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 2166 | UML_CALLH(block, *m_write32); // call write32 |
| 2386 | 2167 | |
| 2387 | 2168 | if (!in_delay_slot) |
| 2388 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2169 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2389 | 2170 | return TRUE; |
| 2390 | 2171 | |
| 2391 | 2172 | case 0x03: // STCMSR(Rn); |
| 2392 | 2173 | UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 |
| 2393 | 2174 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2394 | | UML_MOV(block, I1, mem(&sh2->sr)); // mov r1, sr |
| 2175 | UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr |
| 2395 | 2176 | SETEA(0); // set ea for debug |
| 2396 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 2177 | UML_CALLH(block, *m_write32); // call write32 |
| 2397 | 2178 | |
| 2398 | 2179 | if (!in_delay_slot) |
| 2399 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2180 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2400 | 2181 | return TRUE; |
| 2401 | 2182 | |
| 2402 | 2183 | case 0x06: // LDSMMACH(Rn); |
| 2403 | 2184 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2404 | 2185 | SETEA(0); |
| 2405 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2186 | UML_CALLH(block, *m_read32); // call read32 |
| 2406 | 2187 | UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 |
| 2407 | | UML_MOV(block, mem(&sh2->mach), I0); // mov mach, r0 |
| 2188 | UML_MOV(block, mem(&m_sh2_state->mach), I0); // mov mach, r0 |
| 2408 | 2189 | |
| 2409 | 2190 | if (!in_delay_slot) |
| 2410 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2191 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2411 | 2192 | return TRUE; |
| 2412 | 2193 | |
| 2413 | 2194 | case 0x07: // LDCMSR(Rn); |
| 2414 | 2195 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2415 | 2196 | SETEA(0); |
| 2416 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2197 | UML_CALLH(block, *m_read32); // call read32 |
| 2417 | 2198 | UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 |
| 2418 | | UML_MOV(block, mem(&sh2->sr), I0); // mov sr, r0 |
| 2199 | UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 |
| 2419 | 2200 | |
| 2420 | 2201 | compiler->checkints = TRUE; |
| 2421 | 2202 | if (!in_delay_slot) |
| 2422 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2203 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2423 | 2204 | return TRUE; |
| 2424 | 2205 | |
| 2425 | 2206 | |
| r29568 | r29569 | |
| 2448 | 2229 | return TRUE; |
| 2449 | 2230 | |
| 2450 | 2231 | case 0x0a: // LDSMACH(Rn); |
| 2451 | | UML_MOV(block, mem(&sh2->mach), R32(Rn)); // mov mach, Rn |
| 2232 | UML_MOV(block, mem(&m_sh2_state->mach), R32(Rn)); // mov mach, Rn |
| 2452 | 2233 | return TRUE; |
| 2453 | 2234 | |
| 2454 | 2235 | case 0x0b: // JSR(Rn); |
| 2455 | | UML_MOV(block, mem(&sh2->target), R32(Rn)); // mov target, Rn |
| 2236 | UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn |
| 2456 | 2237 | |
| 2457 | | UML_ADD(block, mem(&sh2->pr), desc->pc, 4); // add sh2->pr, desc->pc, #4 (skip the current insn & delay slot) |
| 2238 | UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) |
| 2458 | 2239 | |
| 2459 | | generate_delay_slot(sh2, block, compiler, desc, sh2->target-4); |
| 2240 | generate_delay_slot(block, compiler, desc, m_sh2_state->target-4); |
| 2460 | 2241 | |
| 2461 | | generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles> |
| 2462 | | UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); // and do the jump |
| 2242 | generate_update_cycles(block, compiler, mem(&m_sh2_state->target), TRUE); // <subtract cycles> |
| 2243 | UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // and do the jump |
| 2463 | 2244 | return TRUE; |
| 2464 | 2245 | |
| 2465 | 2246 | case 0x0e: // LDCSR(Rn); |
| 2466 | 2247 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2467 | 2248 | UML_AND(block, I0, I0, FLAGS); // and r0, r0, FLAGS |
| 2468 | | UML_MOV(block, mem(&sh2->sr), I0); |
| 2249 | UML_MOV(block, mem(&m_sh2_state->sr), I0); |
| 2469 | 2250 | |
| 2470 | 2251 | compiler->checkints = TRUE; |
| 2471 | 2252 | return TRUE; |
| r29568 | r29569 | |
| 2474 | 2255 | case 0x1f: // MAC_W(Rm, Rn); |
| 2475 | 2256 | case 0x2f: // MAC_W(Rm, Rn); |
| 2476 | 2257 | case 0x3f: // MAC_W(Rm, Rn); |
| 2477 | | save_fast_iregs(sh2, block); |
| 2478 | | UML_MOV(block, mem(&sh2->arg0), desc->opptr.w[0]); |
| 2479 | | UML_CALLC(block, cfunc_MAC_W, sh2); |
| 2480 | | load_fast_iregs(sh2, block); |
| 2258 | save_fast_iregs(block); |
| 2259 | UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); |
| 2260 | UML_CALLC(block, cfunc_MAC_W, this); |
| 2261 | load_fast_iregs(block); |
| 2481 | 2262 | return TRUE; |
| 2482 | 2263 | |
| 2483 | 2264 | case 0x10: // DT(Rn); |
| 2484 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 2265 | if (m_cpu_type > CPU_TYPE_SH1) |
| 2485 | 2266 | { |
| 2486 | | UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2267 | UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2487 | 2268 | UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1 |
| 2488 | 2269 | UML_JMPc(block, COND_NZ, compiler->labelnum); // jz compiler->labelnum |
| 2489 | 2270 | |
| 2490 | 2271 | UML_OR(block, I0, I0, T); // or r0, r0, T |
| 2491 | 2272 | UML_LABEL(block, compiler->labelnum++); // desc->pc: |
| 2492 | 2273 | |
| 2493 | | UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0 |
| 2274 | UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 |
| 2494 | 2275 | return TRUE; |
| 2495 | 2276 | } |
| 2496 | 2277 | break; |
| 2497 | 2278 | |
| 2498 | 2279 | case 0x11: // CMPPZ(Rn); |
| 2499 | | UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2280 | UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2500 | 2281 | |
| 2501 | 2282 | UML_CMP(block, R32(Rn), 0); // cmp Rn, 0 |
| 2502 | 2283 | UML_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative) |
| r29568 | r29569 | |
| 2504 | 2285 | UML_OR(block, I0, I0, T); // or r0, r0, T |
| 2505 | 2286 | UML_LABEL(block, compiler->labelnum++); // desc->pc: |
| 2506 | 2287 | |
| 2507 | | UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0 |
| 2288 | UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 |
| 2508 | 2289 | return TRUE; |
| 2509 | 2290 | |
| 2510 | 2291 | case 0x15: // CMPPL(Rn); |
| 2511 | | UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2292 | UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2512 | 2293 | |
| 2513 | 2294 | UML_CMP(block, R32(Rn), 0); // cmp Rn, 0 |
| 2514 | 2295 | |
| r29568 | r29569 | |
| 2518 | 2299 | UML_OR(block, I0, I0, T); // or r0, r0, T |
| 2519 | 2300 | |
| 2520 | 2301 | UML_LABEL(block, compiler->labelnum++); // desc->pc: |
| 2521 | | UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0 |
| 2302 | UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 |
| 2522 | 2303 | return TRUE; |
| 2523 | 2304 | |
| 2524 | 2305 | case 0x12: // STSMMACL(Rn); |
| 2525 | 2306 | UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 |
| 2526 | 2307 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2527 | | UML_MOV(block, I1, mem(&sh2->macl)); // mov r1, macl |
| 2308 | UML_MOV(block, I1, mem(&m_sh2_state->macl)); // mov r1, macl |
| 2528 | 2309 | SETEA(0); // set ea for debug |
| 2529 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 2310 | UML_CALLH(block, *m_write32); // call write32 |
| 2530 | 2311 | |
| 2531 | 2312 | if (!in_delay_slot) |
| 2532 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2313 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2533 | 2314 | return TRUE; |
| 2534 | 2315 | |
| 2535 | 2316 | case 0x13: // STCMGBR(Rn); |
| 2536 | 2317 | UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4 |
| 2537 | 2318 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2538 | | UML_MOV(block, I1, mem(&sh2->gbr)); // mov r1, gbr |
| 2319 | UML_MOV(block, I1, mem(&m_sh2_state->gbr)); // mov r1, gbr |
| 2539 | 2320 | SETEA(0); // set ea for debug |
| 2540 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 2321 | UML_CALLH(block, *m_write32); // call write32 |
| 2541 | 2322 | |
| 2542 | 2323 | if (!in_delay_slot) |
| 2543 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2324 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2544 | 2325 | return TRUE; |
| 2545 | 2326 | |
| 2546 | 2327 | case 0x16: // LDSMMACL(Rn); |
| 2547 | 2328 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2548 | 2329 | SETEA(0); |
| 2549 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2330 | UML_CALLH(block, *m_read32); // call read32 |
| 2550 | 2331 | UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 |
| 2551 | | UML_MOV(block, mem(&sh2->macl), I0); // mov macl, r0 |
| 2332 | UML_MOV(block, mem(&m_sh2_state->macl), I0); // mov macl, r0 |
| 2552 | 2333 | |
| 2553 | 2334 | if (!in_delay_slot) |
| 2554 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2335 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2555 | 2336 | return TRUE; |
| 2556 | 2337 | |
| 2557 | 2338 | case 0x17: // LDCMGBR(Rn); |
| 2558 | 2339 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2559 | 2340 | SETEA(0); |
| 2560 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2341 | UML_CALLH(block, *m_read32); // call read32 |
| 2561 | 2342 | UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 |
| 2562 | | UML_MOV(block, mem(&sh2->gbr), I0); // mov gbr, r0 |
| 2343 | UML_MOV(block, mem(&m_sh2_state->gbr), I0); // mov gbr, r0 |
| 2563 | 2344 | |
| 2564 | 2345 | if (!in_delay_slot) |
| 2565 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2346 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2566 | 2347 | return TRUE; |
| 2567 | 2348 | |
| 2568 | 2349 | case 0x1a: // LDSMACL(Rn); |
| 2569 | | UML_MOV(block, mem(&sh2->macl), R32(Rn)); // mov macl, Rn |
| 2350 | UML_MOV(block, mem(&m_sh2_state->macl), R32(Rn)); // mov macl, Rn |
| 2570 | 2351 | return TRUE; |
| 2571 | 2352 | |
| 2572 | 2353 | case 0x1b: // TAS(Rn); |
| 2573 | 2354 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2574 | 2355 | SETEA(0); |
| 2575 | | UML_CALLH(block, *sh2->read8); // call read8 |
| 2356 | UML_CALLH(block, *m_read8); // call read8 |
| 2576 | 2357 | |
| 2577 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T |
| 2358 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T |
| 2578 | 2359 | |
| 2579 | 2360 | UML_CMP(block, I0, 0); // cmp r0, #0 |
| 2580 | 2361 | UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum |
| 2581 | 2362 | |
| 2582 | | UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T |
| 2363 | UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T |
| 2583 | 2364 | |
| 2584 | 2365 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 2585 | 2366 | |
| 2586 | 2367 | UML_OR(block, I1, I0, 0x80); // or r1, r0, #0x80 |
| 2587 | 2368 | |
| 2588 | 2369 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2589 | | UML_CALLH(block, *sh2->write8); // write the value back |
| 2370 | UML_CALLH(block, *m_write8); // write the value back |
| 2590 | 2371 | |
| 2591 | 2372 | if (!in_delay_slot) |
| 2592 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2373 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2593 | 2374 | return TRUE; |
| 2594 | 2375 | |
| 2595 | 2376 | case 0x1e: // LDCGBR(Rn); |
| 2596 | | UML_MOV(block, mem(&sh2->gbr), R32(Rn)); // mov gbr, Rn |
| 2377 | UML_MOV(block, mem(&m_sh2_state->gbr), R32(Rn)); // mov gbr, Rn |
| 2597 | 2378 | return TRUE; |
| 2598 | 2379 | |
| 2599 | 2380 | case 0x20: // SHAL(Rn); |
| 2600 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T |
| 2381 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T |
| 2601 | 2382 | UML_SHR(block, I0, R32(Rn), 31); // shr r0, Rn, 31 |
| 2602 | 2383 | UML_AND(block, I0, I0, T); // and r0, r0, T |
| 2603 | | UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), I0); // or sr, sr, r0 |
| 2384 | UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), I0); // or sr, sr, r0 |
| 2604 | 2385 | UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1 |
| 2605 | 2386 | return TRUE; |
| 2606 | 2387 | |
| 2607 | 2388 | case 0x21: // SHAR(Rn); |
| 2608 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T |
| 2389 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T |
| 2609 | 2390 | UML_AND(block, I0, R32(Rn), T); // and r0, Rn, T |
| 2610 | | UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), I0); // or sr, sr, r0 |
| 2391 | UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), I0); // or sr, sr, r0 |
| 2611 | 2392 | UML_SAR(block, R32(Rn), R32(Rn), 1); // sar Rn, Rn, 1 |
| 2612 | 2393 | return TRUE; |
| 2613 | 2394 | |
| r29568 | r29569 | |
| 2615 | 2396 | UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 |
| 2616 | 2397 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2617 | 2398 | SETEA(0); |
| 2618 | | UML_MOV(block, I1, mem(&sh2->pr)); // mov r1, pr |
| 2619 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 2399 | UML_MOV(block, I1, mem(&m_sh2_state->pr)); // mov r1, pr |
| 2400 | UML_CALLH(block, *m_write32); // call write32 |
| 2620 | 2401 | |
| 2621 | 2402 | if (!in_delay_slot) |
| 2622 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2403 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2623 | 2404 | return TRUE; |
| 2624 | 2405 | |
| 2625 | 2406 | case 0x23: // STCMVBR(Rn); |
| 2626 | 2407 | UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4 |
| 2627 | 2408 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2628 | 2409 | SETEA(0); |
| 2629 | | UML_MOV(block, I1, mem(&sh2->vbr)); // mov r1, vbr |
| 2630 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 2410 | UML_MOV(block, I1, mem(&m_sh2_state->vbr)); // mov r1, vbr |
| 2411 | UML_CALLH(block, *m_write32); // call write32 |
| 2631 | 2412 | |
| 2632 | 2413 | if (!in_delay_slot) |
| 2633 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2414 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2634 | 2415 | return TRUE; |
| 2635 | 2416 | |
| 2636 | 2417 | case 0x24: // ROTCL(Rn); |
| 2637 | | UML_CARRY(block, mem(&sh2->sr), 0); // carry sr,0 |
| 2418 | UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry sr,0 |
| 2638 | 2419 | UML_ROLC(block, R32(Rn), R32(Rn), 1); // rolc Rn,Rn,1 |
| 2639 | 2420 | UML_SETc(block, COND_C, I0); // set i0,C |
| 2640 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins sr,i0,0,T |
| 2421 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T |
| 2641 | 2422 | return TRUE; |
| 2642 | 2423 | |
| 2643 | 2424 | case 0x25: // ROTCR(Rn); |
| 2644 | | UML_CARRY(block, mem(&sh2->sr), 0); // carry sr,0 |
| 2425 | UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry sr,0 |
| 2645 | 2426 | UML_RORC(block, R32(Rn), R32(Rn), 1); // rorc Rn,Rn,1 |
| 2646 | 2427 | UML_SETc(block, COND_C, I0); // set i0,C |
| 2647 | | UML_ROLINS(block, mem(&sh2->sr), I0, 0, T); // rolins sr,i0,0,T |
| 2428 | UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T |
| 2648 | 2429 | return TRUE; |
| 2649 | 2430 | |
| 2650 | 2431 | case 0x26: // LDSMPR(Rn); |
| 2651 | 2432 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2652 | 2433 | SETEA(0); |
| 2653 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2654 | | UML_MOV(block, mem(&sh2->pr), I0); // mov sh2->pr, r0 |
| 2434 | UML_CALLH(block, *m_read32); // call read32 |
| 2435 | UML_MOV(block, mem(&m_sh2_state->pr), I0); // mov m_pr, r0 |
| 2655 | 2436 | UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4 |
| 2656 | 2437 | |
| 2657 | 2438 | if (!in_delay_slot) |
| 2658 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2439 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2659 | 2440 | return TRUE; |
| 2660 | 2441 | |
| 2661 | 2442 | case 0x27: // LDCMVBR(Rn); |
| 2662 | 2443 | UML_MOV(block, I0, R32(Rn)); // mov r0, Rn |
| 2663 | 2444 | SETEA(0); |
| 2664 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2665 | | UML_MOV(block, mem(&sh2->vbr), I0); // mov sh2->vbr, r0 |
| 2445 | UML_CALLH(block, *m_read32); // call read32 |
| 2446 | UML_MOV(block, mem(&m_sh2_state->vbr), I0); // mov m_sh2_state->vbr, r0 |
| 2666 | 2447 | UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4 |
| 2667 | 2448 | |
| 2668 | 2449 | if (!in_delay_slot) |
| 2669 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2450 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2670 | 2451 | return TRUE; |
| 2671 | 2452 | |
| 2672 | 2453 | case 0x2a: // LDSPR(Rn); |
| 2673 | | UML_MOV(block, mem(&sh2->pr), R32(Rn)); // mov sh2->pr, Rn |
| 2454 | UML_MOV(block, mem(&m_sh2_state->pr), R32(Rn)); // mov m_pr, Rn |
| 2674 | 2455 | return TRUE; |
| 2675 | 2456 | |
| 2676 | 2457 | case 0x2b: // JMP(Rn); |
| 2677 | | UML_MOV(block, mem(&sh2->target), R32(Rn)); // mov target, Rn |
| 2458 | UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn |
| 2678 | 2459 | |
| 2679 | | generate_delay_slot(sh2, block, compiler, desc, sh2->target); |
| 2460 | generate_delay_slot(block, compiler, desc, m_sh2_state->target); |
| 2680 | 2461 | |
| 2681 | | generate_update_cycles(sh2, block, compiler, mem(&sh2->target), TRUE); // <subtract cycles> |
| 2682 | | UML_HASHJMP(block, 0, mem(&sh2->target), *sh2->nocode); // jmp (target) |
| 2462 | generate_update_cycles(block, compiler, mem(&m_sh2_state->target), TRUE); // <subtract cycles> |
| 2463 | UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp (target) |
| 2683 | 2464 | return TRUE; |
| 2684 | 2465 | |
| 2685 | 2466 | case 0x2e: // LDCVBR(Rn); |
| 2686 | | UML_MOV(block, mem(&sh2->vbr), R32(Rn)); // mov vbr, Rn |
| 2467 | UML_MOV(block, mem(&m_sh2_state->vbr), R32(Rn)); // mov vbr, Rn |
| 2687 | 2468 | return TRUE; |
| 2688 | 2469 | |
| 2689 | 2470 | case 0x0c: |
| r29568 | r29569 | |
| 2714 | 2495 | return FALSE; |
| 2715 | 2496 | } |
| 2716 | 2497 | |
| 2717 | | static int generate_group_6(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2498 | int sh2_device::generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2718 | 2499 | { |
| 2719 | 2500 | switch (opcode & 15) |
| 2720 | 2501 | { |
| 2721 | 2502 | case 0: // MOVBL(Rm, Rn); |
| 2722 | 2503 | UML_MOV(block, I0, R32(Rm)); // mov r0, Rm |
| 2723 | 2504 | SETEA(0); // debug: ea = r0 |
| 2724 | | UML_CALLH(block, *sh2->read8); // call read8 |
| 2505 | UML_CALLH(block, *m_read8); // call read8 |
| 2725 | 2506 | UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE |
| 2726 | 2507 | |
| 2727 | 2508 | if (!in_delay_slot) |
| 2728 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2509 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2729 | 2510 | return TRUE; |
| 2730 | 2511 | |
| 2731 | 2512 | case 1: // MOVWL(Rm, Rn); |
| 2732 | 2513 | UML_MOV(block, I0, R32(Rm)); // mov r0, Rm |
| 2733 | 2514 | SETEA(0); // debug: ea = r0 |
| 2734 | | UML_CALLH(block, *sh2->read16); // call read16 |
| 2515 | UML_CALLH(block, *m_read16); // call read16 |
| 2735 | 2516 | UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD |
| 2736 | 2517 | |
| 2737 | 2518 | if (!in_delay_slot) |
| 2738 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2519 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2739 | 2520 | return TRUE; |
| 2740 | 2521 | |
| 2741 | 2522 | case 2: // MOVLL(Rm, Rn); |
| 2742 | 2523 | UML_MOV(block, I0, R32(Rm)); // mov r0, Rm |
| 2743 | 2524 | SETEA(0); // debug: ea = r0 |
| 2744 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2525 | UML_CALLH(block, *m_read32); // call read32 |
| 2745 | 2526 | UML_MOV(block, R32(Rn), I0); // mov Rn, r0 |
| 2746 | 2527 | |
| 2747 | 2528 | if (!in_delay_slot) |
| 2748 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2529 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2749 | 2530 | return TRUE; |
| 2750 | 2531 | |
| 2751 | 2532 | case 3: // MOV(Rm, Rn); |
| r29568 | r29569 | |
| 2782 | 2563 | |
| 2783 | 2564 | case 4: // MOVBP(Rm, Rn); |
| 2784 | 2565 | UML_MOV(block, I0, R32(Rm)); // mov r0, Rm |
| 2785 | | UML_CALLH(block, *sh2->read8); // call read8 |
| 2566 | UML_CALLH(block, *m_read8); // call read8 |
| 2786 | 2567 | UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE |
| 2787 | 2568 | |
| 2788 | 2569 | if (Rm != Rn) |
| 2789 | 2570 | UML_ADD(block, R32(Rm), R32(Rm), 1); // add Rm, Rm, #1 |
| 2790 | 2571 | |
| 2791 | 2572 | if (!in_delay_slot) |
| 2792 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2573 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2793 | 2574 | return TRUE; |
| 2794 | 2575 | |
| 2795 | 2576 | case 5: // MOVWP(Rm, Rn); |
| 2796 | 2577 | UML_MOV(block, I0, R32(Rm)); // mov r0, Rm |
| 2797 | | UML_CALLH(block, *sh2->read16); // call read16 |
| 2578 | UML_CALLH(block, *m_read16); // call read16 |
| 2798 | 2579 | UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD |
| 2799 | 2580 | |
| 2800 | 2581 | if (Rm != Rn) |
| 2801 | 2582 | UML_ADD(block, R32(Rm), R32(Rm), 2); // add Rm, Rm, #2 |
| 2802 | 2583 | |
| 2803 | 2584 | if (!in_delay_slot) |
| 2804 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2585 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2805 | 2586 | return TRUE; |
| 2806 | 2587 | |
| 2807 | 2588 | case 6: // MOVLP(Rm, Rn); |
| 2808 | 2589 | UML_MOV(block, I0, R32(Rm)); // mov r0, Rm |
| 2809 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2590 | UML_CALLH(block, *m_read32); // call read32 |
| 2810 | 2591 | UML_MOV(block, R32(Rn), I0); // mov Rn, r0 |
| 2811 | 2592 | |
| 2812 | 2593 | if (Rm != Rn) |
| 2813 | 2594 | UML_ADD(block, R32(Rm), R32(Rm), 4); // add Rm, Rm, #4 |
| 2814 | 2595 | |
| 2815 | 2596 | if (!in_delay_slot) |
| 2816 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2597 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2817 | 2598 | return TRUE; |
| 2818 | 2599 | |
| 2819 | 2600 | case 8: // SWAPB(Rm, Rn); |
| r29568 | r29569 | |
| 2827 | 2608 | return TRUE; |
| 2828 | 2609 | |
| 2829 | 2610 | case 10: // NEGC(Rm, Rn); |
| 2830 | | UML_MOV(block, I0, mem(&sh2->sr)); // mov r0, sr (save SR) |
| 2831 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T (clear the T bit) |
| 2611 | UML_MOV(block, I0, mem(&m_sh2_state->sr)); // mov r0, sr (save SR) |
| 2612 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) |
| 2832 | 2613 | UML_CARRY(block, I0, 0); // carry = T (T is bit 0 of SR) |
| 2833 | 2614 | UML_SUBB(block, R32(Rn), 0, R32(Rm)); // subb Rn, #0, Rm |
| 2834 | 2615 | |
| 2835 | 2616 | UML_JMPc(block, COND_NC, compiler->labelnum); // jnc labelnum |
| 2836 | 2617 | |
| 2837 | | UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T |
| 2618 | UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T |
| 2838 | 2619 | |
| 2839 | 2620 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 2840 | 2621 | |
| r29568 | r29569 | |
| 2844 | 2625 | return FALSE; |
| 2845 | 2626 | } |
| 2846 | 2627 | |
| 2847 | | static int generate_group_8(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2628 | int sh2_device::generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2848 | 2629 | { |
| 2849 | 2630 | INT32 disp; |
| 2850 | 2631 | UINT32 udisp; |
| r29568 | r29569 | |
| 2856 | 2637 | udisp = (opcode & 0x0f); |
| 2857 | 2638 | UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp |
| 2858 | 2639 | UML_MOV(block, I1, R32(0)); // mov r1, R0 |
| 2859 | | UML_CALLH(block, *sh2->write8); // call write8 |
| 2640 | UML_CALLH(block, *m_write8); // call write8 |
| 2860 | 2641 | |
| 2861 | 2642 | if (!in_delay_slot) |
| 2862 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2643 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2863 | 2644 | return TRUE; |
| 2864 | 2645 | |
| 2865 | 2646 | case 1 << 8: // MOVWS4(opcode & 0x0f, Rm); |
| 2866 | 2647 | udisp = (opcode & 0x0f) * 2; |
| 2867 | 2648 | UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp |
| 2868 | 2649 | UML_MOV(block, I1, R32(0)); // mov r1, R0 |
| 2869 | | UML_CALLH(block, *sh2->write16); // call write16 |
| 2650 | UML_CALLH(block, *m_write16); // call write16 |
| 2870 | 2651 | |
| 2871 | 2652 | if (!in_delay_slot) |
| 2872 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2653 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2873 | 2654 | return TRUE; |
| 2874 | 2655 | |
| 2875 | 2656 | case 2<< 8: |
| r29568 | r29569 | |
| 2885 | 2666 | udisp = opcode & 0x0f; |
| 2886 | 2667 | UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp |
| 2887 | 2668 | SETEA(0); |
| 2888 | | UML_CALLH(block, *sh2->read8); // call read8 |
| 2669 | UML_CALLH(block, *m_read8); // call read8 |
| 2889 | 2670 | UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE |
| 2890 | 2671 | |
| 2891 | 2672 | if (!in_delay_slot) |
| 2892 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2673 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2893 | 2674 | return TRUE; |
| 2894 | 2675 | |
| 2895 | 2676 | case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); |
| 2896 | 2677 | udisp = (opcode & 0x0f)*2; |
| 2897 | 2678 | UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp |
| 2898 | 2679 | SETEA(0); |
| 2899 | | UML_CALLH(block, *sh2->read16); // call read16 |
| 2680 | UML_CALLH(block, *m_read16); // call read16 |
| 2900 | 2681 | UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD |
| 2901 | 2682 | |
| 2902 | 2683 | if (!in_delay_slot) |
| 2903 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2684 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 2904 | 2685 | return TRUE; |
| 2905 | 2686 | |
| 2906 | 2687 | case 8<< 8: // CMPIM(opcode & 0xff); |
| 2907 | | UML_AND(block, I0, mem(&sh2->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2688 | UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) |
| 2908 | 2689 | |
| 2909 | 2690 | UML_SEXT(block, I1, opcode&0xff, SIZE_BYTE); // sext r1, opcode&0xff, BYTE |
| 2910 | 2691 | UML_CMP(block, I1, R32(0)); // cmp r1, R0 |
| r29568 | r29569 | |
| 2913 | 2694 | UML_OR(block, I0, I0, T); // or r0, r0, T |
| 2914 | 2695 | |
| 2915 | 2696 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 2916 | | UML_MOV(block, mem(&sh2->sr), I0); // mov sh2->sr, r0 |
| 2697 | UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 |
| 2917 | 2698 | return TRUE; |
| 2918 | 2699 | |
| 2919 | 2700 | case 9<< 8: // BT(opcode & 0xff); |
| 2920 | | UML_TEST(block, mem(&sh2->sr), T); // test sh2->sr, T |
| 2701 | UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T |
| 2921 | 2702 | UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum |
| 2922 | 2703 | |
| 2923 | 2704 | disp = ((INT32)opcode << 24) >> 24; |
| 2924 | | sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination |
| 2705 | m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination |
| 2925 | 2706 | |
| 2926 | | generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles> |
| 2927 | | UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // jmp sh2->ea |
| 2707 | generate_update_cycles(block, compiler, m_sh2_state->ea, TRUE); // <subtract cycles> |
| 2708 | UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea |
| 2928 | 2709 | |
| 2929 | 2710 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 2930 | 2711 | return TRUE; |
| 2931 | 2712 | |
| 2932 | 2713 | case 11<< 8: // BF(opcode & 0xff); |
| 2933 | | UML_TEST(block, mem(&sh2->sr), T); // test sh2->sr, T |
| 2714 | UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T |
| 2934 | 2715 | UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum |
| 2935 | 2716 | |
| 2936 | 2717 | disp = ((INT32)opcode << 24) >> 24; |
| 2937 | | sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination |
| 2718 | m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination |
| 2938 | 2719 | |
| 2939 | | generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles> |
| 2940 | | UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // jmp sh2->ea |
| 2720 | generate_update_cycles(block, compiler, m_sh2_state->ea, TRUE); // <subtract cycles> |
| 2721 | UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea |
| 2941 | 2722 | |
| 2942 | 2723 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 2943 | 2724 | return TRUE; |
| 2944 | 2725 | |
| 2945 | 2726 | case 13<< 8: // BTS(opcode & 0xff); |
| 2946 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 2727 | if (m_cpu_type > CPU_TYPE_SH1) |
| 2947 | 2728 | { |
| 2948 | | UML_TEST(block, mem(&sh2->sr), T); // test sh2->sr, T |
| 2729 | UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T |
| 2949 | 2730 | UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum |
| 2950 | 2731 | |
| 2951 | 2732 | disp = ((INT32)opcode << 24) >> 24; |
| 2952 | | sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination |
| 2733 | m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination |
| 2953 | 2734 | |
| 2954 | 2735 | templabel = compiler->labelnum; // save our label |
| 2955 | 2736 | compiler->labelnum++; // make sure the delay slot doesn't use it |
| 2956 | | generate_delay_slot(sh2, block, compiler, desc, sh2->ea-2); |
| 2737 | generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); |
| 2957 | 2738 | |
| 2958 | | generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles> |
| 2959 | | UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // jmp sh2->ea |
| 2739 | generate_update_cycles(block, compiler, m_sh2_state->ea, TRUE); // <subtract cycles> |
| 2740 | UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea |
| 2960 | 2741 | |
| 2961 | 2742 | UML_LABEL(block, templabel); // labelnum: |
| 2962 | 2743 | return TRUE; |
| r29568 | r29569 | |
| 2964 | 2745 | break; |
| 2965 | 2746 | |
| 2966 | 2747 | case 15<< 8: // BFS(opcode & 0xff); |
| 2967 | | if (sh2->cpu_type > CPU_TYPE_SH1) |
| 2748 | if (m_cpu_type > CPU_TYPE_SH1) |
| 2968 | 2749 | { |
| 2969 | | UML_TEST(block, mem(&sh2->sr), T); // test sh2->sr, T |
| 2750 | UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T |
| 2970 | 2751 | UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum |
| 2971 | 2752 | |
| 2972 | 2753 | disp = ((INT32)opcode << 24) >> 24; |
| 2973 | | sh2->ea = (desc->pc + 2) + disp * 2 + 2; // sh2->ea = destination |
| 2754 | m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination |
| 2974 | 2755 | |
| 2975 | 2756 | templabel = compiler->labelnum; // save our label |
| 2976 | 2757 | compiler->labelnum++; // make sure the delay slot doesn't use it |
| 2977 | | generate_delay_slot(sh2, block, compiler, desc, sh2->ea-2); // delay slot only if the branch is taken |
| 2758 | generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); // delay slot only if the branch is taken |
| 2978 | 2759 | |
| 2979 | | generate_update_cycles(sh2, block, compiler, sh2->ea, TRUE); // <subtract cycles> |
| 2980 | | UML_HASHJMP(block, 0, sh2->ea, *sh2->nocode); // jmp sh2->ea |
| 2760 | generate_update_cycles(block, compiler, m_sh2_state->ea, TRUE); // <subtract cycles> |
| 2761 | UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea |
| 2981 | 2762 | |
| 2982 | 2763 | UML_LABEL(block, templabel); // labelnum: |
| 2983 | 2764 | return TRUE; |
| r29568 | r29569 | |
| 2988 | 2769 | return FALSE; |
| 2989 | 2770 | } |
| 2990 | 2771 | |
| 2991 | | static int generate_group_12(sh2_state *sh2, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2772 | int sh2_device::generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT16 opcode, int in_delay_slot, UINT32 ovrpc) |
| 2992 | 2773 | { |
| 2993 | 2774 | UINT32 scratch; |
| 2994 | 2775 | |
| r29568 | r29569 | |
| 2996 | 2777 | { |
| 2997 | 2778 | case 0<<8: // MOVBSG(opcode & 0xff); |
| 2998 | 2779 | scratch = (opcode & 0xff); |
| 2999 | | UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch |
| 2780 | UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch |
| 3000 | 2781 | UML_AND(block, I1, R32(0), 0xff); // and r1, R0, 0xff |
| 3001 | | UML_CALLH(block, *sh2->write8); // call write8 |
| 2782 | UML_CALLH(block, *m_write8); // call write8 |
| 3002 | 2783 | |
| 3003 | 2784 | if (!in_delay_slot) |
| 3004 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2785 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 3005 | 2786 | return TRUE; |
| 3006 | 2787 | |
| 3007 | 2788 | case 1<<8: // MOVWSG(opcode & 0xff); |
| 3008 | 2789 | scratch = (opcode & 0xff) * 2; |
| 3009 | | UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch |
| 2790 | UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch |
| 3010 | 2791 | UML_AND(block, I1, R32(0), 0xffff); // and r1, R0, 0xffff |
| 3011 | | UML_CALLH(block, *sh2->write16); // call write16 |
| 2792 | UML_CALLH(block, *m_write16); // call write16 |
| 3012 | 2793 | |
| 3013 | 2794 | if (!in_delay_slot) |
| 3014 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2795 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 3015 | 2796 | return TRUE; |
| 3016 | 2797 | |
| 3017 | 2798 | case 2<<8: // MOVLSG(opcode & 0xff); |
| 3018 | 2799 | scratch = (opcode & 0xff) * 4; |
| 3019 | | UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch |
| 2800 | UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch |
| 3020 | 2801 | UML_MOV(block, I1, R32(0)); // mov r1, R0 |
| 3021 | | UML_CALLH(block, *sh2->write32); // call write32 |
| 2802 | UML_CALLH(block, *m_write32); // call write32 |
| 3022 | 2803 | |
| 3023 | 2804 | if (!in_delay_slot) |
| 3024 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2805 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 3025 | 2806 | return TRUE; |
| 3026 | 2807 | |
| 3027 | 2808 | case 3<<8: // TRAPA(opcode & 0xff); |
| 3028 | 2809 | scratch = (opcode & 0xff) * 4; |
| 3029 | | UML_ADD(block, mem(&sh2->ea), mem(&sh2->vbr), scratch); // add ea, vbr, scratch |
| 2810 | UML_ADD(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->vbr), scratch); // add ea, vbr, scratch |
| 3030 | 2811 | |
| 3031 | 2812 | UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 |
| 3032 | 2813 | UML_MOV(block, I0, R32(15)); // mov r0, R15 |
| 3033 | | UML_MOV(block, I1, mem(&sh2->sr)); // mov r1, sr |
| 3034 | | UML_CALLH(block, *sh2->write32); // write32 |
| 2814 | UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr |
| 2815 | UML_CALLH(block, *m_write32); // write32 |
| 3035 | 2816 | |
| 3036 | 2817 | UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 |
| 3037 | 2818 | UML_MOV(block, I0, R32(15)); // mov r0, R15 |
| 3038 | 2819 | UML_MOV(block, I1, desc->pc+2); // mov r1, pc+2 |
| 3039 | | UML_CALLH(block, *sh2->write32); // write32 |
| 2820 | UML_CALLH(block, *m_write32); // write32 |
| 3040 | 2821 | |
| 3041 | | UML_MOV(block, I0, mem(&sh2->ea)); // mov r0, ea |
| 3042 | | UML_CALLH(block, *sh2->read32); // read32 |
| 3043 | | UML_HASHJMP(block, 0, I0, *sh2->nocode); // jmp (r0) |
| 2822 | UML_MOV(block, I0, mem(&m_sh2_state->ea)); // mov r0, ea |
| 2823 | UML_CALLH(block, *m_read32); // read32 |
| 2824 | UML_HASHJMP(block, 0, I0, *m_nocode); // jmp (r0) |
| 3044 | 2825 | |
| 3045 | 2826 | return TRUE; |
| 3046 | 2827 | |
| 3047 | 2828 | case 4<<8: // MOVBLG(opcode & 0xff); |
| 3048 | 2829 | scratch = (opcode & 0xff); |
| 3049 | | UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch |
| 3050 | | UML_CALLH(block, *sh2->read8); // call read16 |
| 2830 | UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch |
| 2831 | UML_CALLH(block, *m_read8); // call read16 |
| 3051 | 2832 | UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE |
| 3052 | 2833 | |
| 3053 | 2834 | if (!in_delay_slot) |
| 3054 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2835 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 3055 | 2836 | return TRUE; |
| 3056 | 2837 | |
| 3057 | 2838 | case 5<<8: // MOVWLG(opcode & 0xff); |
| 3058 | 2839 | scratch = (opcode & 0xff) * 2; |
| 3059 | | UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch |
| 3060 | | UML_CALLH(block, *sh2->read16); // call read16 |
| 2840 | UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch |
| 2841 | UML_CALLH(block, *m_read16); // call read16 |
| 3061 | 2842 | UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD |
| 3062 | 2843 | |
| 3063 | 2844 | if (!in_delay_slot) |
| 3064 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2845 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 3065 | 2846 | return TRUE; |
| 3066 | 2847 | |
| 3067 | 2848 | case 6<<8: // MOVLLG(opcode & 0xff); |
| 3068 | 2849 | scratch = (opcode & 0xff) * 4; |
| 3069 | | UML_ADD(block, I0, mem(&sh2->gbr), scratch); // add r0, gbr, scratch |
| 3070 | | UML_CALLH(block, *sh2->read32); // call read32 |
| 2850 | UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch |
| 2851 | UML_CALLH(block, *m_read32); // call read32 |
| 3071 | 2852 | UML_MOV(block, R32(0), I0); // mov R0, r0 |
| 3072 | 2853 | |
| 3073 | 2854 | if (!in_delay_slot) |
| 3074 | | generate_update_cycles(sh2, block, compiler, desc->pc + 2, TRUE); |
| 2855 | generate_update_cycles(block, compiler, desc->pc + 2, TRUE); |
| 3075 | 2856 | return TRUE; |
| 3076 | 2857 | |
| 3077 | 2858 | case 7<<8: // MOVA(opcode & 0xff); |
| r29568 | r29569 | |
| 3084 | 2865 | case 8<<8: // TSTI(opcode & 0xff); |
| 3085 | 2866 | scratch = opcode & 0xff; |
| 3086 | 2867 | |
| 3087 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T (clear the T bit) |
| 2868 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) |
| 3088 | 2869 | UML_AND(block, I0, R32(0), scratch); // and r0, R0, scratch |
| 3089 | 2870 | UML_CMP(block, I0, 0); // cmp r0, #0 |
| 3090 | 2871 | UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum |
| 3091 | 2872 | |
| 3092 | | UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T |
| 2873 | UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T |
| 3093 | 2874 | |
| 3094 | 2875 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 3095 | 2876 | return TRUE; |
| r29568 | r29569 | |
| 3107 | 2888 | return TRUE; |
| 3108 | 2889 | |
| 3109 | 2890 | case 12<<8: // TSTM(opcode & 0xff); |
| 3110 | | UML_AND(block, mem(&sh2->sr), mem(&sh2->sr), ~T); // and sr, sr, ~T (clear the T bit) |
| 3111 | | UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr |
| 3112 | | UML_CALLH(block, *sh2->read8); // read8 |
| 2891 | UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) |
| 2892 | UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr |
| 2893 | UML_CALLH(block, *m_read8); // read8 |
| 3113 | 2894 | |
| 3114 | 2895 | UML_AND(block, I0, I0, opcode & 0xff); |
| 3115 | 2896 | UML_CMP(block, I0, 0); // cmp r0, #0 |
| 3116 | 2897 | UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum |
| 3117 | 2898 | |
| 3118 | | UML_OR(block, mem(&sh2->sr), mem(&sh2->sr), T); // or sr, sr, T |
| 2899 | UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T |
| 3119 | 2900 | |
| 3120 | 2901 | UML_LABEL(block, compiler->labelnum++); // labelnum: |
| 3121 | 2902 | return TRUE; |
| 3122 | 2903 | |
| 3123 | 2904 | case 13<<8: // ANDM(opcode & 0xff); |
| 3124 | | UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr |
| 3125 | | UML_CALLH(block, *sh2->read8); // read8 |
| 2905 | UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr |
| 2906 | UML_CALLH(block, *m_read8); // read8 |
| 3126 | 2907 | |
| 3127 | 2908 | UML_AND(block, I1, I0, opcode&0xff); // and r1, r0, #opcode&0xff |
| 3128 | | UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr |
| 2909 | UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr |
| 3129 | 2910 | SETEA(0); |
| 3130 | | UML_CALLH(block, *sh2->write8); // write8 |
| 2911 | UML_CALLH(block, *m_write8); // write8 |
| 3131 | 2912 | return TRUE; |
| 3132 | 2913 | |
| 3133 | 2914 | case 14<<8: // XORM(opcode & 0xff); |
| 3134 | | UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr |
| 3135 | | UML_CALLH(block, *sh2->read8); // read8 |
| 2915 | UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr |
| 2916 | UML_CALLH(block, *m_read8); // read8 |
| 3136 | 2917 | |
| 3137 | 2918 | UML_XOR(block, I1, I0, opcode&0xff); // xor r1, r0, #opcode&0xff |
| 3138 | | UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr |
| 2919 | UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr |
| 3139 | 2920 | SETEA(0); |
| 3140 | | UML_CALLH(block, *sh2->write8); // write8 |
| 2921 | UML_CALLH(block, *m_write8); // write8 |
| 3141 | 2922 | return TRUE; |
| 3142 | 2923 | |
| 3143 | 2924 | case 15<<8: // ORM(opcode & 0xff); |
| 3144 | | UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr |
| 3145 | | UML_CALLH(block, *sh2->read8); // read8 |
| 2925 | UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr |
| 2926 | UML_CALLH(block, *m_read8); // read8 |
| 3146 | 2927 | |
| 3147 | 2928 | UML_OR(block, I1, I0, opcode&0xff); // or r1, r0, #opcode&0xff |
| 3148 | | UML_ADD(block, I0, R32(0), mem(&sh2->gbr)); // add r0, R0, gbr |
| 2929 | UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr |
| 3149 | 2930 | SETEA(0); |
| 3150 | | UML_CALLH(block, *sh2->write8); // write8 |
| 2931 | UML_CALLH(block, *m_write8); // write8 |
| 3151 | 2932 | return TRUE; |
| 3152 | 2933 | } |
| 3153 | 2934 | |
| r29568 | r29569 | |
| 3162 | 2943 | sh2drc_set_options - configure DRC options |
| 3163 | 2944 | -------------------------------------------------*/ |
| 3164 | 2945 | |
| 3165 | | void sh2drc_set_options(device_t *device, UINT32 options) |
| 2946 | void sh2_device::sh2drc_set_options(UINT32 options) |
| 3166 | 2947 | { |
| 3167 | | if (!device->machine().options().drc()) return; |
| 3168 | | sh2_state *sh2 = get_safe_token(device); |
| 3169 | | sh2->drcoptions = options; |
| 2948 | if (!machine().options().drc()) return; |
| 2949 | m_drcoptions = options; |
| 3170 | 2950 | } |
| 3171 | 2951 | |
| 3172 | 2952 | |
| r29568 | r29569 | |
| 3175 | 2955 | the PC must be flushed for speedups to work |
| 3176 | 2956 | -------------------------------------------------*/ |
| 3177 | 2957 | |
| 3178 | | void sh2drc_add_pcflush(device_t *device, offs_t address) |
| 2958 | void sh2_device::sh2drc_add_pcflush(offs_t address) |
| 3179 | 2959 | { |
| 3180 | | if (!device->machine().options().drc()) return; |
| 3181 | | sh2_state *sh2 = get_safe_token(device); |
| 2960 | if (!machine().options().drc()) return; |
| 3182 | 2961 | |
| 3183 | | if (sh2->pcfsel < ARRAY_LENGTH(sh2->pcflushes)) |
| 3184 | | sh2->pcflushes[sh2->pcfsel++] = address; |
| 2962 | if (m_pcfsel < ARRAY_LENGTH(m_pcflushes)) |
| 2963 | m_pcflushes[m_pcfsel++] = address; |
| 3185 | 2964 | } |
| 3186 | 2965 | |
| 3187 | 2966 | |
| r29568 | r29569 | |
| 3190 | 2969 | region |
| 3191 | 2970 | -------------------------------------------------*/ |
| 3192 | 2971 | |
| 3193 | | void sh2drc_add_fastram(device_t *device, offs_t start, offs_t end, UINT8 readonly, void *base) |
| 2972 | void sh2_device::sh2drc_add_fastram(offs_t start, offs_t end, UINT8 readonly, void *base) |
| 3194 | 2973 | { |
| 3195 | | sh2_state *sh2 = get_safe_token(device); |
| 3196 | | if (sh2->fastram_select < ARRAY_LENGTH(sh2->fastram)) |
| 2974 | if (m_fastram_select < ARRAY_LENGTH(m_fastram)) |
| 3197 | 2975 | { |
| 3198 | | sh2->fastram[sh2->fastram_select].start = start; |
| 3199 | | sh2->fastram[sh2->fastram_select].end = end; |
| 3200 | | sh2->fastram[sh2->fastram_select].readonly = readonly; |
| 3201 | | sh2->fastram[sh2->fastram_select].base = base; |
| 3202 | | sh2->fastram_select++; |
| 2976 | m_fastram[m_fastram_select].start = start; |
| 2977 | m_fastram[m_fastram_select].end = end; |
| 2978 | m_fastram[m_fastram_select].readonly = readonly; |
| 2979 | m_fastram[m_fastram_select].base = base; |
| 2980 | m_fastram_select++; |
| 3203 | 2981 | } |
| 3204 | 2982 | } |
| 3205 | 2983 | |
| 3206 | | /*------------------------------------------------- |
| 3207 | | sh2_internal_a5 - read handler for |
| 3208 | | SH2 internal map |
| 3209 | | -------------------------------------------------*/ |
| 3210 | | |
| 3211 | | static READ32_HANDLER(sh2_internal_a5) |
| 3212 | | { |
| 3213 | | return 0xa5a5a5a5; |
| 3214 | | } |
| 3215 | | |
| 3216 | | |
| 3217 | | /*------------------------------------------------- |
| 3218 | | sh2_internal_map - maps SH2 built-ins |
| 3219 | | -------------------------------------------------*/ |
| 3220 | | |
| 3221 | | static ADDRESS_MAP_START( sh2_internal_map, AS_PROGRAM, 32, legacy_cpu_device ) |
| 3222 | | AM_RANGE(0x40000000, 0xbfffffff) AM_READ_LEGACY(sh2_internal_a5) |
| 3223 | | AM_RANGE(0xe0000000, 0xffffffff) AM_READWRITE_LEGACY(sh2_internal_r, sh2_internal_w) |
| 3224 | | ADDRESS_MAP_END |
| 3225 | | |
| 3226 | | /*------------------------------------------------- |
| 3227 | | sh2_set_info - set information about a given |
| 3228 | | CPU instance |
| 3229 | | -------------------------------------------------*/ |
| 3230 | | |
| 3231 | | static CPU_SET_INFO( sh2 ) |
| 3232 | | { |
| 3233 | | sh2_state *sh2 = get_safe_token(device); |
| 3234 | | switch (state) |
| 3235 | | { |
| 3236 | | /* --- the following bits of info are set as 64-bit signed integers --- */ |
| 3237 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: sh2_set_irq_line(sh2, SH2_INT_VBLIN, info->i); break; |
| 3238 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: sh2_set_irq_line(sh2, SH2_INT_VBLOUT, info->i); break; |
| 3239 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: sh2_set_irq_line(sh2, SH2_INT_HBLIN, info->i); break; |
| 3240 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: sh2_set_irq_line(sh2, SH2_INT_TIMER0, info->i); break; |
| 3241 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: sh2_set_irq_line(sh2, SH2_INT_TIMER1, info->i); break; |
| 3242 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: sh2_set_irq_line(sh2, SH2_INT_DSP, info->i); break; |
| 3243 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: sh2_set_irq_line(sh2, SH2_INT_SOUND, info->i); break; |
| 3244 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: sh2_set_irq_line(sh2, SH2_INT_SMPC, info->i); break; |
| 3245 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: sh2_set_irq_line(sh2, SH2_INT_PAD, info->i); break; |
| 3246 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: sh2_set_irq_line(sh2, SH2_INT_DMA2, info->i); break; |
| 3247 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: sh2_set_irq_line(sh2, SH2_INT_DMA1, info->i); break; |
| 3248 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: sh2_set_irq_line(sh2, SH2_INT_DMA0, info->i); break; |
| 3249 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: sh2_set_irq_line(sh2, SH2_INT_DMAILL, info->i); break; |
| 3250 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: sh2_set_irq_line(sh2, SH2_INT_SPRITE, info->i); break; |
| 3251 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_14: sh2_set_irq_line(sh2, SH2_INT_14, info->i); break; |
| 3252 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_15: sh2_set_irq_line(sh2, SH2_INT_15, info->i); break; |
| 3253 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: sh2_set_irq_line(sh2, SH2_INT_ABUS, info->i); break; |
| 3254 | | case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: sh2_set_irq_line(sh2, INPUT_LINE_NMI, info->i); break; |
| 3255 | | |
| 3256 | | case CPUINFO_INT_REGISTER + SH2_PC: |
| 3257 | | case CPUINFO_INT_PC: sh2->pc = info->i; sh2->delay = 0; break; |
| 3258 | | case CPUINFO_INT_SP: sh2->r[15] = info->i; break; |
| 3259 | | case CPUINFO_INT_REGISTER + SH2_PR: sh2->pr = info->i; break; |
| 3260 | | case CPUINFO_INT_REGISTER + SH2_SR: sh2->sr = info->i; break; |
| 3261 | | case CPUINFO_INT_REGISTER + SH2_GBR: sh2->gbr = info->i; break; |
| 3262 | | case CPUINFO_INT_REGISTER + SH2_VBR: sh2->vbr = info->i; break; |
| 3263 | | case CPUINFO_INT_REGISTER + SH2_MACH: sh2->mach = info->i; break; |
| 3264 | | case CPUINFO_INT_REGISTER + SH2_MACL: sh2->macl = info->i; break; |
| 3265 | | case CPUINFO_INT_REGISTER + SH2_R0: sh2->r[ 0] = info->i; break; |
| 3266 | | case CPUINFO_INT_REGISTER + SH2_R1: sh2->r[ 1] = info->i; break; |
| 3267 | | case CPUINFO_INT_REGISTER + SH2_R2: sh2->r[ 2] = info->i; break; |
| 3268 | | case CPUINFO_INT_REGISTER + SH2_R3: sh2->r[ 3] = info->i; break; |
| 3269 | | case CPUINFO_INT_REGISTER + SH2_R4: sh2->r[ 4] = info->i; break; |
| 3270 | | case CPUINFO_INT_REGISTER + SH2_R5: sh2->r[ 5] = info->i; break; |
| 3271 | | case CPUINFO_INT_REGISTER + SH2_R6: sh2->r[ 6] = info->i; break; |
| 3272 | | case CPUINFO_INT_REGISTER + SH2_R7: sh2->r[ 7] = info->i; break; |
| 3273 | | case CPUINFO_INT_REGISTER + SH2_R8: sh2->r[ 8] = info->i; break; |
| 3274 | | case CPUINFO_INT_REGISTER + SH2_R9: sh2->r[ 9] = info->i; break; |
| 3275 | | case CPUINFO_INT_REGISTER + SH2_R10: sh2->r[10] = info->i; break; |
| 3276 | | case CPUINFO_INT_REGISTER + SH2_R11: sh2->r[11] = info->i; break; |
| 3277 | | case CPUINFO_INT_REGISTER + SH2_R12: sh2->r[12] = info->i; break; |
| 3278 | | case CPUINFO_INT_REGISTER + SH2_R13: sh2->r[13] = info->i; break; |
| 3279 | | case CPUINFO_INT_REGISTER + SH2_R14: sh2->r[14] = info->i; break; |
| 3280 | | case CPUINFO_INT_REGISTER + SH2_R15: sh2->r[15] = info->i; break; |
| 3281 | | case CPUINFO_INT_REGISTER + SH2_EA: sh2->ea = info->i; break; |
| 3282 | | } |
| 3283 | | } |
| 3284 | | |
| 3285 | | /*------------------------------------------------- |
| 3286 | | sh2_get_info - return information about a |
| 3287 | | given CPU instance |
| 3288 | | -------------------------------------------------*/ |
| 3289 | | |
| 3290 | | CPU_GET_INFO( sh2_drc ) |
| 3291 | | { |
| 3292 | | sh2_state *sh2 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
| 3293 | | switch (state) |
| 3294 | | { |
| 3295 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 3296 | | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(sh2_state *); break; |
| 3297 | | case CPUINFO_INT_INPUT_LINES: info->i = 16; break; |
| 3298 | | case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; |
| 3299 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; |
| 3300 | | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
| 3301 | | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
| 3302 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break; |
| 3303 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break; |
| 3304 | | case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; |
| 3305 | | case CPUINFO_INT_MAX_CYCLES: info->i = 4; break; |
| 3306 | | |
| 3307 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break; |
| 3308 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break; |
| 3309 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; |
| 3310 | | case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; |
| 3311 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; |
| 3312 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; |
| 3313 | | case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; |
| 3314 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; |
| 3315 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; |
| 3316 | | |
| 3317 | | // Internal maps |
| 3318 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(sh2_internal_map); break; |
| 3319 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map32 = NULL; break; |
| 3320 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map32 = NULL; break; |
| 3321 | | |
| 3322 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: info->i = sh2->irq_line_state[SH2_INT_VBLIN]; break; |
| 3323 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: info->i = sh2->irq_line_state[SH2_INT_VBLOUT]; break; |
| 3324 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: info->i = sh2->irq_line_state[SH2_INT_HBLIN]; break; |
| 3325 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: info->i = sh2->irq_line_state[SH2_INT_TIMER0]; break; |
| 3326 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: info->i = sh2->irq_line_state[SH2_INT_TIMER1]; break; |
| 3327 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: info->i = sh2->irq_line_state[SH2_INT_DSP]; break; |
| 3328 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: info->i = sh2->irq_line_state[SH2_INT_SOUND]; break; |
| 3329 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: info->i = sh2->irq_line_state[SH2_INT_SMPC]; break; |
| 3330 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: info->i = sh2->irq_line_state[SH2_INT_PAD]; break; |
| 3331 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: info->i = sh2->irq_line_state[SH2_INT_DMA2]; break; |
| 3332 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: info->i = sh2->irq_line_state[SH2_INT_DMA1]; break; |
| 3333 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: info->i = sh2->irq_line_state[SH2_INT_DMA0]; break; |
| 3334 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: info->i = sh2->irq_line_state[SH2_INT_DMAILL]; break; |
| 3335 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: info->i = sh2->irq_line_state[SH2_INT_SPRITE]; break; |
| 3336 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_14: info->i = sh2->irq_line_state[SH2_INT_14]; break; |
| 3337 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_15: info->i = sh2->irq_line_state[SH2_INT_15]; break; |
| 3338 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: info->i = sh2->irq_line_state[SH2_INT_ABUS]; break; |
| 3339 | | case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = sh2->nmi_line_state; break; |
| 3340 | | |
| 3341 | | case CPUINFO_INT_PREVIOUSPC: info->i = sh2->ppc; break; |
| 3342 | | |
| 3343 | | case CPUINFO_INT_PC: |
| 3344 | | case CPUINFO_INT_REGISTER + SH2_PC: info->i = (sh2->delay) ? (sh2->delay & AM) : (sh2->pc & AM); break; |
| 3345 | | case CPUINFO_INT_SP: info->i = sh2->r[15]; break; |
| 3346 | | case CPUINFO_INT_REGISTER + SH2_PR: info->i = sh2->pr; break; |
| 3347 | | case CPUINFO_INT_REGISTER + SH2_SR: info->i = sh2->sr; break; |
| 3348 | | case CPUINFO_INT_REGISTER + SH2_GBR: info->i = sh2->gbr; break; |
| 3349 | | case CPUINFO_INT_REGISTER + SH2_VBR: info->i = sh2->vbr; break; |
| 3350 | | case CPUINFO_INT_REGISTER + SH2_MACH: info->i = sh2->mach; break; |
| 3351 | | case CPUINFO_INT_REGISTER + SH2_MACL: info->i = sh2->macl; break; |
| 3352 | | case CPUINFO_INT_REGISTER + SH2_R0: info->i = sh2->r[ 0]; break; |
| 3353 | | case CPUINFO_INT_REGISTER + SH2_R1: info->i = sh2->r[ 1]; break; |
| 3354 | | case CPUINFO_INT_REGISTER + SH2_R2: info->i = sh2->r[ 2]; break; |
| 3355 | | case CPUINFO_INT_REGISTER + SH2_R3: info->i = sh2->r[ 3]; break; |
| 3356 | | case CPUINFO_INT_REGISTER + SH2_R4: info->i = sh2->r[ 4]; break; |
| 3357 | | case CPUINFO_INT_REGISTER + SH2_R5: info->i = sh2->r[ 5]; break; |
| 3358 | | case CPUINFO_INT_REGISTER + SH2_R6: info->i = sh2->r[ 6]; break; |
| 3359 | | case CPUINFO_INT_REGISTER + SH2_R7: info->i = sh2->r[ 7]; break; |
| 3360 | | case CPUINFO_INT_REGISTER + SH2_R8: info->i = sh2->r[ 8]; break; |
| 3361 | | case CPUINFO_INT_REGISTER + SH2_R9: info->i = sh2->r[ 9]; break; |
| 3362 | | case CPUINFO_INT_REGISTER + SH2_R10: info->i = sh2->r[10]; break; |
| 3363 | | case CPUINFO_INT_REGISTER + SH2_R11: info->i = sh2->r[11]; break; |
| 3364 | | case CPUINFO_INT_REGISTER + SH2_R12: info->i = sh2->r[12]; break; |
| 3365 | | case CPUINFO_INT_REGISTER + SH2_R13: info->i = sh2->r[13]; break; |
| 3366 | | case CPUINFO_INT_REGISTER + SH2_R14: info->i = sh2->r[14]; break; |
| 3367 | | case CPUINFO_INT_REGISTER + SH2_R15: info->i = sh2->r[15]; break; |
| 3368 | | case CPUINFO_INT_REGISTER + SH2_EA: info->i = sh2->ea; break; |
| 3369 | | |
| 3370 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 3371 | | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sh2); break; |
| 3372 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sh2); break; |
| 3373 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh2); break; |
| 3374 | | case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(sh2); break; |
| 3375 | | case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh2); break; |
| 3376 | | case CPUINFO_FCT_BURN: info->burn = NULL; break; |
| 3377 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh2); break; |
| 3378 | | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh2->icount; break; |
| 3379 | | |
| 3380 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 3381 | | case CPUINFO_STR_NAME: strcpy(info->s, "SH-2 DRC"); break; |
| 3382 | | case CPUINFO_STR_SHORTNAME: strcpy(info->s, "sh2_drc"); break; |
| 3383 | | case CPUINFO_STR_FAMILY: strcpy(info->s, "Hitachi SuperH RISC"); break; |
| 3384 | | case CPUINFO_STR_VERSION: strcpy(info->s, "2.0"); break; |
| 3385 | | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| 3386 | | case CPUINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME team, all rights reserved."); break; |
| 3387 | | |
| 3388 | | case CPUINFO_STR_FLAGS: |
| 3389 | | sprintf(info->s, "%c%c%d%c%c", |
| 3390 | | sh2->sr & M ? 'M':'.', |
| 3391 | | sh2->sr & Q ? 'Q':'.', |
| 3392 | | (sh2->sr & I) >> 4, |
| 3393 | | sh2->sr & S ? 'S':'.', |
| 3394 | | sh2->sr & T ? 'T':'.'); |
| 3395 | | break; |
| 3396 | | |
| 3397 | | case CPUINFO_STR_REGISTER + SH2_PC: sprintf(info->s, "PC :%08X", sh2->pc); break; |
| 3398 | | case CPUINFO_STR_REGISTER + SH2_SR: sprintf(info->s, "SR :%08X", sh2->sr); break; |
| 3399 | | case CPUINFO_STR_REGISTER + SH2_PR: sprintf(info->s, "PR :%08X", sh2->pr); break; |
| 3400 | | case CPUINFO_STR_REGISTER + SH2_GBR: sprintf(info->s, "GBR :%08X", sh2->gbr); break; |
| 3401 | | case CPUINFO_STR_REGISTER + SH2_VBR: sprintf(info->s, "VBR :%08X", sh2->vbr); break; |
| 3402 | | case CPUINFO_STR_REGISTER + SH2_MACH: sprintf(info->s, "MACH:%08X", sh2->mach); break; |
| 3403 | | case CPUINFO_STR_REGISTER + SH2_MACL: sprintf(info->s, "MACL:%08X", sh2->macl); break; |
| 3404 | | case CPUINFO_STR_REGISTER + SH2_R0: sprintf(info->s, "R0 :%08X", sh2->r[ 0]); break; |
| 3405 | | case CPUINFO_STR_REGISTER + SH2_R1: sprintf(info->s, "R1 :%08X", sh2->r[ 1]); break; |
| 3406 | | case CPUINFO_STR_REGISTER + SH2_R2: sprintf(info->s, "R2 :%08X", sh2->r[ 2]); break; |
| 3407 | | case CPUINFO_STR_REGISTER + SH2_R3: sprintf(info->s, "R3 :%08X", sh2->r[ 3]); break; |
| 3408 | | case CPUINFO_STR_REGISTER + SH2_R4: sprintf(info->s, "R4 :%08X", sh2->r[ 4]); break; |
| 3409 | | case CPUINFO_STR_REGISTER + SH2_R5: sprintf(info->s, "R5 :%08X", sh2->r[ 5]); break; |
| 3410 | | case CPUINFO_STR_REGISTER + SH2_R6: sprintf(info->s, "R6 :%08X", sh2->r[ 6]); break; |
| 3411 | | case CPUINFO_STR_REGISTER + SH2_R7: sprintf(info->s, "R7 :%08X", sh2->r[ 7]); break; |
| 3412 | | case CPUINFO_STR_REGISTER + SH2_R8: sprintf(info->s, "R8 :%08X", sh2->r[ 8]); break; |
| 3413 | | case CPUINFO_STR_REGISTER + SH2_R9: sprintf(info->s, "R9 :%08X", sh2->r[ 9]); break; |
| 3414 | | case CPUINFO_STR_REGISTER + SH2_R10: sprintf(info->s, "R10 :%08X", sh2->r[10]); break; |
| 3415 | | case CPUINFO_STR_REGISTER + SH2_R11: sprintf(info->s, "R11 :%08X", sh2->r[11]); break; |
| 3416 | | case CPUINFO_STR_REGISTER + SH2_R12: sprintf(info->s, "R12 :%08X", sh2->r[12]); break; |
| 3417 | | case CPUINFO_STR_REGISTER + SH2_R13: sprintf(info->s, "R13 :%08X", sh2->r[13]); break; |
| 3418 | | case CPUINFO_STR_REGISTER + SH2_R14: sprintf(info->s, "R14 :%08X", sh2->r[14]); break; |
| 3419 | | case CPUINFO_STR_REGISTER + SH2_R15: sprintf(info->s, "R15 :%08X", sh2->r[15]); break; |
| 3420 | | case CPUINFO_STR_REGISTER + SH2_EA: sprintf(info->s, "EA :%08X", sh2->ea); break; |
| 3421 | | } |
| 3422 | | } |
| 3423 | | |
| 3424 | | /*------------------------------------------------- |
| 3425 | | sh1_get_info - return information about a |
| 3426 | | given CPU instance |
| 3427 | | -------------------------------------------------*/ |
| 3428 | | |
| 3429 | | CPU_GET_INFO( sh1_drc ) |
| 3430 | | { |
| 3431 | | switch (state) |
| 3432 | | { |
| 3433 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 3434 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh1); break; |
| 3435 | | |
| 3436 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 3437 | | case CPUINFO_STR_NAME: strcpy(info->s, "SH-1 DRC"); break; |
| 3438 | | case CPUINFO_STR_SHORTNAME: strcpy(info->s, "sh1_drc"); break; |
| 3439 | | |
| 3440 | | default: CPU_GET_INFO_CALL(sh2_drc); break; |
| 3441 | | } |
| 3442 | | } |
| 3443 | | |
| 3444 | | DEFINE_LEGACY_CPU_DEVICE(SH1_DRC, sh1_drc); |
| 3445 | | DEFINE_LEGACY_CPU_DEVICE(SH2_DRC, sh2_drc); |
branches/new_menus/src/emu/cpu/sh2/sh2comn.c
| r29568 | r29569 | |
| 17 | 17 | |
| 18 | 18 | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
| 19 | 19 | |
| 20 | | INLINE sh2_state *GET_SH2(device_t *dev) |
| 21 | | { |
| 22 | | if (dev->machine().options().drc()) { |
| 23 | | return *(sh2_state **)downcast<legacy_cpu_device *>(dev)->token(); |
| 24 | | } else { |
| 25 | | return (sh2_state *)downcast<legacy_cpu_device *>(dev)->token(); |
| 26 | | } |
| 27 | | } |
| 28 | | |
| 29 | 20 | static const int div_tab[4] = { 3, 5, 7, 0 }; |
| 30 | 21 | |
| 31 | | INLINE UINT32 RL(sh2_state *sh2, offs_t A) |
| 32 | | { |
| 33 | | if (A >= 0xe0000000) /* I/O */ |
| 34 | | return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffffffff); |
| 35 | 22 | |
| 36 | | if (A >= 0xc0000000) /* Cache Data Array */ |
| 37 | | return sh2->program->read_dword(A); |
| 38 | | |
| 39 | | /* 0x60000000 Cache Address Data Array */ |
| 40 | | |
| 41 | | if (A >= 0x40000000) /* Cache Associative Purge Area */ |
| 42 | | return 0xa5a5a5a5; |
| 43 | | |
| 44 | | /* 0x20000000 no Cache */ |
| 45 | | /* 0x00000000 read thru Cache if CE bit is 1 */ |
| 46 | | return sh2->program->read_dword(A & AM); |
| 47 | | } |
| 48 | | |
| 49 | | INLINE void WL(sh2_state *sh2, offs_t A, UINT32 V) |
| 23 | void sh2_device::sh2_timer_resync() |
| 50 | 24 | { |
| 51 | | if (A >= 0xe0000000) /* I/O */ |
| 52 | | { |
| 53 | | sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V, 0xffffffff); |
| 54 | | return; |
| 55 | | } |
| 25 | int divider = div_tab[(m_m[5] >> 8) & 3]; |
| 26 | UINT64 cur_time = total_cycles(); |
| 27 | UINT64 add = (cur_time - m_frc_base) >> divider; |
| 56 | 28 | |
| 57 | | if (A >= 0xc0000000) /* Cache Data Array */ |
| 58 | | { |
| 59 | | sh2->program->write_dword(A,V); |
| 60 | | return; |
| 61 | | } |
| 62 | | |
| 63 | | /* 0x60000000 Cache Address Data Array */ |
| 64 | | |
| 65 | | if (A >= 0x40000000) /* Cache Associative Purge Area */ |
| 66 | | return; |
| 67 | | |
| 68 | | /* 0x20000000 no Cache */ |
| 69 | | /* 0x00000000 read thru Cache if CE bit is 1 */ |
| 70 | | sh2->program->write_dword(A & AM,V); |
| 71 | | } |
| 72 | | |
| 73 | | static void sh2_timer_resync(sh2_state *sh2) |
| 74 | | { |
| 75 | | int divider = div_tab[(sh2->m[5] >> 8) & 3]; |
| 76 | | UINT64 cur_time = sh2->device->total_cycles(); |
| 77 | | UINT64 add = (cur_time - sh2->frc_base) >> divider; |
| 78 | | |
| 79 | 29 | if (add > 0) |
| 80 | 30 | { |
| 81 | 31 | if(divider) |
| 82 | | sh2->frc += add; |
| 32 | m_frc += add; |
| 83 | 33 | |
| 84 | | sh2->frc_base = cur_time; |
| 34 | m_frc_base = cur_time; |
| 85 | 35 | } |
| 86 | 36 | } |
| 87 | 37 | |
| 88 | | static void sh2_timer_activate(sh2_state *sh2) |
| 38 | void sh2_device::sh2_timer_activate() |
| 89 | 39 | { |
| 90 | 40 | int max_delta = 0xfffff; |
| 91 | 41 | UINT16 frc; |
| 92 | 42 | |
| 93 | | sh2->timer->adjust(attotime::never); |
| 43 | m_timer->adjust(attotime::never); |
| 94 | 44 | |
| 95 | | frc = sh2->frc; |
| 96 | | if(!(sh2->m[4] & OCFA)) { |
| 97 | | UINT16 delta = sh2->ocra - frc; |
| 45 | frc = m_frc; |
| 46 | if(!(m_m[4] & OCFA)) { |
| 47 | UINT16 delta = m_ocra - frc; |
| 98 | 48 | if(delta < max_delta) |
| 99 | 49 | max_delta = delta; |
| 100 | 50 | } |
| 101 | 51 | |
| 102 | | if(!(sh2->m[4] & OCFB) && (sh2->ocra <= sh2->ocrb || !(sh2->m[4] & 0x010000))) { |
| 103 | | UINT16 delta = sh2->ocrb - frc; |
| 52 | if(!(m_m[4] & OCFB) && (m_ocra <= m_ocrb || !(m_m[4] & 0x010000))) { |
| 53 | UINT16 delta = m_ocrb - frc; |
| 104 | 54 | if(delta < max_delta) |
| 105 | 55 | max_delta = delta; |
| 106 | 56 | } |
| 107 | 57 | |
| 108 | | if(!(sh2->m[4] & OVF) && !(sh2->m[4] & 0x010000)) { |
| 58 | if(!(m_m[4] & OVF) && !(m_m[4] & 0x010000)) { |
| 109 | 59 | int delta = 0x10000 - frc; |
| 110 | 60 | if(delta < max_delta) |
| 111 | 61 | max_delta = delta; |
| 112 | 62 | } |
| 113 | 63 | |
| 114 | 64 | if(max_delta != 0xfffff) { |
| 115 | | int divider = div_tab[(sh2->m[5] >> 8) & 3]; |
| 65 | int divider = div_tab[(m_m[5] >> 8) & 3]; |
| 116 | 66 | if(divider) { |
| 117 | 67 | max_delta <<= divider; |
| 118 | | sh2->frc_base = sh2->device->total_cycles(); |
| 119 | | sh2->timer->adjust(sh2->device->cycles_to_attotime(max_delta)); |
| 68 | m_frc_base = total_cycles(); |
| 69 | m_timer->adjust(cycles_to_attotime(max_delta)); |
| 120 | 70 | } else { |
| 121 | | logerror("SH2.%s: Timer event in %d cycles of external clock", sh2->device->tag(), max_delta); |
| 71 | logerror("SH2.%s: Timer event in %d cycles of external clock", tag(), max_delta); |
| 122 | 72 | } |
| 123 | 73 | } |
| 124 | 74 | } |
| 125 | 75 | |
| 126 | | |
| 127 | | static TIMER_CALLBACK( sh2_timer_callback ) |
| 76 | TIMER_CALLBACK_MEMBER( sh2_device::sh2_timer_callback ) |
| 128 | 77 | { |
| 129 | | sh2_state *sh2 = (sh2_state *)ptr; |
| 130 | 78 | UINT16 frc; |
| 131 | 79 | |
| 132 | | sh2_timer_resync(sh2); |
| 80 | sh2_timer_resync(); |
| 133 | 81 | |
| 134 | | frc = sh2->frc; |
| 82 | frc = m_frc; |
| 135 | 83 | |
| 136 | | if(frc == sh2->ocrb) |
| 137 | | sh2->m[4] |= OCFB; |
| 84 | if(frc == m_ocrb) |
| 85 | m_m[4] |= OCFB; |
| 138 | 86 | |
| 139 | 87 | if(frc == 0x0000) |
| 140 | | sh2->m[4] |= OVF; |
| 88 | m_m[4] |= OVF; |
| 141 | 89 | |
| 142 | | if(frc == sh2->ocra) |
| 90 | if(frc == m_ocra) |
| 143 | 91 | { |
| 144 | | sh2->m[4] |= OCFA; |
| 92 | m_m[4] |= OCFA; |
| 145 | 93 | |
| 146 | | if(sh2->m[4] & 0x010000) |
| 147 | | sh2->frc = 0; |
| 94 | if(m_m[4] & 0x010000) |
| 95 | m_frc = 0; |
| 148 | 96 | } |
| 149 | 97 | |
| 150 | | sh2_recalc_irq(sh2); |
| 151 | | sh2_timer_activate(sh2); |
| 98 | sh2_recalc_irq(); |
| 99 | sh2_timer_activate(); |
| 152 | 100 | } |
| 153 | 101 | |
| 154 | 102 | |
| r29568 | r29569 | |
| 176 | 124 | |
| 177 | 125 | |
| 178 | 126 | |
| 179 | | void sh2_notify_dma_data_available(device_t *device) |
| 127 | void sh2_device::sh2_notify_dma_data_available() |
| 180 | 128 | { |
| 181 | | sh2_state *sh2 = GET_SH2(device); |
| 182 | 129 | //printf("call notify\n"); |
| 183 | 130 | |
| 184 | 131 | for (int dma=0;dma<2;dma++) |
| 185 | 132 | { |
| 186 | | //printf("sh2->dma_timer_active[dma] %04x\n",sh2->dma_timer_active[dma]); |
| 133 | //printf("m_dma_timer_active[dma] %04x\n",m_dma_timer_active[dma]); |
| 187 | 134 | |
| 188 | | if (sh2->dma_timer_active[dma]==2) // 2 = stalled |
| 135 | if (m_dma_timer_active[dma]==2) // 2 = stalled |
| 189 | 136 | { |
| 190 | 137 | // printf("resuming stalled dma\n"); |
| 191 | | sh2->dma_timer_active[dma]=1; |
| 192 | | sh2->dma_current_active_timer[dma]->adjust(attotime::zero, dma); |
| 138 | m_dma_timer_active[dma]=1; |
| 139 | m_dma_current_active_timer[dma]->adjust(attotime::zero, dma); |
| 193 | 140 | } |
| 194 | 141 | } |
| 195 | 142 | |
| 196 | 143 | } |
| 197 | 144 | |
| 198 | | void sh2_do_dma(sh2_state *sh2, int dma) |
| 145 | void sh2_device::sh2_do_dma(int dma) |
| 199 | 146 | { |
| 200 | 147 | UINT32 dmadata; |
| 201 | 148 | |
| 202 | 149 | UINT32 tempsrc, tempdst; |
| 203 | 150 | |
| 204 | | if (sh2->active_dma_count[dma] > 0) |
| 151 | if (m_active_dma_count[dma] > 0) |
| 205 | 152 | { |
| 206 | 153 | // process current DMA |
| 207 | | switch(sh2->active_dma_size[dma]) |
| 154 | switch(m_active_dma_size[dma]) |
| 208 | 155 | { |
| 209 | 156 | case 0: |
| 210 | 157 | { |
| r29568 | r29569 | |
| 212 | 159 | // to allow for the callback to check if we can process the DMA at this |
| 213 | 160 | // time (we need to know where we're reading / writing to/from) |
| 214 | 161 | |
| 215 | | if(sh2->active_dma_incs[dma] == 2) |
| 216 | | tempsrc = sh2->active_dma_src[dma] - 1; |
| 162 | if(m_active_dma_incs[dma] == 2) |
| 163 | tempsrc = m_active_dma_src[dma] - 1; |
| 217 | 164 | else |
| 218 | | tempsrc = sh2->active_dma_src[dma]; |
| 165 | tempsrc = m_active_dma_src[dma]; |
| 219 | 166 | |
| 220 | | if(sh2->active_dma_incd[dma] == 2) |
| 221 | | tempdst = sh2->active_dma_dst[dma] - 1; |
| 167 | if(m_active_dma_incd[dma] == 2) |
| 168 | tempdst = m_active_dma_dst[dma] - 1; |
| 222 | 169 | else |
| 223 | | tempdst = sh2->active_dma_dst[dma]; |
| 170 | tempdst = m_active_dma_dst[dma]; |
| 224 | 171 | |
| 225 | | if (sh2->dma_callback_fifo_data_available) |
| 172 | if (m_dma_callback_fifo_data_available) |
| 226 | 173 | { |
| 227 | | int available = sh2->dma_callback_fifo_data_available(sh2->device, tempsrc, tempdst, 0, sh2->active_dma_size[dma]); |
| 174 | int available = m_dma_callback_fifo_data_available(this, tempsrc, tempdst, 0, m_active_dma_size[dma]); |
| 228 | 175 | |
| 229 | 176 | if (!available) |
| 230 | 177 | { |
| 231 | 178 | //printf("dma stalled\n"); |
| 232 | | sh2->dma_timer_active[dma]=2;// mark as stalled |
| 179 | m_dma_timer_active[dma]=2;// mark as stalled |
| 233 | 180 | return; |
| 234 | 181 | } |
| 235 | 182 | } |
| 236 | 183 | |
| 237 | 184 | #ifdef USE_TIMER_FOR_DMA |
| 238 | 185 | //schedule next DMA callback |
| 239 | | sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma); |
| 186 | m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); |
| 240 | 187 | #endif |
| 241 | 188 | |
| 242 | 189 | |
| 243 | | dmadata = sh2->program->read_byte(tempsrc); |
| 244 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 245 | | sh2->program->write_byte(tempdst, dmadata); |
| 190 | dmadata = m_program->read_byte(tempsrc); |
| 191 | if (m_dma_callback_kludge) dmadata = m_dma_callback_kludge(this, tempsrc, tempdst, dmadata, m_active_dma_size[dma]); |
| 192 | m_program->write_byte(tempdst, dmadata); |
| 246 | 193 | |
| 247 | | if(sh2->active_dma_incs[dma] == 2) |
| 248 | | sh2->active_dma_src[dma] --; |
| 249 | | if(sh2->active_dma_incd[dma] == 2) |
| 250 | | sh2->active_dma_dst[dma] --; |
| 194 | if(m_active_dma_incs[dma] == 2) |
| 195 | m_active_dma_src[dma] --; |
| 196 | if(m_active_dma_incd[dma] == 2) |
| 197 | m_active_dma_dst[dma] --; |
| 251 | 198 | |
| 252 | 199 | |
| 253 | | if(sh2->active_dma_incs[dma] == 1) |
| 254 | | sh2->active_dma_src[dma] ++; |
| 255 | | if(sh2->active_dma_incd[dma] == 1) |
| 256 | | sh2->active_dma_dst[dma] ++; |
| 200 | if(m_active_dma_incs[dma] == 1) |
| 201 | m_active_dma_src[dma] ++; |
| 202 | if(m_active_dma_incd[dma] == 1) |
| 203 | m_active_dma_dst[dma] ++; |
| 257 | 204 | |
| 258 | | sh2->active_dma_count[dma] --; |
| 205 | m_active_dma_count[dma] --; |
| 259 | 206 | } |
| 260 | 207 | break; |
| 261 | 208 | case 1: |
| 262 | 209 | { |
| 263 | | if(sh2->active_dma_incs[dma] == 2) |
| 264 | | tempsrc = sh2->active_dma_src[dma] - 2; |
| 210 | if(m_active_dma_incs[dma] == 2) |
| 211 | tempsrc = m_active_dma_src[dma] - 2; |
| 265 | 212 | else |
| 266 | | tempsrc = sh2->active_dma_src[dma]; |
| 213 | tempsrc = m_active_dma_src[dma]; |
| 267 | 214 | |
| 268 | | if(sh2->active_dma_incd[dma] == 2) |
| 269 | | tempdst = sh2->active_dma_dst[dma] - 2; |
| 215 | if(m_active_dma_incd[dma] == 2) |
| 216 | tempdst = m_active_dma_dst[dma] - 2; |
| 270 | 217 | else |
| 271 | | tempdst = sh2->active_dma_dst[dma]; |
| 218 | tempdst = m_active_dma_dst[dma]; |
| 272 | 219 | |
| 273 | | if (sh2->dma_callback_fifo_data_available) |
| 220 | if (m_dma_callback_fifo_data_available) |
| 274 | 221 | { |
| 275 | | int available = sh2->dma_callback_fifo_data_available(sh2->device, tempsrc, tempdst, 0, sh2->active_dma_size[dma]); |
| 222 | int available = m_dma_callback_fifo_data_available(this, tempsrc, tempdst, 0, m_active_dma_size[dma]); |
| 276 | 223 | |
| 277 | 224 | if (!available) |
| 278 | 225 | { |
| 279 | 226 | //printf("dma stalled\n"); |
| 280 | | sh2->dma_timer_active[dma]=2;// mark as stalled |
| 227 | m_dma_timer_active[dma]=2;// mark as stalled |
| 281 | 228 | return; |
| 282 | 229 | } |
| 283 | 230 | } |
| 284 | 231 | |
| 285 | 232 | #ifdef USE_TIMER_FOR_DMA |
| 286 | 233 | //schedule next DMA callback |
| 287 | | sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma); |
| 234 | m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); |
| 288 | 235 | #endif |
| 289 | 236 | |
| 290 | 237 | // check: should this really be using read_word_32 / write_word_32? |
| 291 | | dmadata = sh2->program->read_word(tempsrc); |
| 292 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 293 | | sh2->program->write_word(tempdst, dmadata); |
| 238 | dmadata = m_program->read_word(tempsrc); |
| 239 | if (m_dma_callback_kludge) dmadata = m_dma_callback_kludge(this, tempsrc, tempdst, dmadata, m_active_dma_size[dma]); |
| 240 | m_program->write_word(tempdst, dmadata); |
| 294 | 241 | |
| 295 | | if(sh2->active_dma_incs[dma] == 2) |
| 296 | | sh2->active_dma_src[dma] -= 2; |
| 297 | | if(sh2->active_dma_incd[dma] == 2) |
| 298 | | sh2->active_dma_dst[dma] -= 2; |
| 242 | if(m_active_dma_incs[dma] == 2) |
| 243 | m_active_dma_src[dma] -= 2; |
| 244 | if(m_active_dma_incd[dma] == 2) |
| 245 | m_active_dma_dst[dma] -= 2; |
| 299 | 246 | |
| 300 | | if(sh2->active_dma_incs[dma] == 1) |
| 301 | | sh2->active_dma_src[dma] += 2; |
| 302 | | if(sh2->active_dma_incd[dma] == 1) |
| 303 | | sh2->active_dma_dst[dma] += 2; |
| 247 | if(m_active_dma_incs[dma] == 1) |
| 248 | m_active_dma_src[dma] += 2; |
| 249 | if(m_active_dma_incd[dma] == 1) |
| 250 | m_active_dma_dst[dma] += 2; |
| 304 | 251 | |
| 305 | | sh2->active_dma_count[dma] --; |
| 252 | m_active_dma_count[dma] --; |
| 306 | 253 | } |
| 307 | 254 | break; |
| 308 | 255 | case 2: |
| 309 | 256 | { |
| 310 | | if(sh2->active_dma_incs[dma] == 2) |
| 311 | | tempsrc = sh2->active_dma_src[dma] - 4; |
| 257 | if(m_active_dma_incs[dma] == 2) |
| 258 | tempsrc = m_active_dma_src[dma] - 4; |
| 312 | 259 | else |
| 313 | | tempsrc = sh2->active_dma_src[dma]; |
| 260 | tempsrc = m_active_dma_src[dma]; |
| 314 | 261 | |
| 315 | | if(sh2->active_dma_incd[dma] == 2) |
| 316 | | tempdst = sh2->active_dma_dst[dma] - 4; |
| 262 | if(m_active_dma_incd[dma] == 2) |
| 263 | tempdst = m_active_dma_dst[dma] - 4; |
| 317 | 264 | else |
| 318 | | tempdst = sh2->active_dma_dst[dma]; |
| 265 | tempdst = m_active_dma_dst[dma]; |
| 319 | 266 | |
| 320 | | if (sh2->dma_callback_fifo_data_available) |
| 267 | if (m_dma_callback_fifo_data_available) |
| 321 | 268 | { |
| 322 | | int available = sh2->dma_callback_fifo_data_available(sh2->device, tempsrc, tempdst, 0, sh2->active_dma_size[dma]); |
| 269 | int available = m_dma_callback_fifo_data_available(this, tempsrc, tempdst, 0, m_active_dma_size[dma]); |
| 323 | 270 | |
| 324 | 271 | if (!available) |
| 325 | 272 | { |
| 326 | 273 | //printf("dma stalled\n"); |
| 327 | | sh2->dma_timer_active[dma]=2;// mark as stalled |
| 274 | m_dma_timer_active[dma]=2;// mark as stalled |
| 328 | 275 | return; |
| 329 | 276 | } |
| 330 | 277 | } |
| 331 | 278 | |
| 332 | 279 | #ifdef USE_TIMER_FOR_DMA |
| 333 | 280 | //schedule next DMA callback |
| 334 | | sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma); |
| 281 | m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); |
| 335 | 282 | #endif |
| 336 | 283 | |
| 337 | | dmadata = sh2->program->read_dword(tempsrc); |
| 338 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 339 | | sh2->program->write_dword(tempdst, dmadata); |
| 284 | dmadata = m_program->read_dword(tempsrc); |
| 285 | if (m_dma_callback_kludge) dmadata = m_dma_callback_kludge(this, tempsrc, tempdst, dmadata, m_active_dma_size[dma]); |
| 286 | m_program->write_dword(tempdst, dmadata); |
| 340 | 287 | |
| 341 | | if(sh2->active_dma_incs[dma] == 2) |
| 342 | | sh2->active_dma_src[dma] -= 4; |
| 343 | | if(sh2->active_dma_incd[dma] == 2) |
| 344 | | sh2->active_dma_dst[dma] -= 4; |
| 288 | if(m_active_dma_incs[dma] == 2) |
| 289 | m_active_dma_src[dma] -= 4; |
| 290 | if(m_active_dma_incd[dma] == 2) |
| 291 | m_active_dma_dst[dma] -= 4; |
| 345 | 292 | |
| 346 | | if(sh2->active_dma_incs[dma] == 1) |
| 347 | | sh2->active_dma_src[dma] += 4; |
| 348 | | if(sh2->active_dma_incd[dma] == 1) |
| 349 | | sh2->active_dma_dst[dma] += 4; |
| 293 | if(m_active_dma_incs[dma] == 1) |
| 294 | m_active_dma_src[dma] += 4; |
| 295 | if(m_active_dma_incd[dma] == 1) |
| 296 | m_active_dma_dst[dma] += 4; |
| 350 | 297 | |
| 351 | | sh2->active_dma_count[dma] --; |
| 298 | m_active_dma_count[dma] --; |
| 352 | 299 | } |
| 353 | 300 | break; |
| 354 | 301 | case 3: |
| 355 | 302 | { |
| 356 | 303 | // shouldn't this really be 4 calls here instead? |
| 357 | 304 | |
| 358 | | tempsrc = sh2->active_dma_src[dma]; |
| 305 | tempsrc = m_active_dma_src[dma]; |
| 359 | 306 | |
| 360 | | if(sh2->active_dma_incd[dma] == 2) |
| 361 | | tempdst = sh2->active_dma_dst[dma] - 16; |
| 307 | if(m_active_dma_incd[dma] == 2) |
| 308 | tempdst = m_active_dma_dst[dma] - 16; |
| 362 | 309 | else |
| 363 | | tempdst = sh2->active_dma_dst[dma]; |
| 310 | tempdst = m_active_dma_dst[dma]; |
| 364 | 311 | |
| 365 | | if (sh2->dma_callback_fifo_data_available) |
| 312 | if (m_dma_callback_fifo_data_available) |
| 366 | 313 | { |
| 367 | | int available = sh2->dma_callback_fifo_data_available(sh2->device, tempsrc, tempdst, 0, sh2->active_dma_size[dma]); |
| 314 | int available = m_dma_callback_fifo_data_available(this, tempsrc, tempdst, 0, m_active_dma_size[dma]); |
| 368 | 315 | |
| 369 | 316 | if (!available) |
| 370 | 317 | { |
| 371 | 318 | //printf("dma stalled\n"); |
| 372 | | sh2->dma_timer_active[dma]=2;// mark as stalled |
| 319 | m_dma_timer_active[dma]=2;// mark as stalled |
| 373 | 320 | fatalerror("SH2 dma_callback_fifo_data_available == 0 in unsupported mode\n"); |
| 374 | 321 | } |
| 375 | 322 | } |
| 376 | 323 | |
| 377 | 324 | #ifdef USE_TIMER_FOR_DMA |
| 378 | 325 | //schedule next DMA callback |
| 379 | | sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma); |
| 326 | m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); |
| 380 | 327 | #endif |
| 381 | 328 | |
| 382 | | dmadata = sh2->program->read_dword(tempsrc); |
| 383 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 384 | | sh2->program->write_dword(tempdst, dmadata); |
| 329 | dmadata = m_program->read_dword(tempsrc); |
| 330 | if (m_dma_callback_kludge) dmadata = m_dma_callback_kludge(this, tempsrc, tempdst, dmadata, m_active_dma_size[dma]); |
| 331 | m_program->write_dword(tempdst, dmadata); |
| 385 | 332 | |
| 386 | | dmadata = sh2->program->read_dword(tempsrc+4); |
| 387 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 388 | | sh2->program->write_dword(tempdst+4, dmadata); |
| 333 | dmadata = m_program->read_dword(tempsrc+4); |
| 334 | if (m_dma_callback_kludge) dmadata = m_dma_callback_kludge(this, tempsrc, tempdst, dmadata, m_active_dma_size[dma]); |
| 335 | m_program->write_dword(tempdst+4, dmadata); |
| 389 | 336 | |
| 390 | | dmadata = sh2->program->read_dword(tempsrc+8); |
| 391 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 392 | | sh2->program->write_dword(tempdst+8, dmadata); |
| 337 | dmadata = m_program->read_dword(tempsrc+8); |
| 338 | if (m_dma_callback_kludge) dmadata = m_dma_callback_kludge(this, tempsrc, tempdst, dmadata, m_active_dma_size[dma]); |
| 339 | m_program->write_dword(tempdst+8, dmadata); |
| 393 | 340 | |
| 394 | | dmadata = sh2->program->read_dword(tempsrc+12); |
| 395 | | if (sh2->dma_callback_kludge) dmadata = sh2->dma_callback_kludge(sh2->device, tempsrc, tempdst, dmadata, sh2->active_dma_size[dma]); |
| 396 | | sh2->program->write_dword(tempdst+12, dmadata); |
| 341 | dmadata = m_program->read_dword(tempsrc+12); |
| 342 | if (m_dma_callback_kludge) dmadata = m_dma_callback_kludge(this, tempsrc, tempdst, dmadata, m_active_dma_size[dma]); |
| 343 | m_program->write_dword(tempdst+12, dmadata); |
| 397 | 344 | |
| 398 | | if(sh2->active_dma_incd[dma] == 2) |
| 399 | | sh2->active_dma_dst[dma] -= 16; |
| 345 | if(m_active_dma_incd[dma] == 2) |
| 346 | m_active_dma_dst[dma] -= 16; |
| 400 | 347 | |
| 401 | | sh2->active_dma_src[dma] += 16; |
| 402 | | if(sh2->active_dma_incd[dma] == 1) |
| 403 | | sh2->active_dma_dst[dma] += 16; |
| 348 | m_active_dma_src[dma] += 16; |
| 349 | if(m_active_dma_incd[dma] == 1) |
| 350 | m_active_dma_dst[dma] += 16; |
| 404 | 351 | |
| 405 | | sh2->active_dma_count[dma]-=4; |
| 352 | m_active_dma_count[dma]-=4; |
| 406 | 353 | } |
| 407 | 354 | break; |
| 408 | 355 | } |
| r29568 | r29569 | |
| 410 | 357 | else // the dma is complete |
| 411 | 358 | { |
| 412 | 359 | // int dma = param & 1; |
| 413 | | // sh2_state *sh2 = (sh2_state *)ptr; |
| 414 | 360 | |
| 415 | 361 | // fever soccer uses cycle-stealing mode, resume the CPU now DMA has finished |
| 416 | | if (sh2->active_dma_steal[dma]) |
| 362 | if (m_active_dma_steal[dma]) |
| 417 | 363 | { |
| 418 | | sh2->device->resume(SUSPEND_REASON_HALT ); |
| 364 | resume(SUSPEND_REASON_HALT ); |
| 419 | 365 | } |
| 420 | 366 | |
| 421 | 367 | |
| 422 | | LOG(("SH2.%s: DMA %d complete\n", sh2->device->tag(), dma)); |
| 423 | | sh2->m[0x63+4*dma] |= 2; |
| 424 | | sh2->dma_timer_active[dma] = 0; |
| 425 | | sh2->dma_irq[dma] |= 1; |
| 426 | | sh2_recalc_irq(sh2); |
| 368 | LOG(("SH2.%s: DMA %d complete\n", tag(), dma)); |
| 369 | m_m[0x63+4*dma] |= 2; |
| 370 | m_dma_timer_active[dma] = 0; |
| 371 | m_dma_irq[dma] |= 1; |
| 372 | sh2_recalc_irq(); |
| 427 | 373 | |
| 428 | 374 | } |
| 429 | 375 | } |
| 430 | 376 | |
| 431 | | static TIMER_CALLBACK( sh2_dma_current_active_callback ) |
| 377 | TIMER_CALLBACK_MEMBER( sh2_device::sh2_dma_current_active_callback ) |
| 432 | 378 | { |
| 433 | 379 | int dma = param & 1; |
| 434 | | sh2_state *sh2 = (sh2_state *)ptr; |
| 435 | 380 | |
| 436 | | sh2_do_dma(sh2, dma); |
| 381 | sh2_do_dma(dma); |
| 437 | 382 | } |
| 438 | 383 | |
| 439 | 384 | |
| 440 | | static void sh2_dmac_check(sh2_state *sh2, int dma) |
| 385 | void sh2_device::sh2_dmac_check(int dma) |
| 441 | 386 | { |
| 442 | | if(sh2->m[0x63+4*dma] & sh2->m[0x6c] & 1) |
| 387 | if(m_m[0x63+4*dma] & m_m[0x6c] & 1) |
| 443 | 388 | { |
| 444 | | if(!sh2->dma_timer_active[dma] && !(sh2->m[0x63+4*dma] & 2)) |
| 389 | if(!m_dma_timer_active[dma] && !(m_m[0x63+4*dma] & 2)) |
| 445 | 390 | { |
| 446 | | sh2->active_dma_incd[dma] = (sh2->m[0x63+4*dma] >> 14) & 3; |
| 447 | | sh2->active_dma_incs[dma] = (sh2->m[0x63+4*dma] >> 12) & 3; |
| 448 | | sh2->active_dma_size[dma] = (sh2->m[0x63+4*dma] >> 10) & 3; |
| 449 | | sh2->active_dma_steal[dma] = (sh2->m[0x63+4*dma] &0x10); |
| 391 | m_active_dma_incd[dma] = (m_m[0x63+4*dma] >> 14) & 3; |
| 392 | m_active_dma_incs[dma] = (m_m[0x63+4*dma] >> 12) & 3; |
| 393 | m_active_dma_size[dma] = (m_m[0x63+4*dma] >> 10) & 3; |
| 394 | m_active_dma_steal[dma] = (m_m[0x63+4*dma] &0x10); |
| 450 | 395 | |
| 451 | | if(sh2->active_dma_incd[dma] == 3 || sh2->active_dma_incs[dma] == 3) |
| 396 | if(m_active_dma_incd[dma] == 3 || m_active_dma_incs[dma] == 3) |
| 452 | 397 | { |
| 453 | | logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", sh2->active_dma_incd[dma], sh2->active_dma_incs[dma], sh2->active_dma_size[dma], sh2->m[0x63+4*dma]); |
| 398 | logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", m_active_dma_incd[dma], m_active_dma_incs[dma], m_active_dma_size[dma], m_m[0x63+4*dma]); |
| 454 | 399 | return; |
| 455 | 400 | } |
| 456 | | sh2->active_dma_src[dma] = sh2->m[0x60+4*dma]; |
| 457 | | sh2->active_dma_dst[dma] = sh2->m[0x61+4*dma]; |
| 458 | | sh2->active_dma_count[dma] = sh2->m[0x62+4*dma]; |
| 459 | | if(!sh2->active_dma_count[dma]) |
| 460 | | sh2->active_dma_count[dma] = 0x1000000; |
| 401 | m_active_dma_src[dma] = m_m[0x60+4*dma]; |
| 402 | m_active_dma_dst[dma] = m_m[0x61+4*dma]; |
| 403 | m_active_dma_count[dma] = m_m[0x62+4*dma]; |
| 404 | if(!m_active_dma_count[dma]) |
| 405 | m_active_dma_count[dma] = 0x1000000; |
| 461 | 406 | |
| 462 | | LOG(("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, sh2->active_dma_src[dma], sh2->active_dma_dst[dma], sh2->active_dma_count[dma], sh2->m[0x63+4*dma], sh2->active_dma_incs[dma], sh2->active_dma_incd[dma], sh2->active_dma_size[dma])); |
| 407 | LOG(("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dma, m_active_dma_src[dma], m_active_dma_dst[dma], m_active_dma_count[dma], m_m[0x63+4*dma], m_active_dma_incs[dma], m_active_dma_incd[dma], m_active_dma_size[dma])); |
| 463 | 408 | |
| 464 | | sh2->dma_timer_active[dma] = 1; |
| 409 | m_dma_timer_active[dma] = 1; |
| 465 | 410 | |
| 466 | | sh2->active_dma_src[dma] &= AM; |
| 467 | | sh2->active_dma_dst[dma] &= AM; |
| 411 | m_active_dma_src[dma] &= AM; |
| 412 | m_active_dma_dst[dma] &= AM; |
| 468 | 413 | |
| 469 | | switch(sh2->active_dma_size[dma]) |
| 414 | switch(m_active_dma_size[dma]) |
| 470 | 415 | { |
| 471 | 416 | case 0: |
| 472 | 417 | break; |
| 473 | 418 | case 1: |
| 474 | | sh2->active_dma_src[dma] &= ~1; |
| 475 | | sh2->active_dma_dst[dma] &= ~1; |
| 419 | m_active_dma_src[dma] &= ~1; |
| 420 | m_active_dma_dst[dma] &= ~1; |
| 476 | 421 | break; |
| 477 | 422 | case 2: |
| 478 | | sh2->active_dma_src[dma] &= ~3; |
| 479 | | sh2->active_dma_dst[dma] &= ~3; |
| 423 | m_active_dma_src[dma] &= ~3; |
| 424 | m_active_dma_dst[dma] &= ~3; |
| 480 | 425 | break; |
| 481 | 426 | case 3: |
| 482 | | sh2->active_dma_src[dma] &= ~3; |
| 483 | | sh2->active_dma_dst[dma] &= ~3; |
| 484 | | sh2->active_dma_count[dma] &= ~3; |
| 427 | m_active_dma_src[dma] &= ~3; |
| 428 | m_active_dma_dst[dma] &= ~3; |
| 429 | m_active_dma_count[dma] &= ~3; |
| 485 | 430 | break; |
| 486 | 431 | } |
| 487 | 432 | |
| r29568 | r29569 | |
| 492 | 437 | // start DMA timer |
| 493 | 438 | |
| 494 | 439 | // fever soccer uses cycle-stealing mode, requiring the CPU to be halted |
| 495 | | if (sh2->active_dma_steal[dma]) |
| 440 | if (m_active_dma_steal[dma]) |
| 496 | 441 | { |
| 497 | 442 | //printf("cycle stealing DMA\n"); |
| 498 | | sh2->device->suspend(SUSPEND_REASON_HALT, 1 ); |
| 443 | suspend(SUSPEND_REASON_HALT, 1 ); |
| 499 | 444 | } |
| 500 | 445 | |
| 501 | | sh2->dma_current_active_timer[dma]->adjust(sh2->device->cycles_to_attotime(2), dma); |
| 446 | m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); |
| 502 | 447 | #endif |
| 503 | 448 | |
| 504 | 449 | } |
| 505 | 450 | } |
| 506 | 451 | else |
| 507 | 452 | { |
| 508 | | if(sh2->dma_timer_active[dma]) |
| 453 | if(m_dma_timer_active[dma]) |
| 509 | 454 | { |
| 510 | 455 | logerror("SH2: DMA %d cancelled in-flight\n", dma); |
| 511 | | //sh2->dma_complete_timer[dma]->adjust(attotime::never); |
| 512 | | sh2->dma_current_active_timer[dma]->adjust(attotime::never); |
| 456 | //m_dma_complete_timer[dma]->adjust(attotime::never); |
| 457 | m_dma_current_active_timer[dma]->adjust(attotime::never); |
| 513 | 458 | |
| 514 | | sh2->dma_timer_active[dma] = 0; |
| 459 | m_dma_timer_active[dma] = 0; |
| 515 | 460 | } |
| 516 | 461 | } |
| 517 | 462 | } |
| 518 | 463 | |
| 519 | | WRITE32_HANDLER( sh2_internal_w ) |
| 464 | WRITE32_MEMBER( sh2_device::sh2_internal_w ) |
| 520 | 465 | { |
| 521 | | sh2_state *sh2 = GET_SH2(&space.device()); |
| 522 | 466 | UINT32 old; |
| 523 | 467 | |
| 524 | | if (sh2->isdrc) |
| 468 | if (m_isdrc) |
| 525 | 469 | offset &= 0x7f; |
| 526 | 470 | |
| 527 | 471 | |
| 528 | | old = sh2->m[offset]; |
| 529 | | COMBINE_DATA(sh2->m+offset); |
| 472 | old = m_m[offset]; |
| 473 | COMBINE_DATA(m_m+offset); |
| 530 | 474 | |
| 531 | 475 | // if(offset != 0x20) |
| 532 | 476 | // logerror("sh2_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfffffe00+offset*4, offset, data, mem_mask); |
| r29568 | r29569 | |
| 547 | 491 | case 0x04: // TIER, FTCSR, FRC |
| 548 | 492 | if((mem_mask & 0x00ffffff) != 0) |
| 549 | 493 | { |
| 550 | | sh2_timer_resync(sh2); |
| 494 | sh2_timer_resync(); |
| 551 | 495 | } |
| 552 | | // printf("SH2.%s: TIER write %04x @ %04x\n", sh2->device->tag(), data >> 16, mem_mask>>16); |
| 553 | | sh2->m[4] = (sh2->m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & sh2->m[4] & (ICF|OCFA|OCFB|OVF)); |
| 554 | | COMBINE_DATA(&sh2->frc); |
| 496 | // printf("SH2.%s: TIER write %04x @ %04x\n", m_device->tag(), data >> 16, mem_mask>>16); |
| 497 | m_m[4] = (m_m[4] & ~(ICF|OCFA|OCFB|OVF)) | (old & m_m[4] & (ICF|OCFA|OCFB|OVF)); |
| 498 | COMBINE_DATA(&m_frc); |
| 555 | 499 | if((mem_mask & 0x00ffffff) != 0) |
| 556 | | sh2_timer_activate(sh2); |
| 557 | | sh2_recalc_irq(sh2); |
| 500 | sh2_timer_activate(); |
| 501 | sh2_recalc_irq(); |
| 558 | 502 | break; |
| 559 | 503 | case 0x05: // OCRx, TCR, TOCR |
| 560 | | // printf("SH2.%s: TCR write %08x @ %08x\n", sh2->device->tag(), data, mem_mask); |
| 561 | | sh2_timer_resync(sh2); |
| 562 | | if(sh2->m[5] & 0x10) |
| 563 | | sh2->ocrb = (sh2->ocrb & (~mem_mask >> 16)) | ((data & mem_mask) >> 16); |
| 504 | // printf("SH2.%s: TCR write %08x @ %08x\n", m_device->tag(), data, mem_mask); |
| 505 | sh2_timer_resync(); |
| 506 | if(m_m[5] & 0x10) |
| 507 | m_ocrb = (m_ocrb & (~mem_mask >> 16)) | ((data & mem_mask) >> 16); |
| 564 | 508 | else |
| 565 | | sh2->ocra = (sh2->ocra & (~mem_mask >> 16)) | ((data & mem_mask) >> 16); |
| 566 | | sh2_timer_activate(sh2); |
| 509 | m_ocra = (m_ocra & (~mem_mask >> 16)) | ((data & mem_mask) >> 16); |
| 510 | sh2_timer_activate(); |
| 567 | 511 | break; |
| 568 | 512 | |
| 569 | 513 | case 0x06: // ICR |
| r29568 | r29569 | |
| 573 | 517 | case 0x18: // IPRB, VCRA |
| 574 | 518 | case 0x19: // VCRB, VCRC |
| 575 | 519 | case 0x1a: // VCRD |
| 576 | | sh2_recalc_irq(sh2); |
| 520 | sh2_recalc_irq(); |
| 577 | 521 | break; |
| 578 | 522 | |
| 579 | 523 | // DMA |
| r29568 | r29569 | |
| 582 | 526 | |
| 583 | 527 | // Watchdog |
| 584 | 528 | case 0x20: // WTCNT, RSTCSR |
| 585 | | if((sh2->m[0x20] & 0xff000000) == 0x5a000000) |
| 586 | | sh2->wtcnt = (sh2->m[0x20] >> 16) & 0xff; |
| 529 | if((m_m[0x20] & 0xff000000) == 0x5a000000) |
| 530 | m_wtcnt = (m_m[0x20] >> 16) & 0xff; |
| 587 | 531 | |
| 588 | | if((sh2->m[0x20] & 0xff000000) == 0xa5000000) |
| 532 | if((m_m[0x20] & 0xff000000) == 0xa5000000) |
| 589 | 533 | { |
| 590 | 534 | /* |
| 591 | 535 | WTCSR |
| r29568 | r29569 | |
| 596 | 540 | ---- -xxx Clock select |
| 597 | 541 | */ |
| 598 | 542 | |
| 599 | | sh2->wtcsr = (sh2->m[0x20] >> 16) & 0xff; |
| 543 | m_wtcsr = (m_m[0x20] >> 16) & 0xff; |
| 600 | 544 | } |
| 601 | 545 | |
| 602 | | if((sh2->m[0x20] & 0x0000ff00) == 0x00005a00) |
| 546 | if((m_m[0x20] & 0x0000ff00) == 0x00005a00) |
| 603 | 547 | { |
| 604 | 548 | // -x-- ---- RSTE (1: resets wtcnt when overflows 0: no reset) |
| 605 | 549 | // --x- ---- RSTS (0: power-on reset 1: Manual reset) |
| 606 | 550 | // ... |
| 607 | 551 | } |
| 608 | 552 | |
| 609 | | if((sh2->m[0x20] & 0x0000ff00) == 0x0000a500) |
| 553 | if((m_m[0x20] & 0x0000ff00) == 0x0000a500) |
| 610 | 554 | { |
| 611 | 555 | // clear WOVF |
| 612 | 556 | // ... |
| r29568 | r29569 | |
| 640 | 584 | break; |
| 641 | 585 | case 0x41: // DVDNT |
| 642 | 586 | { |
| 643 | | INT32 a = sh2->m[0x41]; |
| 644 | | INT32 b = sh2->m[0x40]; |
| 645 | | LOG(("SH2 '%s' div+mod %d/%d\n", sh2->device->tag(), a, b)); |
| 587 | INT32 a = m_m[0x41]; |
| 588 | INT32 b = m_m[0x40]; |
| 589 | LOG(("SH2 '%s' div+mod %d/%d\n", tag(), a, b)); |
| 646 | 590 | if (b) |
| 647 | 591 | { |
| 648 | | sh2->m[0x45] = a / b; |
| 649 | | sh2->m[0x44] = a % b; |
| 592 | m_m[0x45] = a / b; |
| 593 | m_m[0x44] = a % b; |
| 650 | 594 | } |
| 651 | 595 | else |
| 652 | 596 | { |
| 653 | | sh2->m[0x42] |= 0x00010000; |
| 654 | | sh2->m[0x45] = 0x7fffffff; |
| 655 | | sh2->m[0x44] = 0x7fffffff; |
| 656 | | sh2_recalc_irq(sh2); |
| 597 | m_m[0x42] |= 0x00010000; |
| 598 | m_m[0x45] = 0x7fffffff; |
| 599 | m_m[0x44] = 0x7fffffff; |
| 600 | sh2_recalc_irq(); |
| 657 | 601 | } |
| 658 | 602 | break; |
| 659 | 603 | } |
| 660 | 604 | case 0x42: // DVCR |
| 661 | | sh2->m[0x42] = (sh2->m[0x42] & ~0x00001000) | (old & sh2->m[0x42] & 0x00010000); |
| 662 | | sh2_recalc_irq(sh2); |
| 605 | m_m[0x42] = (m_m[0x42] & ~0x00001000) | (old & m_m[0x42] & 0x00010000); |
| 606 | sh2_recalc_irq(); |
| 663 | 607 | break; |
| 664 | 608 | case 0x43: // VCRDIV |
| 665 | | sh2_recalc_irq(sh2); |
| 609 | sh2_recalc_irq(); |
| 666 | 610 | break; |
| 667 | 611 | case 0x44: // DVDNTH |
| 668 | 612 | break; |
| 669 | 613 | case 0x45: // DVDNTL |
| 670 | 614 | { |
| 671 | | INT64 a = sh2->m[0x45] | ((UINT64)(sh2->m[0x44]) << 32); |
| 672 | | INT64 b = (INT32)sh2->m[0x40]; |
| 673 | | LOG(("SH2 '%s' div+mod %" I64FMT "d/%" I64FMT "d\n", sh2->device->tag(), a, b)); |
| 615 | INT64 a = m_m[0x45] | ((UINT64)(m_m[0x44]) << 32); |
| 616 | INT64 b = (INT32)m_m[0x40]; |
| 617 | LOG(("SH2 '%s' div+mod %" I64FMT "d/%" I64FMT "d\n", tag(), a, b)); |
| 674 | 618 | if (b) |
| 675 | 619 | { |
| 676 | 620 | INT64 q = a / b; |
| 677 | 621 | if (q != (INT32)q) |
| 678 | 622 | { |
| 679 | | sh2->m[0x42] |= 0x00010000; |
| 680 | | sh2->m[0x45] = 0x7fffffff; |
| 681 | | sh2->m[0x44] = 0x7fffffff; |
| 682 | | sh2_recalc_irq(sh2); |
| 623 | m_m[0x42] |= 0x00010000; |
| 624 | m_m[0x45] = 0x7fffffff; |
| 625 | m_m[0x44] = 0x7fffffff; |
| 626 | sh2_recalc_irq(); |
| 683 | 627 | } |
| 684 | 628 | else |
| 685 | 629 | { |
| 686 | | sh2->m[0x45] = q; |
| 687 | | sh2->m[0x44] = a % b; |
| 630 | m_m[0x45] = q; |
| 631 | m_m[0x44] = a % b; |
| 688 | 632 | } |
| 689 | 633 | } |
| 690 | 634 | else |
| 691 | 635 | { |
| 692 | | sh2->m[0x42] |= 0x00010000; |
| 693 | | sh2->m[0x45] = 0x7fffffff; |
| 694 | | sh2->m[0x44] = 0x7fffffff; |
| 695 | | sh2_recalc_irq(sh2); |
| 636 | m_m[0x42] |= 0x00010000; |
| 637 | m_m[0x45] = 0x7fffffff; |
| 638 | m_m[0x44] = 0x7fffffff; |
| 639 | sh2_recalc_irq(); |
| 696 | 640 | } |
| 697 | 641 | break; |
| 698 | 642 | } |
| r29568 | r29569 | |
| 702 | 646 | case 0x61: // DAR0 |
| 703 | 647 | break; |
| 704 | 648 | case 0x62: // DTCR0 |
| 705 | | sh2->m[0x62] &= 0xffffff; |
| 649 | m_m[0x62] &= 0xffffff; |
| 706 | 650 | break; |
| 707 | 651 | case 0x63: // CHCR0 |
| 708 | | sh2->m[0x63] = (sh2->m[0x63] & ~2) | (old & sh2->m[0x63] & 2); |
| 709 | | sh2_dmac_check(sh2, 0); |
| 652 | m_m[0x63] = (m_m[0x63] & ~2) | (old & m_m[0x63] & 2); |
| 653 | sh2_dmac_check(0); |
| 710 | 654 | break; |
| 711 | 655 | case 0x64: // SAR1 |
| 712 | 656 | case 0x65: // DAR1 |
| 713 | 657 | break; |
| 714 | 658 | case 0x66: // DTCR1 |
| 715 | | sh2->m[0x66] &= 0xffffff; |
| 659 | m_m[0x66] &= 0xffffff; |
| 716 | 660 | break; |
| 717 | 661 | case 0x67: // CHCR1 |
| 718 | | sh2->m[0x67] = (sh2->m[0x67] & ~2) | (old & sh2->m[0x67] & 2); |
| 719 | | sh2_dmac_check(sh2, 1); |
| 662 | m_m[0x67] = (m_m[0x67] & ~2) | (old & m_m[0x67] & 2); |
| 663 | sh2_dmac_check(1); |
| 720 | 664 | break; |
| 721 | 665 | case 0x68: // VCRDMA0 |
| 722 | 666 | case 0x6a: // VCRDMA1 |
| 723 | | sh2_recalc_irq(sh2); |
| 667 | sh2_recalc_irq(); |
| 724 | 668 | break; |
| 725 | 669 | case 0x6c: // DMAOR |
| 726 | | sh2->m[0x6c] = (sh2->m[0x6c] & ~6) | (old & sh2->m[0x6c] & 6); |
| 727 | | sh2_dmac_check(sh2, 0); |
| 728 | | sh2_dmac_check(sh2, 1); |
| 670 | m_m[0x6c] = (m_m[0x6c] & ~6) | (old & m_m[0x6c] & 6); |
| 671 | sh2_dmac_check(0); |
| 672 | sh2_dmac_check(1); |
| 729 | 673 | break; |
| 730 | 674 | |
| 731 | 675 | // Bus controller |
| r29568 | r29569 | |
| 744 | 688 | } |
| 745 | 689 | } |
| 746 | 690 | |
| 747 | | READ32_HANDLER( sh2_internal_r ) |
| 691 | READ32_MEMBER( sh2_device::sh2_internal_r ) |
| 748 | 692 | { |
| 749 | | sh2_state *sh2 = GET_SH2(&space.device()); |
| 750 | | |
| 751 | | if (sh2->isdrc) |
| 693 | if (m_isdrc) |
| 752 | 694 | offset &= 0x7f; |
| 753 | 695 | |
| 754 | 696 | // logerror("sh2_internal_r: Read %08x (%x) @ %08x\n", 0xfffffe00+offset*4, offset, mem_mask); |
| r29568 | r29569 | |
| 757 | 699 | case 0x00: |
| 758 | 700 | break; |
| 759 | 701 | case 0x01: |
| 760 | | return sh2->m[1] | 0x80000000; // TDRE: Trasmit Data Register Empty. Force it to be '1' for the time being. |
| 702 | return m_m[1] | 0x80000000; // TDRE: Trasmit Data Register Empty. Force it to be '1' for the time being. |
| 761 | 703 | |
| 762 | 704 | case 0x04: // TIER, FTCSR, FRC |
| 763 | 705 | if ( mem_mask == 0x00ff0000 ) |
| 764 | 706 | { |
| 765 | | if ( sh2->ftcsr_read_callback != NULL ) |
| 707 | if ( m_ftcsr_read_callback != NULL ) |
| 766 | 708 | { |
| 767 | | sh2->ftcsr_read_callback( (sh2->m[4] & 0xffff0000) | sh2->frc ); |
| 709 | m_ftcsr_read_callback( (m_m[4] & 0xffff0000) | m_frc ); |
| 768 | 710 | } |
| 769 | 711 | } |
| 770 | | sh2_timer_resync(sh2); |
| 771 | | return (sh2->m[4] & 0xffff0000) | sh2->frc; |
| 712 | sh2_timer_resync(); |
| 713 | return (m_m[4] & 0xffff0000) | m_frc; |
| 772 | 714 | case 0x05: // OCRx, TCR, TOCR |
| 773 | | if(sh2->m[5] & 0x10) |
| 774 | | return (sh2->ocrb << 16) | (sh2->m[5] & 0xffff); |
| 715 | if(m_m[5] & 0x10) |
| 716 | return (m_ocrb << 16) | (m_m[5] & 0xffff); |
| 775 | 717 | else |
| 776 | | return (sh2->ocra << 16) | (sh2->m[5] & 0xffff); |
| 718 | return (m_ocra << 16) | (m_m[5] & 0xffff); |
| 777 | 719 | case 0x06: // ICR |
| 778 | | return sh2->icr << 16; |
| 720 | return m_icr << 16; |
| 779 | 721 | |
| 780 | 722 | case 0x20: |
| 781 | | return (((sh2->wtcsr | 0x18) & 0xff) << 24) | ((sh2->wtcnt & 0xff) << 16); |
| 723 | return (((m_wtcsr | 0x18) & 0xff) << 24) | ((m_wtcnt & 0xff) << 16); |
| 782 | 724 | |
| 783 | 725 | case 0x24: // SBYCR, CCR |
| 784 | | return sh2->m[0x24] & ~0x3000; /* bit 4-5 of CCR are always zero */ |
| 726 | return m_m[0x24] & ~0x3000; /* bit 4-5 of CCR are always zero */ |
| 785 | 727 | |
| 786 | 728 | case 0x38: // ICR, IPRA |
| 787 | | return (sh2->m[0x38] & 0x7fffffff) | (sh2->nmi_line_state == ASSERT_LINE ? 0 : 0x80000000); |
| 729 | return (m_m[0x38] & 0x7fffffff) | (m_nmi_line_state == ASSERT_LINE ? 0 : 0x80000000); |
| 788 | 730 | |
| 789 | 731 | case 0x78: // BCR1 |
| 790 | | return sh2->is_slave ? 0x00008000 : 0; |
| 732 | return m_is_slave ? 0x00008000 : 0; |
| 791 | 733 | |
| 792 | 734 | case 0x41: // dvdntl mirrors |
| 793 | 735 | case 0x47: |
| 794 | | return sh2->m[0x45]; |
| 736 | return m_m[0x45]; |
| 795 | 737 | |
| 796 | 738 | case 0x46: // dvdnth mirror |
| 797 | | return sh2->m[0x44]; |
| 739 | return m_m[0x44]; |
| 798 | 740 | } |
| 799 | | return sh2->m[offset]; |
| 741 | return m_m[offset]; |
| 800 | 742 | } |
| 801 | 743 | |
| 802 | | void sh2_set_ftcsr_read_callback(device_t *device, void (*callback)(UINT32)) |
| 744 | void sh2_device::sh2_set_ftcsr_read_callback(void (*callback)(UINT32)) |
| 803 | 745 | { |
| 804 | | sh2_state *sh2 = GET_SH2(device); |
| 805 | | sh2->ftcsr_read_callback = callback; |
| 746 | m_ftcsr_read_callback = callback; |
| 806 | 747 | } |
| 807 | 748 | |
| 808 | | void sh2_set_frt_input(device_t *device, int state) |
| 749 | void sh2_device::sh2_set_frt_input(int state) |
| 809 | 750 | { |
| 810 | | sh2_state *sh2 = GET_SH2(device); |
| 811 | | |
| 812 | 751 | if(state == PULSE_LINE) |
| 813 | 752 | { |
| 814 | | sh2_set_frt_input(device, ASSERT_LINE); |
| 815 | | sh2_set_frt_input(device, CLEAR_LINE); |
| 753 | sh2_set_frt_input(ASSERT_LINE); |
| 754 | sh2_set_frt_input(CLEAR_LINE); |
| 816 | 755 | return; |
| 817 | 756 | } |
| 818 | 757 | |
| 819 | | if(sh2->frt_input == state) { |
| 758 | if(m_frt_input == state) { |
| 820 | 759 | return; |
| 821 | 760 | } |
| 822 | 761 | |
| 823 | | sh2->frt_input = state; |
| 762 | m_frt_input = state; |
| 824 | 763 | |
| 825 | | if(sh2->m[5] & 0x8000) { |
| 764 | if(m_m[5] & 0x8000) { |
| 826 | 765 | if(state == CLEAR_LINE) { |
| 827 | 766 | return; |
| 828 | 767 | } |
| r29568 | r29569 | |
| 832 | 771 | } |
| 833 | 772 | } |
| 834 | 773 | |
| 835 | | sh2_timer_resync(sh2); |
| 836 | | sh2->icr = sh2->frc; |
| 837 | | sh2->m[4] |= ICF; |
| 838 | | //logerror("SH2.%s: ICF activated (%x)\n", sh2->device->tag(), sh2->pc & AM); |
| 839 | | sh2_recalc_irq(sh2); |
| 774 | sh2_timer_resync(); |
| 775 | m_icr = m_frc; |
| 776 | m_m[4] |= ICF; |
| 777 | //logerror("SH2.%s: ICF activated (%x)\n", tag(), m_sh2_state->pc & AM); |
| 778 | sh2_recalc_irq(); |
| 840 | 779 | } |
| 841 | 780 | |
| 842 | | void sh2_set_irq_line(sh2_state *sh2, int irqline, int state) |
| 781 | void sh2_device::sh2_recalc_irq() |
| 843 | 782 | { |
| 844 | | if (irqline == INPUT_LINE_NMI) |
| 845 | | { |
| 846 | | if (sh2->nmi_line_state == state) |
| 847 | | return; |
| 848 | | sh2->nmi_line_state = state; |
| 849 | | |
| 850 | | if( state == CLEAR_LINE ) |
| 851 | | { |
| 852 | | LOG(("SH-2 '%s' cleared nmi\n", sh2->device->tag())); |
| 853 | | } |
| 854 | | else |
| 855 | | { |
| 856 | | LOG(("SH-2 '%s' assert nmi\n", sh2->device->tag())); |
| 857 | | |
| 858 | | sh2_exception(sh2, "Set IRQ line", 16); |
| 859 | | |
| 860 | | if (sh2->isdrc) |
| 861 | | sh2->pending_nmi = 1; |
| 862 | | } |
| 863 | | } |
| 864 | | else |
| 865 | | { |
| 866 | | if (sh2->irq_line_state[irqline] == state) |
| 867 | | return; |
| 868 | | sh2->irq_line_state[irqline] = state; |
| 869 | | |
| 870 | | if( state == CLEAR_LINE ) |
| 871 | | { |
| 872 | | LOG(("SH-2 '%s' cleared irq #%d\n", sh2->device->tag(), irqline)); |
| 873 | | sh2->pending_irq &= ~(1 << irqline); |
| 874 | | } |
| 875 | | else |
| 876 | | { |
| 877 | | LOG(("SH-2 '%s' assert irq #%d\n", sh2->device->tag(), irqline)); |
| 878 | | sh2->pending_irq |= 1 << irqline; |
| 879 | | if (sh2->isdrc) |
| 880 | | { |
| 881 | | sh2->test_irq = 1; |
| 882 | | } else { |
| 883 | | if(sh2->delay) |
| 884 | | sh2->test_irq = 1; |
| 885 | | else |
| 886 | | CHECK_PENDING_IRQ("sh2_set_irq_line"); |
| 887 | | } |
| 888 | | } |
| 889 | | } |
| 890 | | } |
| 891 | | |
| 892 | | void sh2_recalc_irq(sh2_state *sh2) |
| 893 | | { |
| 894 | 783 | int irq = 0, vector = -1; |
| 895 | 784 | int level; |
| 896 | 785 | |
| 897 | 786 | // Timer irqs |
| 898 | | if((sh2->m[4]>>8) & sh2->m[4] & (ICF|OCFA|OCFB|OVF)) |
| 787 | if((m_m[4]>>8) & m_m[4] & (ICF|OCFA|OCFB|OVF)) |
| 899 | 788 | { |
| 900 | | level = (sh2->m[0x18] >> 24) & 15; |
| 789 | level = (m_m[0x18] >> 24) & 15; |
| 901 | 790 | if(level > irq) |
| 902 | 791 | { |
| 903 | | int mask = (sh2->m[4]>>8) & sh2->m[4]; |
| 792 | int mask = (m_m[4]>>8) & m_m[4]; |
| 904 | 793 | irq = level; |
| 905 | 794 | if(mask & ICF) |
| 906 | | vector = (sh2->m[0x19] >> 8) & 0x7f; |
| 795 | vector = (m_m[0x19] >> 8) & 0x7f; |
| 907 | 796 | else if(mask & (OCFA|OCFB)) |
| 908 | | vector = sh2->m[0x19] & 0x7f; |
| 797 | vector = m_m[0x19] & 0x7f; |
| 909 | 798 | else |
| 910 | | vector = (sh2->m[0x1a] >> 24) & 0x7f; |
| 799 | vector = (m_m[0x1a] >> 24) & 0x7f; |
| 911 | 800 | } |
| 912 | 801 | } |
| 913 | 802 | |
| 914 | 803 | // DMA irqs |
| 915 | | if((sh2->m[0x63] & 6) == 6 && sh2->dma_irq[0]) { |
| 916 | | level = (sh2->m[0x38] >> 8) & 15; |
| 804 | if((m_m[0x63] & 6) == 6 && m_dma_irq[0]) { |
| 805 | level = (m_m[0x38] >> 8) & 15; |
| 917 | 806 | if(level > irq) { |
| 918 | 807 | irq = level; |
| 919 | | sh2->dma_irq[0] &= ~1; |
| 920 | | vector = (sh2->m[0x68]) & 0x7f; |
| 808 | m_dma_irq[0] &= ~1; |
| 809 | vector = (m_m[0x68]) & 0x7f; |
| 921 | 810 | } |
| 922 | 811 | } |
| 923 | | else if((sh2->m[0x67] & 6) == 6 && sh2->dma_irq[1]) { |
| 924 | | level = (sh2->m[0x38] >> 8) & 15; |
| 812 | else if((m_m[0x67] & 6) == 6 && m_dma_irq[1]) { |
| 813 | level = (m_m[0x38] >> 8) & 15; |
| 925 | 814 | if(level > irq) { |
| 926 | 815 | irq = level; |
| 927 | | sh2->dma_irq[1] &= ~1; |
| 928 | | vector = (sh2->m[0x6a]) & 0x7f; |
| 816 | m_dma_irq[1] &= ~1; |
| 817 | vector = (m_m[0x6a]) & 0x7f; |
| 929 | 818 | } |
| 930 | 819 | } |
| 931 | 820 | |
| 932 | | sh2->internal_irq_level = irq; |
| 933 | | sh2->internal_irq_vector = vector; |
| 934 | | sh2->test_irq = 1; |
| 821 | m_sh2_state->internal_irq_level = irq; |
| 822 | m_internal_irq_vector = vector; |
| 823 | m_test_irq = 1; |
| 935 | 824 | } |
| 936 | 825 | |
| 937 | | void sh2_exception(sh2_state *sh2, const char *message, int irqline) |
| 826 | void sh2_device::sh2_exception(const char *message, int irqline) |
| 938 | 827 | { |
| 939 | 828 | int vector; |
| 940 | 829 | |
| 941 | 830 | if (irqline != 16) |
| 942 | 831 | { |
| 943 | | if (irqline <= ((sh2->sr >> 4) & 15)) /* If the cpu forbids this interrupt */ |
| 832 | if (irqline <= ((m_sh2_state->sr >> 4) & 15)) /* If the cpu forbids this interrupt */ |
| 944 | 833 | return; |
| 945 | 834 | |
| 946 | 835 | // if this is an sh2 internal irq, use its vector |
| 947 | | if (sh2->internal_irq_level == irqline) |
| 836 | if (m_sh2_state->internal_irq_level == irqline) |
| 948 | 837 | { |
| 949 | | vector = sh2->internal_irq_vector; |
| 838 | vector = m_internal_irq_vector; |
| 950 | 839 | /* avoid spurious irqs with this (TODO: needs a better fix) */ |
| 951 | | sh2->internal_irq_level = -1; |
| 952 | | LOG(("SH-2 '%s' exception #%d (internal vector: $%x) after [%s]\n", sh2->device->tag(), irqline, vector, message)); |
| 840 | m_sh2_state->internal_irq_level = -1; |
| 841 | LOG(("SH-2 '%s' exception #%d (internal vector: $%x) after [%s]\n", tag(), irqline, vector, message)); |
| 953 | 842 | } |
| 954 | 843 | else |
| 955 | 844 | { |
| 956 | | if(sh2->m[0x38] & 0x00010000) |
| 845 | if(m_m[0x38] & 0x00010000) |
| 957 | 846 | { |
| 958 | | vector = sh2->irq_callback(sh2->device, irqline); |
| 959 | | LOG(("SH-2 '%s' exception #%d (external vector: $%x) after [%s]\n", sh2->device->tag(), irqline, vector, message)); |
| 847 | vector = standard_irq_callback(irqline); |
| 848 | LOG(("SH-2 '%s' exception #%d (external vector: $%x) after [%s]\n", tag(), irqline, vector, message)); |
| 960 | 849 | } |
| 961 | 850 | else |
| 962 | 851 | { |
| 963 | | sh2->irq_callback(sh2->device, irqline); |
| 852 | standard_irq_callback(irqline); |
| 964 | 853 | vector = 64 + irqline/2; |
| 965 | | LOG(("SH-2 '%s' exception #%d (autovector: $%x) after [%s]\n", sh2->device->tag(), irqline, vector, message)); |
| 854 | LOG(("SH-2 '%s' exception #%d (autovector: $%x) after [%s]\n", tag(), irqline, vector, message)); |
| 966 | 855 | } |
| 967 | 856 | } |
| 968 | 857 | } |
| 969 | 858 | else |
| 970 | 859 | { |
| 971 | 860 | vector = 11; |
| 972 | | LOG(("SH-2 '%s' nmi exception (autovector: $%x) after [%s]\n", sh2->device->tag(), vector, message)); |
| 861 | LOG(("SH-2 '%s' nmi exception (autovector: $%x) after [%s]\n", tag(), vector, message)); |
| 973 | 862 | } |
| 974 | 863 | |
| 975 | | if (sh2->isdrc) |
| 864 | if (m_isdrc) |
| 976 | 865 | { |
| 977 | | sh2->evec = RL( sh2, sh2->vbr + vector * 4 ); |
| 978 | | sh2->evec &= AM; |
| 979 | | sh2->irqsr = sh2->sr; |
| 866 | m_sh2_state->evec = RL( m_sh2_state->vbr + vector * 4 ); |
| 867 | m_sh2_state->evec &= AM; |
| 868 | m_sh2_state->irqsr = m_sh2_state->sr; |
| 980 | 869 | |
| 981 | | /* set I flags in SR */ |
| 982 | | if (irqline > SH2_INT_15) |
| 983 | | sh2->sr = sh2->sr | I; |
| 984 | | else |
| 985 | | sh2->sr = (sh2->sr & ~I) | (irqline << 4); |
| 870 | /* set I flags in SR */ |
| 871 | if (irqline > SH2_INT_15) |
| 872 | m_sh2_state->sr = m_sh2_state->sr | I; |
| 873 | else |
| 874 | m_sh2_state->sr = (m_sh2_state->sr & ~I) | (irqline << 4); |
| 986 | 875 | |
| 987 | | // printf("sh2_exception [%s] irqline %x evec %x save SR %x new SR %x\n", message, irqline, sh2->evec, sh2->irqsr, sh2->sr); |
| 876 | // printf("sh2_exception [%s] irqline %x evec %x save SR %x new SR %x\n", message, irqline, m_sh2_state->evec, m_sh2_state->irqsr, m_sh2_state->sr); |
| 988 | 877 | } else { |
| 989 | | sh2->r[15] -= 4; |
| 990 | | WL( sh2, sh2->r[15], sh2->sr ); /* push SR onto stack */ |
| 991 | | sh2->r[15] -= 4; |
| 992 | | WL( sh2, sh2->r[15], sh2->pc ); /* push PC onto stack */ |
| 878 | m_sh2_state->r[15] -= 4; |
| 879 | WL( m_sh2_state->r[15], m_sh2_state->sr ); /* push SR onto stack */ |
| 880 | m_sh2_state->r[15] -= 4; |
| 881 | WL( m_sh2_state->r[15], m_sh2_state->pc ); /* push PC onto stack */ |
| 993 | 882 | |
| 994 | | /* set I flags in SR */ |
| 995 | | if (irqline > SH2_INT_15) |
| 996 | | sh2->sr = sh2->sr | I; |
| 997 | | else |
| 998 | | sh2->sr = (sh2->sr & ~I) | (irqline << 4); |
| 883 | /* set I flags in SR */ |
| 884 | if (irqline > SH2_INT_15) |
| 885 | m_sh2_state->sr = m_sh2_state->sr | I; |
| 886 | else |
| 887 | m_sh2_state->sr = (m_sh2_state->sr & ~I) | (irqline << 4); |
| 999 | 888 | |
| 1000 | | /* fetch PC */ |
| 1001 | | sh2->pc = RL( sh2, sh2->vbr + vector * 4 ); |
| 889 | /* fetch PC */ |
| 890 | m_sh2_state->pc = RL( m_sh2_state->vbr + vector * 4 ); |
| 1002 | 891 | } |
| 1003 | 892 | |
| 1004 | | if(sh2->sleep_mode == 1) { sh2->sleep_mode = 2; } |
| 893 | if(m_sh2_state->sleep_mode == 1) { m_sh2_state->sleep_mode = 2; } |
| 1005 | 894 | } |
| 1006 | 895 | |
| 1007 | | void sh2_common_init(sh2_state *sh2, legacy_cpu_device *device, device_irq_acknowledge_callback irqcallback, bool drc) |
| 1008 | | { |
| 1009 | | const sh2_cpu_core *conf = (const sh2_cpu_core *)device->static_config(); |
| 1010 | | int i; |
| 1011 | | |
| 1012 | | sh2->isdrc = drc; |
| 1013 | | sh2->timer = device->machine().scheduler().timer_alloc(FUNC(sh2_timer_callback), sh2); |
| 1014 | | sh2->timer->adjust(attotime::never); |
| 1015 | | |
| 1016 | | sh2->dma_current_active_timer[0] = device->machine().scheduler().timer_alloc(FUNC(sh2_dma_current_active_callback), sh2); |
| 1017 | | sh2->dma_current_active_timer[0]->adjust(attotime::never); |
| 1018 | | |
| 1019 | | sh2->dma_current_active_timer[1] = device->machine().scheduler().timer_alloc(FUNC(sh2_dma_current_active_callback), sh2); |
| 1020 | | sh2->dma_current_active_timer[1]->adjust(attotime::never); |
| 1021 | | |
| 1022 | | if(conf) |
| 1023 | | { |
| 1024 | | sh2->is_slave = conf->is_slave; |
| 1025 | | sh2->dma_callback_kludge = conf->dma_callback_kludge; |
| 1026 | | sh2->dma_callback_fifo_data_available = conf->dma_callback_fifo_data_available; |
| 1027 | | } |
| 1028 | | else |
| 1029 | | { |
| 1030 | | sh2->is_slave = 0; |
| 1031 | | sh2->dma_callback_kludge = NULL; |
| 1032 | | sh2->dma_callback_fifo_data_available = NULL; |
| 1033 | | |
| 1034 | | } |
| 1035 | | sh2->irq_callback = irqcallback; |
| 1036 | | sh2->device = device; |
| 1037 | | sh2->program = &device->space(AS_PROGRAM); |
| 1038 | | sh2->direct = &sh2->program->direct(); |
| 1039 | | sh2->internal = &device->space(AS_PROGRAM); |
| 1040 | | |
| 1041 | | device->save_item(NAME(sh2->pc)); |
| 1042 | | device->save_item(NAME(sh2->sr)); |
| 1043 | | device->save_item(NAME(sh2->pr)); |
| 1044 | | device->save_item(NAME(sh2->gbr)); |
| 1045 | | device->save_item(NAME(sh2->vbr)); |
| 1046 | | device->save_item(NAME(sh2->mach)); |
| 1047 | | device->save_item(NAME(sh2->macl)); |
| 1048 | | device->save_item(NAME(sh2->r)); |
| 1049 | | device->save_item(NAME(sh2->ea)); |
| 1050 | | device->save_item(NAME(sh2->delay)); |
| 1051 | | device->save_item(NAME(sh2->cpu_off)); |
| 1052 | | device->save_item(NAME(sh2->dvsr)); |
| 1053 | | device->save_item(NAME(sh2->dvdnth)); |
| 1054 | | device->save_item(NAME(sh2->dvdntl)); |
| 1055 | | device->save_item(NAME(sh2->dvcr)); |
| 1056 | | device->save_item(NAME(sh2->pending_irq)); |
| 1057 | | device->save_item(NAME(sh2->test_irq)); |
| 1058 | | device->save_item(NAME(sh2->pending_nmi)); |
| 1059 | | device->save_item(NAME(sh2->irqline)); |
| 1060 | | device->save_item(NAME(sh2->evec)); |
| 1061 | | device->save_item(NAME(sh2->irqsr)); |
| 1062 | | device->save_item(NAME(sh2->target)); |
| 1063 | | for (i = 0; i < 16; ++i) |
| 1064 | | { |
| 1065 | | device->save_item(NAME(sh2->irq_queue[i].irq_vector), i); |
| 1066 | | device->save_item(NAME(sh2->irq_queue[i].irq_priority), i); |
| 1067 | | } |
| 1068 | | device->save_item(NAME(sh2->pcfsel)); |
| 1069 | | device->save_item(NAME(sh2->maxpcfsel)); |
| 1070 | | device->save_item(NAME(sh2->pcflushes)); |
| 1071 | | device->save_item(NAME(sh2->irq_line_state)); |
| 1072 | | device->save_pointer(NAME(sh2->m), 0x200/4); |
| 1073 | | device->save_item(NAME(sh2->nmi_line_state)); |
| 1074 | | device->save_item(NAME(sh2->frc)); |
| 1075 | | device->save_item(NAME(sh2->ocra)); |
| 1076 | | device->save_item(NAME(sh2->ocrb)); |
| 1077 | | device->save_item(NAME(sh2->icr)); |
| 1078 | | device->save_item(NAME(sh2->frc_base)); |
| 1079 | | device->save_item(NAME(sh2->frt_input)); |
| 1080 | | device->save_item(NAME(sh2->internal_irq_level)); |
| 1081 | | device->save_item(NAME(sh2->internal_irq_vector)); |
| 1082 | | device->save_item(NAME(sh2->dma_timer_active)); |
| 1083 | | device->save_item(NAME(sh2->dma_irq)); |
| 1084 | | device->save_item(NAME(sh2->wtcnt)); |
| 1085 | | device->save_item(NAME(sh2->wtcsr)); |
| 1086 | | device->save_item(NAME(sh2->sleep_mode)); |
| 1087 | | } |
branches/new_menus/src/emu/cpu/sh2/sh2.c
| r29568 | r29569 | |
| 82 | 82 | |
| 83 | 83 | 20010207 Sylvain Glaize (mokona@puupuu.org) |
| 84 | 84 | |
| 85 | | - Bug fix in INLINE void MOVBM(UINT32 m, UINT32 n) (see comment) |
| 85 | - Bug fix in void MOVBM(UINT32 m, UINT32 n) (see comment) |
| 86 | 86 | - Support of full 32 bit addressing (RB, RW, RL and WB, WW, WL functions) |
| 87 | 87 | reason : when the two high bits of the address are set, access is |
| 88 | 88 | done directly in the cache data array. The SUPER KANEKO NOVA SYSTEM |
| r29568 | r29569 | |
| 110 | 110 | #include "sh2.h" |
| 111 | 111 | #include "sh2comn.h" |
| 112 | 112 | |
| 113 | | CPU_DISASSEMBLE( sh2 ); |
| 114 | 113 | |
| 114 | /*************************************************************************** |
| 115 | DEBUGGING |
| 116 | ***************************************************************************/ |
| 115 | 117 | |
| 118 | #define LOG_UML (0) // log UML assembly |
| 119 | #define LOG_NATIVE (0) // log native assembly |
| 120 | |
| 121 | #define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching |
| 122 | #define SINGLE_INSTRUCTION_MODE (0) |
| 123 | |
| 124 | #define VERBOSE 0 |
| 125 | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
| 126 | |
| 127 | /*************************************************************************** |
| 128 | CONSTANTS |
| 129 | ***************************************************************************/ |
| 130 | |
| 131 | /* size of the execution code cache */ |
| 132 | #define CACHE_SIZE (32 * 1024 * 1024) |
| 133 | |
| 134 | /* compilation boundaries -- how far back/forward does the analysis extend? */ |
| 135 | #define COMPILE_BACKWARDS_BYTES 64 |
| 136 | #define COMPILE_FORWARDS_BYTES 256 |
| 137 | #define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/2) + (COMPILE_FORWARDS_BYTES/2)) |
| 138 | #define COMPILE_MAX_SEQUENCE 64 |
| 139 | |
| 140 | |
| 141 | const device_type SH1 = &device_creator<sh1_device>; |
| 142 | const device_type SH2 = &device_creator<sh2_device>; |
| 143 | |
| 144 | |
| 145 | /*------------------------------------------------- |
| 146 | sh2_internal_a5 - read handler for |
| 147 | SH2 internal map |
| 148 | -------------------------------------------------*/ |
| 149 | |
| 150 | READ32_MEMBER(sh2_device::sh2_internal_a5) |
| 151 | { |
| 152 | return 0xa5a5a5a5; |
| 153 | } |
| 154 | |
| 155 | |
| 156 | /*------------------------------------------------- |
| 157 | sh2_internal_map - maps SH2 built-ins |
| 158 | -------------------------------------------------*/ |
| 159 | |
| 160 | static ADDRESS_MAP_START( sh2_internal_map, AS_PROGRAM, 32, sh2_device ) |
| 161 | AM_RANGE(0x40000000, 0xbfffffff) AM_READ(sh2_internal_a5) |
| 162 | AM_RANGE(0xe0000000, 0xffffffff) AM_READWRITE(sh2_internal_r, sh2_internal_w) |
| 163 | ADDRESS_MAP_END |
| 164 | |
| 165 | |
| 166 | sh2_device::sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 167 | : cpu_device(mconfig, SH2, "SH-2", tag, owner, clock, "sh2", __FILE__) |
| 168 | , m_program_config("program", ENDIANNESS_BIG, 32, 32, 0, ADDRESS_MAP_NAME(sh2_internal_map)) |
| 169 | , m_cpu_type(CPU_TYPE_SH2) |
| 170 | , m_cache(CACHE_SIZE + sizeof(internal_sh2_state)) |
| 171 | , m_drcuml(NULL) |
| 172 | // , m_drcuml(*this, m_cache, ( LOG_UML ? DRCUML_OPTION_LOG_UML : 0 ) | ( LOG_NATIVE ? DRCUML_OPTION_LOG_NATIVE : 0 ), 1, 32, 1) |
| 173 | , m_drcfe(NULL) |
| 174 | , m_drcoptions(0) |
| 175 | , m_sh2_state(NULL) |
| 176 | , m_entry(NULL) |
| 177 | , m_read8(NULL) |
| 178 | , m_write8(NULL) |
| 179 | , m_read16(NULL) |
| 180 | , m_write16(NULL) |
| 181 | , m_read32(NULL) |
| 182 | , m_write32(NULL) |
| 183 | , m_interrupt(NULL) |
| 184 | , m_nocode(NULL) |
| 185 | , m_out_of_cycles(NULL) |
| 186 | { |
| 187 | m_isdrc = mconfig.options().drc() ? true : false; |
| 188 | } |
| 189 | |
| 190 | |
| 191 | void sh2_device::device_stop() |
| 192 | { |
| 193 | /* clean up the DRC */ |
| 194 | if ( m_drcuml ) |
| 195 | { |
| 196 | auto_free(machine(), m_drcuml); |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | |
| 201 | sh2_device::sh2_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int cpu_type) |
| 202 | : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) |
| 203 | , m_program_config("program", ENDIANNESS_BIG, 32, 32, 0, ADDRESS_MAP_NAME(sh2_internal_map)) |
| 204 | , m_cpu_type(cpu_type) |
| 205 | , m_cache(CACHE_SIZE + sizeof(internal_sh2_state)) |
| 206 | , m_drcuml(NULL) |
| 207 | // , m_drcuml(*this, m_cache, ( LOG_UML ? DRCUML_OPTION_LOG_UML : 0 ) | ( LOG_NATIVE ? DRCUML_OPTION_LOG_NATIVE : 0 ), 1, 32, 1) |
| 208 | , m_drcfe(NULL) |
| 209 | , m_drcoptions(0) |
| 210 | , m_sh2_state(NULL) |
| 211 | , m_entry(NULL) |
| 212 | , m_read8(NULL) |
| 213 | , m_write8(NULL) |
| 214 | , m_read16(NULL) |
| 215 | , m_write16(NULL) |
| 216 | , m_read32(NULL) |
| 217 | , m_write32(NULL) |
| 218 | , m_interrupt(NULL) |
| 219 | , m_nocode(NULL) |
| 220 | , m_out_of_cycles(NULL) |
| 221 | { |
| 222 | m_isdrc = mconfig.options().drc() ? true : false; |
| 223 | } |
| 224 | |
| 225 | sh1_device::sh1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 226 | : sh2_device(mconfig, SH1, "SH-1", tag, owner, clock, "sh1", __FILE__, CPU_TYPE_SH1 ) |
| 227 | { |
| 228 | } |
| 229 | |
| 230 | |
| 231 | offs_t sh2_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 232 | { |
| 233 | extern CPU_DISASSEMBLE( sh2 ); |
| 234 | return CPU_DISASSEMBLE_NAME( sh2 )(this, buffer, pc, oprom, opram, options); |
| 235 | } |
| 236 | |
| 237 | |
| 238 | void sh2_device::device_config_complete() |
| 239 | { |
| 240 | // inherit a copy of the static data |
| 241 | const sh2_cpu_core *intf = reinterpret_cast<const sh2_cpu_core *>(static_config()); |
| 242 | if (intf != NULL) |
| 243 | *static_cast<sh2_cpu_core *>(this) = *intf; |
| 244 | |
| 245 | // or initialize to defaults if none provided |
| 246 | else |
| 247 | { |
| 248 | memset(&dma_callback_kludge, 0, sizeof(dma_callback_kludge)); |
| 249 | memset(&dma_callback_fifo_data_available, 0, sizeof(dma_callback_fifo_data_available)); |
| 250 | is_slave = 0; |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | |
| 116 | 255 | /* speed up delay loops, bail out of tight loops */ |
| 117 | 256 | #define BUSY_LOOP_HACKS 1 |
| 118 | 257 | |
| r29568 | r29569 | |
| 120 | 259 | |
| 121 | 260 | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
| 122 | 261 | |
| 123 | | INLINE sh2_state *get_safe_token(device_t *device) |
| 124 | | { |
| 125 | | assert(device != NULL); |
| 126 | | assert(device->type() == SH1_INT || |
| 127 | | device->type() == SH2_INT); |
| 128 | | return (sh2_state *)downcast<legacy_cpu_device *>(device)->token(); |
| 129 | | } |
| 130 | 262 | |
| 131 | | INLINE UINT8 RB(sh2_state *sh2, offs_t A) |
| 263 | UINT8 sh2_device::RB(offs_t A) |
| 132 | 264 | { |
| 133 | 265 | if (A >= 0xe0000000) |
| 134 | | return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xff << (((~A) & 3)*8)) >> (((~A) & 3)*8); |
| 266 | return sh2_internal_r(*m_internal, (A & 0x1fc)>>2, 0xff << (((~A) & 3)*8)) >> (((~A) & 3)*8); |
| 135 | 267 | |
| 136 | 268 | if (A >= 0xc0000000) |
| 137 | | return sh2->program->read_byte(A); |
| 269 | return m_program->read_byte(A); |
| 138 | 270 | |
| 139 | 271 | if (A >= 0x40000000) |
| 140 | 272 | return 0xa5; |
| 141 | 273 | |
| 142 | | return sh2->program->read_byte(A & AM); |
| 274 | return m_program->read_byte(A & AM); |
| 143 | 275 | } |
| 144 | 276 | |
| 145 | | INLINE UINT16 RW(sh2_state *sh2, offs_t A) |
| 277 | UINT16 sh2_device::RW(offs_t A) |
| 146 | 278 | { |
| 147 | 279 | if (A >= 0xe0000000) |
| 148 | | return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8); |
| 280 | return sh2_internal_r(*m_internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8); |
| 149 | 281 | |
| 150 | 282 | if (A >= 0xc0000000) |
| 151 | | return sh2->program->read_word(A); |
| 283 | return m_program->read_word(A); |
| 152 | 284 | |
| 153 | 285 | if (A >= 0x40000000) |
| 154 | 286 | return 0xa5a5; |
| 155 | 287 | |
| 156 | | return sh2->program->read_word(A & AM); |
| 288 | return m_program->read_word(A & AM); |
| 157 | 289 | } |
| 158 | 290 | |
| 159 | | INLINE UINT32 RL(sh2_state *sh2, offs_t A) |
| 291 | UINT32 sh2_device::RL(offs_t A) |
| 160 | 292 | { |
| 161 | | if (A >= 0xe0000000) |
| 162 | | return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffffffff); |
| 293 | if (A >= 0xe0000000) /* I/O */ |
| 294 | return sh2_internal_r(*m_internal, (A & 0x1fc)>>2, 0xffffffff); |
| 163 | 295 | |
| 164 | | if (A >= 0xc0000000) |
| 165 | | return sh2->program->read_dword(A); |
| 296 | if (A >= 0xc0000000) /* Cache Data Array */ |
| 297 | return m_program->read_dword(A); |
| 166 | 298 | |
| 167 | | if (A >= 0x40000000) |
| 299 | if (A >= 0x40000000) /* Cache Associative Purge Area */ |
| 168 | 300 | return 0xa5a5a5a5; |
| 169 | 301 | |
| 170 | | return sh2->program->read_dword(A & AM); |
| 302 | /* 0x20000000 no Cache */ |
| 303 | /* 0x00000000 read thru Cache if CE bit is 1 */ |
| 304 | return m_program->read_dword(A & AM); |
| 171 | 305 | } |
| 172 | 306 | |
| 173 | | INLINE void WB(sh2_state *sh2, offs_t A, UINT8 V) |
| 307 | void sh2_device::WB(offs_t A, UINT8 V) |
| 174 | 308 | { |
| 175 | 309 | if (A >= 0xe0000000) |
| 176 | 310 | { |
| 177 | | sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V << (((~A) & 3)*8), 0xff << (((~A) & 3)*8)); |
| 311 | sh2_internal_w(*m_internal, (A & 0x1fc)>>2, V << (((~A) & 3)*8), 0xff << (((~A) & 3)*8)); |
| 178 | 312 | return; |
| 179 | 313 | } |
| 180 | 314 | |
| 181 | 315 | if (A >= 0xc0000000) |
| 182 | 316 | { |
| 183 | | sh2->program->write_byte(A,V); |
| 317 | m_program->write_byte(A,V); |
| 184 | 318 | return; |
| 185 | 319 | } |
| 186 | 320 | |
| 187 | 321 | if (A >= 0x40000000) |
| 188 | 322 | return; |
| 189 | 323 | |
| 190 | | sh2->program->write_byte(A & AM,V); |
| 324 | m_program->write_byte(A & AM,V); |
| 191 | 325 | } |
| 192 | 326 | |
| 193 | | INLINE void WW(sh2_state *sh2, offs_t A, UINT16 V) |
| 327 | void sh2_device::WW(offs_t A, UINT16 V) |
| 194 | 328 | { |
| 195 | 329 | if (A >= 0xe0000000) |
| 196 | 330 | { |
| 197 | | sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V << (((~A) & 2)*8), 0xffff << (((~A) & 2)*8)); |
| 331 | sh2_internal_w(*m_internal, (A & 0x1fc)>>2, V << (((~A) & 2)*8), 0xffff << (((~A) & 2)*8)); |
| 198 | 332 | return; |
| 199 | 333 | } |
| 200 | 334 | |
| 201 | 335 | if (A >= 0xc0000000) |
| 202 | 336 | { |
| 203 | | sh2->program->write_word(A,V); |
| 337 | m_program->write_word(A,V); |
| 204 | 338 | return; |
| 205 | 339 | } |
| 206 | 340 | |
| 207 | 341 | if (A >= 0x40000000) |
| 208 | 342 | return; |
| 209 | 343 | |
| 210 | | sh2->program->write_word(A & AM,V); |
| 344 | m_program->write_word(A & AM,V); |
| 211 | 345 | } |
| 212 | 346 | |
| 213 | | INLINE void WL(sh2_state *sh2, offs_t A, UINT32 V) |
| 347 | void sh2_device::WL(offs_t A, UINT32 V) |
| 214 | 348 | { |
| 215 | | if (A >= 0xe0000000) |
| 349 | if (A >= 0xe0000000) /* I/O */ |
| 216 | 350 | { |
| 217 | | sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V, 0xffffffff); |
| 351 | sh2_internal_w(*m_internal, (A & 0x1fc)>>2, V, 0xffffffff); |
| 218 | 352 | return; |
| 219 | 353 | } |
| 220 | 354 | |
| 221 | | if (A >= 0xc0000000) |
| 355 | if (A >= 0xc0000000) /* Cache Data Array */ |
| 222 | 356 | { |
| 223 | | sh2->program->write_dword(A,V); |
| 357 | m_program->write_dword(A,V); |
| 224 | 358 | return; |
| 225 | 359 | } |
| 226 | 360 | |
| 227 | | if (A >= 0x40000000) |
| 361 | /* 0x60000000 Cache Address Data Array */ |
| 362 | |
| 363 | if (A >= 0x40000000) /* Cache Associative Purge Area */ |
| 228 | 364 | return; |
| 229 | 365 | |
| 230 | | sh2->program->write_dword(A & AM,V); |
| 366 | /* 0x20000000 no Cache */ |
| 367 | /* 0x00000000 read thru Cache if CE bit is 1 */ |
| 368 | m_program->write_dword(A & AM,V); |
| 231 | 369 | } |
| 232 | 370 | |
| 233 | 371 | /* code cycles t-bit |
| 234 | 372 | * 0011 nnnn mmmm 1100 1 - |
| 235 | 373 | * ADD Rm,Rn |
| 236 | 374 | */ |
| 237 | | INLINE void ADD(sh2_state *sh2, UINT32 m, UINT32 n) |
| 375 | void sh2_device::ADD(UINT32 m, UINT32 n) |
| 238 | 376 | { |
| 239 | | sh2->r[n] += sh2->r[m]; |
| 377 | m_sh2_state->r[n] += m_sh2_state->r[m]; |
| 240 | 378 | } |
| 241 | 379 | |
| 242 | 380 | /* code cycles t-bit |
| 243 | 381 | * 0111 nnnn iiii iiii 1 - |
| 244 | 382 | * ADD #imm,Rn |
| 245 | 383 | */ |
| 246 | | INLINE void ADDI(sh2_state *sh2, UINT32 i, UINT32 n) |
| 384 | void sh2_device::ADDI(UINT32 i, UINT32 n) |
| 247 | 385 | { |
| 248 | | sh2->r[n] += (INT32)(INT16)(INT8)i; |
| 386 | m_sh2_state->r[n] += (INT32)(INT16)(INT8)i; |
| 249 | 387 | } |
| 250 | 388 | |
| 251 | 389 | /* code cycles t-bit |
| 252 | 390 | * 0011 nnnn mmmm 1110 1 carry |
| 253 | 391 | * ADDC Rm,Rn |
| 254 | 392 | */ |
| 255 | | INLINE void ADDC(sh2_state *sh2, UINT32 m, UINT32 n) |
| 393 | void sh2_device::ADDC(UINT32 m, UINT32 n) |
| 256 | 394 | { |
| 257 | 395 | UINT32 tmp0, tmp1; |
| 258 | 396 | |
| 259 | | tmp1 = sh2->r[n] + sh2->r[m]; |
| 260 | | tmp0 = sh2->r[n]; |
| 261 | | sh2->r[n] = tmp1 + (sh2->sr & T); |
| 397 | tmp1 = m_sh2_state->r[n] + m_sh2_state->r[m]; |
| 398 | tmp0 = m_sh2_state->r[n]; |
| 399 | m_sh2_state->r[n] = tmp1 + (m_sh2_state->sr & T); |
| 262 | 400 | if (tmp0 > tmp1) |
| 263 | | sh2->sr |= T; |
| 401 | m_sh2_state->sr |= T; |
| 264 | 402 | else |
| 265 | | sh2->sr &= ~T; |
| 266 | | if (tmp1 > sh2->r[n]) |
| 267 | | sh2->sr |= T; |
| 403 | m_sh2_state->sr &= ~T; |
| 404 | if (tmp1 > m_sh2_state->r[n]) |
| 405 | m_sh2_state->sr |= T; |
| 268 | 406 | } |
| 269 | 407 | |
| 270 | 408 | /* code cycles t-bit |
| 271 | 409 | * 0011 nnnn mmmm 1111 1 overflow |
| 272 | 410 | * ADDV Rm,Rn |
| 273 | 411 | */ |
| 274 | | INLINE void ADDV(sh2_state *sh2, UINT32 m, UINT32 n) |
| 412 | void sh2_device::ADDV(UINT32 m, UINT32 n) |
| 275 | 413 | { |
| 276 | 414 | INT32 dest, src, ans; |
| 277 | 415 | |
| 278 | | if ((INT32) sh2->r[n] >= 0) |
| 416 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 279 | 417 | dest = 0; |
| 280 | 418 | else |
| 281 | 419 | dest = 1; |
| 282 | | if ((INT32) sh2->r[m] >= 0) |
| 420 | if ((INT32) m_sh2_state->r[m] >= 0) |
| 283 | 421 | src = 0; |
| 284 | 422 | else |
| 285 | 423 | src = 1; |
| 286 | 424 | src += dest; |
| 287 | | sh2->r[n] += sh2->r[m]; |
| 288 | | if ((INT32) sh2->r[n] >= 0) |
| 425 | m_sh2_state->r[n] += m_sh2_state->r[m]; |
| 426 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 289 | 427 | ans = 0; |
| 290 | 428 | else |
| 291 | 429 | ans = 1; |
| r29568 | r29569 | |
| 293 | 431 | if (src == 0 || src == 2) |
| 294 | 432 | { |
| 295 | 433 | if (ans == 1) |
| 296 | | sh2->sr |= T; |
| 434 | m_sh2_state->sr |= T; |
| 297 | 435 | else |
| 298 | | sh2->sr &= ~T; |
| 436 | m_sh2_state->sr &= ~T; |
| 299 | 437 | } |
| 300 | 438 | else |
| 301 | | sh2->sr &= ~T; |
| 439 | m_sh2_state->sr &= ~T; |
| 302 | 440 | } |
| 303 | 441 | |
| 304 | 442 | /* code cycles t-bit |
| 305 | 443 | * 0010 nnnn mmmm 1001 1 - |
| 306 | 444 | * AND Rm,Rn |
| 307 | 445 | */ |
| 308 | | INLINE void AND(sh2_state *sh2, UINT32 m, UINT32 n) |
| 446 | void sh2_device::AND(UINT32 m, UINT32 n) |
| 309 | 447 | { |
| 310 | | sh2->r[n] &= sh2->r[m]; |
| 448 | m_sh2_state->r[n] &= m_sh2_state->r[m]; |
| 311 | 449 | } |
| 312 | 450 | |
| 313 | 451 | |
| r29568 | r29569 | |
| 315 | 453 | * 1100 1001 iiii iiii 1 - |
| 316 | 454 | * AND #imm,R0 |
| 317 | 455 | */ |
| 318 | | INLINE void ANDI(sh2_state *sh2, UINT32 i) |
| 456 | void sh2_device::ANDI(UINT32 i) |
| 319 | 457 | { |
| 320 | | sh2->r[0] &= i; |
| 458 | m_sh2_state->r[0] &= i; |
| 321 | 459 | } |
| 322 | 460 | |
| 323 | 461 | /* code cycles t-bit |
| 324 | 462 | * 1100 1101 iiii iiii 1 - |
| 325 | 463 | * AND.B #imm,@(R0,GBR) |
| 326 | 464 | */ |
| 327 | | INLINE void ANDM(sh2_state *sh2, UINT32 i) |
| 465 | void sh2_device::ANDM(UINT32 i) |
| 328 | 466 | { |
| 329 | 467 | UINT32 temp; |
| 330 | 468 | |
| 331 | | sh2->ea = sh2->gbr + sh2->r[0]; |
| 332 | | temp = i & RB( sh2, sh2->ea ); |
| 333 | | WB( sh2, sh2->ea, temp ); |
| 334 | | sh2->icount -= 2; |
| 469 | m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; |
| 470 | temp = i & RB( m_sh2_state->ea ); |
| 471 | WB( m_sh2_state->ea, temp ); |
| 472 | m_sh2_state->icount -= 2; |
| 335 | 473 | } |
| 336 | 474 | |
| 337 | 475 | /* code cycles t-bit |
| 338 | 476 | * 1000 1011 dddd dddd 3/1 - |
| 339 | 477 | * BF disp8 |
| 340 | 478 | */ |
| 341 | | INLINE void BF(sh2_state *sh2, UINT32 d) |
| 479 | void sh2_device::BF(UINT32 d) |
| 342 | 480 | { |
| 343 | | if ((sh2->sr & T) == 0) |
| 481 | if ((m_sh2_state->sr & T) == 0) |
| 344 | 482 | { |
| 345 | 483 | INT32 disp = ((INT32)d << 24) >> 24; |
| 346 | | sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; |
| 347 | | sh2->icount -= 2; |
| 484 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; |
| 485 | m_sh2_state->icount -= 2; |
| 348 | 486 | } |
| 349 | 487 | } |
| 350 | 488 | |
| r29568 | r29569 | |
| 352 | 490 | * 1000 1111 dddd dddd 3/1 - |
| 353 | 491 | * BFS disp8 |
| 354 | 492 | */ |
| 355 | | INLINE void BFS(sh2_state *sh2, UINT32 d) |
| 493 | void sh2_device::BFS(UINT32 d) |
| 356 | 494 | { |
| 357 | | if ((sh2->sr & T) == 0) |
| 495 | if ((m_sh2_state->sr & T) == 0) |
| 358 | 496 | { |
| 359 | 497 | INT32 disp = ((INT32)d << 24) >> 24; |
| 360 | | sh2->delay = sh2->pc; |
| 361 | | sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; |
| 362 | | sh2->icount--; |
| 498 | m_delay = m_sh2_state->pc; |
| 499 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; |
| 500 | m_sh2_state->icount--; |
| 363 | 501 | } |
| 364 | 502 | } |
| 365 | 503 | |
| r29568 | r29569 | |
| 367 | 505 | * 1010 dddd dddd dddd 2 - |
| 368 | 506 | * BRA disp12 |
| 369 | 507 | */ |
| 370 | | INLINE void BRA(sh2_state *sh2, UINT32 d) |
| 508 | void sh2_device::BRA(UINT32 d) |
| 371 | 509 | { |
| 372 | 510 | INT32 disp = ((INT32)d << 20) >> 20; |
| 373 | 511 | |
| 374 | 512 | #if BUSY_LOOP_HACKS |
| 375 | 513 | if (disp == -2) |
| 376 | 514 | { |
| 377 | | UINT32 next_opcode = RW( sh2, sh2->ppc & AM ); |
| 515 | UINT32 next_opcode = RW( m_sh2_state->ppc & AM ); |
| 378 | 516 | /* BRA $ |
| 379 | 517 | * NOP |
| 380 | 518 | */ |
| 381 | 519 | if (next_opcode == 0x0009) |
| 382 | | sh2->icount %= 3; /* cycles for BRA $ and NOP taken (3) */ |
| 520 | m_sh2_state->icount %= 3; /* cycles for BRA $ and NOP taken (3) */ |
| 383 | 521 | } |
| 384 | 522 | #endif |
| 385 | | sh2->delay = sh2->pc; |
| 386 | | sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; |
| 387 | | sh2->icount--; |
| 523 | m_delay = m_sh2_state->pc; |
| 524 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; |
| 525 | m_sh2_state->icount--; |
| 388 | 526 | } |
| 389 | 527 | |
| 390 | 528 | /* code cycles t-bit |
| 391 | 529 | * 0000 mmmm 0010 0011 2 - |
| 392 | 530 | * BRAF Rm |
| 393 | 531 | */ |
| 394 | | INLINE void BRAF(sh2_state *sh2, UINT32 m) |
| 532 | void sh2_device::BRAF(UINT32 m) |
| 395 | 533 | { |
| 396 | | sh2->delay = sh2->pc; |
| 397 | | sh2->pc += sh2->r[m] + 2; |
| 398 | | sh2->icount--; |
| 534 | m_delay = m_sh2_state->pc; |
| 535 | m_sh2_state->pc += m_sh2_state->r[m] + 2; |
| 536 | m_sh2_state->icount--; |
| 399 | 537 | } |
| 400 | 538 | |
| 401 | 539 | /* code cycles t-bit |
| 402 | 540 | * 1011 dddd dddd dddd 2 - |
| 403 | 541 | * BSR disp12 |
| 404 | 542 | */ |
| 405 | | INLINE void BSR(sh2_state *sh2, UINT32 d) |
| 543 | void sh2_device::BSR(UINT32 d) |
| 406 | 544 | { |
| 407 | 545 | INT32 disp = ((INT32)d << 20) >> 20; |
| 408 | 546 | |
| 409 | | sh2->pr = sh2->pc + 2; |
| 410 | | sh2->delay = sh2->pc; |
| 411 | | sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; |
| 412 | | sh2->icount--; |
| 547 | m_sh2_state->pr = m_sh2_state->pc + 2; |
| 548 | m_delay = m_sh2_state->pc; |
| 549 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; |
| 550 | m_sh2_state->icount--; |
| 413 | 551 | } |
| 414 | 552 | |
| 415 | 553 | /* code cycles t-bit |
| 416 | 554 | * 0000 mmmm 0000 0011 2 - |
| 417 | 555 | * BSRF Rm |
| 418 | 556 | */ |
| 419 | | INLINE void BSRF(sh2_state *sh2, UINT32 m) |
| 557 | void sh2_device::BSRF(UINT32 m) |
| 420 | 558 | { |
| 421 | | sh2->pr = sh2->pc + 2; |
| 422 | | sh2->delay = sh2->pc; |
| 423 | | sh2->pc += sh2->r[m] + 2; |
| 424 | | sh2->icount--; |
| 559 | m_sh2_state->pr = m_sh2_state->pc + 2; |
| 560 | m_delay = m_sh2_state->pc; |
| 561 | m_sh2_state->pc += m_sh2_state->r[m] + 2; |
| 562 | m_sh2_state->icount--; |
| 425 | 563 | } |
| 426 | 564 | |
| 427 | 565 | /* code cycles t-bit |
| 428 | 566 | * 1000 1001 dddd dddd 3/1 - |
| 429 | 567 | * BT disp8 |
| 430 | 568 | */ |
| 431 | | INLINE void BT(sh2_state *sh2, UINT32 d) |
| 569 | void sh2_device::BT(UINT32 d) |
| 432 | 570 | { |
| 433 | | if ((sh2->sr & T) != 0) |
| 571 | if ((m_sh2_state->sr & T) != 0) |
| 434 | 572 | { |
| 435 | 573 | INT32 disp = ((INT32)d << 24) >> 24; |
| 436 | | sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; |
| 437 | | sh2->icount -= 2; |
| 574 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; |
| 575 | m_sh2_state->icount -= 2; |
| 438 | 576 | } |
| 439 | 577 | } |
| 440 | 578 | |
| r29568 | r29569 | |
| 442 | 580 | * 1000 1101 dddd dddd 2/1 - |
| 443 | 581 | * BTS disp8 |
| 444 | 582 | */ |
| 445 | | INLINE void BTS(sh2_state *sh2, UINT32 d) |
| 583 | void sh2_device::BTS(UINT32 d) |
| 446 | 584 | { |
| 447 | | if ((sh2->sr & T) != 0) |
| 585 | if ((m_sh2_state->sr & T) != 0) |
| 448 | 586 | { |
| 449 | 587 | INT32 disp = ((INT32)d << 24) >> 24; |
| 450 | | sh2->delay = sh2->pc; |
| 451 | | sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; |
| 452 | | sh2->icount--; |
| 588 | m_delay = m_sh2_state->pc; |
| 589 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; |
| 590 | m_sh2_state->icount--; |
| 453 | 591 | } |
| 454 | 592 | } |
| 455 | 593 | |
| r29568 | r29569 | |
| 457 | 595 | * 0000 0000 0010 1000 1 - |
| 458 | 596 | * CLRMAC |
| 459 | 597 | */ |
| 460 | | INLINE void CLRMAC(sh2_state *sh2) |
| 598 | void sh2_device::CLRMAC() |
| 461 | 599 | { |
| 462 | | sh2->mach = 0; |
| 463 | | sh2->macl = 0; |
| 600 | m_sh2_state->mach = 0; |
| 601 | m_sh2_state->macl = 0; |
| 464 | 602 | } |
| 465 | 603 | |
| 466 | 604 | /* code cycles t-bit |
| 467 | 605 | * 0000 0000 0000 1000 1 - |
| 468 | 606 | * CLRT |
| 469 | 607 | */ |
| 470 | | INLINE void CLRT(sh2_state *sh2) |
| 608 | void sh2_device::CLRT() |
| 471 | 609 | { |
| 472 | | sh2->sr &= ~T; |
| 610 | m_sh2_state->sr &= ~T; |
| 473 | 611 | } |
| 474 | 612 | |
| 475 | 613 | /* code cycles t-bit |
| 476 | 614 | * 0011 nnnn mmmm 0000 1 comparison result |
| 477 | 615 | * CMP_EQ Rm,Rn |
| 478 | 616 | */ |
| 479 | | INLINE void CMPEQ(sh2_state *sh2, UINT32 m, UINT32 n) |
| 617 | void sh2_device::CMPEQ(UINT32 m, UINT32 n) |
| 480 | 618 | { |
| 481 | | if (sh2->r[n] == sh2->r[m]) |
| 482 | | sh2->sr |= T; |
| 619 | if (m_sh2_state->r[n] == m_sh2_state->r[m]) |
| 620 | m_sh2_state->sr |= T; |
| 483 | 621 | else |
| 484 | | sh2->sr &= ~T; |
| 622 | m_sh2_state->sr &= ~T; |
| 485 | 623 | } |
| 486 | 624 | |
| 487 | 625 | /* code cycles t-bit |
| 488 | 626 | * 0011 nnnn mmmm 0011 1 comparison result |
| 489 | 627 | * CMP_GE Rm,Rn |
| 490 | 628 | */ |
| 491 | | INLINE void CMPGE(sh2_state *sh2, UINT32 m, UINT32 n) |
| 629 | void sh2_device::CMPGE(UINT32 m, UINT32 n) |
| 492 | 630 | { |
| 493 | | if ((INT32) sh2->r[n] >= (INT32) sh2->r[m]) |
| 494 | | sh2->sr |= T; |
| 631 | if ((INT32) m_sh2_state->r[n] >= (INT32) m_sh2_state->r[m]) |
| 632 | m_sh2_state->sr |= T; |
| 495 | 633 | else |
| 496 | | sh2->sr &= ~T; |
| 634 | m_sh2_state->sr &= ~T; |
| 497 | 635 | } |
| 498 | 636 | |
| 499 | 637 | /* code cycles t-bit |
| 500 | 638 | * 0011 nnnn mmmm 0111 1 comparison result |
| 501 | 639 | * CMP_GT Rm,Rn |
| 502 | 640 | */ |
| 503 | | INLINE void CMPGT(sh2_state *sh2, UINT32 m, UINT32 n) |
| 641 | void sh2_device::CMPGT(UINT32 m, UINT32 n) |
| 504 | 642 | { |
| 505 | | if ((INT32) sh2->r[n] > (INT32) sh2->r[m]) |
| 506 | | sh2->sr |= T; |
| 643 | if ((INT32) m_sh2_state->r[n] > (INT32) m_sh2_state->r[m]) |
| 644 | m_sh2_state->sr |= T; |
| 507 | 645 | else |
| 508 | | sh2->sr &= ~T; |
| 646 | m_sh2_state->sr &= ~T; |
| 509 | 647 | } |
| 510 | 648 | |
| 511 | 649 | /* code cycles t-bit |
| 512 | 650 | * 0011 nnnn mmmm 0110 1 comparison result |
| 513 | 651 | * CMP_HI Rm,Rn |
| 514 | 652 | */ |
| 515 | | INLINE void CMPHI(sh2_state *sh2, UINT32 m, UINT32 n) |
| 653 | void sh2_device::CMPHI(UINT32 m, UINT32 n) |
| 516 | 654 | { |
| 517 | | if ((UINT32) sh2->r[n] > (UINT32) sh2->r[m]) |
| 518 | | sh2->sr |= T; |
| 655 | if ((UINT32) m_sh2_state->r[n] > (UINT32) m_sh2_state->r[m]) |
| 656 | m_sh2_state->sr |= T; |
| 519 | 657 | else |
| 520 | | sh2->sr &= ~T; |
| 658 | m_sh2_state->sr &= ~T; |
| 521 | 659 | } |
| 522 | 660 | |
| 523 | 661 | /* code cycles t-bit |
| 524 | 662 | * 0011 nnnn mmmm 0010 1 comparison result |
| 525 | 663 | * CMP_HS Rm,Rn |
| 526 | 664 | */ |
| 527 | | INLINE void CMPHS(sh2_state *sh2, UINT32 m, UINT32 n) |
| 665 | void sh2_device::CMPHS(UINT32 m, UINT32 n) |
| 528 | 666 | { |
| 529 | | if ((UINT32) sh2->r[n] >= (UINT32) sh2->r[m]) |
| 530 | | sh2->sr |= T; |
| 667 | if ((UINT32) m_sh2_state->r[n] >= (UINT32) m_sh2_state->r[m]) |
| 668 | m_sh2_state->sr |= T; |
| 531 | 669 | else |
| 532 | | sh2->sr &= ~T; |
| 670 | m_sh2_state->sr &= ~T; |
| 533 | 671 | } |
| 534 | 672 | |
| 535 | 673 | |
| r29568 | r29569 | |
| 537 | 675 | * 0100 nnnn 0001 0101 1 comparison result |
| 538 | 676 | * CMP_PL Rn |
| 539 | 677 | */ |
| 540 | | INLINE void CMPPL(sh2_state *sh2, UINT32 n) |
| 678 | void sh2_device::CMPPL(UINT32 n) |
| 541 | 679 | { |
| 542 | | if ((INT32) sh2->r[n] > 0) |
| 543 | | sh2->sr |= T; |
| 680 | if ((INT32) m_sh2_state->r[n] > 0) |
| 681 | m_sh2_state->sr |= T; |
| 544 | 682 | else |
| 545 | | sh2->sr &= ~T; |
| 683 | m_sh2_state->sr &= ~T; |
| 546 | 684 | } |
| 547 | 685 | |
| 548 | 686 | /* code cycles t-bit |
| 549 | 687 | * 0100 nnnn 0001 0001 1 comparison result |
| 550 | 688 | * CMP_PZ Rn |
| 551 | 689 | */ |
| 552 | | INLINE void CMPPZ(sh2_state *sh2, UINT32 n) |
| 690 | void sh2_device::CMPPZ(UINT32 n) |
| 553 | 691 | { |
| 554 | | if ((INT32) sh2->r[n] >= 0) |
| 555 | | sh2->sr |= T; |
| 692 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 693 | m_sh2_state->sr |= T; |
| 556 | 694 | else |
| 557 | | sh2->sr &= ~T; |
| 695 | m_sh2_state->sr &= ~T; |
| 558 | 696 | } |
| 559 | 697 | |
| 560 | 698 | /* code cycles t-bit |
| 561 | 699 | * 0010 nnnn mmmm 1100 1 comparison result |
| 562 | 700 | * CMP_STR Rm,Rn |
| 563 | 701 | */ |
| 564 | | INLINE void CMPSTR(sh2_state *sh2, UINT32 m, UINT32 n) |
| 702 | void sh2_device::CMPSTR(UINT32 m, UINT32 n) |
| 565 | 703 | { |
| 566 | 704 | UINT32 temp; |
| 567 | 705 | INT32 HH, HL, LH, LL; |
| 568 | | temp = sh2->r[n] ^ sh2->r[m]; |
| 706 | temp = m_sh2_state->r[n] ^ m_sh2_state->r[m]; |
| 569 | 707 | HH = (temp >> 24) & 0xff; |
| 570 | 708 | HL = (temp >> 16) & 0xff; |
| 571 | 709 | LH = (temp >> 8) & 0xff; |
| 572 | 710 | LL = temp & 0xff; |
| 573 | 711 | if (HH && HL && LH && LL) |
| 574 | | sh2->sr &= ~T; |
| 712 | m_sh2_state->sr &= ~T; |
| 575 | 713 | else |
| 576 | | sh2->sr |= T; |
| 714 | m_sh2_state->sr |= T; |
| 577 | 715 | } |
| 578 | 716 | |
| 579 | 717 | |
| r29568 | r29569 | |
| 581 | 719 | * 1000 1000 iiii iiii 1 comparison result |
| 582 | 720 | * CMP/EQ #imm,R0 |
| 583 | 721 | */ |
| 584 | | INLINE void CMPIM(sh2_state *sh2, UINT32 i) |
| 722 | void sh2_device::CMPIM(UINT32 i) |
| 585 | 723 | { |
| 586 | 724 | UINT32 imm = (UINT32)(INT32)(INT16)(INT8)i; |
| 587 | 725 | |
| 588 | | if (sh2->r[0] == imm) |
| 589 | | sh2->sr |= T; |
| 726 | if (m_sh2_state->r[0] == imm) |
| 727 | m_sh2_state->sr |= T; |
| 590 | 728 | else |
| 591 | | sh2->sr &= ~T; |
| 729 | m_sh2_state->sr &= ~T; |
| 592 | 730 | } |
| 593 | 731 | |
| 594 | 732 | /* code cycles t-bit |
| 595 | 733 | * 0010 nnnn mmmm 0111 1 calculation result |
| 596 | 734 | * DIV0S Rm,Rn |
| 597 | 735 | */ |
| 598 | | INLINE void DIV0S(sh2_state *sh2, UINT32 m, UINT32 n) |
| 736 | void sh2_device::DIV0S(UINT32 m, UINT32 n) |
| 599 | 737 | { |
| 600 | | if ((sh2->r[n] & 0x80000000) == 0) |
| 601 | | sh2->sr &= ~Q; |
| 738 | if ((m_sh2_state->r[n] & 0x80000000) == 0) |
| 739 | m_sh2_state->sr &= ~Q; |
| 602 | 740 | else |
| 603 | | sh2->sr |= Q; |
| 604 | | if ((sh2->r[m] & 0x80000000) == 0) |
| 605 | | sh2->sr &= ~M; |
| 741 | m_sh2_state->sr |= Q; |
| 742 | if ((m_sh2_state->r[m] & 0x80000000) == 0) |
| 743 | m_sh2_state->sr &= ~M; |
| 606 | 744 | else |
| 607 | | sh2->sr |= M; |
| 608 | | if ((sh2->r[m] ^ sh2->r[n]) & 0x80000000) |
| 609 | | sh2->sr |= T; |
| 745 | m_sh2_state->sr |= M; |
| 746 | if ((m_sh2_state->r[m] ^ m_sh2_state->r[n]) & 0x80000000) |
| 747 | m_sh2_state->sr |= T; |
| 610 | 748 | else |
| 611 | | sh2->sr &= ~T; |
| 749 | m_sh2_state->sr &= ~T; |
| 612 | 750 | } |
| 613 | 751 | |
| 614 | 752 | /* code cycles t-bit |
| 615 | 753 | * 0000 0000 0001 1001 1 0 |
| 616 | 754 | * DIV0U |
| 617 | 755 | */ |
| 618 | | INLINE void DIV0U(sh2_state *sh2) |
| 756 | void sh2_device::DIV0U() |
| 619 | 757 | { |
| 620 | | sh2->sr &= ~(M | Q | T); |
| 758 | m_sh2_state->sr &= ~(M | Q | T); |
| 621 | 759 | } |
| 622 | 760 | |
| 623 | 761 | /* code cycles t-bit |
| 624 | 762 | * 0011 nnnn mmmm 0100 1 calculation result |
| 625 | 763 | * DIV1 Rm,Rn |
| 626 | 764 | */ |
| 627 | | INLINE void DIV1(sh2_state *sh2, UINT32 m, UINT32 n) |
| 765 | void sh2_device::DIV1(UINT32 m, UINT32 n) |
| 628 | 766 | { |
| 629 | 767 | UINT32 tmp0; |
| 630 | 768 | UINT32 old_q; |
| 631 | 769 | |
| 632 | | old_q = sh2->sr & Q; |
| 633 | | if (0x80000000 & sh2->r[n]) |
| 634 | | sh2->sr |= Q; |
| 770 | old_q = m_sh2_state->sr & Q; |
| 771 | if (0x80000000 & m_sh2_state->r[n]) |
| 772 | m_sh2_state->sr |= Q; |
| 635 | 773 | else |
| 636 | | sh2->sr &= ~Q; |
| 774 | m_sh2_state->sr &= ~Q; |
| 637 | 775 | |
| 638 | | sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T); |
| 776 | m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); |
| 639 | 777 | |
| 640 | 778 | if (!old_q) |
| 641 | 779 | { |
| 642 | | if (!(sh2->sr & M)) |
| 780 | if (!(m_sh2_state->sr & M)) |
| 643 | 781 | { |
| 644 | | tmp0 = sh2->r[n]; |
| 645 | | sh2->r[n] -= sh2->r[m]; |
| 646 | | if(!(sh2->sr & Q)) |
| 647 | | if(sh2->r[n] > tmp0) |
| 648 | | sh2->sr |= Q; |
| 782 | tmp0 = m_sh2_state->r[n]; |
| 783 | m_sh2_state->r[n] -= m_sh2_state->r[m]; |
| 784 | if(!(m_sh2_state->sr & Q)) |
| 785 | if(m_sh2_state->r[n] > tmp0) |
| 786 | m_sh2_state->sr |= Q; |
| 649 | 787 | else |
| 650 | | sh2->sr &= ~Q; |
| 788 | m_sh2_state->sr &= ~Q; |
| 651 | 789 | else |
| 652 | | if(sh2->r[n] > tmp0) |
| 653 | | sh2->sr &= ~Q; |
| 790 | if(m_sh2_state->r[n] > tmp0) |
| 791 | m_sh2_state->sr &= ~Q; |
| 654 | 792 | else |
| 655 | | sh2->sr |= Q; |
| 793 | m_sh2_state->sr |= Q; |
| 656 | 794 | } |
| 657 | 795 | else |
| 658 | 796 | { |
| 659 | | tmp0 = sh2->r[n]; |
| 660 | | sh2->r[n] += sh2->r[m]; |
| 661 | | if(!(sh2->sr & Q)) |
| 797 | tmp0 = m_sh2_state->r[n]; |
| 798 | m_sh2_state->r[n] += m_sh2_state->r[m]; |
| 799 | if(!(m_sh2_state->sr & Q)) |
| 662 | 800 | { |
| 663 | | if(sh2->r[n] < tmp0) |
| 664 | | sh2->sr &= ~Q; |
| 801 | if(m_sh2_state->r[n] < tmp0) |
| 802 | m_sh2_state->sr &= ~Q; |
| 665 | 803 | else |
| 666 | | sh2->sr |= Q; |
| 804 | m_sh2_state->sr |= Q; |
| 667 | 805 | } |
| 668 | 806 | else |
| 669 | 807 | { |
| 670 | | if(sh2->r[n] < tmp0) |
| 671 | | sh2->sr |= Q; |
| 808 | if(m_sh2_state->r[n] < tmp0) |
| 809 | m_sh2_state->sr |= Q; |
| 672 | 810 | else |
| 673 | | sh2->sr &= ~Q; |
| 811 | m_sh2_state->sr &= ~Q; |
| 674 | 812 | } |
| 675 | 813 | } |
| 676 | 814 | } |
| 677 | 815 | else |
| 678 | 816 | { |
| 679 | | if (!(sh2->sr & M)) |
| 817 | if (!(m_sh2_state->sr & M)) |
| 680 | 818 | { |
| 681 | | tmp0 = sh2->r[n]; |
| 682 | | sh2->r[n] += sh2->r[m]; |
| 683 | | if(!(sh2->sr & Q)) |
| 684 | | if(sh2->r[n] < tmp0) |
| 685 | | sh2->sr |= Q; |
| 819 | tmp0 = m_sh2_state->r[n]; |
| 820 | m_sh2_state->r[n] += m_sh2_state->r[m]; |
| 821 | if(!(m_sh2_state->sr & Q)) |
| 822 | if(m_sh2_state->r[n] < tmp0) |
| 823 | m_sh2_state->sr |= Q; |
| 686 | 824 | else |
| 687 | | sh2->sr &= ~Q; |
| 825 | m_sh2_state->sr &= ~Q; |
| 688 | 826 | else |
| 689 | | if(sh2->r[n] < tmp0) |
| 690 | | sh2->sr &= ~Q; |
| 827 | if(m_sh2_state->r[n] < tmp0) |
| 828 | m_sh2_state->sr &= ~Q; |
| 691 | 829 | else |
| 692 | | sh2->sr |= Q; |
| 830 | m_sh2_state->sr |= Q; |
| 693 | 831 | } |
| 694 | 832 | else |
| 695 | 833 | { |
| 696 | | tmp0 = sh2->r[n]; |
| 697 | | sh2->r[n] -= sh2->r[m]; |
| 698 | | if(!(sh2->sr & Q)) |
| 699 | | if(sh2->r[n] > tmp0) |
| 700 | | sh2->sr &= ~Q; |
| 834 | tmp0 = m_sh2_state->r[n]; |
| 835 | m_sh2_state->r[n] -= m_sh2_state->r[m]; |
| 836 | if(!(m_sh2_state->sr & Q)) |
| 837 | if(m_sh2_state->r[n] > tmp0) |
| 838 | m_sh2_state->sr &= ~Q; |
| 701 | 839 | else |
| 702 | | sh2->sr |= Q; |
| 840 | m_sh2_state->sr |= Q; |
| 703 | 841 | else |
| 704 | | if(sh2->r[n] > tmp0) |
| 705 | | sh2->sr |= Q; |
| 842 | if(m_sh2_state->r[n] > tmp0) |
| 843 | m_sh2_state->sr |= Q; |
| 706 | 844 | else |
| 707 | | sh2->sr &= ~Q; |
| 845 | m_sh2_state->sr &= ~Q; |
| 708 | 846 | } |
| 709 | 847 | } |
| 710 | 848 | |
| 711 | | tmp0 = (sh2->sr & (Q | M)); |
| 849 | tmp0 = (m_sh2_state->sr & (Q | M)); |
| 712 | 850 | if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ |
| 713 | | sh2->sr |= T; |
| 851 | m_sh2_state->sr |= T; |
| 714 | 852 | else |
| 715 | | sh2->sr &= ~T; |
| 853 | m_sh2_state->sr &= ~T; |
| 716 | 854 | } |
| 717 | 855 | |
| 718 | 856 | /* DMULS.L Rm,Rn */ |
| 719 | | INLINE void DMULS(sh2_state *sh2, UINT32 m, UINT32 n) |
| 857 | void sh2_device::DMULS(UINT32 m, UINT32 n) |
| 720 | 858 | { |
| 721 | 859 | UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; |
| 722 | 860 | UINT32 temp0, temp1, temp2, temp3; |
| 723 | 861 | INT32 tempm, tempn, fnLmL; |
| 724 | 862 | |
| 725 | | tempn = (INT32) sh2->r[n]; |
| 726 | | tempm = (INT32) sh2->r[m]; |
| 863 | tempn = (INT32) m_sh2_state->r[n]; |
| 864 | tempm = (INT32) m_sh2_state->r[m]; |
| 727 | 865 | if (tempn < 0) |
| 728 | 866 | tempn = 0 - tempn; |
| 729 | 867 | if (tempm < 0) |
| 730 | 868 | tempm = 0 - tempm; |
| 731 | | if ((INT32) (sh2->r[n] ^ sh2->r[m]) < 0) |
| 869 | if ((INT32) (m_sh2_state->r[n] ^ m_sh2_state->r[m]) < 0) |
| 732 | 870 | fnLmL = -1; |
| 733 | 871 | else |
| 734 | 872 | fnLmL = 0; |
| r29568 | r29569 | |
| 759 | 897 | else |
| 760 | 898 | Res0 = (~Res0) + 1; |
| 761 | 899 | } |
| 762 | | sh2->mach = Res2; |
| 763 | | sh2->macl = Res0; |
| 764 | | sh2->icount--; |
| 900 | m_sh2_state->mach = Res2; |
| 901 | m_sh2_state->macl = Res0; |
| 902 | m_sh2_state->icount--; |
| 765 | 903 | } |
| 766 | 904 | |
| 767 | 905 | /* DMULU.L Rm,Rn */ |
| 768 | | INLINE void DMULU(sh2_state *sh2, UINT32 m, UINT32 n) |
| 906 | void sh2_device::DMULU(UINT32 m, UINT32 n) |
| 769 | 907 | { |
| 770 | 908 | UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; |
| 771 | 909 | UINT32 temp0, temp1, temp2, temp3; |
| 772 | 910 | |
| 773 | | RnL = sh2->r[n] & 0x0000ffff; |
| 774 | | RnH = (sh2->r[n] >> 16) & 0x0000ffff; |
| 775 | | RmL = sh2->r[m] & 0x0000ffff; |
| 776 | | RmH = (sh2->r[m] >> 16) & 0x0000ffff; |
| 911 | RnL = m_sh2_state->r[n] & 0x0000ffff; |
| 912 | RnH = (m_sh2_state->r[n] >> 16) & 0x0000ffff; |
| 913 | RmL = m_sh2_state->r[m] & 0x0000ffff; |
| 914 | RmH = (m_sh2_state->r[m] >> 16) & 0x0000ffff; |
| 777 | 915 | temp0 = RmL * RnL; |
| 778 | 916 | temp1 = RmH * RnL; |
| 779 | 917 | temp2 = RmL * RnH; |
| r29568 | r29569 | |
| 787 | 925 | if (Res0 < temp0) |
| 788 | 926 | Res2++; |
| 789 | 927 | Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; |
| 790 | | sh2->mach = Res2; |
| 791 | | sh2->macl = Res0; |
| 792 | | sh2->icount--; |
| 928 | m_sh2_state->mach = Res2; |
| 929 | m_sh2_state->macl = Res0; |
| 930 | m_sh2_state->icount--; |
| 793 | 931 | } |
| 794 | 932 | |
| 795 | 933 | /* DT Rn */ |
| 796 | | INLINE void DT(sh2_state *sh2, UINT32 n) |
| 934 | void sh2_device::DT(UINT32 n) |
| 797 | 935 | { |
| 798 | | sh2->r[n]--; |
| 799 | | if (sh2->r[n] == 0) |
| 800 | | sh2->sr |= T; |
| 936 | m_sh2_state->r[n]--; |
| 937 | if (m_sh2_state->r[n] == 0) |
| 938 | m_sh2_state->sr |= T; |
| 801 | 939 | else |
| 802 | | sh2->sr &= ~T; |
| 940 | m_sh2_state->sr &= ~T; |
| 803 | 941 | #if BUSY_LOOP_HACKS |
| 804 | 942 | { |
| 805 | | UINT32 next_opcode = RW( sh2, sh2->ppc & AM ); |
| 943 | UINT32 next_opcode = RW( m_sh2_state->ppc & AM ); |
| 806 | 944 | /* DT Rn |
| 807 | 945 | * BF $-2 |
| 808 | 946 | */ |
| 809 | 947 | if (next_opcode == 0x8bfd) |
| 810 | 948 | { |
| 811 | | while (sh2->r[n] > 1 && sh2->icount > 4) |
| 949 | while (m_sh2_state->r[n] > 1 && m_sh2_state->icount > 4) |
| 812 | 950 | { |
| 813 | | sh2->r[n]--; |
| 814 | | sh2->icount -= 4; /* cycles for DT (1) and BF taken (3) */ |
| 951 | m_sh2_state->r[n]--; |
| 952 | m_sh2_state->icount -= 4; /* cycles for DT (1) and BF taken (3) */ |
| 815 | 953 | } |
| 816 | 954 | } |
| 817 | 955 | } |
| r29568 | r29569 | |
| 819 | 957 | } |
| 820 | 958 | |
| 821 | 959 | /* EXTS.B Rm,Rn */ |
| 822 | | INLINE void EXTSB(sh2_state *sh2, UINT32 m, UINT32 n) |
| 960 | void sh2_device::EXTSB(UINT32 m, UINT32 n) |
| 823 | 961 | { |
| 824 | | sh2->r[n] = ((INT32)sh2->r[m] << 24) >> 24; |
| 962 | m_sh2_state->r[n] = ((INT32)m_sh2_state->r[m] << 24) >> 24; |
| 825 | 963 | } |
| 826 | 964 | |
| 827 | 965 | /* EXTS.W Rm,Rn */ |
| 828 | | INLINE void EXTSW(sh2_state *sh2, UINT32 m, UINT32 n) |
| 966 | void sh2_device::EXTSW(UINT32 m, UINT32 n) |
| 829 | 967 | { |
| 830 | | sh2->r[n] = ((INT32)sh2->r[m] << 16) >> 16; |
| 968 | m_sh2_state->r[n] = ((INT32)m_sh2_state->r[m] << 16) >> 16; |
| 831 | 969 | } |
| 832 | 970 | |
| 833 | 971 | /* EXTU.B Rm,Rn */ |
| 834 | | INLINE void EXTUB(sh2_state *sh2, UINT32 m, UINT32 n) |
| 972 | void sh2_device::EXTUB(UINT32 m, UINT32 n) |
| 835 | 973 | { |
| 836 | | sh2->r[n] = sh2->r[m] & 0x000000ff; |
| 974 | m_sh2_state->r[n] = m_sh2_state->r[m] & 0x000000ff; |
| 837 | 975 | } |
| 838 | 976 | |
| 839 | 977 | /* EXTU.W Rm,Rn */ |
| 840 | | INLINE void EXTUW(sh2_state *sh2, UINT32 m, UINT32 n) |
| 978 | void sh2_device::EXTUW(UINT32 m, UINT32 n) |
| 841 | 979 | { |
| 842 | | sh2->r[n] = sh2->r[m] & 0x0000ffff; |
| 980 | m_sh2_state->r[n] = m_sh2_state->r[m] & 0x0000ffff; |
| 843 | 981 | } |
| 844 | 982 | |
| 845 | 983 | /* ILLEGAL */ |
| 846 | | INLINE void ILLEGAL(sh2_state *sh2) |
| 984 | void sh2_device::ILLEGAL() |
| 847 | 985 | { |
| 848 | | logerror("SH2.%s: Illegal opcode at %08x\n", sh2->device->tag(), sh2->pc - 2); |
| 849 | | sh2->r[15] -= 4; |
| 850 | | WL( sh2, sh2->r[15], sh2->sr ); /* push SR onto stack */ |
| 851 | | sh2->r[15] -= 4; |
| 852 | | WL( sh2, sh2->r[15], sh2->pc - 2 ); /* push PC onto stack */ |
| 986 | logerror("SH2.%s: Illegal opcode at %08x\n", tag(), m_sh2_state->pc - 2); |
| 987 | m_sh2_state->r[15] -= 4; |
| 988 | WL( m_sh2_state->r[15], m_sh2_state->sr ); /* push SR onto stack */ |
| 989 | m_sh2_state->r[15] -= 4; |
| 990 | WL( m_sh2_state->r[15], m_sh2_state->pc - 2 ); /* push PC onto stack */ |
| 853 | 991 | |
| 854 | 992 | /* fetch PC */ |
| 855 | | sh2->pc = RL( sh2, sh2->vbr + 4 * 4 ); |
| 993 | m_sh2_state->pc = RL( m_sh2_state->vbr + 4 * 4 ); |
| 856 | 994 | |
| 857 | 995 | /* TODO: timing is a guess */ |
| 858 | | sh2->icount -= 5; |
| 996 | m_sh2_state->icount -= 5; |
| 859 | 997 | } |
| 860 | 998 | |
| 861 | 999 | |
| 862 | 1000 | /* JMP @Rm */ |
| 863 | | INLINE void JMP(sh2_state *sh2, UINT32 m) |
| 1001 | void sh2_device::JMP(UINT32 m) |
| 864 | 1002 | { |
| 865 | | sh2->delay = sh2->pc; |
| 866 | | sh2->pc = sh2->ea = sh2->r[m]; |
| 867 | | sh2->icount--; |
| 1003 | m_delay = m_sh2_state->pc; |
| 1004 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->r[m]; |
| 1005 | m_sh2_state->icount--; |
| 868 | 1006 | } |
| 869 | 1007 | |
| 870 | 1008 | /* JSR @Rm */ |
| 871 | | INLINE void JSR(sh2_state *sh2, UINT32 m) |
| 1009 | void sh2_device::JSR(UINT32 m) |
| 872 | 1010 | { |
| 873 | | sh2->delay = sh2->pc; |
| 874 | | sh2->pr = sh2->pc + 2; |
| 875 | | sh2->pc = sh2->ea = sh2->r[m]; |
| 876 | | sh2->icount--; |
| 1011 | m_delay = m_sh2_state->pc; |
| 1012 | m_sh2_state->pr = m_sh2_state->pc + 2; |
| 1013 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->r[m]; |
| 1014 | m_sh2_state->icount--; |
| 877 | 1015 | } |
| 878 | 1016 | |
| 879 | 1017 | |
| 880 | 1018 | /* LDC Rm,SR */ |
| 881 | | INLINE void LDCSR(sh2_state *sh2, UINT32 m) |
| 1019 | void sh2_device::LDCSR(UINT32 m) |
| 882 | 1020 | { |
| 883 | | sh2->sr = sh2->r[m] & FLAGS; |
| 884 | | sh2->test_irq = 1; |
| 1021 | m_sh2_state->sr = m_sh2_state->r[m] & FLAGS; |
| 1022 | m_test_irq = 1; |
| 885 | 1023 | } |
| 886 | 1024 | |
| 887 | 1025 | /* LDC Rm,GBR */ |
| 888 | | INLINE void LDCGBR(sh2_state *sh2, UINT32 m) |
| 1026 | void sh2_device::LDCGBR(UINT32 m) |
| 889 | 1027 | { |
| 890 | | sh2->gbr = sh2->r[m]; |
| 1028 | m_sh2_state->gbr = m_sh2_state->r[m]; |
| 891 | 1029 | } |
| 892 | 1030 | |
| 893 | 1031 | /* LDC Rm,VBR */ |
| 894 | | INLINE void LDCVBR(sh2_state *sh2, UINT32 m) |
| 1032 | void sh2_device::LDCVBR(UINT32 m) |
| 895 | 1033 | { |
| 896 | | sh2->vbr = sh2->r[m]; |
| 1034 | m_sh2_state->vbr = m_sh2_state->r[m]; |
| 897 | 1035 | } |
| 898 | 1036 | |
| 899 | 1037 | /* LDC.L @Rm+,SR */ |
| 900 | | INLINE void LDCMSR(sh2_state *sh2, UINT32 m) |
| 1038 | void sh2_device::LDCMSR(UINT32 m) |
| 901 | 1039 | { |
| 902 | | sh2->ea = sh2->r[m]; |
| 903 | | sh2->sr = RL( sh2, sh2->ea ) & FLAGS; |
| 904 | | sh2->r[m] += 4; |
| 905 | | sh2->icount -= 2; |
| 906 | | sh2->test_irq = 1; |
| 1040 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1041 | m_sh2_state->sr = RL( m_sh2_state->ea ) & FLAGS; |
| 1042 | m_sh2_state->r[m] += 4; |
| 1043 | m_sh2_state->icount -= 2; |
| 1044 | m_test_irq = 1; |
| 907 | 1045 | } |
| 908 | 1046 | |
| 909 | 1047 | /* LDC.L @Rm+,GBR */ |
| 910 | | INLINE void LDCMGBR(sh2_state *sh2, UINT32 m) |
| 1048 | void sh2_device::LDCMGBR(UINT32 m) |
| 911 | 1049 | { |
| 912 | | sh2->ea = sh2->r[m]; |
| 913 | | sh2->gbr = RL( sh2, sh2->ea ); |
| 914 | | sh2->r[m] += 4; |
| 915 | | sh2->icount -= 2; |
| 1050 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1051 | m_sh2_state->gbr = RL( m_sh2_state->ea ); |
| 1052 | m_sh2_state->r[m] += 4; |
| 1053 | m_sh2_state->icount -= 2; |
| 916 | 1054 | } |
| 917 | 1055 | |
| 918 | 1056 | /* LDC.L @Rm+,VBR */ |
| 919 | | INLINE void LDCMVBR(sh2_state *sh2, UINT32 m) |
| 1057 | void sh2_device::LDCMVBR(UINT32 m) |
| 920 | 1058 | { |
| 921 | | sh2->ea = sh2->r[m]; |
| 922 | | sh2->vbr = RL( sh2, sh2->ea ); |
| 923 | | sh2->r[m] += 4; |
| 924 | | sh2->icount -= 2; |
| 1059 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1060 | m_sh2_state->vbr = RL( m_sh2_state->ea ); |
| 1061 | m_sh2_state->r[m] += 4; |
| 1062 | m_sh2_state->icount -= 2; |
| 925 | 1063 | } |
| 926 | 1064 | |
| 927 | 1065 | /* LDS Rm,MACH */ |
| 928 | | INLINE void LDSMACH(sh2_state *sh2, UINT32 m) |
| 1066 | void sh2_device::LDSMACH(UINT32 m) |
| 929 | 1067 | { |
| 930 | | sh2->mach = sh2->r[m]; |
| 1068 | m_sh2_state->mach = m_sh2_state->r[m]; |
| 931 | 1069 | } |
| 932 | 1070 | |
| 933 | 1071 | /* LDS Rm,MACL */ |
| 934 | | INLINE void LDSMACL(sh2_state *sh2, UINT32 m) |
| 1072 | void sh2_device::LDSMACL(UINT32 m) |
| 935 | 1073 | { |
| 936 | | sh2->macl = sh2->r[m]; |
| 1074 | m_sh2_state->macl = m_sh2_state->r[m]; |
| 937 | 1075 | } |
| 938 | 1076 | |
| 939 | 1077 | /* LDS Rm,PR */ |
| 940 | | INLINE void LDSPR(sh2_state *sh2, UINT32 m) |
| 1078 | void sh2_device::LDSPR(UINT32 m) |
| 941 | 1079 | { |
| 942 | | sh2->pr = sh2->r[m]; |
| 1080 | m_sh2_state->pr = m_sh2_state->r[m]; |
| 943 | 1081 | } |
| 944 | 1082 | |
| 945 | 1083 | /* LDS.L @Rm+,MACH */ |
| 946 | | INLINE void LDSMMACH(sh2_state *sh2, UINT32 m) |
| 1084 | void sh2_device::LDSMMACH(UINT32 m) |
| 947 | 1085 | { |
| 948 | | sh2->ea = sh2->r[m]; |
| 949 | | sh2->mach = RL( sh2, sh2->ea ); |
| 950 | | sh2->r[m] += 4; |
| 1086 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1087 | m_sh2_state->mach = RL( m_sh2_state->ea ); |
| 1088 | m_sh2_state->r[m] += 4; |
| 951 | 1089 | } |
| 952 | 1090 | |
| 953 | 1091 | /* LDS.L @Rm+,MACL */ |
| 954 | | INLINE void LDSMMACL(sh2_state *sh2, UINT32 m) |
| 1092 | void sh2_device::LDSMMACL(UINT32 m) |
| 955 | 1093 | { |
| 956 | | sh2->ea = sh2->r[m]; |
| 957 | | sh2->macl = RL( sh2, sh2->ea ); |
| 958 | | sh2->r[m] += 4; |
| 1094 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1095 | m_sh2_state->macl = RL( m_sh2_state->ea ); |
| 1096 | m_sh2_state->r[m] += 4; |
| 959 | 1097 | } |
| 960 | 1098 | |
| 961 | 1099 | /* LDS.L @Rm+,PR */ |
| 962 | | INLINE void LDSMPR(sh2_state *sh2, UINT32 m) |
| 1100 | void sh2_device::LDSMPR(UINT32 m) |
| 963 | 1101 | { |
| 964 | | sh2->ea = sh2->r[m]; |
| 965 | | sh2->pr = RL( sh2, sh2->ea ); |
| 966 | | sh2->r[m] += 4; |
| 1102 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1103 | m_sh2_state->pr = RL( m_sh2_state->ea ); |
| 1104 | m_sh2_state->r[m] += 4; |
| 967 | 1105 | } |
| 968 | 1106 | |
| 969 | 1107 | /* MAC.L @Rm+,@Rn+ */ |
| 970 | | INLINE void MAC_L(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1108 | void sh2_device::MAC_L(UINT32 m, UINT32 n) |
| 971 | 1109 | { |
| 972 | 1110 | UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; |
| 973 | 1111 | UINT32 temp0, temp1, temp2, temp3; |
| 974 | 1112 | INT32 tempm, tempn, fnLmL; |
| 975 | 1113 | |
| 976 | | tempn = (INT32) RL( sh2, sh2->r[n] ); |
| 977 | | sh2->r[n] += 4; |
| 978 | | tempm = (INT32) RL( sh2, sh2->r[m] ); |
| 979 | | sh2->r[m] += 4; |
| 1114 | tempn = (INT32) RL( m_sh2_state->r[n] ); |
| 1115 | m_sh2_state->r[n] += 4; |
| 1116 | tempm = (INT32) RL( m_sh2_state->r[m] ); |
| 1117 | m_sh2_state->r[m] += 4; |
| 980 | 1118 | if ((INT32) (tempn ^ tempm) < 0) |
| 981 | 1119 | fnLmL = -1; |
| 982 | 1120 | else |
| r29568 | r29569 | |
| 1012 | 1150 | else |
| 1013 | 1151 | Res0 = (~Res0) + 1; |
| 1014 | 1152 | } |
| 1015 | | if (sh2->sr & S) |
| 1153 | if (m_sh2_state->sr & S) |
| 1016 | 1154 | { |
| 1017 | | Res0 = sh2->macl + Res0; |
| 1018 | | if (sh2->macl > Res0) |
| 1155 | Res0 = m_sh2_state->macl + Res0; |
| 1156 | if (m_sh2_state->macl > Res0) |
| 1019 | 1157 | Res2++; |
| 1020 | | Res2 += (sh2->mach & 0x0000ffff); |
| 1158 | Res2 += (m_sh2_state->mach & 0x0000ffff); |
| 1021 | 1159 | if (((INT32) Res2 < 0) && (Res2 < 0xffff8000)) |
| 1022 | 1160 | { |
| 1023 | 1161 | Res2 = 0x00008000; |
| r29568 | r29569 | |
| 1028 | 1166 | Res2 = 0x00007fff; |
| 1029 | 1167 | Res0 = 0xffffffff; |
| 1030 | 1168 | } |
| 1031 | | sh2->mach = Res2; |
| 1032 | | sh2->macl = Res0; |
| 1169 | m_sh2_state->mach = Res2; |
| 1170 | m_sh2_state->macl = Res0; |
| 1033 | 1171 | } |
| 1034 | 1172 | else |
| 1035 | 1173 | { |
| 1036 | | Res0 = sh2->macl + Res0; |
| 1037 | | if (sh2->macl > Res0) |
| 1174 | Res0 = m_sh2_state->macl + Res0; |
| 1175 | if (m_sh2_state->macl > Res0) |
| 1038 | 1176 | Res2++; |
| 1039 | | Res2 += sh2->mach; |
| 1040 | | sh2->mach = Res2; |
| 1041 | | sh2->macl = Res0; |
| 1177 | Res2 += m_sh2_state->mach; |
| 1178 | m_sh2_state->mach = Res2; |
| 1179 | m_sh2_state->macl = Res0; |
| 1042 | 1180 | } |
| 1043 | | sh2->icount -= 2; |
| 1181 | m_sh2_state->icount -= 2; |
| 1044 | 1182 | } |
| 1045 | 1183 | |
| 1046 | 1184 | /* MAC.W @Rm+,@Rn+ */ |
| 1047 | | INLINE void MAC_W(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1185 | void sh2_device::MAC_W(UINT32 m, UINT32 n) |
| 1048 | 1186 | { |
| 1049 | 1187 | INT32 tempm, tempn, dest, src, ans; |
| 1050 | 1188 | UINT32 templ; |
| 1051 | 1189 | |
| 1052 | | tempn = (INT32) RW( sh2, sh2->r[n] ); |
| 1053 | | sh2->r[n] += 2; |
| 1054 | | tempm = (INT32) RW( sh2, sh2->r[m] ); |
| 1055 | | sh2->r[m] += 2; |
| 1056 | | templ = sh2->macl; |
| 1190 | tempn = (INT32) RW( m_sh2_state->r[n] ); |
| 1191 | m_sh2_state->r[n] += 2; |
| 1192 | tempm = (INT32) RW( m_sh2_state->r[m] ); |
| 1193 | m_sh2_state->r[m] += 2; |
| 1194 | templ = m_sh2_state->macl; |
| 1057 | 1195 | tempm = ((INT32) (short) tempn * (INT32) (short) tempm); |
| 1058 | | if ((INT32) sh2->macl >= 0) |
| 1196 | if ((INT32) m_sh2_state->macl >= 0) |
| 1059 | 1197 | dest = 0; |
| 1060 | 1198 | else |
| 1061 | 1199 | dest = 1; |
| r29568 | r29569 | |
| 1070 | 1208 | tempn = 0xffffffff; |
| 1071 | 1209 | } |
| 1072 | 1210 | src += dest; |
| 1073 | | sh2->macl += tempm; |
| 1074 | | if ((INT32) sh2->macl >= 0) |
| 1211 | m_sh2_state->macl += tempm; |
| 1212 | if ((INT32) m_sh2_state->macl >= 0) |
| 1075 | 1213 | ans = 0; |
| 1076 | 1214 | else |
| 1077 | 1215 | ans = 1; |
| 1078 | 1216 | ans += dest; |
| 1079 | | if (sh2->sr & S) |
| 1217 | if (m_sh2_state->sr & S) |
| 1080 | 1218 | { |
| 1081 | 1219 | if (ans == 1) |
| 1082 | 1220 | { |
| 1083 | 1221 | if (src == 0) |
| 1084 | | sh2->macl = 0x7fffffff; |
| 1222 | m_sh2_state->macl = 0x7fffffff; |
| 1085 | 1223 | if (src == 2) |
| 1086 | | sh2->macl = 0x80000000; |
| 1224 | m_sh2_state->macl = 0x80000000; |
| 1087 | 1225 | } |
| 1088 | 1226 | } |
| 1089 | 1227 | else |
| 1090 | 1228 | { |
| 1091 | | sh2->mach += tempn; |
| 1092 | | if (templ > sh2->macl) |
| 1093 | | sh2->mach += 1; |
| 1229 | m_sh2_state->mach += tempn; |
| 1230 | if (templ > m_sh2_state->macl) |
| 1231 | m_sh2_state->mach += 1; |
| 1094 | 1232 | } |
| 1095 | | sh2->icount -= 2; |
| 1233 | m_sh2_state->icount -= 2; |
| 1096 | 1234 | } |
| 1097 | 1235 | |
| 1098 | 1236 | /* MOV Rm,Rn */ |
| 1099 | | INLINE void MOV(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1237 | void sh2_device::MOV(UINT32 m, UINT32 n) |
| 1100 | 1238 | { |
| 1101 | | sh2->r[n] = sh2->r[m]; |
| 1239 | m_sh2_state->r[n] = m_sh2_state->r[m]; |
| 1102 | 1240 | } |
| 1103 | 1241 | |
| 1104 | 1242 | /* MOV.B Rm,@Rn */ |
| 1105 | | INLINE void MOVBS(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1243 | void sh2_device::MOVBS(UINT32 m, UINT32 n) |
| 1106 | 1244 | { |
| 1107 | | sh2->ea = sh2->r[n]; |
| 1108 | | WB( sh2, sh2->ea, sh2->r[m] & 0x000000ff); |
| 1245 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1246 | WB( m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff); |
| 1109 | 1247 | } |
| 1110 | 1248 | |
| 1111 | 1249 | /* MOV.W Rm,@Rn */ |
| 1112 | | INLINE void MOVWS(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1250 | void sh2_device::MOVWS(UINT32 m, UINT32 n) |
| 1113 | 1251 | { |
| 1114 | | sh2->ea = sh2->r[n]; |
| 1115 | | WW( sh2, sh2->ea, sh2->r[m] & 0x0000ffff); |
| 1252 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1253 | WW( m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff); |
| 1116 | 1254 | } |
| 1117 | 1255 | |
| 1118 | 1256 | /* MOV.L Rm,@Rn */ |
| 1119 | | INLINE void MOVLS(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1257 | void sh2_device::MOVLS(UINT32 m, UINT32 n) |
| 1120 | 1258 | { |
| 1121 | | sh2->ea = sh2->r[n]; |
| 1122 | | WL( sh2, sh2->ea, sh2->r[m] ); |
| 1259 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1260 | WL( m_sh2_state->ea, m_sh2_state->r[m] ); |
| 1123 | 1261 | } |
| 1124 | 1262 | |
| 1125 | 1263 | /* MOV.B @Rm,Rn */ |
| 1126 | | INLINE void MOVBL(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1264 | void sh2_device::MOVBL(UINT32 m, UINT32 n) |
| 1127 | 1265 | { |
| 1128 | | sh2->ea = sh2->r[m]; |
| 1129 | | sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea ); |
| 1266 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1267 | m_sh2_state->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( m_sh2_state->ea ); |
| 1130 | 1268 | } |
| 1131 | 1269 | |
| 1132 | 1270 | /* MOV.W @Rm,Rn */ |
| 1133 | | INLINE void MOVWL(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1271 | void sh2_device::MOVWL(UINT32 m, UINT32 n) |
| 1134 | 1272 | { |
| 1135 | | sh2->ea = sh2->r[m]; |
| 1136 | | sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea ); |
| 1273 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1274 | m_sh2_state->r[n] = (UINT32)(INT32)(INT16) RW( m_sh2_state->ea ); |
| 1137 | 1275 | } |
| 1138 | 1276 | |
| 1139 | 1277 | /* MOV.L @Rm,Rn */ |
| 1140 | | INLINE void MOVLL(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1278 | void sh2_device::MOVLL(UINT32 m, UINT32 n) |
| 1141 | 1279 | { |
| 1142 | | sh2->ea = sh2->r[m]; |
| 1143 | | sh2->r[n] = RL( sh2, sh2->ea ); |
| 1280 | m_sh2_state->ea = m_sh2_state->r[m]; |
| 1281 | m_sh2_state->r[n] = RL( m_sh2_state->ea ); |
| 1144 | 1282 | } |
| 1145 | 1283 | |
| 1146 | 1284 | /* MOV.B Rm,@-Rn */ |
| 1147 | | INLINE void MOVBM(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1285 | void sh2_device::MOVBM(UINT32 m, UINT32 n) |
| 1148 | 1286 | { |
| 1149 | | /* SMG : bug fix, was reading sh2->r[n] */ |
| 1150 | | UINT32 data = sh2->r[m] & 0x000000ff; |
| 1287 | /* SMG : bug fix, was reading m_sh2_state->r[n] */ |
| 1288 | UINT32 data = m_sh2_state->r[m] & 0x000000ff; |
| 1151 | 1289 | |
| 1152 | | sh2->r[n] -= 1; |
| 1153 | | WB( sh2, sh2->r[n], data ); |
| 1290 | m_sh2_state->r[n] -= 1; |
| 1291 | WB( m_sh2_state->r[n], data ); |
| 1154 | 1292 | } |
| 1155 | 1293 | |
| 1156 | 1294 | /* MOV.W Rm,@-Rn */ |
| 1157 | | INLINE void MOVWM(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1295 | void sh2_device::MOVWM(UINT32 m, UINT32 n) |
| 1158 | 1296 | { |
| 1159 | | UINT32 data = sh2->r[m] & 0x0000ffff; |
| 1297 | UINT32 data = m_sh2_state->r[m] & 0x0000ffff; |
| 1160 | 1298 | |
| 1161 | | sh2->r[n] -= 2; |
| 1162 | | WW( sh2, sh2->r[n], data ); |
| 1299 | m_sh2_state->r[n] -= 2; |
| 1300 | WW( m_sh2_state->r[n], data ); |
| 1163 | 1301 | } |
| 1164 | 1302 | |
| 1165 | 1303 | /* MOV.L Rm,@-Rn */ |
| 1166 | | INLINE void MOVLM(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1304 | void sh2_device::MOVLM(UINT32 m, UINT32 n) |
| 1167 | 1305 | { |
| 1168 | | UINT32 data = sh2->r[m]; |
| 1306 | UINT32 data = m_sh2_state->r[m]; |
| 1169 | 1307 | |
| 1170 | | sh2->r[n] -= 4; |
| 1171 | | WL( sh2, sh2->r[n], data ); |
| 1308 | m_sh2_state->r[n] -= 4; |
| 1309 | WL( m_sh2_state->r[n], data ); |
| 1172 | 1310 | } |
| 1173 | 1311 | |
| 1174 | 1312 | /* MOV.B @Rm+,Rn */ |
| 1175 | | INLINE void MOVBP(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1313 | void sh2_device::MOVBP(UINT32 m, UINT32 n) |
| 1176 | 1314 | { |
| 1177 | | sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->r[m] ); |
| 1315 | m_sh2_state->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( m_sh2_state->r[m] ); |
| 1178 | 1316 | if (n != m) |
| 1179 | | sh2->r[m] += 1; |
| 1317 | m_sh2_state->r[m] += 1; |
| 1180 | 1318 | } |
| 1181 | 1319 | |
| 1182 | 1320 | /* MOV.W @Rm+,Rn */ |
| 1183 | | INLINE void MOVWP(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1321 | void sh2_device::MOVWP(UINT32 m, UINT32 n) |
| 1184 | 1322 | { |
| 1185 | | sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->r[m] ); |
| 1323 | m_sh2_state->r[n] = (UINT32)(INT32)(INT16) RW( m_sh2_state->r[m] ); |
| 1186 | 1324 | if (n != m) |
| 1187 | | sh2->r[m] += 2; |
| 1325 | m_sh2_state->r[m] += 2; |
| 1188 | 1326 | } |
| 1189 | 1327 | |
| 1190 | 1328 | /* MOV.L @Rm+,Rn */ |
| 1191 | | INLINE void MOVLP(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1329 | void sh2_device::MOVLP(UINT32 m, UINT32 n) |
| 1192 | 1330 | { |
| 1193 | | sh2->r[n] = RL( sh2, sh2->r[m] ); |
| 1331 | m_sh2_state->r[n] = RL( m_sh2_state->r[m] ); |
| 1194 | 1332 | if (n != m) |
| 1195 | | sh2->r[m] += 4; |
| 1333 | m_sh2_state->r[m] += 4; |
| 1196 | 1334 | } |
| 1197 | 1335 | |
| 1198 | 1336 | /* MOV.B Rm,@(R0,Rn) */ |
| 1199 | | INLINE void MOVBS0(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1337 | void sh2_device::MOVBS0(UINT32 m, UINT32 n) |
| 1200 | 1338 | { |
| 1201 | | sh2->ea = sh2->r[n] + sh2->r[0]; |
| 1202 | | WB( sh2, sh2->ea, sh2->r[m] & 0x000000ff ); |
| 1339 | m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; |
| 1340 | WB( m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff ); |
| 1203 | 1341 | } |
| 1204 | 1342 | |
| 1205 | 1343 | /* MOV.W Rm,@(R0,Rn) */ |
| 1206 | | INLINE void MOVWS0(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1344 | void sh2_device::MOVWS0(UINT32 m, UINT32 n) |
| 1207 | 1345 | { |
| 1208 | | sh2->ea = sh2->r[n] + sh2->r[0]; |
| 1209 | | WW( sh2, sh2->ea, sh2->r[m] & 0x0000ffff ); |
| 1346 | m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; |
| 1347 | WW( m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff ); |
| 1210 | 1348 | } |
| 1211 | 1349 | |
| 1212 | 1350 | /* MOV.L Rm,@(R0,Rn) */ |
| 1213 | | INLINE void MOVLS0(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1351 | void sh2_device::MOVLS0(UINT32 m, UINT32 n) |
| 1214 | 1352 | { |
| 1215 | | sh2->ea = sh2->r[n] + sh2->r[0]; |
| 1216 | | WL( sh2, sh2->ea, sh2->r[m] ); |
| 1353 | m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0]; |
| 1354 | WL( m_sh2_state->ea, m_sh2_state->r[m] ); |
| 1217 | 1355 | } |
| 1218 | 1356 | |
| 1219 | 1357 | /* MOV.B @(R0,Rm),Rn */ |
| 1220 | | INLINE void MOVBL0(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1358 | void sh2_device::MOVBL0(UINT32 m, UINT32 n) |
| 1221 | 1359 | { |
| 1222 | | sh2->ea = sh2->r[m] + sh2->r[0]; |
| 1223 | | sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea ); |
| 1360 | m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; |
| 1361 | m_sh2_state->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( m_sh2_state->ea ); |
| 1224 | 1362 | } |
| 1225 | 1363 | |
| 1226 | 1364 | /* MOV.W @(R0,Rm),Rn */ |
| 1227 | | INLINE void MOVWL0(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1365 | void sh2_device::MOVWL0(UINT32 m, UINT32 n) |
| 1228 | 1366 | { |
| 1229 | | sh2->ea = sh2->r[m] + sh2->r[0]; |
| 1230 | | sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea ); |
| 1367 | m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; |
| 1368 | m_sh2_state->r[n] = (UINT32)(INT32)(INT16) RW( m_sh2_state->ea ); |
| 1231 | 1369 | } |
| 1232 | 1370 | |
| 1233 | 1371 | /* MOV.L @(R0,Rm),Rn */ |
| 1234 | | INLINE void MOVLL0(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1372 | void sh2_device::MOVLL0(UINT32 m, UINT32 n) |
| 1235 | 1373 | { |
| 1236 | | sh2->ea = sh2->r[m] + sh2->r[0]; |
| 1237 | | sh2->r[n] = RL( sh2, sh2->ea ); |
| 1374 | m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0]; |
| 1375 | m_sh2_state->r[n] = RL( m_sh2_state->ea ); |
| 1238 | 1376 | } |
| 1239 | 1377 | |
| 1240 | 1378 | /* MOV #imm,Rn */ |
| 1241 | | INLINE void MOVI(sh2_state *sh2, UINT32 i, UINT32 n) |
| 1379 | void sh2_device::MOVI(UINT32 i, UINT32 n) |
| 1242 | 1380 | { |
| 1243 | | sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) i; |
| 1381 | m_sh2_state->r[n] = (UINT32)(INT32)(INT16)(INT8) i; |
| 1244 | 1382 | } |
| 1245 | 1383 | |
| 1246 | 1384 | /* MOV.W @(disp8,PC),Rn */ |
| 1247 | | INLINE void MOVWI(sh2_state *sh2, UINT32 d, UINT32 n) |
| 1385 | void sh2_device::MOVWI(UINT32 d, UINT32 n) |
| 1248 | 1386 | { |
| 1249 | 1387 | UINT32 disp = d & 0xff; |
| 1250 | | sh2->ea = sh2->pc + disp * 2 + 2; |
| 1251 | | sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea ); |
| 1388 | m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; |
| 1389 | m_sh2_state->r[n] = (UINT32)(INT32)(INT16) RW( m_sh2_state->ea ); |
| 1252 | 1390 | } |
| 1253 | 1391 | |
| 1254 | 1392 | /* MOV.L @(disp8,PC),Rn */ |
| 1255 | | INLINE void MOVLI(sh2_state *sh2, UINT32 d, UINT32 n) |
| 1393 | void sh2_device::MOVLI(UINT32 d, UINT32 n) |
| 1256 | 1394 | { |
| 1257 | 1395 | UINT32 disp = d & 0xff; |
| 1258 | | sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4; |
| 1259 | | sh2->r[n] = RL( sh2, sh2->ea ); |
| 1396 | m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4; |
| 1397 | m_sh2_state->r[n] = RL( m_sh2_state->ea ); |
| 1260 | 1398 | } |
| 1261 | 1399 | |
| 1262 | 1400 | /* MOV.B @(disp8,GBR),R0 */ |
| 1263 | | INLINE void MOVBLG(sh2_state *sh2, UINT32 d) |
| 1401 | void sh2_device::MOVBLG(UINT32 d) |
| 1264 | 1402 | { |
| 1265 | 1403 | UINT32 disp = d & 0xff; |
| 1266 | | sh2->ea = sh2->gbr + disp; |
| 1267 | | sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea ); |
| 1404 | m_sh2_state->ea = m_sh2_state->gbr + disp; |
| 1405 | m_sh2_state->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( m_sh2_state->ea ); |
| 1268 | 1406 | } |
| 1269 | 1407 | |
| 1270 | 1408 | /* MOV.W @(disp8,GBR),R0 */ |
| 1271 | | INLINE void MOVWLG(sh2_state *sh2, UINT32 d) |
| 1409 | void sh2_device::MOVWLG(UINT32 d) |
| 1272 | 1410 | { |
| 1273 | 1411 | UINT32 disp = d & 0xff; |
| 1274 | | sh2->ea = sh2->gbr + disp * 2; |
| 1275 | | sh2->r[0] = (INT32)(INT16) RW( sh2, sh2->ea ); |
| 1412 | m_sh2_state->ea = m_sh2_state->gbr + disp * 2; |
| 1413 | m_sh2_state->r[0] = (INT32)(INT16) RW( m_sh2_state->ea ); |
| 1276 | 1414 | } |
| 1277 | 1415 | |
| 1278 | 1416 | /* MOV.L @(disp8,GBR),R0 */ |
| 1279 | | INLINE void MOVLLG(sh2_state *sh2, UINT32 d) |
| 1417 | void sh2_device::MOVLLG(UINT32 d) |
| 1280 | 1418 | { |
| 1281 | 1419 | UINT32 disp = d & 0xff; |
| 1282 | | sh2->ea = sh2->gbr + disp * 4; |
| 1283 | | sh2->r[0] = RL( sh2, sh2->ea ); |
| 1420 | m_sh2_state->ea = m_sh2_state->gbr + disp * 4; |
| 1421 | m_sh2_state->r[0] = RL( m_sh2_state->ea ); |
| 1284 | 1422 | } |
| 1285 | 1423 | |
| 1286 | 1424 | /* MOV.B R0,@(disp8,GBR) */ |
| 1287 | | INLINE void MOVBSG(sh2_state *sh2, UINT32 d) |
| 1425 | void sh2_device::MOVBSG(UINT32 d) |
| 1288 | 1426 | { |
| 1289 | 1427 | UINT32 disp = d & 0xff; |
| 1290 | | sh2->ea = sh2->gbr + disp; |
| 1291 | | WB( sh2, sh2->ea, sh2->r[0] & 0x000000ff ); |
| 1428 | m_sh2_state->ea = m_sh2_state->gbr + disp; |
| 1429 | WB( m_sh2_state->ea, m_sh2_state->r[0] & 0x000000ff ); |
| 1292 | 1430 | } |
| 1293 | 1431 | |
| 1294 | 1432 | /* MOV.W R0,@(disp8,GBR) */ |
| 1295 | | INLINE void MOVWSG(sh2_state *sh2, UINT32 d) |
| 1433 | void sh2_device::MOVWSG(UINT32 d) |
| 1296 | 1434 | { |
| 1297 | 1435 | UINT32 disp = d & 0xff; |
| 1298 | | sh2->ea = sh2->gbr + disp * 2; |
| 1299 | | WW( sh2, sh2->ea, sh2->r[0] & 0x0000ffff ); |
| 1436 | m_sh2_state->ea = m_sh2_state->gbr + disp * 2; |
| 1437 | WW( m_sh2_state->ea, m_sh2_state->r[0] & 0x0000ffff ); |
| 1300 | 1438 | } |
| 1301 | 1439 | |
| 1302 | 1440 | /* MOV.L R0,@(disp8,GBR) */ |
| 1303 | | INLINE void MOVLSG(sh2_state *sh2, UINT32 d) |
| 1441 | void sh2_device::MOVLSG(UINT32 d) |
| 1304 | 1442 | { |
| 1305 | 1443 | UINT32 disp = d & 0xff; |
| 1306 | | sh2->ea = sh2->gbr + disp * 4; |
| 1307 | | WL( sh2, sh2->ea, sh2->r[0] ); |
| 1444 | m_sh2_state->ea = m_sh2_state->gbr + disp * 4; |
| 1445 | WL( m_sh2_state->ea, m_sh2_state->r[0] ); |
| 1308 | 1446 | } |
| 1309 | 1447 | |
| 1310 | 1448 | /* MOV.B R0,@(disp4,Rn) */ |
| 1311 | | INLINE void MOVBS4(sh2_state *sh2, UINT32 d, UINT32 n) |
| 1449 | void sh2_device::MOVBS4(UINT32 d, UINT32 n) |
| 1312 | 1450 | { |
| 1313 | 1451 | UINT32 disp = d & 0x0f; |
| 1314 | | sh2->ea = sh2->r[n] + disp; |
| 1315 | | WB( sh2, sh2->ea, sh2->r[0] & 0x000000ff ); |
| 1452 | m_sh2_state->ea = m_sh2_state->r[n] + disp; |
| 1453 | WB( m_sh2_state->ea, m_sh2_state->r[0] & 0x000000ff ); |
| 1316 | 1454 | } |
| 1317 | 1455 | |
| 1318 | 1456 | /* MOV.W R0,@(disp4,Rn) */ |
| 1319 | | INLINE void MOVWS4(sh2_state *sh2, UINT32 d, UINT32 n) |
| 1457 | void sh2_device::MOVWS4(UINT32 d, UINT32 n) |
| 1320 | 1458 | { |
| 1321 | 1459 | UINT32 disp = d & 0x0f; |
| 1322 | | sh2->ea = sh2->r[n] + disp * 2; |
| 1323 | | WW( sh2, sh2->ea, sh2->r[0] & 0x0000ffff ); |
| 1460 | m_sh2_state->ea = m_sh2_state->r[n] + disp * 2; |
| 1461 | WW( m_sh2_state->ea, m_sh2_state->r[0] & 0x0000ffff ); |
| 1324 | 1462 | } |
| 1325 | 1463 | |
| 1326 | 1464 | /* MOV.L Rm,@(disp4,Rn) */ |
| 1327 | | INLINE void MOVLS4(sh2_state *sh2, UINT32 m, UINT32 d, UINT32 n) |
| 1465 | void sh2_device::MOVLS4(UINT32 m, UINT32 d, UINT32 n) |
| 1328 | 1466 | { |
| 1329 | 1467 | UINT32 disp = d & 0x0f; |
| 1330 | | sh2->ea = sh2->r[n] + disp * 4; |
| 1331 | | WL( sh2, sh2->ea, sh2->r[m] ); |
| 1468 | m_sh2_state->ea = m_sh2_state->r[n] + disp * 4; |
| 1469 | WL( m_sh2_state->ea, m_sh2_state->r[m] ); |
| 1332 | 1470 | } |
| 1333 | 1471 | |
| 1334 | 1472 | /* MOV.B @(disp4,Rm),R0 */ |
| 1335 | | INLINE void MOVBL4(sh2_state *sh2, UINT32 m, UINT32 d) |
| 1473 | void sh2_device::MOVBL4(UINT32 m, UINT32 d) |
| 1336 | 1474 | { |
| 1337 | 1475 | UINT32 disp = d & 0x0f; |
| 1338 | | sh2->ea = sh2->r[m] + disp; |
| 1339 | | sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea ); |
| 1476 | m_sh2_state->ea = m_sh2_state->r[m] + disp; |
| 1477 | m_sh2_state->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( m_sh2_state->ea ); |
| 1340 | 1478 | } |
| 1341 | 1479 | |
| 1342 | 1480 | /* MOV.W @(disp4,Rm),R0 */ |
| 1343 | | INLINE void MOVWL4(sh2_state *sh2, UINT32 m, UINT32 d) |
| 1481 | void sh2_device::MOVWL4(UINT32 m, UINT32 d) |
| 1344 | 1482 | { |
| 1345 | 1483 | UINT32 disp = d & 0x0f; |
| 1346 | | sh2->ea = sh2->r[m] + disp * 2; |
| 1347 | | sh2->r[0] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea ); |
| 1484 | m_sh2_state->ea = m_sh2_state->r[m] + disp * 2; |
| 1485 | m_sh2_state->r[0] = (UINT32)(INT32)(INT16) RW( m_sh2_state->ea ); |
| 1348 | 1486 | } |
| 1349 | 1487 | |
| 1350 | 1488 | /* MOV.L @(disp4,Rm),Rn */ |
| 1351 | | INLINE void MOVLL4(sh2_state *sh2, UINT32 m, UINT32 d, UINT32 n) |
| 1489 | void sh2_device::MOVLL4(UINT32 m, UINT32 d, UINT32 n) |
| 1352 | 1490 | { |
| 1353 | 1491 | UINT32 disp = d & 0x0f; |
| 1354 | | sh2->ea = sh2->r[m] + disp * 4; |
| 1355 | | sh2->r[n] = RL( sh2, sh2->ea ); |
| 1492 | m_sh2_state->ea = m_sh2_state->r[m] + disp * 4; |
| 1493 | m_sh2_state->r[n] = RL( m_sh2_state->ea ); |
| 1356 | 1494 | } |
| 1357 | 1495 | |
| 1358 | 1496 | /* MOVA @(disp8,PC),R0 */ |
| 1359 | | INLINE void MOVA(sh2_state *sh2, UINT32 d) |
| 1497 | void sh2_device::MOVA(UINT32 d) |
| 1360 | 1498 | { |
| 1361 | 1499 | UINT32 disp = d & 0xff; |
| 1362 | | sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4; |
| 1363 | | sh2->r[0] = sh2->ea; |
| 1500 | m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4; |
| 1501 | m_sh2_state->r[0] = m_sh2_state->ea; |
| 1364 | 1502 | } |
| 1365 | 1503 | |
| 1366 | 1504 | /* MOVT Rn */ |
| 1367 | | INLINE void MOVT(sh2_state *sh2, UINT32 n) |
| 1505 | void sh2_device::MOVT(UINT32 n) |
| 1368 | 1506 | { |
| 1369 | | sh2->r[n] = sh2->sr & T; |
| 1507 | m_sh2_state->r[n] = m_sh2_state->sr & T; |
| 1370 | 1508 | } |
| 1371 | 1509 | |
| 1372 | 1510 | /* MUL.L Rm,Rn */ |
| 1373 | | INLINE void MULL(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1511 | void sh2_device::MULL(UINT32 m, UINT32 n) |
| 1374 | 1512 | { |
| 1375 | | sh2->macl = sh2->r[n] * sh2->r[m]; |
| 1376 | | sh2->icount--; |
| 1513 | m_sh2_state->macl = m_sh2_state->r[n] * m_sh2_state->r[m]; |
| 1514 | m_sh2_state->icount--; |
| 1377 | 1515 | } |
| 1378 | 1516 | |
| 1379 | 1517 | /* MULS Rm,Rn */ |
| 1380 | | INLINE void MULS(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1518 | void sh2_device::MULS(UINT32 m, UINT32 n) |
| 1381 | 1519 | { |
| 1382 | | sh2->macl = (INT16) sh2->r[n] * (INT16) sh2->r[m]; |
| 1520 | m_sh2_state->macl = (INT16) m_sh2_state->r[n] * (INT16) m_sh2_state->r[m]; |
| 1383 | 1521 | } |
| 1384 | 1522 | |
| 1385 | 1523 | /* MULU Rm,Rn */ |
| 1386 | | INLINE void MULU(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1524 | void sh2_device::MULU(UINT32 m, UINT32 n) |
| 1387 | 1525 | { |
| 1388 | | sh2->macl = (UINT16) sh2->r[n] * (UINT16) sh2->r[m]; |
| 1526 | m_sh2_state->macl = (UINT16) m_sh2_state->r[n] * (UINT16) m_sh2_state->r[m]; |
| 1389 | 1527 | } |
| 1390 | 1528 | |
| 1391 | 1529 | /* NEG Rm,Rn */ |
| 1392 | | INLINE void NEG(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1530 | void sh2_device::NEG(UINT32 m, UINT32 n) |
| 1393 | 1531 | { |
| 1394 | | sh2->r[n] = 0 - sh2->r[m]; |
| 1532 | m_sh2_state->r[n] = 0 - m_sh2_state->r[m]; |
| 1395 | 1533 | } |
| 1396 | 1534 | |
| 1397 | 1535 | /* NEGC Rm,Rn */ |
| 1398 | | INLINE void NEGC(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1536 | void sh2_device::NEGC(UINT32 m, UINT32 n) |
| 1399 | 1537 | { |
| 1400 | 1538 | UINT32 temp; |
| 1401 | 1539 | |
| 1402 | | temp = sh2->r[m]; |
| 1403 | | sh2->r[n] = -temp - (sh2->sr & T); |
| 1404 | | if (temp || (sh2->sr & T)) |
| 1405 | | sh2->sr |= T; |
| 1540 | temp = m_sh2_state->r[m]; |
| 1541 | m_sh2_state->r[n] = -temp - (m_sh2_state->sr & T); |
| 1542 | if (temp || (m_sh2_state->sr & T)) |
| 1543 | m_sh2_state->sr |= T; |
| 1406 | 1544 | else |
| 1407 | | sh2->sr &= ~T; |
| 1545 | m_sh2_state->sr &= ~T; |
| 1408 | 1546 | } |
| 1409 | 1547 | |
| 1410 | 1548 | /* NOP */ |
| 1411 | | INLINE void NOP(void) |
| 1549 | void sh2_device::NOP(void) |
| 1412 | 1550 | { |
| 1413 | 1551 | } |
| 1414 | 1552 | |
| 1415 | 1553 | /* NOT Rm,Rn */ |
| 1416 | | INLINE void NOT(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1554 | void sh2_device::NOT(UINT32 m, UINT32 n) |
| 1417 | 1555 | { |
| 1418 | | sh2->r[n] = ~sh2->r[m]; |
| 1556 | m_sh2_state->r[n] = ~m_sh2_state->r[m]; |
| 1419 | 1557 | } |
| 1420 | 1558 | |
| 1421 | 1559 | /* OR Rm,Rn */ |
| 1422 | | INLINE void OR(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1560 | void sh2_device::OR(UINT32 m, UINT32 n) |
| 1423 | 1561 | { |
| 1424 | | sh2->r[n] |= sh2->r[m]; |
| 1562 | m_sh2_state->r[n] |= m_sh2_state->r[m]; |
| 1425 | 1563 | } |
| 1426 | 1564 | |
| 1427 | 1565 | /* OR #imm,R0 */ |
| 1428 | | INLINE void ORI(sh2_state *sh2, UINT32 i) |
| 1566 | void sh2_device::ORI(UINT32 i) |
| 1429 | 1567 | { |
| 1430 | | sh2->r[0] |= i; |
| 1568 | m_sh2_state->r[0] |= i; |
| 1431 | 1569 | } |
| 1432 | 1570 | |
| 1433 | 1571 | /* OR.B #imm,@(R0,GBR) */ |
| 1434 | | INLINE void ORM(sh2_state *sh2, UINT32 i) |
| 1572 | void sh2_device::ORM(UINT32 i) |
| 1435 | 1573 | { |
| 1436 | 1574 | UINT32 temp; |
| 1437 | 1575 | |
| 1438 | | sh2->ea = sh2->gbr + sh2->r[0]; |
| 1439 | | temp = RB( sh2, sh2->ea ); |
| 1576 | m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; |
| 1577 | temp = RB( m_sh2_state->ea ); |
| 1440 | 1578 | temp |= i; |
| 1441 | | WB( sh2, sh2->ea, temp ); |
| 1442 | | sh2->icount -= 2; |
| 1579 | WB( m_sh2_state->ea, temp ); |
| 1580 | m_sh2_state->icount -= 2; |
| 1443 | 1581 | } |
| 1444 | 1582 | |
| 1445 | 1583 | /* ROTCL Rn */ |
| 1446 | | INLINE void ROTCL(sh2_state *sh2, UINT32 n) |
| 1584 | void sh2_device::ROTCL(UINT32 n) |
| 1447 | 1585 | { |
| 1448 | 1586 | UINT32 temp; |
| 1449 | 1587 | |
| 1450 | | temp = (sh2->r[n] >> 31) & T; |
| 1451 | | sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T); |
| 1452 | | sh2->sr = (sh2->sr & ~T) | temp; |
| 1588 | temp = (m_sh2_state->r[n] >> 31) & T; |
| 1589 | m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); |
| 1590 | m_sh2_state->sr = (m_sh2_state->sr & ~T) | temp; |
| 1453 | 1591 | } |
| 1454 | 1592 | |
| 1455 | 1593 | /* ROTCR Rn */ |
| 1456 | | INLINE void ROTCR(sh2_state *sh2, UINT32 n) |
| 1594 | void sh2_device::ROTCR(UINT32 n) |
| 1457 | 1595 | { |
| 1458 | 1596 | UINT32 temp; |
| 1459 | | temp = (sh2->sr & T) << 31; |
| 1460 | | if (sh2->r[n] & T) |
| 1461 | | sh2->sr |= T; |
| 1597 | temp = (m_sh2_state->sr & T) << 31; |
| 1598 | if (m_sh2_state->r[n] & T) |
| 1599 | m_sh2_state->sr |= T; |
| 1462 | 1600 | else |
| 1463 | | sh2->sr &= ~T; |
| 1464 | | sh2->r[n] = (sh2->r[n] >> 1) | temp; |
| 1601 | m_sh2_state->sr &= ~T; |
| 1602 | m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | temp; |
| 1465 | 1603 | } |
| 1466 | 1604 | |
| 1467 | 1605 | /* ROTL Rn */ |
| 1468 | | INLINE void ROTL(sh2_state *sh2, UINT32 n) |
| 1606 | void sh2_device::ROTL(UINT32 n) |
| 1469 | 1607 | { |
| 1470 | | sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); |
| 1471 | | sh2->r[n] = (sh2->r[n] << 1) | (sh2->r[n] >> 31); |
| 1608 | m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); |
| 1609 | m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->r[n] >> 31); |
| 1472 | 1610 | } |
| 1473 | 1611 | |
| 1474 | 1612 | /* ROTR Rn */ |
| 1475 | | INLINE void ROTR(sh2_state *sh2, UINT32 n) |
| 1613 | void sh2_device::ROTR(UINT32 n) |
| 1476 | 1614 | { |
| 1477 | | sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); |
| 1478 | | sh2->r[n] = (sh2->r[n] >> 1) | (sh2->r[n] << 31); |
| 1615 | m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); |
| 1616 | m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | (m_sh2_state->r[n] << 31); |
| 1479 | 1617 | } |
| 1480 | 1618 | |
| 1481 | 1619 | /* RTE */ |
| 1482 | | INLINE void RTE(sh2_state *sh2) |
| 1620 | void sh2_device::RTE() |
| 1483 | 1621 | { |
| 1484 | | sh2->ea = sh2->r[15]; |
| 1485 | | sh2->delay = sh2->pc; |
| 1486 | | sh2->pc = RL( sh2, sh2->ea ); |
| 1487 | | sh2->r[15] += 4; |
| 1488 | | sh2->ea = sh2->r[15]; |
| 1489 | | sh2->sr = RL( sh2, sh2->ea ) & FLAGS; |
| 1490 | | sh2->r[15] += 4; |
| 1491 | | sh2->icount -= 3; |
| 1492 | | sh2->test_irq = 1; |
| 1622 | m_sh2_state->ea = m_sh2_state->r[15]; |
| 1623 | m_delay = m_sh2_state->pc; |
| 1624 | m_sh2_state->pc = RL( m_sh2_state->ea ); |
| 1625 | m_sh2_state->r[15] += 4; |
| 1626 | m_sh2_state->ea = m_sh2_state->r[15]; |
| 1627 | m_sh2_state->sr = RL( m_sh2_state->ea ) & FLAGS; |
| 1628 | m_sh2_state->r[15] += 4; |
| 1629 | m_sh2_state->icount -= 3; |
| 1630 | m_test_irq = 1; |
| 1493 | 1631 | } |
| 1494 | 1632 | |
| 1495 | 1633 | /* RTS */ |
| 1496 | | INLINE void RTS(sh2_state *sh2) |
| 1634 | void sh2_device::RTS() |
| 1497 | 1635 | { |
| 1498 | | sh2->delay = sh2->pc; |
| 1499 | | sh2->pc = sh2->ea = sh2->pr; |
| 1500 | | sh2->icount--; |
| 1636 | m_delay = m_sh2_state->pc; |
| 1637 | m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pr; |
| 1638 | m_sh2_state->icount--; |
| 1501 | 1639 | } |
| 1502 | 1640 | |
| 1503 | 1641 | /* SETT */ |
| 1504 | | INLINE void SETT(sh2_state *sh2) |
| 1642 | void sh2_device::SETT() |
| 1505 | 1643 | { |
| 1506 | | sh2->sr |= T; |
| 1644 | m_sh2_state->sr |= T; |
| 1507 | 1645 | } |
| 1508 | 1646 | |
| 1509 | 1647 | /* SHAL Rn (same as SHLL) */ |
| 1510 | | INLINE void SHAL(sh2_state *sh2, UINT32 n) |
| 1648 | void sh2_device::SHAL(UINT32 n) |
| 1511 | 1649 | { |
| 1512 | | sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); |
| 1513 | | sh2->r[n] <<= 1; |
| 1650 | m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); |
| 1651 | m_sh2_state->r[n] <<= 1; |
| 1514 | 1652 | } |
| 1515 | 1653 | |
| 1516 | 1654 | /* SHAR Rn */ |
| 1517 | | INLINE void SHAR(sh2_state *sh2, UINT32 n) |
| 1655 | void sh2_device::SHAR(UINT32 n) |
| 1518 | 1656 | { |
| 1519 | | sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); |
| 1520 | | sh2->r[n] = (UINT32)((INT32)sh2->r[n] >> 1); |
| 1657 | m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); |
| 1658 | m_sh2_state->r[n] = (UINT32)((INT32)m_sh2_state->r[n] >> 1); |
| 1521 | 1659 | } |
| 1522 | 1660 | |
| 1523 | 1661 | /* SHLL Rn (same as SHAL) */ |
| 1524 | | INLINE void SHLL(sh2_state *sh2, UINT32 n) |
| 1662 | void sh2_device::SHLL(UINT32 n) |
| 1525 | 1663 | { |
| 1526 | | sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); |
| 1527 | | sh2->r[n] <<= 1; |
| 1664 | m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); |
| 1665 | m_sh2_state->r[n] <<= 1; |
| 1528 | 1666 | } |
| 1529 | 1667 | |
| 1530 | 1668 | /* SHLL2 Rn */ |
| 1531 | | INLINE void SHLL2(sh2_state *sh2, UINT32 n) |
| 1669 | void sh2_device::SHLL2(UINT32 n) |
| 1532 | 1670 | { |
| 1533 | | sh2->r[n] <<= 2; |
| 1671 | m_sh2_state->r[n] <<= 2; |
| 1534 | 1672 | } |
| 1535 | 1673 | |
| 1536 | 1674 | /* SHLL8 Rn */ |
| 1537 | | INLINE void SHLL8(sh2_state *sh2, UINT32 n) |
| 1675 | void sh2_device::SHLL8(UINT32 n) |
| 1538 | 1676 | { |
| 1539 | | sh2->r[n] <<= 8; |
| 1677 | m_sh2_state->r[n] <<= 8; |
| 1540 | 1678 | } |
| 1541 | 1679 | |
| 1542 | 1680 | /* SHLL16 Rn */ |
| 1543 | | INLINE void SHLL16(sh2_state *sh2, UINT32 n) |
| 1681 | void sh2_device::SHLL16(UINT32 n) |
| 1544 | 1682 | { |
| 1545 | | sh2->r[n] <<= 16; |
| 1683 | m_sh2_state->r[n] <<= 16; |
| 1546 | 1684 | } |
| 1547 | 1685 | |
| 1548 | 1686 | /* SHLR Rn */ |
| 1549 | | INLINE void SHLR(sh2_state *sh2, UINT32 n) |
| 1687 | void sh2_device::SHLR(UINT32 n) |
| 1550 | 1688 | { |
| 1551 | | sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); |
| 1552 | | sh2->r[n] >>= 1; |
| 1689 | m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); |
| 1690 | m_sh2_state->r[n] >>= 1; |
| 1553 | 1691 | } |
| 1554 | 1692 | |
| 1555 | 1693 | /* SHLR2 Rn */ |
| 1556 | | INLINE void SHLR2(sh2_state *sh2, UINT32 n) |
| 1694 | void sh2_device::SHLR2(UINT32 n) |
| 1557 | 1695 | { |
| 1558 | | sh2->r[n] >>= 2; |
| 1696 | m_sh2_state->r[n] >>= 2; |
| 1559 | 1697 | } |
| 1560 | 1698 | |
| 1561 | 1699 | /* SHLR8 Rn */ |
| 1562 | | INLINE void SHLR8(sh2_state *sh2, UINT32 n) |
| 1700 | void sh2_device::SHLR8(UINT32 n) |
| 1563 | 1701 | { |
| 1564 | | sh2->r[n] >>= 8; |
| 1702 | m_sh2_state->r[n] >>= 8; |
| 1565 | 1703 | } |
| 1566 | 1704 | |
| 1567 | 1705 | /* SHLR16 Rn */ |
| 1568 | | INLINE void SHLR16(sh2_state *sh2, UINT32 n) |
| 1706 | void sh2_device::SHLR16(UINT32 n) |
| 1569 | 1707 | { |
| 1570 | | sh2->r[n] >>= 16; |
| 1708 | m_sh2_state->r[n] >>= 16; |
| 1571 | 1709 | } |
| 1572 | 1710 | |
| 1573 | 1711 | /* SLEEP */ |
| 1574 | | INLINE void SLEEP(sh2_state *sh2) |
| 1712 | void sh2_device::SLEEP() |
| 1575 | 1713 | { |
| 1576 | | if(sh2->sleep_mode != 2) |
| 1577 | | sh2->pc -= 2; |
| 1578 | | sh2->icount -= 2; |
| 1714 | if(m_sh2_state->sleep_mode != 2) |
| 1715 | m_sh2_state->pc -= 2; |
| 1716 | m_sh2_state->icount -= 2; |
| 1579 | 1717 | /* Wait_for_exception; */ |
| 1580 | | if(sh2->sleep_mode == 0) |
| 1581 | | sh2->sleep_mode = 1; |
| 1582 | | else if(sh2->sleep_mode == 2) |
| 1583 | | sh2->sleep_mode = 0; |
| 1718 | if(m_sh2_state->sleep_mode == 0) |
| 1719 | m_sh2_state->sleep_mode = 1; |
| 1720 | else if(m_sh2_state->sleep_mode == 2) |
| 1721 | m_sh2_state->sleep_mode = 0; |
| 1584 | 1722 | } |
| 1585 | 1723 | |
| 1586 | 1724 | /* STC SR,Rn */ |
| 1587 | | INLINE void STCSR(sh2_state *sh2, UINT32 n) |
| 1725 | void sh2_device::STCSR(UINT32 n) |
| 1588 | 1726 | { |
| 1589 | | sh2->r[n] = sh2->sr; |
| 1727 | m_sh2_state->r[n] = m_sh2_state->sr; |
| 1590 | 1728 | } |
| 1591 | 1729 | |
| 1592 | 1730 | /* STC GBR,Rn */ |
| 1593 | | INLINE void STCGBR(sh2_state *sh2, UINT32 n) |
| 1731 | void sh2_device::STCGBR(UINT32 n) |
| 1594 | 1732 | { |
| 1595 | | sh2->r[n] = sh2->gbr; |
| 1733 | m_sh2_state->r[n] = m_sh2_state->gbr; |
| 1596 | 1734 | } |
| 1597 | 1735 | |
| 1598 | 1736 | /* STC VBR,Rn */ |
| 1599 | | INLINE void STCVBR(sh2_state *sh2, UINT32 n) |
| 1737 | void sh2_device::STCVBR(UINT32 n) |
| 1600 | 1738 | { |
| 1601 | | sh2->r[n] = sh2->vbr; |
| 1739 | m_sh2_state->r[n] = m_sh2_state->vbr; |
| 1602 | 1740 | } |
| 1603 | 1741 | |
| 1604 | 1742 | /* STC.L SR,@-Rn */ |
| 1605 | | INLINE void STCMSR(sh2_state *sh2, UINT32 n) |
| 1743 | void sh2_device::STCMSR(UINT32 n) |
| 1606 | 1744 | { |
| 1607 | | sh2->r[n] -= 4; |
| 1608 | | sh2->ea = sh2->r[n]; |
| 1609 | | WL( sh2, sh2->ea, sh2->sr ); |
| 1610 | | sh2->icount--; |
| 1745 | m_sh2_state->r[n] -= 4; |
| 1746 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1747 | WL( m_sh2_state->ea, m_sh2_state->sr ); |
| 1748 | m_sh2_state->icount--; |
| 1611 | 1749 | } |
| 1612 | 1750 | |
| 1613 | 1751 | /* STC.L GBR,@-Rn */ |
| 1614 | | INLINE void STCMGBR(sh2_state *sh2, UINT32 n) |
| 1752 | void sh2_device::STCMGBR(UINT32 n) |
| 1615 | 1753 | { |
| 1616 | | sh2->r[n] -= 4; |
| 1617 | | sh2->ea = sh2->r[n]; |
| 1618 | | WL( sh2, sh2->ea, sh2->gbr ); |
| 1619 | | sh2->icount--; |
| 1754 | m_sh2_state->r[n] -= 4; |
| 1755 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1756 | WL( m_sh2_state->ea, m_sh2_state->gbr ); |
| 1757 | m_sh2_state->icount--; |
| 1620 | 1758 | } |
| 1621 | 1759 | |
| 1622 | 1760 | /* STC.L VBR,@-Rn */ |
| 1623 | | INLINE void STCMVBR(sh2_state *sh2, UINT32 n) |
| 1761 | void sh2_device::STCMVBR(UINT32 n) |
| 1624 | 1762 | { |
| 1625 | | sh2->r[n] -= 4; |
| 1626 | | sh2->ea = sh2->r[n]; |
| 1627 | | WL( sh2, sh2->ea, sh2->vbr ); |
| 1628 | | sh2->icount--; |
| 1763 | m_sh2_state->r[n] -= 4; |
| 1764 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1765 | WL( m_sh2_state->ea, m_sh2_state->vbr ); |
| 1766 | m_sh2_state->icount--; |
| 1629 | 1767 | } |
| 1630 | 1768 | |
| 1631 | 1769 | /* STS MACH,Rn */ |
| 1632 | | INLINE void STSMACH(sh2_state *sh2, UINT32 n) |
| 1770 | void sh2_device::STSMACH(UINT32 n) |
| 1633 | 1771 | { |
| 1634 | | sh2->r[n] = sh2->mach; |
| 1772 | m_sh2_state->r[n] = m_sh2_state->mach; |
| 1635 | 1773 | } |
| 1636 | 1774 | |
| 1637 | 1775 | /* STS MACL,Rn */ |
| 1638 | | INLINE void STSMACL(sh2_state *sh2, UINT32 n) |
| 1776 | void sh2_device::STSMACL(UINT32 n) |
| 1639 | 1777 | { |
| 1640 | | sh2->r[n] = sh2->macl; |
| 1778 | m_sh2_state->r[n] = m_sh2_state->macl; |
| 1641 | 1779 | } |
| 1642 | 1780 | |
| 1643 | 1781 | /* STS PR,Rn */ |
| 1644 | | INLINE void STSPR(sh2_state *sh2, UINT32 n) |
| 1782 | void sh2_device::STSPR(UINT32 n) |
| 1645 | 1783 | { |
| 1646 | | sh2->r[n] = sh2->pr; |
| 1784 | m_sh2_state->r[n] = m_sh2_state->pr; |
| 1647 | 1785 | } |
| 1648 | 1786 | |
| 1649 | 1787 | /* STS.L MACH,@-Rn */ |
| 1650 | | INLINE void STSMMACH(sh2_state *sh2, UINT32 n) |
| 1788 | void sh2_device::STSMMACH(UINT32 n) |
| 1651 | 1789 | { |
| 1652 | | sh2->r[n] -= 4; |
| 1653 | | sh2->ea = sh2->r[n]; |
| 1654 | | WL( sh2, sh2->ea, sh2->mach ); |
| 1790 | m_sh2_state->r[n] -= 4; |
| 1791 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1792 | WL( m_sh2_state->ea, m_sh2_state->mach ); |
| 1655 | 1793 | } |
| 1656 | 1794 | |
| 1657 | 1795 | /* STS.L MACL,@-Rn */ |
| 1658 | | INLINE void STSMMACL(sh2_state *sh2, UINT32 n) |
| 1796 | void sh2_device::STSMMACL(UINT32 n) |
| 1659 | 1797 | { |
| 1660 | | sh2->r[n] -= 4; |
| 1661 | | sh2->ea = sh2->r[n]; |
| 1662 | | WL( sh2, sh2->ea, sh2->macl ); |
| 1798 | m_sh2_state->r[n] -= 4; |
| 1799 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1800 | WL( m_sh2_state->ea, m_sh2_state->macl ); |
| 1663 | 1801 | } |
| 1664 | 1802 | |
| 1665 | 1803 | /* STS.L PR,@-Rn */ |
| 1666 | | INLINE void STSMPR(sh2_state *sh2, UINT32 n) |
| 1804 | void sh2_device::STSMPR(UINT32 n) |
| 1667 | 1805 | { |
| 1668 | | sh2->r[n] -= 4; |
| 1669 | | sh2->ea = sh2->r[n]; |
| 1670 | | WL( sh2, sh2->ea, sh2->pr ); |
| 1806 | m_sh2_state->r[n] -= 4; |
| 1807 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1808 | WL( m_sh2_state->ea, m_sh2_state->pr ); |
| 1671 | 1809 | } |
| 1672 | 1810 | |
| 1673 | 1811 | /* SUB Rm,Rn */ |
| 1674 | | INLINE void SUB(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1812 | void sh2_device::SUB(UINT32 m, UINT32 n) |
| 1675 | 1813 | { |
| 1676 | | sh2->r[n] -= sh2->r[m]; |
| 1814 | m_sh2_state->r[n] -= m_sh2_state->r[m]; |
| 1677 | 1815 | } |
| 1678 | 1816 | |
| 1679 | 1817 | /* SUBC Rm,Rn */ |
| 1680 | | INLINE void SUBC(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1818 | void sh2_device::SUBC(UINT32 m, UINT32 n) |
| 1681 | 1819 | { |
| 1682 | 1820 | UINT32 tmp0, tmp1; |
| 1683 | 1821 | |
| 1684 | | tmp1 = sh2->r[n] - sh2->r[m]; |
| 1685 | | tmp0 = sh2->r[n]; |
| 1686 | | sh2->r[n] = tmp1 - (sh2->sr & T); |
| 1822 | tmp1 = m_sh2_state->r[n] - m_sh2_state->r[m]; |
| 1823 | tmp0 = m_sh2_state->r[n]; |
| 1824 | m_sh2_state->r[n] = tmp1 - (m_sh2_state->sr & T); |
| 1687 | 1825 | if (tmp0 < tmp1) |
| 1688 | | sh2->sr |= T; |
| 1826 | m_sh2_state->sr |= T; |
| 1689 | 1827 | else |
| 1690 | | sh2->sr &= ~T; |
| 1691 | | if (tmp1 < sh2->r[n]) |
| 1692 | | sh2->sr |= T; |
| 1828 | m_sh2_state->sr &= ~T; |
| 1829 | if (tmp1 < m_sh2_state->r[n]) |
| 1830 | m_sh2_state->sr |= T; |
| 1693 | 1831 | } |
| 1694 | 1832 | |
| 1695 | 1833 | /* SUBV Rm,Rn */ |
| 1696 | | INLINE void SUBV(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1834 | void sh2_device::SUBV(UINT32 m, UINT32 n) |
| 1697 | 1835 | { |
| 1698 | 1836 | INT32 dest, src, ans; |
| 1699 | 1837 | |
| 1700 | | if ((INT32) sh2->r[n] >= 0) |
| 1838 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 1701 | 1839 | dest = 0; |
| 1702 | 1840 | else |
| 1703 | 1841 | dest = 1; |
| 1704 | | if ((INT32) sh2->r[m] >= 0) |
| 1842 | if ((INT32) m_sh2_state->r[m] >= 0) |
| 1705 | 1843 | src = 0; |
| 1706 | 1844 | else |
| 1707 | 1845 | src = 1; |
| 1708 | 1846 | src += dest; |
| 1709 | | sh2->r[n] -= sh2->r[m]; |
| 1710 | | if ((INT32) sh2->r[n] >= 0) |
| 1847 | m_sh2_state->r[n] -= m_sh2_state->r[m]; |
| 1848 | if ((INT32) m_sh2_state->r[n] >= 0) |
| 1711 | 1849 | ans = 0; |
| 1712 | 1850 | else |
| 1713 | 1851 | ans = 1; |
| r29568 | r29569 | |
| 1715 | 1853 | if (src == 1) |
| 1716 | 1854 | { |
| 1717 | 1855 | if (ans == 1) |
| 1718 | | sh2->sr |= T; |
| 1856 | m_sh2_state->sr |= T; |
| 1719 | 1857 | else |
| 1720 | | sh2->sr &= ~T; |
| 1858 | m_sh2_state->sr &= ~T; |
| 1721 | 1859 | } |
| 1722 | 1860 | else |
| 1723 | | sh2->sr &= ~T; |
| 1861 | m_sh2_state->sr &= ~T; |
| 1724 | 1862 | } |
| 1725 | 1863 | |
| 1726 | 1864 | /* SWAP.B Rm,Rn */ |
| 1727 | | INLINE void SWAPB(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1865 | void sh2_device::SWAPB(UINT32 m, UINT32 n) |
| 1728 | 1866 | { |
| 1729 | 1867 | UINT32 temp0, temp1; |
| 1730 | 1868 | |
| 1731 | | temp0 = sh2->r[m] & 0xffff0000; |
| 1732 | | temp1 = (sh2->r[m] & 0x000000ff) << 8; |
| 1733 | | sh2->r[n] = (sh2->r[m] >> 8) & 0x000000ff; |
| 1734 | | sh2->r[n] = sh2->r[n] | temp1 | temp0; |
| 1869 | temp0 = m_sh2_state->r[m] & 0xffff0000; |
| 1870 | temp1 = (m_sh2_state->r[m] & 0x000000ff) << 8; |
| 1871 | m_sh2_state->r[n] = (m_sh2_state->r[m] >> 8) & 0x000000ff; |
| 1872 | m_sh2_state->r[n] = m_sh2_state->r[n] | temp1 | temp0; |
| 1735 | 1873 | } |
| 1736 | 1874 | |
| 1737 | 1875 | /* SWAP.W Rm,Rn */ |
| 1738 | | INLINE void SWAPW(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1876 | void sh2_device::SWAPW(UINT32 m, UINT32 n) |
| 1739 | 1877 | { |
| 1740 | 1878 | UINT32 temp; |
| 1741 | 1879 | |
| 1742 | | temp = (sh2->r[m] >> 16) & 0x0000ffff; |
| 1743 | | sh2->r[n] = (sh2->r[m] << 16) | temp; |
| 1880 | temp = (m_sh2_state->r[m] >> 16) & 0x0000ffff; |
| 1881 | m_sh2_state->r[n] = (m_sh2_state->r[m] << 16) | temp; |
| 1744 | 1882 | } |
| 1745 | 1883 | |
| 1746 | 1884 | /* TAS.B @Rn */ |
| 1747 | | INLINE void TAS(sh2_state *sh2, UINT32 n) |
| 1885 | void sh2_device::TAS(UINT32 n) |
| 1748 | 1886 | { |
| 1749 | 1887 | UINT32 temp; |
| 1750 | | sh2->ea = sh2->r[n]; |
| 1888 | m_sh2_state->ea = m_sh2_state->r[n]; |
| 1751 | 1889 | /* Bus Lock enable */ |
| 1752 | | temp = RB( sh2, sh2->ea ); |
| 1890 | temp = RB( m_sh2_state->ea ); |
| 1753 | 1891 | if (temp == 0) |
| 1754 | | sh2->sr |= T; |
| 1892 | m_sh2_state->sr |= T; |
| 1755 | 1893 | else |
| 1756 | | sh2->sr &= ~T; |
| 1894 | m_sh2_state->sr &= ~T; |
| 1757 | 1895 | temp |= 0x80; |
| 1758 | 1896 | /* Bus Lock disable */ |
| 1759 | | WB( sh2, sh2->ea, temp ); |
| 1760 | | sh2->icount -= 3; |
| 1897 | WB( m_sh2_state->ea, temp ); |
| 1898 | m_sh2_state->icount -= 3; |
| 1761 | 1899 | } |
| 1762 | 1900 | |
| 1763 | 1901 | /* TRAPA #imm */ |
| 1764 | | INLINE void TRAPA(sh2_state *sh2, UINT32 i) |
| 1902 | void sh2_device::TRAPA(UINT32 i) |
| 1765 | 1903 | { |
| 1766 | 1904 | UINT32 imm = i & 0xff; |
| 1767 | 1905 | |
| 1768 | | sh2->ea = sh2->vbr + imm * 4; |
| 1906 | m_sh2_state->ea = m_sh2_state->vbr + imm * 4; |
| 1769 | 1907 | |
| 1770 | | sh2->r[15] -= 4; |
| 1771 | | WL( sh2, sh2->r[15], sh2->sr ); |
| 1772 | | sh2->r[15] -= 4; |
| 1773 | | WL( sh2, sh2->r[15], sh2->pc ); |
| 1908 | m_sh2_state->r[15] -= 4; |
| 1909 | WL( m_sh2_state->r[15], m_sh2_state->sr ); |
| 1910 | m_sh2_state->r[15] -= 4; |
| 1911 | WL( m_sh2_state->r[15], m_sh2_state->pc ); |
| 1774 | 1912 | |
| 1775 | | sh2->pc = RL( sh2, sh2->ea ); |
| 1913 | m_sh2_state->pc = RL( m_sh2_state->ea ); |
| 1776 | 1914 | |
| 1777 | | sh2->icount -= 7; |
| 1915 | m_sh2_state->icount -= 7; |
| 1778 | 1916 | } |
| 1779 | 1917 | |
| 1780 | 1918 | /* TST Rm,Rn */ |
| 1781 | | INLINE void TST(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1919 | void sh2_device::TST(UINT32 m, UINT32 n) |
| 1782 | 1920 | { |
| 1783 | | if ((sh2->r[n] & sh2->r[m]) == 0) |
| 1784 | | sh2->sr |= T; |
| 1921 | if ((m_sh2_state->r[n] & m_sh2_state->r[m]) == 0) |
| 1922 | m_sh2_state->sr |= T; |
| 1785 | 1923 | else |
| 1786 | | sh2->sr &= ~T; |
| 1924 | m_sh2_state->sr &= ~T; |
| 1787 | 1925 | } |
| 1788 | 1926 | |
| 1789 | 1927 | /* TST #imm,R0 */ |
| 1790 | | INLINE void TSTI(sh2_state *sh2, UINT32 i) |
| 1928 | void sh2_device::TSTI(UINT32 i) |
| 1791 | 1929 | { |
| 1792 | 1930 | UINT32 imm = i & 0xff; |
| 1793 | 1931 | |
| 1794 | | if ((imm & sh2->r[0]) == 0) |
| 1795 | | sh2->sr |= T; |
| 1932 | if ((imm & m_sh2_state->r[0]) == 0) |
| 1933 | m_sh2_state->sr |= T; |
| 1796 | 1934 | else |
| 1797 | | sh2->sr &= ~T; |
| 1935 | m_sh2_state->sr &= ~T; |
| 1798 | 1936 | } |
| 1799 | 1937 | |
| 1800 | 1938 | /* TST.B #imm,@(R0,GBR) */ |
| 1801 | | INLINE void TSTM(sh2_state *sh2, UINT32 i) |
| 1939 | void sh2_device::TSTM(UINT32 i) |
| 1802 | 1940 | { |
| 1803 | 1941 | UINT32 imm = i & 0xff; |
| 1804 | 1942 | |
| 1805 | | sh2->ea = sh2->gbr + sh2->r[0]; |
| 1806 | | if ((imm & RB( sh2, sh2->ea )) == 0) |
| 1807 | | sh2->sr |= T; |
| 1943 | m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; |
| 1944 | if ((imm & RB( m_sh2_state->ea )) == 0) |
| 1945 | m_sh2_state->sr |= T; |
| 1808 | 1946 | else |
| 1809 | | sh2->sr &= ~T; |
| 1810 | | sh2->icount -= 2; |
| 1947 | m_sh2_state->sr &= ~T; |
| 1948 | m_sh2_state->icount -= 2; |
| 1811 | 1949 | } |
| 1812 | 1950 | |
| 1813 | 1951 | /* XOR Rm,Rn */ |
| 1814 | | INLINE void XOR(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1952 | void sh2_device::XOR(UINT32 m, UINT32 n) |
| 1815 | 1953 | { |
| 1816 | | sh2->r[n] ^= sh2->r[m]; |
| 1954 | m_sh2_state->r[n] ^= m_sh2_state->r[m]; |
| 1817 | 1955 | } |
| 1818 | 1956 | |
| 1819 | 1957 | /* XOR #imm,R0 */ |
| 1820 | | INLINE void XORI(sh2_state *sh2, UINT32 i) |
| 1958 | void sh2_device::XORI(UINT32 i) |
| 1821 | 1959 | { |
| 1822 | 1960 | UINT32 imm = i & 0xff; |
| 1823 | | sh2->r[0] ^= imm; |
| 1961 | m_sh2_state->r[0] ^= imm; |
| 1824 | 1962 | } |
| 1825 | 1963 | |
| 1826 | 1964 | /* XOR.B #imm,@(R0,GBR) */ |
| 1827 | | INLINE void XORM(sh2_state *sh2, UINT32 i) |
| 1965 | void sh2_device::XORM(UINT32 i) |
| 1828 | 1966 | { |
| 1829 | 1967 | UINT32 imm = i & 0xff; |
| 1830 | 1968 | UINT32 temp; |
| 1831 | 1969 | |
| 1832 | | sh2->ea = sh2->gbr + sh2->r[0]; |
| 1833 | | temp = RB( sh2, sh2->ea ); |
| 1970 | m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0]; |
| 1971 | temp = RB( m_sh2_state->ea ); |
| 1834 | 1972 | temp ^= imm; |
| 1835 | | WB( sh2, sh2->ea, temp ); |
| 1836 | | sh2->icount -= 2; |
| 1973 | WB( m_sh2_state->ea, temp ); |
| 1974 | m_sh2_state->icount -= 2; |
| 1837 | 1975 | } |
| 1838 | 1976 | |
| 1839 | 1977 | /* XTRCT Rm,Rn */ |
| 1840 | | INLINE void XTRCT(sh2_state *sh2, UINT32 m, UINT32 n) |
| 1978 | void sh2_device::XTRCT(UINT32 m, UINT32 n) |
| 1841 | 1979 | { |
| 1842 | 1980 | UINT32 temp; |
| 1843 | 1981 | |
| 1844 | | temp = (sh2->r[m] << 16) & 0xffff0000; |
| 1845 | | sh2->r[n] = (sh2->r[n] >> 16) & 0x0000ffff; |
| 1846 | | sh2->r[n] |= temp; |
| 1982 | temp = (m_sh2_state->r[m] << 16) & 0xffff0000; |
| 1983 | m_sh2_state->r[n] = (m_sh2_state->r[n] >> 16) & 0x0000ffff; |
| 1984 | m_sh2_state->r[n] |= temp; |
| 1847 | 1985 | } |
| 1848 | 1986 | |
| 1849 | 1987 | /***************************************************************************** |
| 1850 | 1988 | * OPCODE DISPATCHERS |
| 1851 | 1989 | *****************************************************************************/ |
| 1852 | 1990 | |
| 1853 | | INLINE void op0000(sh2_state *sh2, UINT16 opcode) |
| 1991 | void sh2_device::op0000(UINT16 opcode) |
| 1854 | 1992 | { |
| 1855 | 1993 | switch (opcode & 0x3F) |
| 1856 | 1994 | { |
| 1857 | | case 0x00: ILLEGAL(sh2); break; |
| 1858 | | case 0x01: ILLEGAL(sh2); break; |
| 1859 | | case 0x02: STCSR(sh2, Rn); break; |
| 1860 | | case 0x03: BSRF(sh2, Rn); break; |
| 1861 | | case 0x04: MOVBS0(sh2, Rm, Rn); break; |
| 1862 | | case 0x05: MOVWS0(sh2, Rm, Rn); break; |
| 1863 | | case 0x06: MOVLS0(sh2, Rm, Rn); break; |
| 1864 | | case 0x07: MULL(sh2, Rm, Rn); break; |
| 1865 | | case 0x08: CLRT(sh2); break; |
| 1995 | case 0x00: ILLEGAL(); break; |
| 1996 | case 0x01: ILLEGAL(); break; |
| 1997 | case 0x02: STCSR(Rn); break; |
| 1998 | case 0x03: BSRF(Rn); break; |
| 1999 | case 0x04: MOVBS0(Rm, Rn); break; |
| 2000 | case 0x05: MOVWS0(Rm, Rn); break; |
| 2001 | case 0x06: MOVLS0(Rm, Rn); break; |
| 2002 | case 0x07: MULL(Rm, Rn); break; |
| 2003 | case 0x08: CLRT(); break; |
| 1866 | 2004 | case 0x09: NOP(); break; |
| 1867 | | case 0x0a: STSMACH(sh2, Rn); break; |
| 1868 | | case 0x0b: RTS(sh2); break; |
| 1869 | | case 0x0c: MOVBL0(sh2, Rm, Rn); break; |
| 1870 | | case 0x0d: MOVWL0(sh2, Rm, Rn); break; |
| 1871 | | case 0x0e: MOVLL0(sh2, Rm, Rn); break; |
| 1872 | | case 0x0f: MAC_L(sh2, Rm, Rn); break; |
| 2005 | case 0x0a: STSMACH(Rn); break; |
| 2006 | case 0x0b: RTS(); break; |
| 2007 | case 0x0c: MOVBL0(Rm, Rn); break; |
| 2008 | case 0x0d: MOVWL0(Rm, Rn); break; |
| 2009 | case 0x0e: MOVLL0(Rm, Rn); break; |
| 2010 | case 0x0f: MAC_L(Rm, Rn); break; |
| 1873 | 2011 | |
| 1874 | | case 0x10: ILLEGAL(sh2); break; |
| 1875 | | case 0x11: ILLEGAL(sh2); break; |
| 1876 | | case 0x12: STCGBR(sh2, Rn); break; |
| 1877 | | case 0x13: ILLEGAL(sh2); break; |
| 1878 | | case 0x14: MOVBS0(sh2, Rm, Rn); break; |
| 1879 | | case 0x15: MOVWS0(sh2, Rm, Rn); break; |
| 1880 | | case 0x16: MOVLS0(sh2, Rm, Rn); break; |
| 1881 | | case 0x17: MULL(sh2, Rm, Rn); break; |
| 1882 | | case 0x18: SETT(sh2); break; |
| 1883 | | case 0x19: DIV0U(sh2); break; |
| 1884 | | case 0x1a: STSMACL(sh2, Rn); break; |
| 1885 | | case 0x1b: SLEEP(sh2); break; |
| 1886 | | case 0x1c: MOVBL0(sh2, Rm, Rn); break; |
| 1887 | | case 0x1d: MOVWL0(sh2, Rm, Rn); break; |
| 1888 | | case 0x1e: MOVLL0(sh2, Rm, Rn); break; |
| 1889 | | case 0x1f: MAC_L(sh2, Rm, Rn); break; |
| 2012 | case 0x10: ILLEGAL(); break; |
| 2013 | case 0x11: ILLEGAL(); break; |
| 2014 | case 0x12: STCGBR(Rn); break; |
| 2015 | case 0x13: ILLEGAL(); break; |
| 2016 | case 0x14: MOVBS0(Rm, Rn); break; |
| 2017 | case 0x15: MOVWS0(Rm, Rn); break; |
| 2018 | case 0x16: MOVLS0(Rm, Rn); break; |
| 2019 | case 0x17: MULL(Rm, Rn); break; |
| 2020 | case 0x18: SETT(); break; |
| 2021 | case 0x19: DIV0U(); break; |
| 2022 | case 0x1a: STSMACL(Rn); break; |
| 2023 | case 0x1b: SLEEP(); break; |
| 2024 | case 0x1c: MOVBL0(Rm, Rn); break; |
| 2025 | case 0x1d: MOVWL0(Rm, Rn); break; |
| 2026 | case 0x1e: MOVLL0(Rm, Rn); break; |
| 2027 | case 0x1f: MAC_L(Rm, Rn); break; |
| 1890 | 2028 | |
| 1891 | | case 0x20: ILLEGAL(sh2); break; |
| 1892 | | case 0x21: ILLEGAL(sh2); break; |
| 1893 | | case 0x22: STCVBR(sh2, Rn); break; |
| 1894 | | case 0x23: BRAF(sh2, Rn); break; |
| 1895 | | case 0x24: MOVBS0(sh2, Rm, Rn); break; |
| 1896 | | case 0x25: MOVWS0(sh2, Rm, Rn); break; |
| 1897 | | case 0x26: MOVLS0(sh2, Rm, Rn); break; |
| 1898 | | case 0x27: MULL(sh2, Rm, Rn); break; |
| 1899 | | case 0x28: CLRMAC(sh2); break; |
| 1900 | | case 0x29: MOVT(sh2, Rn); break; |
| 1901 | | case 0x2a: STSPR(sh2, Rn); break; |
| 1902 | | case 0x2b: RTE(sh2); break; |
| 1903 | | case 0x2c: MOVBL0(sh2, Rm, Rn); break; |
| 1904 | | case 0x2d: MOVWL0(sh2, Rm, Rn); break; |
| 1905 | | case 0x2e: MOVLL0(sh2, Rm, Rn); break; |
| 1906 | | case 0x2f: MAC_L(sh2, Rm, Rn); break; |
| 2029 | case 0x20: ILLEGAL(); break; |
| 2030 | case 0x21: ILLEGAL(); break; |
| 2031 | case 0x22: STCVBR(Rn); break; |
| 2032 | case 0x23: BRAF(Rn); break; |
| 2033 | case 0x24: MOVBS0(Rm, Rn); break; |
| 2034 | case 0x25: MOVWS0(Rm, Rn); break; |
| 2035 | case 0x26: MOVLS0(Rm, Rn); break; |
| 2036 | case 0x27: MULL(Rm, Rn); break; |
| 2037 | case 0x28: CLRMAC(); break; |
| 2038 | case 0x29: MOVT(Rn); break; |
| 2039 | case 0x2a: STSPR(Rn); break; |
| 2040 | case 0x2b: RTE(); break; |
| 2041 | case 0x2c: MOVBL0(Rm, Rn); break; |
| 2042 | case 0x2d: MOVWL0(Rm, Rn); break; |
| 2043 | case 0x2e: MOVLL0(Rm, Rn); break; |
| 2044 | case 0x2f: MAC_L(Rm, Rn); break; |
| 1907 | 2045 | |
| 1908 | | case 0x30: ILLEGAL(sh2); break; |
| 1909 | | case 0x31: ILLEGAL(sh2); break; |
| 1910 | | case 0x32: ILLEGAL(sh2); break; |
| 1911 | | case 0x33: ILLEGAL(sh2); break; |
| 1912 | | case 0x34: MOVBS0(sh2, Rm, Rn); break; |
| 1913 | | case 0x35: MOVWS0(sh2, Rm, Rn); break; |
| 1914 | | case 0x36: MOVLS0(sh2, Rm, Rn); break; |
| 1915 | | case 0x37: MULL(sh2, Rm, Rn); break; |
| 1916 | | case 0x38: ILLEGAL(sh2); break; |
| 1917 | | case 0x39: ILLEGAL(sh2); break; |
| 1918 | | case 0x3c: MOVBL0(sh2, Rm, Rn); break; |
| 1919 | | case 0x3d: MOVWL0(sh2, Rm, Rn); break; |
| 1920 | | case 0x3e: MOVLL0(sh2, Rm, Rn); break; |
| 1921 | | case 0x3f: MAC_L(sh2, Rm, Rn); break; |
| 1922 | | case 0x3a: ILLEGAL(sh2); break; |
| 1923 | | case 0x3b: ILLEGAL(sh2); break; |
| 2046 | case 0x30: ILLEGAL(); break; |
| 2047 | case 0x31: ILLEGAL(); break; |
| 2048 | case 0x32: ILLEGAL(); break; |
| 2049 | case 0x33: ILLEGAL(); break; |
| 2050 | case 0x34: MOVBS0(Rm, Rn); break; |
| 2051 | case 0x35: MOVWS0(Rm, Rn); break; |
| 2052 | case 0x36: MOVLS0(Rm, Rn); break; |
| 2053 | case 0x37: MULL(Rm, Rn); break; |
| 2054 | case 0x38: ILLEGAL(); break; |
| 2055 | case 0x39: ILLEGAL(); break; |
| 2056 | case 0x3c: MOVBL0(Rm, Rn); break; |
| 2057 | case 0x3d: MOVWL0(Rm, Rn); break; |
| 2058 | case 0x3e: MOVLL0(Rm, Rn); break; |
| 2059 | case 0x3f: MAC_L(Rm, Rn); break; |
| 2060 | case 0x3a: ILLEGAL(); break; |
| 2061 | case 0x3b: ILLEGAL(); break; |
| 1924 | 2062 | |
| 1925 | 2063 | |
| 1926 | 2064 | |
| 1927 | 2065 | } |
| 1928 | 2066 | } |
| 1929 | 2067 | |
| 1930 | | INLINE void op0001(sh2_state *sh2, UINT16 opcode) |
| 2068 | void sh2_device::op0001(UINT16 opcode) |
| 1931 | 2069 | { |
| 1932 | | MOVLS4(sh2, Rm, opcode & 0x0f, Rn); |
| 2070 | MOVLS4(Rm, opcode & 0x0f, Rn); |
| 1933 | 2071 | } |
| 1934 | 2072 | |
| 1935 | | INLINE void op0010(sh2_state *sh2, UINT16 opcode) |
| 2073 | void sh2_device::op0010(UINT16 opcode) |
| 1936 | 2074 | { |
| 1937 | 2075 | switch (opcode & 15) |
| 1938 | 2076 | { |
| 1939 | | case 0: MOVBS(sh2, Rm, Rn); break; |
| 1940 | | case 1: MOVWS(sh2, Rm, Rn); break; |
| 1941 | | case 2: MOVLS(sh2, Rm, Rn); break; |
| 1942 | | case 3: ILLEGAL(sh2); break; |
| 1943 | | case 4: MOVBM(sh2, Rm, Rn); break; |
| 1944 | | case 5: MOVWM(sh2, Rm, Rn); break; |
| 1945 | | case 6: MOVLM(sh2, Rm, Rn); break; |
| 1946 | | case 7: DIV0S(sh2, Rm, Rn); break; |
| 1947 | | case 8: TST(sh2, Rm, Rn); break; |
| 1948 | | case 9: AND(sh2, Rm, Rn); break; |
| 1949 | | case 10: XOR(sh2, Rm, Rn); break; |
| 1950 | | case 11: OR(sh2, Rm, Rn); break; |
| 1951 | | case 12: CMPSTR(sh2, Rm, Rn); break; |
| 1952 | | case 13: XTRCT(sh2, Rm, Rn); break; |
| 1953 | | case 14: MULU(sh2, Rm, Rn); break; |
| 1954 | | case 15: MULS(sh2, Rm, Rn); break; |
| 2077 | case 0: MOVBS(Rm, Rn); break; |
| 2078 | case 1: MOVWS(Rm, Rn); break; |
| 2079 | case 2: MOVLS(Rm, Rn); break; |
| 2080 | case 3: ILLEGAL(); break; |
| 2081 | case 4: MOVBM(Rm, Rn); break; |
| 2082 | case 5: MOVWM(Rm, Rn); break; |
| 2083 | case 6: MOVLM(Rm, Rn); break; |
| 2084 | case 7: DIV0S(Rm, Rn); break; |
| 2085 | case 8: TST(Rm, Rn); break; |
| 2086 | case 9: AND(Rm, Rn); break; |
| 2087 | case 10: XOR(Rm, Rn); break; |
| 2088 | case 11: OR(Rm, Rn); break; |
| 2089 | case 12: CMPSTR(Rm, Rn); break; |
| 2090 | case 13: XTRCT(Rm, Rn); break; |
| 2091 | case 14: MULU(Rm, Rn); break; |
| 2092 | case 15: MULS(Rm, Rn); break; |
| 1955 | 2093 | } |
| 1956 | 2094 | } |
| 1957 | 2095 | |
| 1958 | | INLINE void op0011(sh2_state *sh2, UINT16 opcode) |
| 2096 | void sh2_device::op0011(UINT16 opcode) |
| 1959 | 2097 | { |
| 1960 | 2098 | switch (opcode & 15) |
| 1961 | 2099 | { |
| 1962 | | case 0: CMPEQ(sh2, Rm, Rn); break; |
| 1963 | | case 1: ILLEGAL(sh2); break; |
| 1964 | | case 2: CMPHS(sh2, Rm, Rn); break; |
| 1965 | | case 3: CMPGE(sh2, Rm, Rn); break; |
| 1966 | | case 4: DIV1(sh2, Rm, Rn); break; |
| 1967 | | case 5: DMULU(sh2, Rm, Rn); break; |
| 1968 | | case 6: CMPHI(sh2, Rm, Rn); break; |
| 1969 | | case 7: CMPGT(sh2, Rm, Rn); break; |
| 1970 | | case 8: SUB(sh2, Rm, Rn); break; |
| 1971 | | case 9: ILLEGAL(sh2); break; |
| 1972 | | case 10: SUBC(sh2, Rm, Rn); break; |
| 1973 | | case 11: SUBV(sh2, Rm, Rn); break; |
| 1974 | | case 12: ADD(sh2, Rm, Rn); break; |
| 1975 | | case 13: DMULS(sh2, Rm, Rn); break; |
| 1976 | | case 14: ADDC(sh2, Rm, Rn); break; |
| 1977 | | case 15: ADDV(sh2, Rm, Rn); break; |
| 2100 | case 0: CMPEQ(Rm, Rn); break; |
| 2101 | case 1: ILLEGAL(); break; |
| 2102 | case 2: CMPHS(Rm, Rn); break; |
| 2103 | case 3: CMPGE(Rm, Rn); break; |
| 2104 | case 4: DIV1(Rm, Rn); break; |
| 2105 | case 5: DMULU(Rm, Rn); break; |
| 2106 | case 6: CMPHI(Rm, Rn); break; |
| 2107 | case 7: CMPGT(Rm, Rn); break; |
| 2108 | case 8: SUB(Rm, Rn); break; |
| 2109 | case 9: ILLEGAL(); break; |
| 2110 | case 10: SUBC(Rm, Rn); break; |
| 2111 | case 11: SUBV(Rm, Rn); break; |
| 2112 | case 12: ADD(Rm, Rn); break; |
| 2113 | case 13: DMULS(Rm, Rn); break; |
| 2114 | case 14: ADDC(Rm, Rn); break; |
| 2115 | case 15: ADDV(Rm, Rn); break; |
| 1978 | 2116 | } |
| 1979 | 2117 | } |
| 1980 | 2118 | |
| 1981 | | INLINE void op0100(sh2_state *sh2, UINT16 opcode) |
| 2119 | void sh2_device::op0100(UINT16 opcode) |
| 1982 | 2120 | { |
| 1983 | 2121 | switch (opcode & 0x3F) |
| 1984 | 2122 | { |
| 1985 | | case 0x00: SHLL(sh2, Rn); break; |
| 1986 | | case 0x01: SHLR(sh2, Rn); break; |
| 1987 | | case 0x02: STSMMACH(sh2, Rn); break; |
| 1988 | | case 0x03: STCMSR(sh2, Rn); break; |
| 1989 | | case 0x04: ROTL(sh2, Rn); break; |
| 1990 | | case 0x05: ROTR(sh2, Rn); break; |
| 1991 | | case 0x06: LDSMMACH(sh2, Rn); break; |
| 1992 | | case 0x07: LDCMSR(sh2, Rn); break; |
| 1993 | | case 0x08: SHLL2(sh2, Rn); break; |
| 1994 | | case 0x09: SHLR2(sh2, Rn); break; |
| 1995 | | case 0x0a: LDSMACH(sh2, Rn); break; |
| 1996 | | case 0x0b: JSR(sh2, Rn); break; |
| 1997 | | case 0x0c: ILLEGAL(sh2); break; |
| 1998 | | case 0x0d: ILLEGAL(sh2); break; |
| 1999 | | case 0x0e: LDCSR(sh2, Rn); break; |
| 2000 | | case 0x0f: MAC_W(sh2, Rm, Rn); break; |
| 2123 | case 0x00: SHLL(Rn); break; |
| 2124 | case 0x01: SHLR(Rn); break; |
| 2125 | case 0x02: STSMMACH(Rn); break; |
| 2126 | case 0x03: STCMSR(Rn); break; |
| 2127 | case 0x04: ROTL(Rn); break; |
| 2128 | case 0x05: ROTR(Rn); break; |
| 2129 | case 0x06: LDSMMACH(Rn); break; |
| 2130 | case 0x07: LDCMSR(Rn); break; |
| 2131 | case 0x08: SHLL2(Rn); break; |
| 2132 | case 0x09: SHLR2(Rn); break; |
| 2133 | case 0x0a: LDSMACH(Rn); break; |
| 2134 | case 0x0b: JSR(Rn); break; |
| 2135 | case 0x0c: ILLEGAL(); break; |
| 2136 | case 0x0d: ILLEGAL(); break; |
| 2137 | case 0x0e: LDCSR(Rn); break; |
| 2138 | case 0x0f: MAC_W(Rm, Rn); break; |
| 2001 | 2139 | |
| 2002 | | case 0x10: DT(sh2, Rn); break; |
| 2003 | | case 0x11: CMPPZ(sh2, Rn); break; |
| 2004 | | case 0x12: STSMMACL(sh2, Rn); break; |
| 2005 | | case 0x13: STCMGBR(sh2, Rn); break; |
| 2006 | | case 0x14: ILLEGAL(sh2); break; |
| 2007 | | case 0x15: CMPPL(sh2, Rn); break; |
| 2008 | | case 0x16: LDSMMACL(sh2, Rn); break; |
| 2009 | | case 0x17: LDCMGBR(sh2, Rn); break; |
| 2010 | | case 0x18: SHLL8(sh2, Rn); break; |
| 2011 | | case 0x19: SHLR8(sh2, Rn); break; |
| 2012 | | case 0x1a: LDSMACL(sh2, Rn); break; |
| 2013 | | case 0x1b: TAS(sh2, Rn); break; |
| 2014 | | case 0x1c: ILLEGAL(sh2); break; |
| 2015 | | case 0x1d: ILLEGAL(sh2); break; |
| 2016 | | case 0x1e: LDCGBR(sh2, Rn); break; |
| 2017 | | case 0x1f: MAC_W(sh2, Rm, Rn); break; |
| 2140 | case 0x10: DT(Rn); break; |
| 2141 | case 0x11: CMPPZ(Rn); break; |
| 2142 | case 0x12: STSMMACL(Rn); break; |
| 2143 | case 0x13: STCMGBR(Rn); break; |
| 2144 | case 0x14: ILLEGAL(); break; |
| 2145 | case 0x15: CMPPL(Rn); break; |
| 2146 | case 0x16: LDSMMACL(Rn); break; |
| 2147 | case 0x17: LDCMGBR(Rn); break; |
| 2148 | case 0x18: SHLL8(Rn); break; |
| 2149 | case 0x19: SHLR8(Rn); break; |
| 2150 | case 0x1a: LDSMACL(Rn); break; |
| 2151 | case 0x1b: TAS(Rn); break; |
| 2152 | case 0x1c: ILLEGAL(); break; |
| 2153 | case 0x1d: ILLEGAL(); break; |
| 2154 | case 0x1e: LDCGBR(Rn); break; |
| 2155 | case 0x1f: MAC_W(Rm, Rn); break; |
| 2018 | 2156 | |
| 2019 | | case 0x20: SHAL(sh2, Rn); break; |
| 2020 | | case 0x21: SHAR(sh2, Rn); break; |
| 2021 | | case 0x22: STSMPR(sh2, Rn); break; |
| 2022 | | case 0x23: STCMVBR(sh2, Rn); break; |
| 2023 | | case 0x24: ROTCL(sh2, Rn); break; |
| 2024 | | case 0x25: ROTCR(sh2, Rn); break; |
| 2025 | | case 0x26: LDSMPR(sh2, Rn); break; |
| 2026 | | case 0x27: LDCMVBR(sh2, Rn); break; |
| 2027 | | case 0x28: SHLL16(sh2, Rn); break; |
| 2028 | | case 0x29: SHLR16(sh2, Rn); break; |
| 2029 | | case 0x2a: LDSPR(sh2, Rn); break; |
| 2030 | | case 0x2b: JMP(sh2, Rn); break; |
| 2031 | | case 0x2c: ILLEGAL(sh2); break; |
| 2032 | | case 0x2d: ILLEGAL(sh2); break; |
| 2033 | | case 0x2e: LDCVBR(sh2, Rn); break; |
| 2034 | | case 0x2f: MAC_W(sh2, Rm, Rn); break; |
| 2157 | case 0x20: SHAL(Rn); break; |
| 2158 | case 0x21: SHAR(Rn); break; |
| 2159 | case 0x22: STSMPR(Rn); break; |
| 2160 | case 0x23: STCMVBR(Rn); break; |
| 2161 | case 0x24: ROTCL(Rn); break; |
| 2162 | case 0x25: ROTCR(Rn); break; |
| 2163 | case 0x26: LDSMPR(Rn); break; |
| 2164 | case 0x27: LDCMVBR(Rn); break; |
| 2165 | case 0x28: SHLL16(Rn); break; |
| 2166 | case 0x29: SHLR16(Rn); break; |
| 2167 | case 0x2a: LDSPR(Rn); break; |
| 2168 | case 0x2b: JMP(Rn); break; |
| 2169 | case 0x2c: ILLEGAL(); break; |
| 2170 | case 0x2d: ILLEGAL(); break; |
| 2171 | case 0x2e: LDCVBR(Rn); break; |
| 2172 | case 0x2f: MAC_W(Rm, Rn); break; |
| 2035 | 2173 | |
| 2036 | | case 0x30: ILLEGAL(sh2); break; |
| 2037 | | case 0x31: ILLEGAL(sh2); break; |
| 2038 | | case 0x32: ILLEGAL(sh2); break; |
| 2039 | | case 0x33: ILLEGAL(sh2); break; |
| 2040 | | case 0x34: ILLEGAL(sh2); break; |
| 2041 | | case 0x35: ILLEGAL(sh2); break; |
| 2042 | | case 0x36: ILLEGAL(sh2); break; |
| 2043 | | case 0x37: ILLEGAL(sh2); break; |
| 2044 | | case 0x38: ILLEGAL(sh2); break; |
| 2045 | | case 0x39: ILLEGAL(sh2); break; |
| 2046 | | case 0x3a: ILLEGAL(sh2); break; |
| 2047 | | case 0x3b: ILLEGAL(sh2); break; |
| 2048 | | case 0x3c: ILLEGAL(sh2); break; |
| 2049 | | case 0x3d: ILLEGAL(sh2); break; |
| 2050 | | case 0x3e: ILLEGAL(sh2); break; |
| 2051 | | case 0x3f: MAC_W(sh2, Rm, Rn); break; |
| 2174 | case 0x30: ILLEGAL(); break; |
| 2175 | case 0x31: ILLEGAL(); break; |
| 2176 | case 0x32: ILLEGAL(); break; |
| 2177 | case 0x33: ILLEGAL(); break; |
| 2178 | case 0x34: ILLEGAL(); break; |
| 2179 | case 0x35: ILLEGAL(); break; |
| 2180 | case 0x36: ILLEGAL(); break; |
| 2181 | case 0x37: ILLEGAL(); break; |
| 2182 | case 0x38: ILLEGAL(); break; |
| 2183 | case 0x39: ILLEGAL(); break; |
| 2184 | case 0x3a: ILLEGAL(); break; |
| 2185 | case 0x3b: ILLEGAL(); break; |
| 2186 | case 0x3c: ILLEGAL(); break; |
| 2187 | case 0x3d: ILLEGAL(); break; |
| 2188 | case 0x3e: ILLEGAL(); break; |
| 2189 | case 0x3f: MAC_W(Rm, Rn); break; |
| 2052 | 2190 | |
| 2053 | 2191 | } |
| 2054 | 2192 | } |
| 2055 | 2193 | |
| 2056 | | INLINE void op0101(sh2_state *sh2, UINT16 opcode) |
| 2194 | void sh2_device::op0101(UINT16 opcode) |
| 2057 | 2195 | { |
| 2058 | | MOVLL4(sh2, Rm, opcode & 0x0f, Rn); |
| 2196 | MOVLL4(Rm, opcode & 0x0f, Rn); |
| 2059 | 2197 | } |
| 2060 | 2198 | |
| 2061 | | INLINE void op0110(sh2_state *sh2, UINT16 opcode) |
| 2199 | void sh2_device::op0110(UINT16 opcode) |
| 2062 | 2200 | { |
| 2063 | 2201 | switch (opcode & 15) |
| 2064 | 2202 | { |
| 2065 | | case 0: MOVBL(sh2, Rm, Rn); break; |
| 2066 | | case 1: MOVWL(sh2, Rm, Rn); break; |
| 2067 | | case 2: MOVLL(sh2, Rm, Rn); break; |
| 2068 | | case 3: MOV(sh2, Rm, Rn); break; |
| 2069 | | case 4: MOVBP(sh2, Rm, Rn); break; |
| 2070 | | case 5: MOVWP(sh2, Rm, Rn); break; |
| 2071 | | case 6: MOVLP(sh2, Rm, Rn); break; |
| 2072 | | case 7: NOT(sh2, Rm, Rn); break; |
| 2073 | | case 8: SWAPB(sh2, Rm, Rn); break; |
| 2074 | | case 9: SWAPW(sh2, Rm, Rn); break; |
| 2075 | | case 10: NEGC(sh2, Rm, Rn); break; |
| 2076 | | case 11: NEG(sh2, Rm, Rn); break; |
| 2077 | | case 12: EXTUB(sh2, Rm, Rn); break; |
| 2078 | | case 13: EXTUW(sh2, Rm, Rn); break; |
| 2079 | | case 14: EXTSB(sh2, Rm, Rn); break; |
| 2080 | | case 15: EXTSW(sh2, Rm, Rn); break; |
| 2203 | case 0: MOVBL(Rm, Rn); break; |
| 2204 | case 1: MOVWL(Rm, Rn); break; |
| 2205 | case 2: MOVLL(Rm, Rn); break; |
| 2206 | case 3: MOV(Rm, Rn); break; |
| 2207 | case 4: MOVBP(Rm, Rn); break; |
| 2208 | case 5: MOVWP(Rm, Rn); break; |
| 2209 | case 6: MOVLP(Rm, Rn); break; |
| 2210 | case 7: NOT(Rm, Rn); break; |
| 2211 | case 8: SWAPB(Rm, Rn); break; |
| 2212 | case 9: SWAPW(Rm, Rn); break; |
| 2213 | case 10: NEGC(Rm, Rn); break; |
| 2214 | case 11: NEG(Rm, Rn); break; |
| 2215 | case 12: EXTUB(Rm, Rn); break; |
| 2216 | case 13: EXTUW(Rm, Rn); break; |
| 2217 | case 14: EXTSB(Rm, Rn); break; |
| 2218 | case 15: EXTSW(Rm, Rn); break; |
| 2081 | 2219 | } |
| 2082 | 2220 | } |
| 2083 | 2221 | |
| 2084 | | INLINE void op0111(sh2_state *sh2, UINT16 opcode) |
| 2222 | void sh2_device::op0111(UINT16 opcode) |
| 2085 | 2223 | { |
| 2086 | | ADDI(sh2, opcode & 0xff, Rn); |
| 2224 | ADDI(opcode & 0xff, Rn); |
| 2087 | 2225 | } |
| 2088 | 2226 | |
| 2089 | | INLINE void op1000(sh2_state *sh2, UINT16 opcode) |
| 2227 | void sh2_device::op1000(UINT16 opcode) |
| 2090 | 2228 | { |
| 2091 | 2229 | switch ( opcode & (15<<8) ) |
| 2092 | 2230 | { |
| 2093 | | case 0 << 8: MOVBS4(sh2, opcode & 0x0f, Rm); break; |
| 2094 | | case 1 << 8: MOVWS4(sh2, opcode & 0x0f, Rm); break; |
| 2095 | | case 2<< 8: ILLEGAL(sh2); break; |
| 2096 | | case 3<< 8: ILLEGAL(sh2); break; |
| 2097 | | case 4<< 8: MOVBL4(sh2, Rm, opcode & 0x0f); break; |
| 2098 | | case 5<< 8: MOVWL4(sh2, Rm, opcode & 0x0f); break; |
| 2099 | | case 6<< 8: ILLEGAL(sh2); break; |
| 2100 | | case 7<< 8: ILLEGAL(sh2); break; |
| 2101 | | case 8<< 8: CMPIM(sh2, opcode & 0xff); break; |
| 2102 | | case 9<< 8: BT(sh2, opcode & 0xff); break; |
| 2103 | | case 10<< 8: ILLEGAL(sh2); break; |
| 2104 | | case 11<< 8: BF(sh2, opcode & 0xff); break; |
| 2105 | | case 12<< 8: ILLEGAL(sh2); break; |
| 2106 | | case 13<< 8: BTS(sh2, opcode & 0xff); break; |
| 2107 | | case 14<< 8: ILLEGAL(sh2); break; |
| 2108 | | case 15<< 8: BFS(sh2, opcode & 0xff); break; |
| 2231 | case 0 << 8: MOVBS4(opcode & 0x0f, Rm); break; |
| 2232 | case 1 << 8: MOVWS4(opcode & 0x0f, Rm); break; |
| 2233 | case 2<< 8: ILLEGAL(); break; |
| 2234 | case 3<< 8: ILLEGAL(); break; |
| 2235 | case 4<< 8: MOVBL4(Rm, opcode & 0x0f); break; |
| 2236 | case 5<< 8: MOVWL4(Rm, opcode & 0x0f); break; |
| 2237 | case 6<< 8: ILLEGAL(); break; |
| 2238 | case 7<< 8: ILLEGAL(); break; |
| 2239 | case 8<< 8: CMPIM(opcode & 0xff); break; |
| 2240 | case 9<< 8: BT(opcode & 0xff); break; |
| 2241 | case 10<< 8: ILLEGAL(); break; |
| 2242 | case 11<< 8: BF(opcode & 0xff); break; |
| 2243 | case 12<< 8: ILLEGAL(); break; |
| 2244 | case 13<< 8: BTS(opcode & 0xff); break; |
| 2245 | case 14<< 8: ILLEGAL(); break; |
| 2246 | case 15<< 8: BFS(opcode & 0xff); break; |
| 2109 | 2247 | } |
| 2110 | 2248 | } |
| 2111 | 2249 | |
| 2112 | 2250 | |
| 2113 | | INLINE void op1001(sh2_state *sh2, UINT16 opcode) |
| 2251 | void sh2_device::op1001(UINT16 opcode) |
| 2114 | 2252 | { |
| 2115 | | MOVWI(sh2, opcode & 0xff, Rn); |
| 2253 | MOVWI(opcode & 0xff, Rn); |
| 2116 | 2254 | } |
| 2117 | 2255 | |
| 2118 | | INLINE void op1010(sh2_state *sh2, UINT16 opcode) |
| 2256 | void sh2_device::op1010(UINT16 opcode) |
| 2119 | 2257 | { |
| 2120 | | BRA(sh2, opcode & 0xfff); |
| 2258 | BRA(opcode & 0xfff); |
| 2121 | 2259 | } |
| 2122 | 2260 | |
| 2123 | | INLINE void op1011(sh2_state *sh2, UINT16 opcode) |
| 2261 | void sh2_device::op1011(UINT16 opcode) |
| 2124 | 2262 | { |
| 2125 | | BSR(sh2, opcode & 0xfff); |
| 2263 | BSR(opcode & 0xfff); |
| 2126 | 2264 | } |
| 2127 | 2265 | |
| 2128 | | INLINE void op1100(sh2_state *sh2, UINT16 opcode) |
| 2266 | void sh2_device::op1100(UINT16 opcode) |
| 2129 | 2267 | { |
| 2130 | 2268 | switch (opcode & (15<<8)) |
| 2131 | 2269 | { |
| 2132 | | case 0<<8: MOVBSG(sh2, opcode & 0xff); break; |
| 2133 | | case 1<<8: MOVWSG(sh2, opcode & 0xff); break; |
| 2134 | | case 2<<8: MOVLSG(sh2, opcode & 0xff); break; |
| 2135 | | case 3<<8: TRAPA(sh2, opcode & 0xff); break; |
| 2136 | | case 4<<8: MOVBLG(sh2, opcode & 0xff); break; |
| 2137 | | case 5<<8: MOVWLG(sh2, opcode & 0xff); break; |
| 2138 | | case 6<<8: MOVLLG(sh2, opcode & 0xff); break; |
| 2139 | | case 7<<8: MOVA(sh2, opcode & 0xff); break; |
| 2140 | | case 8<<8: TSTI(sh2, opcode & 0xff); break; |
| 2141 | | case 9<<8: ANDI(sh2, opcode & 0xff); break; |
| 2142 | | case 10<<8: XORI(sh2, opcode & 0xff); break; |
| 2143 | | case 11<<8: ORI(sh2, opcode & 0xff); break; |
| 2144 | | case 12<<8: TSTM(sh2, opcode & 0xff); break; |
| 2145 | | case 13<<8: ANDM(sh2, opcode & 0xff); break; |
| 2146 | | case 14<<8: XORM(sh2, opcode & 0xff); break; |
| 2147 | | case 15<<8: ORM(sh2, opcode & 0xff); break; |
| 2270 | case 0<<8: MOVBSG(opcode & 0xff); break; |
| 2271 | case 1<<8: MOVWSG(opcode & 0xff); break; |
| 2272 | case 2<<8: MOVLSG(opcode & 0xff); break; |
| 2273 | case 3<<8: TRAPA(opcode & 0xff); break; |
| 2274 | case 4<<8: MOVBLG(opcode & 0xff); break; |
| 2275 | case 5<<8: MOVWLG(opcode & 0xff); break; |
| 2276 | case 6<<8: MOVLLG(opcode & 0xff); break; |
| 2277 | case 7<<8: MOVA(opcode & 0xff); break; |
| 2278 | case 8<<8: TSTI(opcode & 0xff); break; |
| 2279 | case 9<<8: ANDI(opcode & 0xff); break; |
| 2280 | case 10<<8: XORI(opcode & 0xff); break; |
| 2281 | case 11<<8: ORI(opcode & 0xff); break; |
| 2282 | case 12<<8: TSTM(opcode & 0xff); break; |
| 2283 | case 13<<8: ANDM(opcode & 0xff); break; |
| 2284 | case 14<<8: XORM(opcode & 0xff); break; |
| 2285 | case 15<<8: ORM(opcode & 0xff); break; |
| 2148 | 2286 | } |
| 2149 | 2287 | } |
| 2150 | 2288 | |
| 2151 | | INLINE void op1101(sh2_state *sh2, UINT16 opcode) |
| 2289 | void sh2_device::op1101(UINT16 opcode) |
| 2152 | 2290 | { |
| 2153 | | MOVLI(sh2, opcode & 0xff, Rn); |
| 2291 | MOVLI(opcode & 0xff, Rn); |
| 2154 | 2292 | } |
| 2155 | 2293 | |
| 2156 | | INLINE void op1110(sh2_state *sh2, UINT16 opcode) |
| 2294 | void sh2_device::op1110(UINT16 opcode) |
| 2157 | 2295 | { |
| 2158 | | MOVI(sh2, opcode & 0xff, Rn); |
| 2296 | MOVI(opcode & 0xff, Rn); |
| 2159 | 2297 | } |
| 2160 | 2298 | |
| 2161 | | INLINE void op1111(sh2_state *sh2, UINT16 opcode) |
| 2299 | void sh2_device::op1111(UINT16 opcode) |
| 2162 | 2300 | { |
| 2163 | | ILLEGAL(sh2); |
| 2301 | ILLEGAL(); |
| 2164 | 2302 | } |
| 2165 | 2303 | |
| 2166 | 2304 | /***************************************************************************** |
| 2167 | 2305 | * MAME CPU INTERFACE |
| 2168 | 2306 | *****************************************************************************/ |
| 2169 | 2307 | |
| 2170 | | static CPU_RESET( sh2 ) |
| 2308 | void sh2_device::device_reset() |
| 2171 | 2309 | { |
| 2172 | | sh2_state *sh2 = get_safe_token(device); |
| 2173 | | int (*dma_callback_kludge)(device_t *device, UINT32 src, UINT32 dst, UINT32 data, int size); |
| 2174 | | int (*dma_callback_fifo_data_available)(device_t *device, UINT32 src, UINT32 dst, UINT32 data, int size); |
| 2175 | | int save_is_slave; |
| 2310 | m_sh2_state->ppc = m_sh2_state->pc = m_sh2_state->pr = m_sh2_state->sr = m_sh2_state->gbr = m_sh2_state->vbr = m_sh2_state->mach = m_sh2_state->macl = 0; |
| 2311 | m_sh2_state->evec = m_sh2_state->irqsr = 0; |
| 2312 | memset(&m_sh2_state->r[0], 0, sizeof(m_sh2_state->r[0])*16); |
| 2313 | m_sh2_state->ea = m_delay = m_cpu_off = m_dvsr = m_dvdnth = m_dvdntl = m_dvcr = 0; |
| 2314 | m_sh2_state->pending_irq = m_test_irq = 0; |
| 2315 | memset(&m_irq_queue[0], 0, sizeof(m_irq_queue[0])*16); |
| 2316 | memset(&m_irq_line_state[0], 0, sizeof(m_irq_line_state[0])*17); |
| 2317 | m_frc = m_ocra = m_ocrb = m_icr = 0; |
| 2318 | m_frc_base = 0; |
| 2319 | m_frt_input = m_sh2_state->internal_irq_level = m_internal_irq_vector = 0; |
| 2320 | m_dma_timer_active[0] = m_dma_timer_active[1] = 0; |
| 2321 | m_dma_irq[0] = m_dma_irq[1] = 0; |
| 2176 | 2322 | |
| 2177 | | void (*f)(UINT32 data); |
| 2178 | | device_irq_acknowledge_callback save_irqcallback; |
| 2323 | memset(m_m, 0, 0x200); |
| 2179 | 2324 | |
| 2180 | | f = sh2->ftcsr_read_callback; |
| 2181 | | save_irqcallback = sh2->irq_callback; |
| 2182 | | save_is_slave = sh2->is_slave; |
| 2183 | | dma_callback_kludge = sh2->dma_callback_kludge; |
| 2184 | | dma_callback_fifo_data_available = sh2->dma_callback_fifo_data_available; |
| 2325 | m_sh2_state->pc = RL(0); |
| 2326 | m_sh2_state->r[15] = RL(4); |
| 2327 | m_sh2_state->sr = I; |
| 2328 | m_sh2_state->sleep_mode = 0; |
| 2185 | 2329 | |
| 2186 | | sh2->ppc = sh2->pc = sh2->pr = sh2->sr = sh2->gbr = sh2->vbr = sh2->mach = sh2->macl = 0; |
| 2187 | | sh2->evec = sh2->irqsr = 0; |
| 2188 | | memset(&sh2->r[0], 0, sizeof(sh2->r[0])*16); |
| 2189 | | sh2->ea = sh2->delay = sh2->cpu_off = sh2->dvsr = sh2->dvdnth = sh2->dvdntl = sh2->dvcr = 0; |
| 2190 | | sh2->pending_irq = sh2->test_irq = 0; |
| 2191 | | memset(&sh2->irq_queue[0], 0, sizeof(sh2->irq_queue[0])*16); |
| 2192 | | memset(&sh2->irq_line_state[0], 0, sizeof(sh2->irq_line_state[0])*17); |
| 2193 | | sh2->frc = sh2->ocra = sh2->ocrb = sh2->icr = 0; |
| 2194 | | sh2->frc_base = 0; |
| 2195 | | sh2->frt_input = sh2->internal_irq_level = sh2->internal_irq_vector = 0; |
| 2196 | | sh2->dma_timer_active[0] = sh2->dma_timer_active[1] = 0; |
| 2197 | | sh2->dma_irq[0] = sh2->dma_irq[1] = 0; |
| 2330 | m_sh2_state->internal_irq_level = -1; |
| 2198 | 2331 | |
| 2199 | | sh2->dma_callback_kludge = dma_callback_kludge; |
| 2200 | | sh2->dma_callback_fifo_data_available = dma_callback_fifo_data_available; |
| 2201 | | sh2->is_slave = save_is_slave; |
| 2202 | | sh2->ftcsr_read_callback = f; |
| 2203 | | sh2->irq_callback = save_irqcallback; |
| 2204 | | sh2->device = device; |
| 2205 | | |
| 2206 | | memset(sh2->m, 0, 0x200); |
| 2207 | | |
| 2208 | | sh2->pc = RL(sh2, 0); |
| 2209 | | sh2->r[15] = RL(sh2, 4); |
| 2210 | | sh2->sr = I; |
| 2211 | | sh2->sleep_mode = 0; |
| 2212 | | |
| 2213 | | sh2->internal_irq_level = -1; |
| 2332 | m_cache_dirty = TRUE; |
| 2214 | 2333 | } |
| 2215 | 2334 | |
| 2216 | | /*------------------------------------------------- |
| 2217 | | sh1_reset - reset the processor |
| 2218 | | -------------------------------------------------*/ |
| 2219 | 2335 | |
| 2220 | | static CPU_RESET( sh1 ) |
| 2221 | | { |
| 2222 | | sh2_state *sh2 = get_safe_token(device); |
| 2223 | | CPU_RESET_CALL( sh2 ); |
| 2224 | | sh2->cpu_type = CPU_TYPE_SH1; |
| 2225 | | } |
| 2226 | | |
| 2227 | 2336 | /* Execute cycles - returns number of cycles actually run */ |
| 2228 | | static CPU_EXECUTE( sh2 ) |
| 2337 | void sh2_device::execute_run() |
| 2229 | 2338 | { |
| 2230 | | sh2_state *sh2 = get_safe_token(device); |
| 2339 | if ( m_isdrc ) |
| 2340 | { |
| 2341 | execute_run_drc(); |
| 2342 | return; |
| 2343 | } |
| 2231 | 2344 | |
| 2232 | | if (sh2->cpu_off) |
| 2345 | if (m_cpu_off) |
| 2233 | 2346 | { |
| 2234 | | sh2->icount = 0; |
| 2347 | m_sh2_state->icount = 0; |
| 2235 | 2348 | return; |
| 2236 | 2349 | } |
| 2237 | 2350 | |
| 2238 | 2351 | // run any active DMAs now |
| 2239 | 2352 | #ifndef USE_TIMER_FOR_DMA |
| 2240 | | for ( int i = 0; i < sh2->icount ; i++) |
| 2353 | for ( int i = 0; i < m_sh2_state->icount ; i++) |
| 2241 | 2354 | { |
| 2242 | 2355 | for( int dma=0;dma<1;dma++) |
| 2243 | 2356 | { |
| 2244 | | if (sh2->dma_timer_active[dma]) |
| 2245 | | sh2_do_dma(sh2, dma); |
| 2357 | if (m_dma_timer_active[dma]) |
| 2358 | sh2_do_dma(dma); |
| 2246 | 2359 | } |
| 2247 | 2360 | } |
| 2248 | 2361 | #endif |
| r29568 | r29569 | |
| 2251 | 2364 | { |
| 2252 | 2365 | UINT32 opcode; |
| 2253 | 2366 | |
| 2254 | | if (sh2->delay) |
| 2367 | if (m_delay) |
| 2255 | 2368 | { |
| 2256 | | opcode = sh2->program->read_word(((UINT32)(sh2->delay & AM))); |
| 2257 | | sh2->pc -= 2; |
| 2369 | opcode = m_program->read_word(((UINT32)(m_delay & AM))); |
| 2370 | m_sh2_state->pc -= 2; |
| 2258 | 2371 | } |
| 2259 | 2372 | else |
| 2260 | | opcode = sh2->program->read_word(((UINT32)(sh2->pc & AM))); |
| 2373 | opcode = m_program->read_word(((UINT32)(m_sh2_state->pc & AM))); |
| 2261 | 2374 | |
| 2262 | | debugger_instruction_hook(device, sh2->pc); |
| 2375 | debugger_instruction_hook(this, m_sh2_state->pc); |
| 2263 | 2376 | |
| 2264 | | sh2->delay = 0; |
| 2265 | | sh2->pc += 2; |
| 2266 | | sh2->ppc = sh2->pc; |
| 2377 | m_delay = 0; |
| 2378 | m_sh2_state->pc += 2; |
| 2379 | m_sh2_state->ppc = m_sh2_state->pc; |
| 2267 | 2380 | |
| 2268 | 2381 | switch (opcode & ( 15 << 12)) |
| 2269 | 2382 | { |
| 2270 | | case 0<<12: op0000(sh2, opcode); break; |
| 2271 | | case 1<<12: op0001(sh2, opcode); break; |
| 2272 | | case 2<<12: op0010(sh2, opcode); break; |
| 2273 | | case 3<<12: op0011(sh2, opcode); break; |
| 2274 | | case 4<<12: op0100(sh2, opcode); break; |
| 2275 | | case 5<<12: op0101(sh2, opcode); break; |
| 2276 | | case 6<<12: op0110(sh2, opcode); break; |
| 2277 | | case 7<<12: op0111(sh2, opcode); break; |
| 2278 | | case 8<<12: op1000(sh2, opcode); break; |
| 2279 | | case 9<<12: op1001(sh2, opcode); break; |
| 2280 | | case 10<<12: op1010(sh2, opcode); break; |
| 2281 | | case 11<<12: op1011(sh2, opcode); break; |
| 2282 | | case 12<<12: op1100(sh2, opcode); break; |
| 2283 | | case 13<<12: op1101(sh2, opcode); break; |
| 2284 | | case 14<<12: op1110(sh2, opcode); break; |
| 2285 | | default: op1111(sh2, opcode); break; |
| 2383 | case 0<<12: op0000(opcode); break; |
| 2384 | case 1<<12: op0001(opcode); break; |
| 2385 | case 2<<12: op0010(opcode); break; |
| 2386 | case 3<<12: op0011(opcode); break; |
| 2387 | case 4<<12: op0100(opcode); break; |
| 2388 | case 5<<12: op0101(opcode); break; |
| 2389 | case 6<<12: op0110(opcode); break; |
| 2390 | case 7<<12: op0111(opcode); break; |
| 2391 | case 8<<12: op1000(opcode); break; |
| 2392 | case 9<<12: op1001(opcode); break; |
| 2393 | case 10<<12: op1010(opcode); break; |
| 2394 | case 11<<12: op1011(opcode); break; |
| 2395 | case 12<<12: op1100(opcode); break; |
| 2396 | case 13<<12: op1101(opcode); break; |
| 2397 | case 14<<12: op1110(opcode); break; |
| 2398 | default: op1111(opcode); break; |
| 2286 | 2399 | } |
| 2287 | 2400 | |
| 2288 | | if(sh2->test_irq && !sh2->delay) |
| 2401 | if(m_test_irq && !m_delay) |
| 2289 | 2402 | { |
| 2290 | 2403 | CHECK_PENDING_IRQ("mame_sh2_execute"); |
| 2291 | | sh2->test_irq = 0; |
| 2404 | m_test_irq = 0; |
| 2292 | 2405 | } |
| 2293 | | sh2->icount--; |
| 2294 | | } while( sh2->icount > 0 ); |
| 2406 | m_sh2_state->icount--; |
| 2407 | } while( m_sh2_state->icount > 0 ); |
| 2295 | 2408 | } |
| 2296 | 2409 | |
| 2297 | | static CPU_INIT( sh2 ) |
| 2410 | void sh2_device::device_start() |
| 2298 | 2411 | { |
| 2299 | | sh2_state *sh2 = get_safe_token(device); |
| 2412 | /* allocate the implementation-specific state from the full cache */ |
| 2413 | m_sh2_state = (internal_sh2_state *)m_cache.alloc_near(sizeof(internal_sh2_state)); |
| 2300 | 2414 | |
| 2301 | | /* initialize the common core parts */ |
| 2302 | | sh2_common_init(sh2, device, irqcallback,false); |
| 2303 | | } |
| 2415 | m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_timer_callback), this)); |
| 2416 | m_timer->adjust(attotime::never); |
| 2304 | 2417 | |
| 2305 | | /************************************************************************** |
| 2306 | | * Generic set_info |
| 2307 | | **************************************************************************/ |
| 2418 | m_dma_current_active_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_dma_current_active_callback), this)); |
| 2419 | m_dma_current_active_timer[0]->adjust(attotime::never); |
| 2308 | 2420 | |
| 2309 | | static CPU_SET_INFO( sh2 ) |
| 2310 | | { |
| 2311 | | sh2_state *sh2 = get_safe_token(device); |
| 2312 | | switch (state) |
| 2421 | m_dma_current_active_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_dma_current_active_callback), this)); |
| 2422 | m_dma_current_active_timer[1]->adjust(attotime::never); |
| 2423 | |
| 2424 | m_is_slave = is_slave; |
| 2425 | m_dma_callback_kludge = dma_callback_kludge; |
| 2426 | m_dma_callback_fifo_data_available = dma_callback_fifo_data_available; |
| 2427 | |
| 2428 | m_program = &space(AS_PROGRAM); |
| 2429 | m_direct = &m_program->direct(); |
| 2430 | m_internal = &space(AS_PROGRAM); |
| 2431 | |
| 2432 | save_item(NAME(m_sh2_state->pc)); |
| 2433 | save_item(NAME(m_sh2_state->sr)); |
| 2434 | save_item(NAME(m_sh2_state->pr)); |
| 2435 | save_item(NAME(m_sh2_state->gbr)); |
| 2436 | save_item(NAME(m_sh2_state->vbr)); |
| 2437 | save_item(NAME(m_sh2_state->mach)); |
| 2438 | save_item(NAME(m_sh2_state->macl)); |
| 2439 | save_item(NAME(m_sh2_state->r)); |
| 2440 | save_item(NAME(m_sh2_state->ea)); |
| 2441 | save_item(NAME(m_delay)); |
| 2442 | save_item(NAME(m_cpu_off)); |
| 2443 | save_item(NAME(m_dvsr)); |
| 2444 | save_item(NAME(m_dvdnth)); |
| 2445 | save_item(NAME(m_dvdntl)); |
| 2446 | save_item(NAME(m_dvcr)); |
| 2447 | save_item(NAME(m_sh2_state->pending_irq)); |
| 2448 | save_item(NAME(m_test_irq)); |
| 2449 | save_item(NAME(m_sh2_state->pending_nmi)); |
| 2450 | save_item(NAME(m_sh2_state->irqline)); |
| 2451 | save_item(NAME(m_sh2_state->evec)); |
| 2452 | save_item(NAME(m_sh2_state->irqsr)); |
| 2453 | save_item(NAME(m_sh2_state->target)); |
| 2454 | for (int i = 0; i < 16; ++i) |
| 2313 | 2455 | { |
| 2314 | | /* --- the following bits of info are set as 64-bit signed integers --- */ |
| 2315 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: sh2_set_irq_line(sh2, SH2_INT_VBLIN, info->i); break; |
| 2316 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: sh2_set_irq_line(sh2, SH2_INT_VBLOUT, info->i); break; |
| 2317 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: sh2_set_irq_line(sh2, SH2_INT_HBLIN, info->i); break; |
| 2318 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: sh2_set_irq_line(sh2, SH2_INT_TIMER0, info->i); break; |
| 2319 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: sh2_set_irq_line(sh2, SH2_INT_TIMER1, info->i); break; |
| 2320 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: sh2_set_irq_line(sh2, SH2_INT_DSP, info->i); break; |
| 2321 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: sh2_set_irq_line(sh2, SH2_INT_SOUND, info->i); break; |
| 2322 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: sh2_set_irq_line(sh2, SH2_INT_SMPC, info->i); break; |
| 2323 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: sh2_set_irq_line(sh2, SH2_INT_PAD, info->i); break; |
| 2324 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: sh2_set_irq_line(sh2, SH2_INT_DMA2, info->i); break; |
| 2325 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: sh2_set_irq_line(sh2, SH2_INT_DMA1, info->i); break; |
| 2326 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: sh2_set_irq_line(sh2, SH2_INT_DMA0, info->i); break; |
| 2327 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: sh2_set_irq_line(sh2, SH2_INT_DMAILL, info->i); break; |
| 2328 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: sh2_set_irq_line(sh2, SH2_INT_SPRITE, info->i); break; |
| 2329 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_14: sh2_set_irq_line(sh2, SH2_INT_14, info->i); break; |
| 2330 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_15: sh2_set_irq_line(sh2, SH2_INT_15, info->i); break; |
| 2331 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: sh2_set_irq_line(sh2, SH2_INT_ABUS, info->i); break; |
| 2332 | | case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: sh2_set_irq_line(sh2, INPUT_LINE_NMI, info->i); break; |
| 2333 | | |
| 2334 | | case CPUINFO_INT_REGISTER + SH2_PC: |
| 2335 | | case CPUINFO_INT_PC: sh2->pc = info->i; sh2->delay = 0; break; |
| 2336 | | case CPUINFO_INT_SP: sh2->r[15] = info->i; break; |
| 2337 | | case CPUINFO_INT_REGISTER + SH2_PR: sh2->pr = info->i; break; |
| 2338 | | case CPUINFO_INT_REGISTER + SH2_SR: sh2->sr = info->i; CHECK_PENDING_IRQ("sh2_set_reg"); break; |
| 2339 | | case CPUINFO_INT_REGISTER + SH2_GBR: sh2->gbr = info->i; break; |
| 2340 | | case CPUINFO_INT_REGISTER + SH2_VBR: sh2->vbr = info->i; break; |
| 2341 | | case CPUINFO_INT_REGISTER + SH2_MACH: sh2->mach = info->i; break; |
| 2342 | | case CPUINFO_INT_REGISTER + SH2_MACL: sh2->macl = info->i; break; |
| 2343 | | case CPUINFO_INT_REGISTER + SH2_R0: sh2->r[ 0] = info->i; break; |
| 2344 | | case CPUINFO_INT_REGISTER + SH2_R1: sh2->r[ 1] = info->i; break; |
| 2345 | | case CPUINFO_INT_REGISTER + SH2_R2: sh2->r[ 2] = info->i; break; |
| 2346 | | case CPUINFO_INT_REGISTER + SH2_R3: sh2->r[ 3] = info->i; break; |
| 2347 | | case CPUINFO_INT_REGISTER + SH2_R4: sh2->r[ 4] = info->i; break; |
| 2348 | | case CPUINFO_INT_REGISTER + SH2_R5: sh2->r[ 5] = info->i; break; |
| 2349 | | case CPUINFO_INT_REGISTER + SH2_R6: sh2->r[ 6] = info->i; break; |
| 2350 | | case CPUINFO_INT_REGISTER + SH2_R7: sh2->r[ 7] = info->i; break; |
| 2351 | | case CPUINFO_INT_REGISTER + SH2_R8: sh2->r[ 8] = info->i; break; |
| 2352 | | case CPUINFO_INT_REGISTER + SH2_R9: sh2->r[ 9] = info->i; break; |
| 2353 | | case CPUINFO_INT_REGISTER + SH2_R10: sh2->r[10] = info->i; break; |
| 2354 | | case CPUINFO_INT_REGISTER + SH2_R11: sh2->r[11] = info->i; break; |
| 2355 | | case CPUINFO_INT_REGISTER + SH2_R12: sh2->r[12] = info->i; break; |
| 2356 | | case CPUINFO_INT_REGISTER + SH2_R13: sh2->r[13] = info->i; break; |
| 2357 | | case CPUINFO_INT_REGISTER + SH2_R14: sh2->r[14] = info->i; break; |
| 2358 | | case CPUINFO_INT_REGISTER + SH2_R15: sh2->r[15] = info->i; break; |
| 2359 | | case CPUINFO_INT_REGISTER + SH2_EA: sh2->ea = info->i; break; |
| 2456 | save_item(NAME(m_irq_queue[i].irq_vector), i); |
| 2457 | save_item(NAME(m_irq_queue[i].irq_priority), i); |
| 2360 | 2458 | } |
| 2361 | | } |
| 2459 | save_item(NAME(m_pcfsel)); |
| 2460 | save_item(NAME(m_maxpcfsel)); |
| 2461 | save_item(NAME(m_pcflushes)); |
| 2462 | save_item(NAME(m_irq_line_state)); |
| 2463 | save_item(NAME(m_m)); |
| 2464 | save_item(NAME(m_nmi_line_state)); |
| 2465 | save_item(NAME(m_frc)); |
| 2466 | save_item(NAME(m_ocra)); |
| 2467 | save_item(NAME(m_ocrb)); |
| 2468 | save_item(NAME(m_icr)); |
| 2469 | save_item(NAME(m_frc_base)); |
| 2470 | save_item(NAME(m_frt_input)); |
| 2471 | save_item(NAME(m_sh2_state->internal_irq_level)); |
| 2472 | save_item(NAME(m_internal_irq_vector)); |
| 2473 | save_item(NAME(m_dma_timer_active)); |
| 2474 | save_item(NAME(m_dma_irq)); |
| 2475 | save_item(NAME(m_wtcnt)); |
| 2476 | save_item(NAME(m_wtcsr)); |
| 2477 | save_item(NAME(m_sh2_state->sleep_mode)); |
| 2362 | 2478 | |
| 2479 | state_add( SH2_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%08X"); |
| 2480 | state_add( SH2_SR, "SR", m_sh2_state->sr).callimport().formatstr("%08X"); |
| 2481 | state_add( SH2_PR, "PR", m_sh2_state->pr).formatstr("%08X"); |
| 2482 | state_add( SH2_GBR, "GBR", m_sh2_state->gbr).formatstr("%08X"); |
| 2483 | state_add( SH2_VBR, "VBR", m_sh2_state->vbr).formatstr("%08X"); |
| 2484 | state_add( SH2_MACH, "MACH", m_sh2_state->mach).formatstr("%08X"); |
| 2485 | state_add( SH2_MACL, "MACL", m_sh2_state->macl).formatstr("%08X"); |
| 2486 | state_add( SH2_R0, "R0", m_sh2_state->r[ 0]).formatstr("%08X"); |
| 2487 | state_add( SH2_R1, "R1", m_sh2_state->r[ 1]).formatstr("%08X"); |
| 2488 | state_add( SH2_R2, "R2", m_sh2_state->r[ 2]).formatstr("%08X"); |
| 2489 | state_add( SH2_R3, "R3", m_sh2_state->r[ 3]).formatstr("%08X"); |
| 2490 | state_add( SH2_R4, "R4", m_sh2_state->r[ 4]).formatstr("%08X"); |
| 2491 | state_add( SH2_R5, "R5", m_sh2_state->r[ 5]).formatstr("%08X"); |
| 2492 | state_add( SH2_R6, "R6", m_sh2_state->r[ 6]).formatstr("%08X"); |
| 2493 | state_add( SH2_R7, "R7", m_sh2_state->r[ 7]).formatstr("%08X"); |
| 2494 | state_add( SH2_R8, "R8", m_sh2_state->r[ 8]).formatstr("%08X"); |
| 2495 | state_add( SH2_R9, "R9", m_sh2_state->r[ 9]).formatstr("%08X"); |
| 2496 | state_add( SH2_R10, "R10", m_sh2_state->r[10]).formatstr("%08X"); |
| 2497 | state_add( SH2_R11, "R11", m_sh2_state->r[11]).formatstr("%08X"); |
| 2498 | state_add( SH2_R12, "R12", m_sh2_state->r[12]).formatstr("%08X"); |
| 2499 | state_add( SH2_R13, "R13", m_sh2_state->r[13]).formatstr("%08X"); |
| 2500 | state_add( SH2_R14, "R14", m_sh2_state->r[14]).formatstr("%08X"); |
| 2501 | state_add( SH2_R15, "R15", m_sh2_state->r[15]).formatstr("%08X"); |
| 2502 | state_add( SH2_EA, "EA", m_sh2_state->ea).formatstr("%08X"); |
| 2363 | 2503 | |
| 2504 | state_add( STATE_GENPC, "GENPC", m_sh2_state->pc ).noshow(); |
| 2505 | state_add( STATE_GENSP, "GENSP", m_sh2_state->r[15] ).noshow(); |
| 2506 | state_add( STATE_GENPCBASE, "GENPCBASE", m_sh2_state->ppc ).noshow(); |
| 2507 | state_add( STATE_GENFLAGS, "GENFLAGS", m_sh2_state->sr ).formatstr("%6s").noshow(); |
| 2364 | 2508 | |
| 2365 | | /************************************************************************** |
| 2366 | | * Generic get_info |
| 2367 | | **************************************************************************/ |
| 2509 | m_icountptr = &m_sh2_state->icount; |
| 2368 | 2510 | |
| 2369 | | CPU_GET_INFO( sh2_int ) |
| 2370 | | { |
| 2371 | | sh2_state *sh2 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
| 2372 | | switch (state) |
| 2511 | // Clear state |
| 2512 | m_sh2_state->ppc = 0; |
| 2513 | m_sh2_state->pc = 0; |
| 2514 | m_sh2_state->pr = 0; |
| 2515 | m_sh2_state->sr = 0; |
| 2516 | m_sh2_state->gbr = 0; |
| 2517 | m_sh2_state->vbr = 0; |
| 2518 | m_sh2_state->mach = 0; |
| 2519 | m_sh2_state->macl = 0; |
| 2520 | memset(m_sh2_state->r, 0, sizeof(m_sh2_state->r)); |
| 2521 | m_sh2_state->ea = 0; |
| 2522 | m_delay = 0; |
| 2523 | m_cpu_off = 0; |
| 2524 | m_dvsr = 0; |
| 2525 | m_dvdnth = 0; |
| 2526 | m_dvdntl = 0; |
| 2527 | m_dvcr = 0; |
| 2528 | m_sh2_state->pending_irq = 0; |
| 2529 | m_test_irq = 0; |
| 2530 | m_sh2_state->pending_nmi = 0; |
| 2531 | m_sh2_state->irqline = 0; |
| 2532 | m_sh2_state->evec = 0; |
| 2533 | m_sh2_state->irqsr = 0; |
| 2534 | m_sh2_state->target = 0; |
| 2535 | memset(m_irq_queue, 0, sizeof(m_irq_queue)); |
| 2536 | m_maxpcfsel = 0; |
| 2537 | memset(m_pcflushes, 0, sizeof(m_pcflushes)); |
| 2538 | memset(m_irq_line_state, 0, sizeof(m_irq_line_state)); |
| 2539 | memset(m_m, 0, sizeof(m_m)); |
| 2540 | m_nmi_line_state = 0; |
| 2541 | m_frc = 0; |
| 2542 | m_ocra = 0; |
| 2543 | m_ocrb = 0; |
| 2544 | m_icr = 0; |
| 2545 | m_frc_base = 0; |
| 2546 | m_frt_input = 0; |
| 2547 | m_sh2_state->internal_irq_level = 0; |
| 2548 | m_internal_irq_vector = 0; |
| 2549 | m_sh2_state->icount = 0; |
| 2550 | for ( int i = 0; i < 2; i++ ) |
| 2373 | 2551 | { |
| 2374 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 2375 | | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(sh2_state); break; |
| 2376 | | case CPUINFO_INT_INPUT_LINES: info->i = 16; break; |
| 2377 | | case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; |
| 2378 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; |
| 2379 | | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
| 2380 | | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
| 2381 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break; |
| 2382 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break; |
| 2383 | | case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; |
| 2384 | | case CPUINFO_INT_MAX_CYCLES: info->i = 4; break; |
| 2552 | m_dma_timer_active[i] = 0; |
| 2553 | m_dma_irq[i] = 0; |
| 2554 | m_active_dma_incs[i] = 0; |
| 2555 | m_active_dma_incd[i] = 0; |
| 2556 | m_active_dma_size[i] = 0; |
| 2557 | m_active_dma_steal[i] = 0; |
| 2558 | m_active_dma_src[i] = 0; |
| 2559 | m_active_dma_dst[i] = 0; |
| 2560 | m_active_dma_count[i] = 0; |
| 2561 | } |
| 2562 | m_wtcnt = 0; |
| 2563 | m_wtcsr = 0; |
| 2564 | m_sh2_state->sleep_mode = 0; |
| 2565 | m_numcycles = 0; |
| 2566 | m_sh2_state->arg0 = 0; |
| 2567 | m_arg1 = 0; |
| 2568 | m_irq = 0; |
| 2569 | m_fastram_select = 0; |
| 2570 | memset(m_fastram, 0, sizeof(m_fastram)); |
| 2385 | 2571 | |
| 2386 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break; |
| 2387 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break; |
| 2388 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; |
| 2389 | | case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; |
| 2390 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; |
| 2391 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; |
| 2392 | | case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; |
| 2393 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; |
| 2394 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; |
| 2572 | /* reset per-driver pcflushes */ |
| 2573 | m_pcfsel = 0; |
| 2395 | 2574 | |
| 2396 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLIN: info->i = sh2->irq_line_state[SH2_INT_VBLIN]; break; |
| 2397 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_VBLOUT: info->i = sh2->irq_line_state[SH2_INT_VBLOUT]; break; |
| 2398 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_HBLIN: info->i = sh2->irq_line_state[SH2_INT_HBLIN]; break; |
| 2399 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER0: info->i = sh2->irq_line_state[SH2_INT_TIMER0]; break; |
| 2400 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_TIMER1: info->i = sh2->irq_line_state[SH2_INT_TIMER1]; break; |
| 2401 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DSP: info->i = sh2->irq_line_state[SH2_INT_DSP]; break; |
| 2402 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SOUND: info->i = sh2->irq_line_state[SH2_INT_SOUND]; break; |
| 2403 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SMPC: info->i = sh2->irq_line_state[SH2_INT_SMPC]; break; |
| 2404 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_PAD: info->i = sh2->irq_line_state[SH2_INT_PAD]; break; |
| 2405 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA2: info->i = sh2->irq_line_state[SH2_INT_DMA2]; break; |
| 2406 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA1: info->i = sh2->irq_line_state[SH2_INT_DMA1]; break; |
| 2407 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMA0: info->i = sh2->irq_line_state[SH2_INT_DMA0]; break; |
| 2408 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_DMAILL: info->i = sh2->irq_line_state[SH2_INT_DMAILL]; break; |
| 2409 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_SPRITE: info->i = sh2->irq_line_state[SH2_INT_SPRITE]; break; |
| 2410 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_14: info->i = sh2->irq_line_state[SH2_INT_14]; break; |
| 2411 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_15: info->i = sh2->irq_line_state[SH2_INT_15]; break; |
| 2412 | | case CPUINFO_INT_INPUT_STATE + SH2_INT_ABUS: info->i = sh2->irq_line_state[SH2_INT_ABUS]; break; |
| 2413 | | case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = sh2->nmi_line_state; break; |
| 2575 | /* initialize the UML generator */ |
| 2576 | UINT32 flags = 0; |
| 2577 | if (LOG_UML) |
| 2578 | flags |= DRCUML_OPTION_LOG_UML; |
| 2579 | if (LOG_NATIVE) |
| 2580 | flags |= DRCUML_OPTION_LOG_NATIVE; |
| 2581 | m_drcuml = auto_alloc(machine(), drcuml_state(*this, m_cache, flags, 1, 32, 1)); |
| 2414 | 2582 | |
| 2415 | | case CPUINFO_INT_PREVIOUSPC: info->i = sh2->ppc; break; |
| 2583 | /* add symbols for our stuff */ |
| 2584 | m_drcuml->symbol_add(&m_sh2_state->pc, sizeof(m_sh2_state->pc), "pc"); |
| 2585 | m_drcuml->symbol_add(&m_sh2_state->icount, sizeof(m_sh2_state->icount), "icount"); |
| 2586 | for (int regnum = 0; regnum < 16; regnum++) |
| 2587 | { |
| 2588 | char buf[10]; |
| 2589 | sprintf(buf, "r%d", regnum); |
| 2590 | m_drcuml->symbol_add(&m_sh2_state->r[regnum], sizeof(m_sh2_state->r[regnum]), buf); |
| 2591 | } |
| 2592 | m_drcuml->symbol_add(&m_sh2_state->pr, sizeof(m_sh2_state->pr), "pr"); |
| 2593 | m_drcuml->symbol_add(&m_sh2_state->sr, sizeof(m_sh2_state->sr), "sr"); |
| 2594 | m_drcuml->symbol_add(&m_sh2_state->gbr, sizeof(m_sh2_state->gbr), "gbr"); |
| 2595 | m_drcuml->symbol_add(&m_sh2_state->vbr, sizeof(m_sh2_state->vbr), "vbr"); |
| 2596 | m_drcuml->symbol_add(&m_sh2_state->macl, sizeof(m_sh2_state->macl), "macl"); |
| 2597 | m_drcuml->symbol_add(&m_sh2_state->mach, sizeof(m_sh2_state->macl), "mach"); |
| 2416 | 2598 | |
| 2417 | | case CPUINFO_INT_PC: |
| 2418 | | case CPUINFO_INT_REGISTER + SH2_PC: info->i = (sh2->delay) ? (sh2->delay & AM) : (sh2->pc & AM); break; |
| 2419 | | case CPUINFO_INT_SP: info->i = sh2->r[15]; break; |
| 2420 | | case CPUINFO_INT_REGISTER + SH2_PR: info->i = sh2->pr; break; |
| 2421 | | case CPUINFO_INT_REGISTER + SH2_SR: info->i = sh2->sr; break; |
| 2422 | | case CPUINFO_INT_REGISTER + SH2_GBR: info->i = sh2->gbr; break; |
| 2423 | | case CPUINFO_INT_REGISTER + SH2_VBR: info->i = sh2->vbr; break; |
| 2424 | | case CPUINFO_INT_REGISTER + SH2_MACH: info->i = sh2->mach; break; |
| 2425 | | case CPUINFO_INT_REGISTER + SH2_MACL: info->i = sh2->macl; break; |
| 2426 | | case CPUINFO_INT_REGISTER + SH2_R0: info->i = sh2->r[ 0]; break; |
| 2427 | | case CPUINFO_INT_REGISTER + SH2_R1: info->i = sh2->r[ 1]; break; |
| 2428 | | case CPUINFO_INT_REGISTER + SH2_R2: info->i = sh2->r[ 2]; break; |
| 2429 | | case CPUINFO_INT_REGISTER + SH2_R3: info->i = sh2->r[ 3]; break; |
| 2430 | | case CPUINFO_INT_REGISTER + SH2_R4: info->i = sh2->r[ 4]; break; |
| 2431 | | case CPUINFO_INT_REGISTER + SH2_R5: info->i = sh2->r[ 5]; break; |
| 2432 | | case CPUINFO_INT_REGISTER + SH2_R6: info->i = sh2->r[ 6]; break; |
| 2433 | | case CPUINFO_INT_REGISTER + SH2_R7: info->i = sh2->r[ 7]; break; |
| 2434 | | case CPUINFO_INT_REGISTER + SH2_R8: info->i = sh2->r[ 8]; break; |
| 2435 | | case CPUINFO_INT_REGISTER + SH2_R9: info->i = sh2->r[ 9]; break; |
| 2436 | | case CPUINFO_INT_REGISTER + SH2_R10: info->i = sh2->r[10]; break; |
| 2437 | | case CPUINFO_INT_REGISTER + SH2_R11: info->i = sh2->r[11]; break; |
| 2438 | | case CPUINFO_INT_REGISTER + SH2_R12: info->i = sh2->r[12]; break; |
| 2439 | | case CPUINFO_INT_REGISTER + SH2_R13: info->i = sh2->r[13]; break; |
| 2440 | | case CPUINFO_INT_REGISTER + SH2_R14: info->i = sh2->r[14]; break; |
| 2441 | | case CPUINFO_INT_REGISTER + SH2_R15: info->i = sh2->r[15]; break; |
| 2442 | | case CPUINFO_INT_REGISTER + SH2_EA: info->i = sh2->ea; break; |
| 2599 | /* initialize the front-end helper */ |
| 2600 | m_drcfe = auto_alloc(machine(), sh2_frontend(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE)); |
| 2443 | 2601 | |
| 2444 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 2445 | | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sh2); break; |
| 2446 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sh2); break; |
| 2447 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh2); break; |
| 2448 | | case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh2); break; |
| 2449 | | case CPUINFO_FCT_BURN: info->burn = NULL; break; |
| 2450 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh2); break; |
| 2451 | | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh2->icount; break; |
| 2602 | /* compute the register parameters */ |
| 2603 | for (int regnum = 0; regnum < 16; regnum++) |
| 2604 | { |
| 2605 | m_regmap[regnum] = uml::mem(&m_sh2_state->r[regnum]); |
| 2606 | } |
| 2452 | 2607 | |
| 2453 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 2454 | | case CPUINFO_STR_NAME: strcpy(info->s, "SH-2"); break; |
| 2455 | | case CPUINFO_STR_SHORTNAME: strcpy(info->s, "sh2"); break; |
| 2456 | | case CPUINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7600"); break; |
| 2457 | | case CPUINFO_STR_VERSION: strcpy(info->s, "1.01"); break; |
| 2458 | | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| 2459 | | case CPUINFO_STR_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller, all rights reserved."); break; |
| 2608 | /* if we have registers to spare, assign r0, r1, r2 to leftovers */ |
| 2609 | /* WARNING: do not use synthetic registers that are mapped here! */ |
| 2610 | if (!DISABLE_FAST_REGISTERS) |
| 2611 | { |
| 2612 | drcbe_info beinfo; |
| 2613 | m_drcuml->get_backend_info(beinfo); |
| 2614 | if (beinfo.direct_iregs > 4) |
| 2615 | { |
| 2616 | m_regmap[0] = uml::I4; |
| 2617 | } |
| 2618 | if (beinfo.direct_iregs > 5) |
| 2619 | { |
| 2620 | m_regmap[1] = uml::I5; |
| 2621 | } |
| 2622 | if (beinfo.direct_iregs > 6) |
| 2623 | { |
| 2624 | m_regmap[2] = uml::I6; |
| 2625 | } |
| 2626 | } |
| 2460 | 2627 | |
| 2461 | | case CPUINFO_STR_FLAGS: |
| 2462 | | sprintf(info->s, "%c%c%d%c%c", |
| 2463 | | sh2->sr & M ? 'M':'.', |
| 2464 | | sh2->sr & Q ? 'Q':'.', |
| 2465 | | (sh2->sr & I) >> 4, |
| 2466 | | sh2->sr & S ? 'S':'.', |
| 2467 | | sh2->sr & T ? 'T':'.'); |
| 2628 | /* mark the cache dirty so it is updated on next execute */ |
| 2629 | m_cache_dirty = TRUE; |
| 2630 | } |
| 2631 | |
| 2632 | |
| 2633 | void sh2_device::state_string_export(const device_state_entry &entry, astring &string) |
| 2634 | { |
| 2635 | switch (entry.index()) |
| 2636 | { |
| 2637 | case STATE_GENFLAGS: |
| 2638 | string.printf("%c%c%d%c%c", |
| 2639 | m_sh2_state->sr & M ? 'M':'.', |
| 2640 | m_sh2_state->sr & Q ? 'Q':'.', |
| 2641 | (m_sh2_state->sr & I) >> 4, |
| 2642 | m_sh2_state->sr & S ? 'S':'.', |
| 2643 | m_sh2_state->sr & T ? 'T':'.'); |
| 2468 | 2644 | break; |
| 2645 | } |
| 2646 | } |
| 2469 | 2647 | |
| 2470 | | case CPUINFO_STR_REGISTER + SH2_PC: sprintf(info->s, "PC :%08X", sh2->pc); break; |
| 2471 | | case CPUINFO_STR_REGISTER + SH2_SR: sprintf(info->s, "SR :%08X", sh2->sr); break; |
| 2472 | | case CPUINFO_STR_REGISTER + SH2_PR: sprintf(info->s, "PR :%08X", sh2->pr); break; |
| 2473 | | case CPUINFO_STR_REGISTER + SH2_GBR: sprintf(info->s, "GBR :%08X", sh2->gbr); break; |
| 2474 | | case CPUINFO_STR_REGISTER + SH2_VBR: sprintf(info->s, "VBR :%08X", sh2->vbr); break; |
| 2475 | | case CPUINFO_STR_REGISTER + SH2_MACH: sprintf(info->s, "MACH:%08X", sh2->mach); break; |
| 2476 | | case CPUINFO_STR_REGISTER + SH2_MACL: sprintf(info->s, "MACL:%08X", sh2->macl); break; |
| 2477 | | case CPUINFO_STR_REGISTER + SH2_R0: sprintf(info->s, "R0 :%08X", sh2->r[ 0]); break; |
| 2478 | | case CPUINFO_STR_REGISTER + SH2_R1: sprintf(info->s, "R1 :%08X", sh2->r[ 1]); break; |
| 2479 | | case CPUINFO_STR_REGISTER + SH2_R2: sprintf(info->s, "R2 :%08X", sh2->r[ 2]); break; |
| 2480 | | case CPUINFO_STR_REGISTER + SH2_R3: sprintf(info->s, "R3 :%08X", sh2->r[ 3]); break; |
| 2481 | | case CPUINFO_STR_REGISTER + SH2_R4: sprintf(info->s, "R4 :%08X", sh2->r[ 4]); break; |
| 2482 | | case CPUINFO_STR_REGISTER + SH2_R5: sprintf(info->s, "R5 :%08X", sh2->r[ 5]); break; |
| 2483 | | case CPUINFO_STR_REGISTER + SH2_R6: sprintf(info->s, "R6 :%08X", sh2->r[ 6]); break; |
| 2484 | | case CPUINFO_STR_REGISTER + SH2_R7: sprintf(info->s, "R7 :%08X", sh2->r[ 7]); break; |
| 2485 | | case CPUINFO_STR_REGISTER + SH2_R8: sprintf(info->s, "R8 :%08X", sh2->r[ 8]); break; |
| 2486 | | case CPUINFO_STR_REGISTER + SH2_R9: sprintf(info->s, "R9 :%08X", sh2->r[ 9]); break; |
| 2487 | | case CPUINFO_STR_REGISTER + SH2_R10: sprintf(info->s, "R10 :%08X", sh2->r[10]); break; |
| 2488 | | case CPUINFO_STR_REGISTER + SH2_R11: sprintf(info->s, "R11 :%08X", sh2->r[11]); break; |
| 2489 | | case CPUINFO_STR_REGISTER + SH2_R12: sprintf(info->s, "R12 :%08X", sh2->r[12]); break; |
| 2490 | | case CPUINFO_STR_REGISTER + SH2_R13: sprintf(info->s, "R13 :%08X", sh2->r[13]); break; |
| 2491 | | case CPUINFO_STR_REGISTER + SH2_R14: sprintf(info->s, "R14 :%08X", sh2->r[14]); break; |
| 2492 | | case CPUINFO_STR_REGISTER + SH2_R15: sprintf(info->s, "R15 :%08X", sh2->r[15]); break; |
| 2493 | | case CPUINFO_STR_REGISTER + SH2_EA: sprintf(info->s, "EA :%08X", sh2->ea); break; |
| 2494 | 2648 | |
| 2649 | void sh2_device::state_import(const device_state_entry &entry) |
| 2650 | { |
| 2651 | switch (entry.index()) |
| 2652 | { |
| 2653 | case SH2_PC: |
| 2654 | m_sh2_state->pc = m_debugger_temp; |
| 2655 | m_delay = 0; |
| 2656 | break; |
| 2657 | |
| 2658 | case SH2_SR: |
| 2659 | CHECK_PENDING_IRQ("sh2_set_reg"); |
| 2660 | break; |
| 2495 | 2661 | } |
| 2496 | 2662 | } |
| 2497 | 2663 | |
| 2498 | | CPU_GET_INFO( sh1_int ) |
| 2664 | |
| 2665 | void sh2_device::state_export(const device_state_entry &entry) |
| 2499 | 2666 | { |
| 2500 | | switch (state) |
| 2667 | switch (entry.index()) |
| 2501 | 2668 | { |
| 2502 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 2503 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh1); break; |
| 2669 | case SH2_PC: |
| 2670 | m_debugger_temp = (m_delay) ? (m_delay & AM) : (m_sh2_state->pc & AM); |
| 2671 | break; |
| 2672 | } |
| 2673 | } |
| 2504 | 2674 | |
| 2505 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 2506 | | case CPUINFO_STR_NAME: strcpy(info->s, "SH-1"); break; |
| 2507 | | case CPUINFO_STR_SHORTNAME: strcpy(info->s, "sh1"); break; |
| 2508 | 2675 | |
| 2509 | | default: CPU_GET_INFO_CALL(sh2_int); break; |
| 2676 | void sh2_device::execute_set_input(int irqline, int state) |
| 2677 | { |
| 2678 | if (irqline == INPUT_LINE_NMI) |
| 2679 | { |
| 2680 | if (m_nmi_line_state == state) |
| 2681 | return; |
| 2682 | m_nmi_line_state = state; |
| 2683 | |
| 2684 | if( state == CLEAR_LINE ) |
| 2685 | { |
| 2686 | LOG(("SH-2 '%s' cleared nmi\n", tag())); |
| 2687 | } |
| 2688 | else |
| 2689 | { |
| 2690 | LOG(("SH-2 '%s' assert nmi\n", tag())); |
| 2691 | |
| 2692 | sh2_exception("Set IRQ line", 16); |
| 2693 | |
| 2694 | if (m_isdrc) |
| 2695 | m_sh2_state->pending_nmi = 1; |
| 2696 | } |
| 2510 | 2697 | } |
| 2698 | else |
| 2699 | { |
| 2700 | if (m_irq_line_state[irqline] == state) |
| 2701 | return; |
| 2702 | m_irq_line_state[irqline] = state; |
| 2703 | |
| 2704 | if( state == CLEAR_LINE ) |
| 2705 | { |
| 2706 | LOG(("SH-2 '%s' cleared irq #%d\n", tag(), irqline)); |
| 2707 | m_sh2_state->pending_irq &= ~(1 << irqline); |
| 2708 | } |
| 2709 | else |
| 2710 | { |
| 2711 | LOG(("SH-2 '%s' assert irq #%d\n", tag(), irqline)); |
| 2712 | m_sh2_state->pending_irq |= 1 << irqline; |
| 2713 | if (m_isdrc) |
| 2714 | { |
| 2715 | m_test_irq = 1; |
| 2716 | } else { |
| 2717 | if(m_delay) |
| 2718 | m_test_irq = 1; |
| 2719 | else |
| 2720 | CHECK_PENDING_IRQ("sh2_set_irq_line"); |
| 2721 | } |
| 2722 | } |
| 2723 | } |
| 2511 | 2724 | } |
| 2512 | 2725 | |
| 2513 | | DEFINE_LEGACY_CPU_DEVICE(SH1_INT, sh1_int); |
| 2514 | | DEFINE_LEGACY_CPU_DEVICE(SH2_INT, sh2_int); |
| 2726 | #include "sh2comn.c" |
| 2727 | #include "sh2drc.c" |
| 2515 | 2728 | |
| 2516 | | |
| 2517 | | const device_type SH1 = &legacy_device_creator_drc<sh1_int_device, sh1_drc_device>; |
| 2518 | | const device_type SH2 = &legacy_device_creator_drc<sh2_int_device, sh2_drc_device>; |
branches/new_menus/src/mess/drivers/oric.c
| r29568 | r29569 | |
| 12 | 12 | Pravetz is a Bulgarian copy of the Oric Atmos and uses |
| 13 | 13 | Apple 2 disc drives for storage. |
| 14 | 14 | |
| 15 | | This driver originally by Paul Cook, rewritten by Kevin Thacker. |
| 15 | This driver originally by Paul Cook, rewritten by Kevin Thacker, |
| 16 | re-rewritten by Olivier Galibert. |
| 16 | 17 | |
| 17 | 18 | *********************************************************************/ |
| 18 | 19 | |
| 19 | | #include "includes/oric.h" |
| 20 | #include "emu.h" |
| 21 | #include "bus/oricext/oricext.h" |
| 22 | #include "cpu/m6502/m6502.h" |
| 23 | #include "sound/ay8910.h" |
| 24 | #include "sound/wave.h" |
| 25 | #include "machine/6522via.h" |
| 26 | #include "machine/mos6551.h" |
| 27 | #include "bus/centronics/ctronics.h" |
| 28 | #include "imagedev/floppy.h" |
| 29 | #include "imagedev/cassette.h" |
| 30 | #include "machine/wd_fdc.h" |
| 31 | #include "formats/oric_dsk.h" |
| 32 | #include "formats/oric_tap.h" |
| 20 | 33 | |
| 21 | | /* |
| 22 | | Explanation of memory regions: |
| 34 | class oric_state : public driver_device |
| 35 | { |
| 36 | public: |
| 37 | // Permanent attributes (kept from one line to the other) and line |
| 38 | // attributes (reset at start of line) |
| 39 | enum { |
| 40 | PATTR_50HZ = 0x02, |
| 41 | PATTR_HIRES = 0x04, |
| 42 | LATTR_ALT = 0x01, |
| 43 | LATTR_DSIZE = 0x02, |
| 44 | LATTR_BLINK = 0x04 |
| 45 | }; |
| 23 | 46 | |
| 24 | | I have split the memory region &c000-&ffff in this way because: |
| 47 | oric_state(const machine_config &mconfig, device_type type, const char *tag) |
| 48 | : driver_device(mconfig, type, tag), |
| 49 | m_maincpu(*this, "maincpu"), |
| 50 | m_psg(*this, "ay8912"), |
| 51 | m_centronics(*this, "centronics"), |
| 52 | m_cent_data_out(*this, "cent_data_out"), |
| 53 | m_cassette(*this, "cassette"), |
| 54 | m_via(*this, "via6522"), |
| 55 | m_ram(*this, "ram"), |
| 56 | m_rom(*this, "maincpu"), |
| 57 | m_bank_c000_r(*this, "bank_c000_r"), |
| 58 | m_bank_e000_r(*this, "bank_e000_r"), |
| 59 | m_bank_f800_r(*this, "bank_f800_r"), |
| 60 | m_bank_c000_w(*this, "bank_c000_w"), |
| 61 | m_bank_e000_w(*this, "bank_e000_w"), |
| 62 | m_bank_f800_w(*this, "bank_f800_w"), |
| 63 | m_config(*this, "CONFIG") { } |
| 25 | 64 | |
| 26 | | All roms (os, microdisc and jasmin) use the 6502 IRQ vectors at the end |
| 27 | | of memory &fff8-&ffff, but they are different sizes. The os is 16k, microdisc |
| 28 | | is 8k and jasmin is 2k. |
| 65 | DECLARE_INPUT_CHANGED_MEMBER(nmi_pressed); |
| 66 | DECLARE_WRITE8_MEMBER(via_a_w); |
| 67 | DECLARE_WRITE8_MEMBER(via_b_w); |
| 68 | DECLARE_WRITE_LINE_MEMBER(via_ca2_w); |
| 69 | DECLARE_WRITE_LINE_MEMBER(via_cb2_w); |
| 70 | DECLARE_WRITE_LINE_MEMBER(via_irq_w); |
| 71 | DECLARE_WRITE_LINE_MEMBER(ext_irq_w); |
| 72 | DECLARE_WRITE8_MEMBER(psg_a_w); |
| 73 | TIMER_DEVICE_CALLBACK_MEMBER(update_tape); |
| 29 | 74 | |
| 30 | | There is also 16k of ram at &c000-&ffff which is normally masked |
| 31 | | by the os rom, but when the microdisc or jasmin interfaces are used, |
| 32 | | this ram can be accessed. For the microdisc and jasmin, the ram not |
| 33 | | covered by the roms for these interfaces, can be accessed |
| 34 | | if it is enabled. |
| 75 | virtual void machine_start(); |
| 76 | virtual void video_start(); |
| 77 | UINT32 screen_update_oric(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| 78 | void vblank_w(screen_device &screen, bool state); |
| 35 | 79 | |
| 36 | | SMH_BANK(1),SMH_BANK(2) and SMH_BANK(3) are used for a 16k rom. |
| 37 | | SMH_BANK(2) and SMH_BANK(3) are used for a 8k rom. |
| 38 | | SMH_BANK(3) is used for a 2k rom. |
| 80 | protected: |
| 81 | required_device<cpu_device> m_maincpu; |
| 82 | required_device<ay8910_device> m_psg; |
| 83 | required_device<centronics_device> m_centronics; |
| 84 | required_device<output_latch_device> m_cent_data_out; |
| 85 | required_device<cassette_image_device> m_cassette; |
| 86 | required_device<via6522_device> m_via; |
| 87 | required_shared_ptr<UINT8> m_ram; |
| 88 | optional_memory_region m_rom; |
| 89 | required_memory_bank m_bank_c000_r; |
| 90 | optional_memory_bank m_bank_e000_r; |
| 91 | optional_memory_bank m_bank_f800_r; |
| 92 | required_memory_bank m_bank_c000_w; |
| 93 | optional_memory_bank m_bank_e000_w; |
| 94 | optional_memory_bank m_bank_f800_w; |
| 95 | required_ioport m_config; |
| 96 | ioport_port *m_kbd_row[8]; |
| 39 | 97 | |
| 40 | | 0x0300-0x03ff is I/O access. It is not defined below because the |
| 41 | | memory is setup dynamically depending on hardware that has been selected (microdisc, jasmin, apple2) etc. |
| 98 | int m_blink_counter; |
| 99 | UINT8 m_pattr; |
| 100 | UINT8 m_via_a, m_via_b, m_psg_a; |
| 101 | bool m_via_ca2, m_via_cb2, m_via_irq; |
| 102 | bool m_ext_irq; |
| 42 | 103 | |
| 43 | | */ |
| 104 | virtual void update_irq(); |
| 105 | void update_psg(address_space &space); |
| 106 | void update_keyboard(); |
| 107 | void machine_start_common(); |
| 108 | }; |
| 44 | 109 | |
| 110 | class telestrat_state : public oric_state |
| 111 | { |
| 112 | public: |
| 113 | telestrat_state(const machine_config &mconfig, device_type type, const char *tag) : |
| 114 | oric_state(mconfig, type, tag), |
| 115 | m_via2(*this, "via6522_2"), |
| 116 | m_fdc(*this, "fdc"), |
| 117 | m_telmatic(*this, "telmatic"), |
| 118 | m_teleass(*this, "teleass"), |
| 119 | m_hyperbas(*this, "hyperbas"), |
| 120 | m_telmon24(*this, "telmon24"), |
| 121 | m_joy1(*this, "JOY1"), |
| 122 | m_joy2(*this, "JOY2") |
| 123 | { } |
| 45 | 124 | |
| 125 | DECLARE_WRITE8_MEMBER(via2_a_w); |
| 126 | DECLARE_WRITE8_MEMBER(via2_b_w); |
| 127 | DECLARE_WRITE_LINE_MEMBER(via2_ca2_w); |
| 128 | DECLARE_WRITE_LINE_MEMBER(via2_cb2_w); |
| 129 | DECLARE_WRITE_LINE_MEMBER(via2_irq_w); |
| 130 | DECLARE_WRITE8_MEMBER(port_314_w); |
| 131 | DECLARE_READ8_MEMBER(port_314_r); |
| 132 | DECLARE_READ8_MEMBER(port_318_r); |
| 133 | |
| 134 | DECLARE_WRITE_LINE_MEMBER(acia_irq_w); |
| 135 | |
| 136 | DECLARE_WRITE_LINE_MEMBER(fdc_irq_w); |
| 137 | DECLARE_WRITE_LINE_MEMBER(fdc_drq_w); |
| 138 | DECLARE_WRITE_LINE_MEMBER(fdc_hld_w); |
| 139 | |
| 140 | DECLARE_FLOPPY_FORMATS(floppy_formats); |
| 141 | |
| 142 | virtual void machine_start(); |
| 143 | virtual void machine_reset(); |
| 144 | |
| 145 | protected: |
| 146 | enum { |
| 147 | P_IRQEN = 0x01, |
| 148 | P_DDS = 0x04, |
| 149 | P_DDEN = 0x08, |
| 150 | P_SS = 0x10, |
| 151 | P_DRIVE = 0x60 |
| 152 | }; |
| 153 | |
| 154 | required_device<via6522_device> m_via2; |
| 155 | required_device<fd1793_t> m_fdc; |
| 156 | required_memory_region m_telmatic; |
| 157 | required_memory_region m_teleass; |
| 158 | required_memory_region m_hyperbas; |
| 159 | required_memory_region m_telmon24; |
| 160 | required_ioport m_joy1; |
| 161 | required_ioport m_joy2; |
| 162 | |
| 163 | floppy_image_device *m_floppies[4]; |
| 164 | UINT8 m_port_314; |
| 165 | UINT8 m_via2_a, m_via2_b; |
| 166 | bool m_via2_ca2, m_via2_cb2, m_via2_irq; |
| 167 | bool m_acia_irq; |
| 168 | bool m_fdc_irq, m_fdc_drq, m_fdc_hld; |
| 169 | |
| 170 | UINT8 m_junk_read[0x4000], m_junk_write[0x4000]; |
| 171 | |
| 172 | virtual void update_irq(); |
| 173 | void remap(); |
| 174 | }; |
| 175 | |
| 176 | /* Ram is 64K, with 16K hidden by the rom. The 300-3ff is also hidden by the i/o */ |
| 46 | 177 | static ADDRESS_MAP_START(oric_mem, AS_PROGRAM, 8, oric_state ) |
| 47 | | AM_RANGE( 0x0000, 0xbfff) AM_RAM AM_SHARE("ram") |
| 48 | | AM_RANGE( 0xc000, 0xdfff) AM_READ_BANK("bank1") AM_WRITE_BANK("bank5") |
| 49 | | AM_RANGE( 0xe000, 0xf7ff) AM_READ_BANK("bank2") AM_WRITE_BANK("bank6") |
| 50 | | AM_RANGE( 0xf800, 0xffff) AM_READ_BANK("bank3") AM_WRITE_BANK("bank7") |
| 178 | AM_RANGE( 0x0300, 0x030f) AM_DEVREADWRITE("via6522", via6522_device, read, write) AM_MIRROR(0xf0) |
| 179 | AM_RANGE( 0xc000, 0xdfff) AM_READ_BANK("bank_c000_r") AM_WRITE_BANK("bank_c000_w") |
| 180 | AM_RANGE( 0xe000, 0xf7ff) AM_READ_BANK("bank_e000_r") AM_WRITE_BANK("bank_e000_w") |
| 181 | AM_RANGE( 0xf800, 0xffff) AM_READ_BANK("bank_f800_r") AM_WRITE_BANK("bank_f800_w") |
| 182 | AM_RANGE( 0x0000, 0xffff) AM_RAM AM_SHARE("ram") |
| 51 | 183 | ADDRESS_MAP_END |
| 52 | 184 | |
| 53 | 185 | /* |
| 54 | 186 | The telestrat has the memory regions split into 16k blocks. |
| 55 | 187 | Memory region &c000-&ffff can be ram or rom. */ |
| 56 | | static ADDRESS_MAP_START(telestrat_mem, AS_PROGRAM, 8, oric_state ) |
| 57 | | AM_RANGE( 0x0000, 0x02ff) AM_RAM |
| 58 | | AM_RANGE( 0x0300, 0x030f) AM_DEVREADWRITE("via6522_0", via6522_device, read, write) |
| 59 | | AM_RANGE( 0x0310, 0x031b) AM_READWRITE(oric_microdisc_r, oric_microdisc_w ) |
| 188 | static ADDRESS_MAP_START(telestrat_mem, AS_PROGRAM, 8, telestrat_state ) |
| 189 | AM_RANGE( 0x0300, 0x030f) AM_DEVREADWRITE("via6522", via6522_device, read, write) |
| 190 | AM_RANGE( 0x0310, 0x0313) AM_DEVREADWRITE("fdc", fd1793_t, read, write) |
| 191 | AM_RANGE( 0x0314, 0x0314) AM_READWRITE(port_314_r, port_314_w) |
| 192 | AM_RANGE( 0x0318, 0x0318) AM_READ(port_318_r) |
| 60 | 193 | AM_RANGE( 0x031c, 0x031f) AM_DEVREADWRITE("acia", mos6551_device, read, write) |
| 61 | | AM_RANGE( 0x0320, 0x032f) AM_DEVREADWRITE("via6522_1", via6522_device, read, write) |
| 62 | | AM_RANGE( 0x0400, 0xbfff) AM_RAM |
| 63 | | AM_RANGE( 0xc000, 0xffff) AM_READ_BANK("bank1") AM_WRITE_BANK("bank2") |
| 194 | AM_RANGE( 0x0320, 0x032f) AM_DEVREADWRITE("via6522_2", via6522_device, read, write) |
| 195 | AM_RANGE( 0xc000, 0xffff) AM_READ_BANK("bank_c000_r") AM_WRITE_BANK("bank_c000_w") |
| 196 | AM_RANGE( 0x0000, 0xffff) AM_RAM AM_SHARE("ram") |
| 64 | 197 | ADDRESS_MAP_END |
| 65 | 198 | |
| 199 | UINT32 oric_state::screen_update_oric(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 200 | { |
| 201 | static const UINT32 colors[8] = { |
| 202 | 0x000000, |
| 203 | 0xff0000, |
| 204 | 0x00ff00, |
| 205 | 0xffff00, |
| 206 | 0x0000ff, |
| 207 | 0xff00ff, |
| 208 | 0x00ffff, |
| 209 | 0xffffff |
| 210 | }; |
| 66 | 211 | |
| 212 | bool blink_state = m_blink_counter & 0x20; |
| 213 | m_blink_counter = (m_blink_counter + 1) & 0x3f; |
| 214 | |
| 215 | UINT8 pattr = m_pattr; |
| 216 | |
| 217 | for(int y=0; y<224; y++) { |
| 218 | // Line attributes and current colors |
| 219 | UINT8 lattr = 0; |
| 220 | UINT32 fgcol = colors[7]; |
| 221 | UINT32 bgcol = colors[0]; |
| 222 | |
| 223 | UINT32 *p = &bitmap.pix32(y); |
| 224 | |
| 225 | for(int x=0; x<40; x++) { |
| 226 | // Lookup the byte and, if needed, the pattern data |
| 227 | UINT8 ch, pat; |
| 228 | if((pattr & PATTR_HIRES) && y < 200) |
| 229 | ch = pat = m_ram[0xa000 + y*40 + x]; |
| 230 | |
| 231 | else { |
| 232 | ch = m_ram[0xbb80 + (y>>3)*40 + x]; |
| 233 | int off = (lattr & LATTR_DSIZE ? y >> 1 : y ) & 7; |
| 234 | const UINT8 *base; |
| 235 | if(pattr & PATTR_HIRES) |
| 236 | if(lattr & LATTR_ALT) |
| 237 | base = m_ram + 0x9c00; |
| 238 | else |
| 239 | base = m_ram + 0x9800; |
| 240 | else |
| 241 | if(lattr & LATTR_ALT) |
| 242 | base = m_ram + 0xb800; |
| 243 | else |
| 244 | base = m_ram + 0xb400; |
| 245 | pat = base[((ch & 0x7f) << 3) | off]; |
| 246 | } |
| 247 | |
| 248 | // Handle state-chaging attributes |
| 249 | if(!(ch & 0x60)) { |
| 250 | pat = 0x00; |
| 251 | switch(ch & 0x18) { |
| 252 | case 0x00: fgcol = colors[ch & 7]; break; |
| 253 | case 0x08: lattr = ch & 7; break; |
| 254 | case 0x10: bgcol = colors[ch & 7]; break; |
| 255 | case 0x18: pattr = ch & 7; break; |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | // Pick up the colors for the pattern |
| 260 | UINT32 c_fgcol = fgcol; |
| 261 | UINT32 c_bgcol = bgcol; |
| 262 | |
| 263 | // inverse video |
| 264 | if(ch & 0x80) { |
| 265 | c_bgcol = c_bgcol ^ 0xffffff; |
| 266 | c_fgcol = c_fgcol ^ 0xffffff; |
| 267 | } |
| 268 | // blink |
| 269 | if((lattr & LATTR_BLINK) && blink_state) |
| 270 | c_fgcol = c_bgcol; |
| 271 | |
| 272 | // Draw the pattern |
| 273 | *p++ = pat & 0x20 ? c_fgcol : c_bgcol; |
| 274 | *p++ = pat & 0x10 ? c_fgcol : c_bgcol; |
| 275 | *p++ = pat & 0x08 ? c_fgcol : c_bgcol; |
| 276 | *p++ = pat & 0x04 ? c_fgcol : c_bgcol; |
| 277 | *p++ = pat & 0x02 ? c_fgcol : c_bgcol; |
| 278 | *p++ = pat & 0x01 ? c_fgcol : c_bgcol; |
| 279 | } |
| 280 | } |
| 281 | |
| 282 | m_pattr = pattr; |
| 283 | |
| 284 | return 0; |
| 285 | } |
| 286 | |
| 287 | void oric_state::update_keyboard() |
| 288 | { |
| 289 | m_via->write_pb3((m_kbd_row[m_via_b & 7]->read() | m_psg_a) != 0xff); |
| 290 | } |
| 291 | |
| 292 | void oric_state::update_psg(address_space &space) |
| 293 | { |
| 294 | if(m_via_ca2) |
| 295 | if(m_via_cb2) |
| 296 | m_psg->address_w(space, 0, m_via_a); |
| 297 | else |
| 298 | m_via->write_pa(space, 0, m_psg->data_r(space, 0)); |
| 299 | else if(m_via_cb2) |
| 300 | m_psg->data_w(space, 0, m_via_a); |
| 301 | } |
| 302 | |
| 303 | void oric_state::update_irq() |
| 304 | { |
| 305 | m_maincpu->set_input_line(m6502_device::IRQ_LINE, m_via_irq || m_ext_irq ? ASSERT_LINE : CLEAR_LINE); |
| 306 | } |
| 307 | |
| 308 | INPUT_CHANGED_MEMBER(oric_state::nmi_pressed) |
| 309 | { |
| 310 | m_maincpu->set_input_line(m6502_device::NMI_LINE, newval ? ASSERT_LINE : CLEAR_LINE); |
| 311 | } |
| 312 | |
| 313 | WRITE8_MEMBER(oric_state::via_a_w) |
| 314 | { |
| 315 | m_via_a = data; |
| 316 | m_cent_data_out->write(space, 0, m_via_a); |
| 317 | update_psg(space); |
| 318 | } |
| 319 | |
| 320 | WRITE8_MEMBER(oric_state::via_b_w) |
| 321 | { |
| 322 | m_via_b = data; |
| 323 | update_keyboard(); |
| 324 | m_centronics->write_strobe(data & 0x10 ? 1 : 0); |
| 325 | m_cassette->change_state(data & 0x40 ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, |
| 326 | CASSETTE_MOTOR_DISABLED); |
| 327 | m_cassette->output(data & 0x80 ? -1.0 : +1.0); |
| 328 | } |
| 329 | |
| 330 | WRITE_LINE_MEMBER(oric_state::via_ca2_w) |
| 331 | { |
| 332 | m_via_ca2 = state; |
| 333 | update_psg(m_maincpu->space(AS_PROGRAM)); |
| 334 | } |
| 335 | |
| 336 | WRITE_LINE_MEMBER(oric_state::via_cb2_w) |
| 337 | { |
| 338 | m_via_cb2 = state; |
| 339 | update_psg(m_maincpu->space(AS_PROGRAM)); |
| 340 | } |
| 341 | |
| 342 | WRITE_LINE_MEMBER(oric_state::via_irq_w) |
| 343 | { |
| 344 | m_via_irq = state; |
| 345 | update_irq(); |
| 346 | } |
| 347 | |
| 348 | WRITE_LINE_MEMBER(oric_state::ext_irq_w) |
| 349 | { |
| 350 | m_ext_irq = state; |
| 351 | update_irq(); |
| 352 | } |
| 353 | |
| 354 | WRITE8_MEMBER(oric_state::psg_a_w) |
| 355 | { |
| 356 | m_psg_a = data; |
| 357 | update_keyboard(); |
| 358 | } |
| 359 | |
| 360 | TIMER_DEVICE_CALLBACK_MEMBER(oric_state::update_tape) |
| 361 | { |
| 362 | if(!m_config->read()) |
| 363 | m_via->write_cb1(m_cassette->input() > 0.0038); |
| 364 | } |
| 365 | |
| 366 | void oric_state::vblank_w(screen_device &screen, bool state) |
| 367 | { |
| 368 | if(m_config->read()) |
| 369 | m_via->write_cb1(state); |
| 370 | } |
| 371 | |
| 372 | void oric_state::video_start() |
| 373 | { |
| 374 | m_blink_counter = 0; |
| 375 | m_pattr = 0; |
| 376 | } |
| 377 | |
| 378 | void oric_state::machine_start_common() |
| 379 | { |
| 380 | m_via_a = 0xff; |
| 381 | m_via_b = 0xff; |
| 382 | m_psg_a = 0x00; |
| 383 | m_via_ca2 = false; |
| 384 | m_via_cb2 = false; |
| 385 | m_via_irq = false; |
| 386 | m_ext_irq = false; |
| 387 | |
| 388 | for(int i=0; i<8; i++) { |
| 389 | char name[10]; |
| 390 | sprintf(name, "ROW%d", i); |
| 391 | m_kbd_row[i] = machine().root_device().ioport(name); |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | void oric_state::machine_start() |
| 396 | { |
| 397 | machine_start_common(); |
| 398 | m_bank_c000_r->set_base(m_rom->base()); |
| 399 | m_bank_e000_r->set_base(m_rom->base() + 0x2000); |
| 400 | m_bank_f800_r->set_base(m_rom->base() + 0x3800); |
| 401 | } |
| 402 | |
| 403 | |
| 404 | void telestrat_state::machine_start() |
| 405 | { |
| 406 | machine_start_common(); |
| 407 | for(int i=0; i<4; i++) { |
| 408 | char name[32]; |
| 409 | sprintf(name, "fdc:%d", i); |
| 410 | m_floppies[i] = subdevice<floppy_connector>(name)->get_device(); |
| 411 | } |
| 412 | m_fdc_irq = m_fdc_drq = m_fdc_hld = false; |
| 413 | m_acia_irq = false; |
| 414 | |
| 415 | memset(m_junk_read, 0x00, sizeof(m_junk_read)); |
| 416 | memset(m_junk_write, 0x00, sizeof(m_junk_write)); |
| 417 | } |
| 418 | |
| 419 | void telestrat_state::machine_reset() |
| 420 | { |
| 421 | m_port_314 = 0x00; |
| 422 | m_via2_a = 0xff; |
| 423 | remap(); |
| 424 | } |
| 425 | |
| 426 | void telestrat_state::update_irq() |
| 427 | { |
| 428 | m_maincpu->set_input_line(m6502_device::IRQ_LINE, |
| 429 | m_via_irq || |
| 430 | m_ext_irq || |
| 431 | (m_fdc_irq && (m_port_314 & P_IRQEN)) || |
| 432 | m_via2_irq || |
| 433 | m_acia_irq ? ASSERT_LINE : CLEAR_LINE); |
| 434 | } |
| 435 | |
| 436 | WRITE8_MEMBER(telestrat_state::via2_a_w) |
| 437 | { |
| 438 | m_via2_a = data; |
| 439 | remap(); |
| 440 | } |
| 441 | |
| 442 | WRITE8_MEMBER(telestrat_state::via2_b_w) |
| 443 | { |
| 444 | m_via2_b = data; |
| 445 | UINT8 port = 0xff; |
| 446 | if(!(m_via2_b & 0x40)) |
| 447 | port &= m_joy1->read(); |
| 448 | if(!(m_via2_b & 0x80)) |
| 449 | port &= m_joy2->read(); |
| 450 | |
| 451 | m_via2->write_pb(space, 0, port); |
| 452 | } |
| 453 | |
| 454 | WRITE_LINE_MEMBER(telestrat_state::via2_ca2_w) |
| 455 | { |
| 456 | m_via2_ca2 = state; |
| 457 | } |
| 458 | |
| 459 | WRITE_LINE_MEMBER(telestrat_state::via2_cb2_w) |
| 460 | { |
| 461 | m_via2_cb2 = state; |
| 462 | } |
| 463 | |
| 464 | WRITE_LINE_MEMBER(telestrat_state::via2_irq_w) |
| 465 | { |
| 466 | m_via2_irq = state; |
| 467 | update_irq(); |
| 468 | } |
| 469 | |
| 470 | WRITE8_MEMBER(telestrat_state::port_314_w) |
| 471 | { |
| 472 | m_port_314 = data; |
| 473 | floppy_image_device *floppy = m_floppies[(m_port_314 >> 5) & 3]; |
| 474 | m_fdc->set_floppy(floppy); |
| 475 | m_fdc->dden_w(m_port_314 & P_DDEN); |
| 476 | if(floppy) { |
| 477 | floppy->ss_w(m_port_314 & P_SS ? 1 : 0); |
| 478 | floppy->mon_w(0); |
| 479 | } |
| 480 | update_irq(); |
| 481 | } |
| 482 | |
| 483 | READ8_MEMBER(telestrat_state::port_314_r) |
| 484 | { |
| 485 | return (m_fdc_irq && (m_port_314 & P_IRQEN)) ? 0x7f : 0xff; |
| 486 | } |
| 487 | |
| 488 | READ8_MEMBER(telestrat_state::port_318_r) |
| 489 | { |
| 490 | return m_fdc_drq ? 0x7f : 0xff; |
| 491 | } |
| 492 | |
| 493 | |
| 494 | WRITE_LINE_MEMBER(telestrat_state::acia_irq_w) |
| 495 | { |
| 496 | m_acia_irq = state; |
| 497 | update_irq(); |
| 498 | } |
| 499 | |
| 500 | WRITE_LINE_MEMBER(telestrat_state::fdc_irq_w) |
| 501 | { |
| 502 | m_fdc_irq = state; |
| 503 | update_irq(); |
| 504 | } |
| 505 | |
| 506 | WRITE_LINE_MEMBER(telestrat_state::fdc_drq_w) |
| 507 | { |
| 508 | m_fdc_drq = state; |
| 509 | } |
| 510 | |
| 511 | WRITE_LINE_MEMBER(telestrat_state::fdc_hld_w) |
| 512 | { |
| 513 | m_fdc_hld = state; |
| 514 | } |
| 515 | |
| 516 | void telestrat_state::remap() |
| 517 | { |
| 518 | // Theorically, these are cartridges. There's no real point to |
| 519 | // making them configurable, when only 4 existed and there are 7 |
| 520 | // slots. |
| 521 | |
| 522 | switch(m_via2_a & 7) { |
| 523 | case 0: |
| 524 | m_bank_c000_r->set_base(m_ram+0xc000); |
| 525 | m_bank_c000_w->set_base(m_ram+0xc000); |
| 526 | break; |
| 527 | case 1: |
| 528 | case 2: |
| 529 | case 3: |
| 530 | m_bank_c000_r->set_base(m_junk_read); |
| 531 | m_bank_c000_w->set_base(m_junk_write); |
| 532 | break; |
| 533 | case 4: |
| 534 | m_bank_c000_r->set_base(m_telmatic->base()); |
| 535 | m_bank_c000_w->set_base(m_junk_write); |
| 536 | break; |
| 537 | case 5: |
| 538 | m_bank_c000_r->set_base(m_teleass->base()); |
| 539 | m_bank_c000_w->set_base(m_junk_write); |
| 540 | break; |
| 541 | case 6: |
| 542 | m_bank_c000_r->set_base(m_hyperbas->base()); |
| 543 | m_bank_c000_w->set_base(m_junk_write); |
| 544 | break; |
| 545 | case 7: |
| 546 | m_bank_c000_r->set_base(m_telmon24->base()); |
| 547 | m_bank_c000_w->set_base(m_junk_write); |
| 548 | break; |
| 549 | } |
| 550 | } |
| 551 | |
| 552 | |
| 553 | |
| 67 | 554 | static INPUT_PORTS_START(oric) |
| 68 | 555 | PORT_START("ROW0") |
| 69 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') |
| 70 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') |
| 71 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') |
| 72 | | PORT_BIT(0x10, 0x00, IPT_UNUSED) |
| 73 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') |
| 74 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') |
| 75 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') |
| 76 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') |
| 556 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') |
| 557 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') |
| 558 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') |
| 559 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 560 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') |
| 561 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') |
| 562 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') |
| 563 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') |
| 77 | 564 | |
| 78 | 565 | PORT_START("ROW1") |
| 79 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') |
| 80 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') |
| 81 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(ESC)) |
| 82 | | PORT_BIT(0x10, 0x00, IPT_UNUSED) |
| 83 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') |
| 84 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') |
| 85 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') |
| 86 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') |
| 566 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') |
| 567 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') |
| 568 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(ESC)) |
| 569 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 570 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') |
| 571 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') |
| 572 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') |
| 573 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') |
| 87 | 574 | |
| 88 | 575 | PORT_START("ROW2") |
| 89 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') |
| 90 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') |
| 91 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') |
| 92 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) |
| 93 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') |
| 94 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') |
| 95 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') |
| 96 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') |
| 576 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') |
| 577 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') |
| 578 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') |
| 579 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) |
| 580 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') |
| 581 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') |
| 582 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') |
| 583 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') |
| 97 | 584 | |
| 98 | 585 | PORT_START("ROW3") |
| 99 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') |
| 100 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CHAR('|') |
| 101 | | PORT_BIT(0x20, 0x00, IPT_UNUSED) |
| 102 | | PORT_BIT(0x10, 0x00, IPT_UNUSED) |
| 103 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('\xA3') |
| 104 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') |
| 105 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') |
| 106 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') |
| 586 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') |
| 587 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CHAR('|') |
| 588 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED) |
| 589 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 590 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('\xA3') |
| 591 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') |
| 592 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') |
| 593 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') |
| 107 | 594 | |
| 108 | 595 | PORT_START("ROW4") |
| 109 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) |
| 110 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) |
| 111 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) |
| 112 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT)) |
| 113 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) |
| 114 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') |
| 115 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') |
| 116 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') |
| 596 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) |
| 597 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) |
| 598 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) |
| 599 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT)) |
| 600 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) |
| 601 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') |
| 602 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') |
| 603 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') |
| 117 | 604 | |
| 118 | 605 | PORT_START("ROW5") |
| 119 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') |
| 120 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') |
| 121 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) |
| 122 | | PORT_BIT(0x10, 0x00, IPT_UNUSED) |
| 123 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') |
| 124 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') |
| 125 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') |
| 126 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') |
| 606 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') |
| 607 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') |
| 608 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) |
| 609 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 610 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') |
| 611 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') |
| 612 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') |
| 613 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') |
| 127 | 614 | |
| 128 | 615 | PORT_START("ROW6") |
| 129 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') |
| 130 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') |
| 131 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') |
| 132 | | PORT_BIT(0x10, 0x00, IPT_UNUSED) |
| 133 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') |
| 134 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') |
| 135 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') |
| 136 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') |
| 616 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') |
| 617 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') |
| 618 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') |
| 619 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 620 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') |
| 621 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') |
| 622 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') |
| 623 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') |
| 137 | 624 | |
| 138 | 625 | PORT_START("ROW7") |
| 139 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') |
| 140 | | PORT_BIT(0x40, 0x00, IPT_UNUSED) |
| 141 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) |
| 142 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) |
| 143 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') |
| 144 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') |
| 145 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') |
| 146 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') |
| 626 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') |
| 627 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED) |
| 628 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) |
| 629 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) |
| 630 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') |
| 631 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') |
| 632 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') |
| 633 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') |
| 147 | 634 | |
| 148 | | PORT_START("FLOPPY") |
| 149 | | /* floppy interface */ |
| 150 | | PORT_CONFNAME( 0x03, 0x00, "Floppy disc interface" ) |
| 151 | | PORT_CONFSETTING( 0x00, DEF_STR( None ) ) |
| 152 | | PORT_CONFSETTING( 0x01, "Microdisc" ) |
| 153 | | PORT_CONFSETTING( 0x02, "Jasmin" ) |
| 154 | | /* PORT_CONFSETTING( 0x03, "Low 8D DOS" ) */ |
| 155 | | /* PORT_CONFSETTING( 0x04, "High 8D DOS" ) */ |
| 635 | PORT_START("NMI") |
| 636 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("NMI") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CHANGED_MEMBER(DEVICE_SELF, oric_state, nmi_pressed, 0) |
| 156 | 637 | |
| 157 | 638 | /* vsync cable hardware. This is a simple cable connected to the video output |
| 158 | 639 | to the monitor/television. The sync signal is connected to the cassette input |
| 159 | 640 | allowing interrupts to be generated from the vsync signal. */ |
| 160 | | PORT_CONFNAME(0x08, 0x00, "Vsync cable hardware") |
| 161 | | PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) |
| 162 | | PORT_CONFSETTING( 0x08, DEF_STR( On ) ) |
| 163 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_VBLANK("screen") |
| 641 | PORT_START("CONFIG") |
| 642 | PORT_CONFNAME(0x01, 0x00, "Tape input") |
| 643 | PORT_CONFSETTING( 0x00, "Tape") |
| 644 | PORT_CONFSETTING( 0x01, "VSync cable") |
| 164 | 645 | INPUT_PORTS_END |
| 165 | 646 | |
| 166 | 647 | static INPUT_PORTS_START(orica) |
| 167 | 648 | PORT_INCLUDE( oric ) |
| 168 | 649 | |
| 169 | 650 | PORT_MODIFY("ROW5") |
| 170 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Funct") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(F1)) |
| 651 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Funct") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) |
| 171 | 652 | INPUT_PORTS_END |
| 172 | 653 | |
| 173 | 654 | static INPUT_PORTS_START(prav8d) |
| 174 | 655 | PORT_START("ROW0") |
| 175 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') |
| 176 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("X \xd0\xac") PORT_CODE(KEYCODE_X) PORT_CHAR('X') |
| 177 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') |
| 178 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 179 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("V \xd0\x96") PORT_CODE(KEYCODE_V) PORT_CHAR('V') |
| 180 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') |
| 181 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("N \xd0\x9d") PORT_CODE(KEYCODE_N) PORT_CHAR('N') |
| 182 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') |
| 656 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') |
| 657 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X \xd0\xac") PORT_CODE(KEYCODE_X) PORT_CHAR('X') |
| 658 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') |
| 659 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 660 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V \xd0\x96") PORT_CODE(KEYCODE_V) PORT_CHAR('V') |
| 661 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') |
| 662 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N \xd0\x9d") PORT_CODE(KEYCODE_N) PORT_CHAR('N') |
| 663 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') |
| 183 | 664 | |
| 184 | 665 | PORT_START("ROW1") |
| 185 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D \xd0\x94") PORT_CODE(KEYCODE_D) PORT_CHAR('D') |
| 186 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Q \xd0\xaf") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') |
| 187 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) |
| 188 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 189 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F \xd0\xa4") PORT_CODE(KEYCODE_F) PORT_CHAR('F') |
| 190 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("R \xd0\xa0") PORT_CODE(KEYCODE_R) PORT_CHAR('R') |
| 191 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("T \xd0\xa2") PORT_CODE(KEYCODE_T) PORT_CHAR('T') |
| 192 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("J \xd0\x99") PORT_CODE(KEYCODE_J) PORT_CHAR('J') |
| 666 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D \xd0\x94") PORT_CODE(KEYCODE_D) PORT_CHAR('D') |
| 667 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q \xd0\xaf") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') |
| 668 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) |
| 669 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 670 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F \xd0\xa4") PORT_CODE(KEYCODE_F) PORT_CHAR('F') |
| 671 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R \xd0\xa0") PORT_CODE(KEYCODE_R) PORT_CHAR('R') |
| 672 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T \xd0\xa2") PORT_CODE(KEYCODE_T) PORT_CHAR('T') |
| 673 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J \xd0\x99") PORT_CODE(KEYCODE_J) PORT_CHAR('J') |
| 193 | 674 | |
| 194 | 675 | PORT_START("ROW2") |
| 195 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C \xd0\xa6") PORT_CODE(KEYCODE_C) PORT_CHAR('C') |
| 196 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') |
| 197 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Z \xd0\x97") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') |
| 198 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("MK") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) |
| 199 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') |
| 200 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B \xd0\x91") PORT_CODE(KEYCODE_B) PORT_CHAR('B') |
| 201 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') |
| 202 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("M \xd0\x9c") PORT_CODE(KEYCODE_M) PORT_CHAR('M') |
| 676 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C \xd0\xa6") PORT_CODE(KEYCODE_C) PORT_CHAR('C') |
| 677 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') |
| 678 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z \xd0\x97") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') |
| 679 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("MK") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) |
| 680 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') |
| 681 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B \xd0\x91") PORT_CODE(KEYCODE_B) PORT_CHAR('B') |
| 682 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') |
| 683 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M \xd0\x9c") PORT_CODE(KEYCODE_M) PORT_CHAR('M') |
| 203 | 684 | |
| 204 | 685 | PORT_START("ROW3") |
| 205 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("] \xd0\xa9") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(']') |
| 206 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR(';') PORT_CHAR('+') |
| 207 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C/L") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) // this one is 5th line, 1st key from right |
| 208 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 209 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(':') PORT_CHAR('*') |
| 210 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("[ \xd0\xa8") PORT_CODE(KEYCODE_COLON) PORT_CHAR('[') |
| 211 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') |
| 212 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("K \xd0\x9a") PORT_CODE(KEYCODE_K) PORT_CHAR('K') |
| 686 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("] \xd0\xa9") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(']') |
| 687 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR(';') PORT_CHAR('+') |
| 688 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C/L") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) // this one is 5th line, 1st key from right |
| 689 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 690 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(':') PORT_CHAR('*') |
| 691 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("[ \xd0\xa8") PORT_CODE(KEYCODE_COLON) PORT_CHAR('[') |
| 692 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') |
| 693 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K \xd0\x9a") PORT_CODE(KEYCODE_K) PORT_CHAR('K') |
| 213 | 694 | |
| 214 | 695 | PORT_START("ROW4") |
| 215 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) |
| 216 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) |
| 217 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) |
| 218 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT)) |
| 219 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) |
| 220 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') |
| 221 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') |
| 222 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') |
| 696 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) |
| 697 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) |
| 698 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) |
| 699 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT)) |
| 700 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) |
| 701 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') |
| 702 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') |
| 703 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') |
| 223 | 704 | |
| 224 | 705 | PORT_START("ROW5") |
| 225 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("@ \xd0\xae") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') |
| 226 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("\\ \xd0\xad") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('\\') |
| 227 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) // this one is 5th line, 1st key from left |
| 228 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 229 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P \xd0\x9f") PORT_CODE(KEYCODE_P) PORT_CHAR('P') |
| 230 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("O \xd0\x9e") PORT_CODE(KEYCODE_O) PORT_CHAR('O') |
| 231 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("I \xd0\x98") PORT_CODE(KEYCODE_I) PORT_CHAR('I') |
| 232 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("U \xd0\xa3") PORT_CODE(KEYCODE_U) PORT_CHAR('U') |
| 706 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("@ \xd0\xae") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') |
| 707 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\\ \xd0\xad") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('\\') |
| 708 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) // this one is 5th line, 1st key from left |
| 709 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 710 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P \xd0\x9f") PORT_CODE(KEYCODE_P) PORT_CHAR('P') |
| 711 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O \xd0\x9e") PORT_CODE(KEYCODE_O) PORT_CHAR('O') |
| 712 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I \xd0\x98") PORT_CODE(KEYCODE_I) PORT_CHAR('I') |
| 713 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U \xd0\xa3") PORT_CODE(KEYCODE_U) PORT_CHAR('U') |
| 233 | 714 | |
| 234 | 715 | PORT_START("ROW6") |
| 235 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("W \xd0\x92") PORT_CODE(KEYCODE_W) PORT_CHAR('W') |
| 236 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("S \xd0\xa1") PORT_CODE(KEYCODE_S) PORT_CHAR('S') |
| 237 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A \xd0\x90") PORT_CODE(KEYCODE_A) PORT_CHAR('A') |
| 238 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 239 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E \xd0\x95") PORT_CODE(KEYCODE_E) PORT_CHAR('E') |
| 240 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G \xd0\x93") PORT_CODE(KEYCODE_G) PORT_CHAR('G') |
| 241 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("H \xd0\xa5") PORT_CODE(KEYCODE_H) PORT_CHAR('H') |
| 242 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Y \xd0\xaa") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') |
| 716 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W \xd0\x92") PORT_CODE(KEYCODE_W) PORT_CHAR('W') |
| 717 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S \xd0\xa1") PORT_CODE(KEYCODE_S) PORT_CHAR('S') |
| 718 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A \xd0\x90") PORT_CODE(KEYCODE_A) PORT_CHAR('A') |
| 719 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) |
| 720 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E \xd0\x95") PORT_CODE(KEYCODE_E) PORT_CHAR('E') |
| 721 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G \xd0\x93") PORT_CODE(KEYCODE_G) PORT_CHAR('G') |
| 722 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H \xd0\xa5") PORT_CODE(KEYCODE_H) PORT_CHAR('H') |
| 723 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y \xd0\xaa") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') |
| 243 | 724 | |
| 244 | 725 | PORT_START("ROW7") |
| 245 | | PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('=') |
| 246 | | PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("^ \xd0\xa7") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('^') // this one would be on 2nd line, 3rd key from 'P' |
| 247 | | PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) |
| 248 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) |
| 249 | | PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') |
| 250 | | PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') |
| 251 | | PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L \xd0\x9b") PORT_CODE(KEYCODE_L) PORT_CHAR('L') |
| 252 | | PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') |
| 726 | PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('=') |
| 727 | PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^ \xd0\xa7") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('^') // this one would be on 2nd line, 3rd key from 'P' |
| 728 | PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) |
| 729 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) |
| 730 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') |
| 731 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') |
| 732 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L \xd0\x9b") PORT_CODE(KEYCODE_L) PORT_CHAR('L') |
| 733 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') |
| 253 | 734 | |
| 254 | | PORT_START("FLOPPY") |
| 255 | | /* force apple2 disc interface for pravetz */ |
| 256 | | PORT_START("oric_floppy_interface") |
| 257 | | PORT_CONFNAME( 0x07, 0x00, "Floppy disc interface" ) |
| 258 | | PORT_CONFSETTING( 0x00, DEF_STR( None ) ) |
| 259 | | PORT_CONFSETTING( 0x03, "Low 8D DOS" ) |
| 260 | | PORT_CONFSETTING( 0x04, "High 8D DOS" ) |
| 735 | PORT_START("NMI") |
| 736 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("NMI") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CHANGED_MEMBER(DEVICE_SELF, oric_state, nmi_pressed, 0) |
| 261 | 737 | |
| 262 | 738 | /* vsync cable hardware. This is a simple cable connected to the video output |
| 263 | 739 | to the monitor/television. The sync signal is connected to the cassette input |
| 264 | 740 | allowing interrupts to be generated from the vsync signal. */ |
| 265 | | PORT_CONFNAME(0x08, 0x00, "Vsync cable hardware") |
| 266 | | PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) |
| 267 | | PORT_CONFSETTING( 0x08, DEF_STR( On ) ) |
| 268 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_VBLANK("screen") |
| 741 | PORT_START("CONFIG") |
| 742 | PORT_CONFNAME(0x01, 0x00, "Tape input") |
| 743 | PORT_CONFSETTING( 0x00, "Tape") |
| 744 | PORT_CONFSETTING( 0x01, "VSync cable") |
| 269 | 745 | INPUT_PORTS_END |
| 270 | 746 | |
| 271 | 747 | static INPUT_PORTS_START(telstrat) |
| 272 | | PORT_INCLUDE( oric ) |
| 748 | PORT_INCLUDE( orica ) |
| 273 | 749 | |
| 274 | | PORT_MODIFY("ROW5") |
| 275 | | PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Funct") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(F1)) |
| 750 | // The telestrat does not have the NMI button |
| 751 | PORT_MODIFY("NMI") |
| 752 | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 276 | 753 | |
| 277 | | PORT_MODIFY("FLOPPY") |
| 278 | | /* vsync cable hardware. This is a simple cable connected to the video output |
| 279 | | to the monitor/television. The sync signal is connected to the cassette input |
| 280 | | allowing interrupts to be generated from the vsync signal. */ |
| 281 | | PORT_BIT(0x07, 0x00, IPT_UNUSED) |
| 282 | | PORT_CONFNAME(0x08, 0x00, "Vsync cable hardware") |
| 283 | | PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) |
| 284 | | PORT_CONFSETTING( 0x08, DEF_STR( On ) ) |
| 285 | | PORT_BIT( 0x010, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_VBLANK("screen") |
| 754 | PORT_START("JOY1") /* left joystick port */ |
| 755 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1) |
| 756 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1) |
| 757 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) |
| 758 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1) |
| 759 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1) |
| 286 | 760 | |
| 287 | | PORT_START("JOY0") /* left joystick port */ |
| 288 | | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 0 Up") PORT_CODE(JOYCODE_X_RIGHT_SWITCH) |
| 289 | | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 0 Down") PORT_CODE(JOYCODE_X_LEFT_SWITCH) |
| 290 | | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 0 Left") PORT_CODE(JOYCODE_BUTTON1) |
| 291 | | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 0 Right") PORT_CODE(JOYCODE_Y_DOWN_SWITCH) |
| 292 | | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 0 Fire 1") PORT_CODE(JOYCODE_Y_UP_SWITCH) |
| 293 | | |
| 294 | | PORT_START("JOY1") /* right joystick port */ |
| 295 | | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 1 Up") PORT_CODE(JOYCODE_X_RIGHT_SWITCH) |
| 296 | | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 1 Down") PORT_CODE(JOYCODE_X_LEFT_SWITCH) |
| 297 | | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 1 Left") PORT_CODE(JOYCODE_BUTTON1) |
| 298 | | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 1 Right") PORT_CODE(JOYCODE_Y_DOWN_SWITCH) |
| 299 | | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Joystick 1 Fire 1") PORT_CODE(JOYCODE_Y_UP_SWITCH) |
| 761 | PORT_START("JOY2") /* right joystick port */ |
| 762 | PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2) |
| 763 | PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2) |
| 764 | PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) |
| 765 | PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2) |
| 766 | PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2) |
| 300 | 767 | INPUT_PORTS_END |
| 301 | 768 | |
| 302 | 769 | |
| 303 | | static const unsigned char oric_palette[8*3] = |
| 304 | | { |
| 305 | | 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, |
| 306 | | 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, |
| 307 | | 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, |
| 308 | | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 309 | | }; |
| 310 | | |
| 311 | | /* Initialise the palette */ |
| 312 | | PALETTE_INIT_MEMBER(oric_state, oric) |
| 313 | | { |
| 314 | | int i; |
| 315 | | |
| 316 | | for ( i = 0; i < sizeof(oric_palette) / 3; i++ ) { |
| 317 | | palette.set_pen_color(i, oric_palette[i*3], oric_palette[i*3+1], oric_palette[i*3+2]); |
| 318 | | } |
| 319 | | } |
| 320 | | |
| 321 | | |
| 322 | | |
| 323 | 770 | static const ay8910_interface oric_ay_interface = |
| 324 | 771 | { |
| 325 | | AY8910_LEGACY_OUTPUT, |
| 326 | | AY8910_DEFAULT_LOADS, |
| 772 | AY8910_DISCRETE_OUTPUT, |
| 773 | { 4700, 4700, 4700}, |
| 327 | 774 | DEVCB_NULL, |
| 328 | 775 | DEVCB_NULL, |
| 329 | | DEVCB_DRIVER_MEMBER(oric_state, oric_psg_porta_write), |
| 776 | DEVCB_DRIVER_MEMBER(oric_state, psg_a_w), |
| 330 | 777 | DEVCB_NULL, |
| 331 | 778 | }; |
| 332 | 779 | |
| r29568 | r29569 | |
| 340 | 787 | NULL |
| 341 | 788 | }; |
| 342 | 789 | |
| 343 | | static const floppy_interface oric1_floppy_interface = |
| 344 | | { |
| 345 | | DEVCB_NULL, |
| 346 | | DEVCB_NULL, |
| 347 | | DEVCB_NULL, |
| 348 | | DEVCB_NULL, |
| 349 | | DEVCB_NULL, |
| 350 | | FLOPPY_STANDARD_5_25_DSHD, |
| 351 | | LEGACY_FLOPPY_OPTIONS_NAME(oric), |
| 352 | | NULL, |
| 353 | | NULL |
| 354 | | }; |
| 355 | | |
| 356 | | static const floppy_interface prav8d_floppy_interface = |
| 357 | | { |
| 358 | | DEVCB_NULL, |
| 359 | | DEVCB_NULL, |
| 360 | | DEVCB_NULL, |
| 361 | | DEVCB_NULL, |
| 362 | | DEVCB_NULL, |
| 363 | | FLOPPY_STANDARD_5_25_DSHD, |
| 364 | | LEGACY_FLOPPY_OPTIONS_NAME(apple2), |
| 365 | | NULL, |
| 366 | | NULL |
| 367 | | }; |
| 368 | | |
| 369 | 790 | static MACHINE_CONFIG_START( oric, oric_state ) |
| 370 | 791 | /* basic machine hardware */ |
| 371 | | MCFG_CPU_ADD("maincpu", M6502, 1000000) |
| 792 | MCFG_CPU_ADD("maincpu", M6502, XTAL_12MHz/12) |
| 372 | 793 | MCFG_CPU_PROGRAM_MAP(oric_mem) |
| 373 | 794 | MCFG_QUANTUM_TIME(attotime::from_hz(60)) |
| 374 | 795 | |
| 375 | | |
| 376 | 796 | /* video hardware */ |
| 377 | 797 | MCFG_SCREEN_ADD("screen", RASTER) |
| 378 | 798 | MCFG_SCREEN_REFRESH_RATE(60) |
| r29568 | r29569 | |
| 380 | 800 | MCFG_SCREEN_SIZE(40*6, 28*8) |
| 381 | 801 | MCFG_SCREEN_VISIBLE_AREA(0, 40*6-1, 0, 28*8-1) |
| 382 | 802 | MCFG_SCREEN_UPDATE_DRIVER(oric_state, screen_update_oric) |
| 383 | | MCFG_SCREEN_PALETTE("palette") |
| 803 | MCFG_SCREEN_VBLANK_DRIVER(oric_state, vblank_w) |
| 384 | 804 | |
| 385 | | MCFG_PALETTE_ADD("palette", 8) |
| 386 | | MCFG_PALETTE_INIT_OWNER(oric_state, oric) |
| 387 | | |
| 388 | | |
| 389 | 805 | /* sound hardware */ |
| 390 | 806 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 391 | 807 | MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette") |
| 392 | 808 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 393 | | MCFG_SOUND_ADD("ay8912", AY8912, 1000000) |
| 809 | MCFG_SOUND_ADD("ay8912", AY8912, XTAL_12MHz/12) |
| 394 | 810 | MCFG_SOUND_CONFIG(oric_ay_interface) |
| 395 | 811 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
| 396 | 812 | |
| 397 | 813 | /* printer */ |
| 398 | 814 | MCFG_CENTRONICS_ADD("centronics", centronics_printers, "image") |
| 399 | | MCFG_CENTRONICS_ACK_HANDLER(DEVWRITELINE("via6522_0", via6522_device, write_ca1)) |
| 400 | | |
| 815 | MCFG_CENTRONICS_ACK_HANDLER(DEVWRITELINE("via6522", via6522_device, write_ca1)) |
| 401 | 816 | MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", "centronics") |
| 402 | 817 | |
| 403 | 818 | /* cassette */ |
| 404 | 819 | MCFG_CASSETTE_ADD( "cassette", oric_cassette_interface ) |
| 820 | MCFG_TIMER_DRIVER_ADD_PERIODIC("tape_timer", oric_state, update_tape, attotime::from_hz(4800)) |
| 405 | 821 | |
| 406 | 822 | /* via */ |
| 407 | | MCFG_DEVICE_ADD( "via6522_0", VIA6522, 1000000 ) |
| 408 | | MCFG_VIA6522_READPA_HANDLER(READ8(oric_state, oric_via_in_a_func)) |
| 409 | | MCFG_VIA6522_READPB_HANDLER(READ8(oric_state, oric_via_in_b_func)) |
| 410 | | MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(oric_state, oric_via_out_a_func)) |
| 411 | | MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(oric_state, oric_via_out_b_func)) |
| 412 | | MCFG_VIA6522_CA2_HANDLER(WRITELINE(oric_state, oric_via_out_ca2_func)) |
| 413 | | MCFG_VIA6522_CB2_HANDLER(WRITELINE(oric_state, oric_via_out_cb2_func)) |
| 414 | | MCFG_VIA6522_IRQ_HANDLER(WRITELINE(oric_state, oric_via_irq_func)) |
| 823 | MCFG_DEVICE_ADD( "via6522", VIA6522, XTAL_12MHz/12 ) |
| 824 | MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(oric_state, via_a_w)) |
| 825 | MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(oric_state, via_b_w)) |
| 826 | MCFG_VIA6522_CA2_HANDLER(WRITELINE(oric_state, via_ca2_w)) |
| 827 | MCFG_VIA6522_CB2_HANDLER(WRITELINE(oric_state, via_cb2_w)) |
| 828 | MCFG_VIA6522_IRQ_HANDLER(WRITELINE(oric_state, via_irq_w)) |
| 415 | 829 | |
| 416 | | MCFG_WD1770_ADD("wd179x", oric_wd17xx_interface ) |
| 417 | | |
| 418 | | MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(oric1_floppy_interface) |
| 830 | /* extension port */ |
| 831 | MCFG_ORICEXT_ADD( "ext", oricext_intf, NULL, "maincpu", WRITELINE(oric_state, ext_irq_w)) |
| 419 | 832 | MACHINE_CONFIG_END |
| 420 | 833 | |
| 421 | 834 | static MACHINE_CONFIG_DERIVED( prav8d, oric ) |
| 422 | | MCFG_LEGACY_FLOPPY_4_DRIVES_REMOVE() |
| 423 | | MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, prav8d_floppy_interface) |
| 424 | 835 | MACHINE_CONFIG_END |
| 425 | 836 | |
| 426 | | static MACHINE_CONFIG_DERIVED( telstrat, oric ) |
| 837 | FLOPPY_FORMATS_MEMBER( telestrat_state::floppy_formats ) |
| 838 | FLOPPY_ORIC_DSK_FORMAT |
| 839 | FLOPPY_FORMATS_END |
| 840 | |
| 841 | static SLOT_INTERFACE_START( telestrat_floppies ) |
| 842 | SLOT_INTERFACE( "3dsdd", FLOPPY_3_DSDD ) |
| 843 | SLOT_INTERFACE_END |
| 844 | |
| 845 | static MACHINE_CONFIG_DERIVED_CLASS( telstrat, oric, telestrat_state ) |
| 427 | 846 | MCFG_CPU_MODIFY( "maincpu" ) |
| 428 | | MCFG_CPU_PROGRAM_MAP( telestrat_mem) |
| 847 | MCFG_CPU_PROGRAM_MAP(telestrat_mem) |
| 429 | 848 | |
| 430 | | MCFG_MACHINE_START_OVERRIDE(oric_state, telestrat ) |
| 431 | | |
| 432 | 849 | /* acia */ |
| 433 | 850 | MCFG_DEVICE_ADD("acia", MOS6551, 0) |
| 434 | 851 | MCFG_MOS6551_XTAL(XTAL_1_8432MHz) |
| 435 | | MCFG_MOS6551_IRQ_HANDLER(WRITELINE(oric_state, telestrat_acia_callback)) |
| 852 | MCFG_MOS6551_IRQ_HANDLER(WRITELINE(telestrat_state, acia_irq_w)) |
| 436 | 853 | |
| 437 | 854 | /* via */ |
| 438 | | MCFG_DEVICE_ADD( "via6522_1", VIA6522, 1000000 ) |
| 439 | | MCFG_VIA6522_READPA_HANDLER(READ8(oric_state, telestrat_via2_in_a_func)) |
| 440 | | MCFG_VIA6522_READPB_HANDLER(READ8(oric_state, telestrat_via2_in_b_func)) |
| 441 | | MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(oric_state, telestrat_via2_out_a_func)) |
| 442 | | MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(oric_state, telestrat_via2_out_b_func)) |
| 443 | | MCFG_VIA6522_IRQ_HANDLER(WRITELINE(oric_state, telestrat_via2_irq_func)) |
| 855 | MCFG_DEVICE_ADD( "via6522_2", VIA6522, XTAL_12MHz/12 ) |
| 856 | MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(telestrat_state, via2_a_w)) |
| 857 | MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(telestrat_state, via2_b_w)) |
| 858 | MCFG_VIA6522_CA2_HANDLER(WRITELINE(telestrat_state, via2_ca2_w)) |
| 859 | MCFG_VIA6522_CB2_HANDLER(WRITELINE(telestrat_state, via2_cb2_w)) |
| 860 | MCFG_VIA6522_IRQ_HANDLER(WRITELINE(telestrat_state, via2_irq_w)) |
| 861 | |
| 862 | /* microdisc */ |
| 863 | MCFG_FD1793x_ADD("fdc", XTAL_8MHz/8) |
| 864 | MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(telestrat_state, fdc_irq_w)) |
| 865 | MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(telestrat_state, fdc_drq_w)) |
| 866 | MCFG_WD_FDC_HLD_CALLBACK(WRITELINE(telestrat_state, fdc_hld_w)) |
| 867 | MCFG_WD_FDC_FORCE_READY |
| 868 | |
| 869 | MCFG_FLOPPY_DRIVE_ADD("fdc:0", telestrat_floppies, "3dsdd", telestrat_state::floppy_formats) |
| 870 | MCFG_FLOPPY_DRIVE_ADD("fdc:1", telestrat_floppies, NULL, telestrat_state::floppy_formats) |
| 871 | MCFG_FLOPPY_DRIVE_ADD("fdc:2", telestrat_floppies, NULL, telestrat_state::floppy_formats) |
| 872 | MCFG_FLOPPY_DRIVE_ADD("fdc:3", telestrat_floppies, NULL, telestrat_state::floppy_formats) |
| 444 | 873 | MACHINE_CONFIG_END |
| 445 | 874 | |
| 446 | 875 | |
| 447 | 876 | ROM_START(oric1) |
| 448 | | ROM_REGION(0x16800, "maincpu", 0) /* 0x10000 + 0x04000 + 0x02000 + 0x00800 */ |
| 449 | | ROM_LOAD ("basic10.rom", 0x10000, 0x04000, CRC(f18710b4) SHA1(333116e6884d85aaa4dfc7578a91cceeea66d016)) |
| 450 | | ROM_LOAD_OPTIONAL ("microdis.rom", 0x14000, 0x02000, CRC(a9664a9c) SHA1(0d2ef6e67322f48f4b7e08d8bbe68827e2074561) ) |
| 451 | | ROM_LOAD_OPTIONAL ("jasmin.rom", 0x16000, 0x00800, CRC(37220e89) SHA1(70e59b8abd67092f050462abc6cb5271e4c15f01) ) |
| 877 | ROM_REGION(0x4000, "maincpu", 0) |
| 878 | ROM_LOAD ("basic10.rom", 0, 0x04000, CRC(f18710b4) SHA1(333116e6884d85aaa4dfc7578a91cceeea66d016)) |
| 452 | 879 | ROM_END |
| 453 | 880 | |
| 454 | 881 | ROM_START(orica) |
| 455 | | ROM_REGION(0x16800, "maincpu", 0) /* 0x10000 + 0x04000 + 0x02000 + 0x00800 */ |
| 882 | ROM_REGION(0x4000, "maincpu", 0) |
| 456 | 883 | ROM_SYSTEM_BIOS( 0, "ver11", "Basic 1.1") |
| 457 | | ROMX_LOAD ("basic11b.rom", 0x10000, 0x04000, CRC(c3a92bef) SHA1(9451a1a09d8f75944dbd6f91193fc360f1de80ac), ROM_BIOS(1) ) |
| 884 | ROMX_LOAD ("basic11b.rom", 0, 0x04000, CRC(c3a92bef) SHA1(9451a1a09d8f75944dbd6f91193fc360f1de80ac), ROM_BIOS(1) ) |
| 458 | 885 | ROM_SYSTEM_BIOS( 1, "ver12", "Basic 1.2 (Pascal Leclerc)") // 1987/1999 - various enhancements and bugfixes |
| 459 | | ROMX_LOAD ("basic12.rom", 0x10000, 0x04000, CRC(dc4f22dc) SHA1(845e1a893de3dc0f856fdf2f69c3b73770b4094f), ROM_BIOS(2) ) |
| 886 | ROMX_LOAD ("basic12.rom", 0, 0x04000, CRC(dc4f22dc) SHA1(845e1a893de3dc0f856fdf2f69c3b73770b4094f), ROM_BIOS(2) ) |
| 460 | 887 | ROM_SYSTEM_BIOS( 2, "ver121", "Basic 1.21 (Pascal Leclerc)") // 07.1999 - DRAW enhancement |
| 461 | | ROMX_LOAD ("basic121.rom", 0x10000, 0x04000, CRC(0a2860b1) SHA1(b727d5c3bbc8cb1d510f224eb1e0d90d609e8506), ROM_BIOS(3) ) |
| 888 | ROMX_LOAD ("basic121.rom", 0, 0x04000, CRC(0a2860b1) SHA1(b727d5c3bbc8cb1d510f224eb1e0d90d609e8506), ROM_BIOS(3) ) |
| 462 | 889 | ROM_SYSTEM_BIOS( 3, "ver122", "Basic 1.22 (Pascal Leclerc)") // 08.2001 - added EUR symbol |
| 463 | | ROMX_LOAD ("basic122.rom", 0x10000, 0x04000, CRC(5ef2a861) SHA1(9ab6dc47b6e9dc65a4137ce0f0f12fc2b6ca8442), ROM_BIOS(4) ) |
| 890 | ROMX_LOAD ("basic122.rom", 0, 0x04000, CRC(5ef2a861) SHA1(9ab6dc47b6e9dc65a4137ce0f0f12fc2b6ca8442), ROM_BIOS(4) ) |
| 464 | 891 | ROM_SYSTEM_BIOS( 4, "ver11de", "Basic 1.1 DE") |
| 465 | | ROMX_LOAD( "bas11_de.rom", 0x10000, 0x04000, CRC(65233b2d) SHA1(b01cabb1a21980a6785a2fe37a8f8572c892123f), ROM_BIOS(5)) |
| 892 | ROMX_LOAD( "bas11_de.rom", 0, 0x04000, CRC(65233b2d) SHA1(b01cabb1a21980a6785a2fe37a8f8572c892123f), ROM_BIOS(5)) |
| 466 | 893 | ROM_SYSTEM_BIOS( 5, "ver11es", "Basic 1.1 ES") |
| 467 | | ROMX_LOAD( "bas11_es.rom", 0x10000, 0x04000, CRC(47bf26c7) SHA1(4fdbadd68db9ab8ad1cd56b4e5cbe51a9c3f11ae), ROM_BIOS(6)) |
| 894 | ROMX_LOAD( "bas11_es.rom", 0, 0x04000, CRC(47bf26c7) SHA1(4fdbadd68db9ab8ad1cd56b4e5cbe51a9c3f11ae), ROM_BIOS(6)) |
| 468 | 895 | ROM_SYSTEM_BIOS( 6, "ver11fr", "Basic 1.1 FR") |
| 469 | | ROMX_LOAD( "bas11_fr.rom", 0x10000, 0x04000, CRC(603b1fbf) SHA1(2a4583df3b59ca454d67d5631f242c96ec4cf99a), ROM_BIOS(7)) |
| 896 | ROMX_LOAD( "bas11_fr.rom", 0, 0x04000, CRC(603b1fbf) SHA1(2a4583df3b59ca454d67d5631f242c96ec4cf99a), ROM_BIOS(7)) |
| 470 | 897 | ROM_SYSTEM_BIOS( 7, "ver11se", "Basic 1.1 SE") |
| 471 | | ROMX_LOAD( "bas11_se.rom", 0x10000, 0x04000, CRC(a71523ac) SHA1(ce53acf84baec6ab5cbac9f9cefa71b3efeb2ead), ROM_BIOS(8)) |
| 898 | ROMX_LOAD( "bas11_se.rom", 0, 0x04000, CRC(a71523ac) SHA1(ce53acf84baec6ab5cbac9f9cefa71b3efeb2ead), ROM_BIOS(8)) |
| 472 | 899 | ROM_SYSTEM_BIOS( 8, "ver11uk", "Basic 1.1 UK") |
| 473 | | ROMX_LOAD( "bas11_uk.rom", 0x10000, 0x04000, CRC(303370d1) SHA1(589ff66fac8e06d65af3369491faa67a71f1322a), ROM_BIOS(9)) |
| 900 | ROMX_LOAD( "bas11_uk.rom", 0, 0x04000, CRC(303370d1) SHA1(589ff66fac8e06d65af3369491faa67a71f1322a), ROM_BIOS(9)) |
| 474 | 901 | ROM_SYSTEM_BIOS( 9, "ver12es", "Basic 1.2 ES") |
| 475 | | ROMX_LOAD( "bas12es_le.rom", 0x10000, 0x04000, CRC(70de4aeb) SHA1(b327418aa7d8a5a03c135e3d8acdd511df625893), ROM_BIOS(10)) |
| 902 | ROMX_LOAD( "bas12es_le.rom", 0, 0x04000, CRC(70de4aeb) SHA1(b327418aa7d8a5a03c135e3d8acdd511df625893), ROM_BIOS(10)) |
| 476 | 903 | ROM_SYSTEM_BIOS( 10, "ver12fr", "Basic 1.2 FR") |
| 477 | | ROMX_LOAD( "bas12fr_le.rom", 0x10000, 0x04000, CRC(47a437fc) SHA1(70271bc3ed5c3bf4d339d6f5de3de8c3c50ff573), ROM_BIOS(11)) |
| 904 | ROMX_LOAD( "bas12fr_le.rom", 0, 0x04000, CRC(47a437fc) SHA1(70271bc3ed5c3bf4d339d6f5de3de8c3c50ff573), ROM_BIOS(11)) |
| 478 | 905 | ROM_SYSTEM_BIOS( 11, "ver12ge", "Basic 1.2 GE") |
| 479 | | ROMX_LOAD( "bas12ge_le.rom", 0x10000, 0x04000, CRC(f5f0dd52) SHA1(75359302452ee7b19537698f124aaefd333688d0), ROM_BIOS(12)) |
| 906 | ROMX_LOAD( "bas12ge_le.rom", 0, 0x04000, CRC(f5f0dd52) SHA1(75359302452ee7b19537698f124aaefd333688d0), ROM_BIOS(12)) |
| 480 | 907 | ROM_SYSTEM_BIOS( 12, "ver12sw", "Basic 1.2 SW") |
| 481 | | ROMX_LOAD( "bas12sw_le.rom", 0x10000, 0x04000, CRC(100abe68) SHA1(6211d5969c4d7a6acb86ed19c5e51a33a3bef431), ROM_BIOS(13)) |
| 908 | ROMX_LOAD( "bas12sw_le.rom", 0, 0x04000, CRC(100abe68) SHA1(6211d5969c4d7a6acb86ed19c5e51a33a3bef431), ROM_BIOS(13)) |
| 482 | 909 | ROM_SYSTEM_BIOS( 13, "ver12uk", "Basic 1.2 UK") |
| 483 | | ROMX_LOAD( "bas12uk_le.rom", 0x10000, 0x04000, CRC(00fce8a6) SHA1(d40558bdf61b8aba6260293c9424fd463be7fad8), ROM_BIOS(14)) |
| 910 | ROMX_LOAD( "bas12uk_le.rom", 0, 0x04000, CRC(00fce8a6) SHA1(d40558bdf61b8aba6260293c9424fd463be7fad8), ROM_BIOS(14)) |
| 484 | 911 | ROM_SYSTEM_BIOS( 14, "ver121es", "Basic 1.211 ES") |
| 485 | | ROMX_LOAD( "bas121es_le.rom", 0x10000, 0x04000, CRC(87ec679b) SHA1(5de6a5f5121f69069c9b93d678046e814b5b64e9), ROM_BIOS(15)) |
| 912 | ROMX_LOAD( "bas121es_le.rom", 0, 0x04000, CRC(87ec679b) SHA1(5de6a5f5121f69069c9b93d678046e814b5b64e9), ROM_BIOS(15)) |
| 486 | 913 | ROM_SYSTEM_BIOS( 15, "ver121fr", "Basic 1.211 FR") |
| 487 | | ROMX_LOAD( "bas121fr_le.rom", 0x10000, 0x04000, CRC(e683dec2) SHA1(20df7ebc0f13aa835f286d50137f1a7ff7430c29), ROM_BIOS(16)) |
| 914 | ROMX_LOAD( "bas121fr_le.rom", 0, 0x04000, CRC(e683dec2) SHA1(20df7ebc0f13aa835f286d50137f1a7ff7430c29), ROM_BIOS(16)) |
| 488 | 915 | ROM_SYSTEM_BIOS( 16, "ver121ge", "Basic 1.211 GE") |
| 489 | | ROMX_LOAD( "bas121ge_le.rom", 0x10000, 0x04000, CRC(94fe32bf) SHA1(1024776d20030d602e432e50014502524658643a), ROM_BIOS(17)) |
| 916 | ROMX_LOAD( "bas121ge_le.rom", 0, 0x04000, CRC(94fe32bf) SHA1(1024776d20030d602e432e50014502524658643a), ROM_BIOS(17)) |
| 490 | 917 | ROM_SYSTEM_BIOS( 17, "ver121sw", "Basic 1.211 SW") |
| 491 | | ROMX_LOAD( "bas121sw_le.rom", 0x10000, 0x04000, CRC(e6ad11c7) SHA1(309c94a9861fcb770636dcde1801a5c68ca819b4), ROM_BIOS(18)) |
| 918 | ROMX_LOAD( "bas121sw_le.rom", 0, 0x04000, CRC(e6ad11c7) SHA1(309c94a9861fcb770636dcde1801a5c68ca819b4), ROM_BIOS(18)) |
| 492 | 919 | ROM_SYSTEM_BIOS( 18, "ver121uk", "Basic 1.211 UK") |
| 493 | | ROMX_LOAD( "bas121uk_le.rom", 0x10000, 0x04000, CRC(75aa1aa9) SHA1(ca99e244d9cbef625344c2054023504a4f9dcfe4), ROM_BIOS(19)) |
| 920 | ROMX_LOAD( "bas121uk_le.rom", 0, 0x04000, CRC(75aa1aa9) SHA1(ca99e244d9cbef625344c2054023504a4f9dcfe4), ROM_BIOS(19)) |
| 494 | 921 | ROM_SYSTEM_BIOS( 19, "ver122es", "Basic 1.22 ES") |
| 495 | | ROMX_LOAD( "bas122es_le.rom", 0x10000, 0x04000, CRC(9144f9e0) SHA1(acf2094078af057e74a31d90d7010be51b9033fa), ROM_BIOS(20)) |
| 922 | ROMX_LOAD( "bas122es_le.rom", 0, 0x04000, CRC(9144f9e0) SHA1(acf2094078af057e74a31d90d7010be51b9033fa), ROM_BIOS(20)) |
| 496 | 923 | ROM_SYSTEM_BIOS( 20, "ver122fr", "Basic 1.22 FR") |
| 497 | | ROMX_LOAD( "bas122fr_le.rom", 0x10000, 0x04000, CRC(370cfda4) SHA1(fad9a0661256e59bcc2915578647573e4128e1bb), ROM_BIOS(21)) |
| 924 | ROMX_LOAD( "bas122fr_le.rom", 0, 0x04000, CRC(370cfda4) SHA1(fad9a0661256e59bcc2915578647573e4128e1bb), ROM_BIOS(21)) |
| 498 | 925 | ROM_SYSTEM_BIOS( 21, "ver122ge", "Basic 1.22 GE") |
| 499 | | ROMX_LOAD( "bas122ge_le.rom", 0x10000, 0x04000, CRC(9a42bd62) SHA1(8a9c80f314daf4e5e64fa202e583b8a65796db8b), ROM_BIOS(22)) |
| 926 | ROMX_LOAD( "bas122ge_le.rom", 0, 0x04000, CRC(9a42bd62) SHA1(8a9c80f314daf4e5e64fa202e583b8a65796db8b), ROM_BIOS(22)) |
| 500 | 927 | ROM_SYSTEM_BIOS( 22, "ver122sw", "Basic 1.22 SW") |
| 501 | | ROMX_LOAD( "bas122sw_le.rom", 0x10000, 0x04000, CRC(e7fd57a4) SHA1(c75cbf7cfafaa02712dc7ca2f972220aef86fb8d), ROM_BIOS(23)) |
| 928 | ROMX_LOAD( "bas122sw_le.rom", 0, 0x04000, CRC(e7fd57a4) SHA1(c75cbf7cfafaa02712dc7ca2f972220aef86fb8d), ROM_BIOS(23)) |
| 502 | 929 | ROM_SYSTEM_BIOS( 23, "ver122uk", "Basic 1.22 UK") |
| 503 | | ROMX_LOAD( "bas122uk_le.rom", 0x10000, 0x04000, CRC(9865bcd7) SHA1(2a92e2d119463e682bf10647e3880e26656d65b5), ROM_BIOS(24)) |
| 504 | | |
| 505 | | ROM_LOAD_OPTIONAL ("microdis.rom", 0x14000, 0x02000, CRC(a9664a9c) SHA1(0d2ef6e67322f48f4b7e08d8bbe68827e2074561) ) |
| 506 | | ROM_LOAD_OPTIONAL ("jasmin.rom", 0x16000, 0x00800, CRC(37220e89) SHA1(70e59b8abd67092f050462abc6cb5271e4c15f01) ) |
| 930 | ROMX_LOAD( "bas122uk_le.rom", 0, 0x04000, CRC(9865bcd7) SHA1(2a92e2d119463e682bf10647e3880e26656d65b5), ROM_BIOS(24)) |
| 507 | 931 | ROM_END |
| 508 | 932 | |
| 509 | 933 | ROM_START(telstrat) |
| 510 | | ROM_REGION(0x30000, "maincpu", 0) /* 0x10000 + (0x04000 * 4) */ |
| 511 | | ROM_LOAD ("telmatic.rom", 0x010000, 0x02000, CRC(94358dc6) SHA1(35f92a0477a88f5cf564971125047ffcfa02ec10) ) |
| 512 | | ROM_LOAD ("teleass.rom", 0x014000, 0x04000, CRC(68b0fde6) SHA1(9e9af51dae3199cccf49ab3f0d47e2b9be4ba97d) ) |
| 513 | | ROM_LOAD ("hyperbas.rom", 0x018000, 0x04000, CRC(1d96ab50) SHA1(f5f70a0eb59f8cd6c261e179ae78ef906f68ed63) ) |
| 514 | | ROM_LOAD ("telmon24.rom", 0x01c000, 0x04000, CRC(aa727c5d) SHA1(86fc8dc0932f983efa199e31ae05a4424772f959) ) |
| 934 | ROM_REGION(0x4000, "telmatic", 0) |
| 935 | ROM_LOAD ("telmatic.rom", 0, 0x2000, CRC(94358dc6) SHA1(35f92a0477a88f5cf564971125047ffcfa02ec10) ) |
| 936 | ROM_RELOAD (0x2000, 0x2000) |
| 937 | |
| 938 | ROM_REGION(0x4000, "teleass", 0) |
| 939 | ROM_LOAD ("teleass.rom", 0, 0x4000, CRC(68b0fde6) SHA1(9e9af51dae3199cccf49ab3f0d47e2b9be4ba97d) ) |
| 940 | |
| 941 | ROM_REGION(0x4000, "hyperbas", 0) |
| 942 | ROM_LOAD ("hyperbas.rom", 0, 0x4000, CRC(1d96ab50) SHA1(f5f70a0eb59f8cd6c261e179ae78ef906f68ed63) ) |
| 943 | |
| 944 | ROM_REGION(0x4000, "telmon24", 0) |
| 945 | ROM_LOAD ("telmon24.rom", 0, 0x4000, CRC(aa727c5d) SHA1(86fc8dc0932f983efa199e31ae05a4424772f959) ) |
| 515 | 946 | ROM_END |
| 516 | 947 | |
| 517 | 948 | ROM_START(prav8d) |
| 518 | | ROM_REGION(0x14300, "maincpu", 0) /* 0x10000 + 0x04000 + 0x00100 + 0x00200 */ |
| 519 | | ROM_LOAD( "pravetzt.rom", 0x10000, 0x4000, CRC(58079502) SHA1(7afc276cb118adff72e4f16698f94bf3b2c64146) ) |
| 520 | | ROM_LOAD_OPTIONAL( "8ddoslo.rom", 0x014000, 0x0100, CRC(0c82f636) SHA1(b29d151a0dfa3c7cd50439b51d0a8f95559bc2b6) ) |
| 521 | | ROM_LOAD_OPTIONAL( "8ddoshi.rom", 0x014100, 0x0200, CRC(66309641) SHA1(9c2e82b3c4d385ade6215fcb89f8b92e6fd2bf4b) ) |
| 949 | ROM_REGION(0x4000, "maincpu", 0) /* 0x10000 + 0x04000 + 0x00100 + 0x00200 */ |
| 950 | ROM_LOAD( "pravetzt.rom", 0, 0x4000, CRC(58079502) SHA1(7afc276cb118adff72e4f16698f94bf3b2c64146) ) |
| 951 | // ROM_LOAD_OPTIONAL( "8ddoslo.rom", 0x014000, 0x0100, CRC(0c82f636) SHA1(b29d151a0dfa3c7cd50439b51d0a8f95559bc2b6) ) |
| 952 | // ROM_LOAD_OPTIONAL( "8ddoshi.rom", 0x014100, 0x0200, CRC(66309641) SHA1(9c2e82b3c4d385ade6215fcb89f8b92e6fd2bf4b) ) |
| 522 | 953 | ROM_END |
| 523 | 954 | |
| 524 | 955 | ROM_START(prav8dd) |
| 525 | | ROM_REGION(0x14300, "maincpu", 0) /* 0x10000 + 0x04000 + 0x00100 + 0x00200 */ |
| 956 | ROM_REGION(0x4000, "maincpu", 0) /* 0x10000 + 0x04000 + 0x00100 + 0x00200 */ |
| 526 | 957 | ROM_SYSTEM_BIOS( 0, "default", "Disk ROM, 1989") |
| 527 | | ROMX_LOAD( "8d.rom", 0x10000, 0x4000, CRC(b48973ef) SHA1(fd47c977fc215a3b577596a7483df53e8a1e9c83), ROM_BIOS(1) ) |
| 958 | ROMX_LOAD( "8d.rom", 0, 0x4000, CRC(b48973ef) SHA1(fd47c977fc215a3b577596a7483df53e8a1e9c83), ROM_BIOS(1) ) |
| 528 | 959 | ROM_SYSTEM_BIOS( 1, "radosoft", "RadoSoft Disk ROM, 1992") |
| 529 | | ROMX_LOAD( "pravetzd.rom", 0x10000, 0x4000, CRC(f8d23821) SHA1(f87ad3c5832773b6e0614905552a80c98dc8e2a5), ROM_BIOS(2) ) |
| 530 | | ROM_LOAD_OPTIONAL( "8ddoslo.rom", 0x014000, 0x0100, CRC(0c82f636) SHA1(b29d151a0dfa3c7cd50439b51d0a8f95559bc2b6) ) |
| 531 | | ROM_LOAD_OPTIONAL( "8ddoshi.rom", 0x014100, 0x0200, CRC(66309641) SHA1(9c2e82b3c4d385ade6215fcb89f8b92e6fd2bf4b) ) |
| 960 | ROMX_LOAD( "pravetzd.rom", 0, 0x4000, CRC(f8d23821) SHA1(f87ad3c5832773b6e0614905552a80c98dc8e2a5), ROM_BIOS(2) ) |
| 961 | // ROM_LOAD_OPTIONAL( "8ddoslo.rom", 0x014000, 0x0100, CRC(0c82f636) SHA1(b29d151a0dfa3c7cd50439b51d0a8f95559bc2b6) ) |
| 962 | // ROM_LOAD_OPTIONAL( "8ddoshi.rom", 0x014100, 0x0200, CRC(66309641) SHA1(9c2e82b3c4d385ade6215fcb89f8b92e6fd2bf4b) ) |
| 532 | 963 | ROM_END |
| 533 | 964 | |
| 534 | 965 | |
| r29568 | r29569 | |
| 537 | 968 | COMP( 1984, orica, oric1, 0, oric, orica, driver_device, 0, "Tangerine", "Oric Atmos" , 0) |
| 538 | 969 | COMP( 1985, prav8d, oric1, 0, prav8d, prav8d, driver_device, 0, "Pravetz", "Pravetz 8D", 0) |
| 539 | 970 | COMP( 1989, prav8dd, oric1, 0, prav8d, prav8d, driver_device, 0, "Pravetz", "Pravetz 8D (Disk ROM)", GAME_UNOFFICIAL) |
| 540 | | COMP( 1986, telstrat, oric1, 0, telstrat, telstrat, driver_device, 0, "Tangerine", "Oric Telestrat", GAME_NOT_WORKING ) |
| 971 | COMP( 1986, telstrat, oric1, 0, telstrat, telstrat, driver_device, 0, "Tangerine", "Oric Telestrat", 0 ) |