1// license:BSD-3-Clause 2// copyright-holders:Nathan Woods 3NMI: 4 m_nmi_asserted = false; 5 m_cc |= CC_E; 6 set_regop16(m_s); 7 m_temp.w = entire_state_registers(); 8 %PUSH_REGISTERS; 9 m_cc |= CC_I | CC_F; 10 set_ea(VECTOR_NMI); 11 eat(1); 12 standard_irq_callback(INPUT_LINE_NMI); 13 goto INTERRUPT_VECTOR; 14 15FIRQ: 16 if (firq_saves_entire_state()) 17 { 18 m_cc |= CC_E; 19 m_temp.w = entire_state_registers(); 20 } 21 else 22 { 23 m_cc &= ~CC_E; 24 m_temp.w = partial_state_registers(); 25 } 26 set_regop16(m_s); 27 %PUSH_REGISTERS; 28 m_cc |= CC_I | CC_F; 29 set_ea(VECTOR_FIRQ); 30 eat(1); 31 standard_irq_callback(M6809_FIRQ_LINE); 32 goto INTERRUPT_VECTOR; 33 34IRQ: 35 m_cc |= CC_E; 36 set_regop16(m_s); 37 m_temp.w = entire_state_registers(); 38 %PUSH_REGISTERS; 39 m_cc |= CC_I; 40 set_ea(VECTOR_IRQ); 41 eat(1); 42 standard_irq_callback(M6809_IRQ_LINE); 43 goto INTERRUPT_VECTOR; 44 45INTERRUPT_VECTOR: 46 @eat(4); 47 @m_pc.b.h = read_operand(0); // Not sure if this is cycle exact 48 @m_pc.b.l = read_operand(1); // Not sure if this is cycle exact 49 return; 50 51NEG8: 52 @m_temp.b.l = read_operand(); 53 m_temp.b.l = set_flags(CC_NZVC, (uint8_t)0, m_temp.b.l, -m_temp.b.l); 54 @eat(hd6309_native_mode() ? 0 : 1); 55 @write_operand(m_temp.b.l); 56 return; 57 58COM8: 59 @m_temp.b.l = read_operand(); 60 m_cc &= ~CC_V; 61 m_cc |= CC_C; 62 m_temp.b.l = set_flags(CC_NZ, (uint8_t) ~m_temp.b.l); 63 @eat(hd6309_native_mode() ? 0 : 1); 64 @write_operand(m_temp.b.l); 65 return; 66 67LSR8: 68 @m_temp.b.l = read_operand(); 69 m_cc &= ~CC_C; 70 m_cc |= (m_temp.b.l & 1) ? CC_C : 0; 71 m_temp.b.l = set_flags<uint8_t>(CC_NZ, m_temp.b.l >> 1); 72 @eat(hd6309_native_mode() ? 0 : 1); 73 @write_operand(m_temp.b.l); 74 return; 75 76ROR8: 77 @m_temp.b.l = read_operand(); 78 m_temp.b.l = set_flags<uint8_t>(CC_NZ, rotate_right(m_temp.b.l)); 79 @eat(hd6309_native_mode() ? 0 : 1); 80 @write_operand(m_temp.b.l); 81 return; 82 83ASR8: 84 @m_temp.b.l = read_operand(); 85 m_cc &= ~CC_C; 86 m_cc |= (m_temp.b.l & 1) ? CC_C : 0; 87 m_temp.b.l = set_flags<uint8_t>(CC_NZ, ((int8_t) m_temp.b.l) >> 1); 88 @eat(hd6309_native_mode() ? 0 : 1); 89 @write_operand(m_temp.b.l); 90 return; 91 92ASL8: 93 @m_temp.b.l = read_operand(); 94 m_temp.b.l = set_flags<uint8_t>(CC_NZVC, m_temp.b.l, m_temp.b.l, m_temp.b.l << 1); 95 @eat(hd6309_native_mode() ? 0 : 1); 96 @write_operand(m_temp.b.l); 97 return; 98 99ROL8: 100 @m_temp.b.l = read_operand(); 101 m_temp.b.l = set_flags<uint8_t>(CC_NZV, m_temp.b.l, m_temp.b.l, rotate_left(m_temp.b.l)); 102 @eat(hd6309_native_mode() ? 0 : 1); 103 @write_operand(m_temp.b.l); 104 return; 105 106DEC8: 107 @m_temp.b.l = read_operand(); 108 m_temp.b.l = set_flags<uint8_t>(CC_NZV, m_temp.b.l, 1, m_temp.b.l - 1); 109 @eat(hd6309_native_mode() && is_register_addressing_mode() ? 0 : 1); 110 @write_operand(m_temp.b.l); 111 return; 112 113INC8: 114 @m_temp.b.l = read_operand(); 115 m_temp.b.l = set_flags<uint8_t>(CC_NZV, m_temp.b.l, 1, m_temp.b.l + 1); 116 @eat(hd6309_native_mode() && is_register_addressing_mode() ? 0 : 1); 117 @write_operand(m_temp.b.l); 118 return; 119 120TST8: 121 @m_temp.b.l = read_operand(); 122 set_flags(CC_NZV, m_temp.b.l); 123 eat(hd6309_native_mode() ? 0 : 1); 124 eat(is_register_addressing_mode() ? 0 : 1); 125 return; 126 127JMP: 128 m_pc.w = m_ea.w; 129 return; 130 131CLR8: 132 @read_operand(); 133 m_cc &= ~CC_NZVC; 134 m_cc |= CC_Z; 135 @eat(hd6309_native_mode() && is_register_addressing_mode() ? 0 : 1); 136 @write_operand(0); 137 return; 138 139NEG16: 140 m_temp.b.h = read_operand(0); 141 m_temp.b.l = read_operand(1); 142 m_temp.w = set_flags(CC_NZVC, (uint16_t)0, m_temp.w, -m_temp.w); 143 eat(hd6309_native_mode() ? 0 : 1); 144 write_operand(0, m_temp.b.h); 145 write_operand(1, m_temp.b.l); 146 return; 147 148LSR16: 149 @m_temp.b.h = read_operand(0); 150 @m_temp.b.l = read_operand(1); 151 m_cc &= ~CC_C; 152 m_cc |= (m_temp.w & 1) ? CC_C : 0; 153 m_temp.w = set_flags<uint16_t>(CC_NZ, m_temp.w >> 1); 154 @eat(hd6309_native_mode() ? 0 : 1); 155 @write_operand(0, m_temp.b.h); 156 write_operand(1, m_temp.b.l); 157 return; 158 159ROR16: 160 @m_temp.b.h = read_operand(0); 161 @m_temp.b.l = read_operand(1); 162 m_temp.w = set_flags<uint16_t>(CC_NZ, rotate_right(m_temp.w)); 163 @eat(hd6309_native_mode() ? 0 : 1); 164 @write_operand(0, m_temp.b.h); 165 write_operand(1, m_temp.b.l); 166 return; 167 168ASR16: 169 @m_temp.b.h = read_operand(0); 170 @m_temp.b.l = read_operand(1); 171 m_cc &= ~CC_C; 172 m_cc |= (m_temp.w & 1) ? CC_C : 0; 173 m_temp.w = set_flags<uint16_t>(CC_NZ, ((int16_t) m_temp.w) >> 1); 174 @eat(hd6309_native_mode() ? 0 : 1); 175 @write_operand(0, m_temp.b.h); 176 write_operand(1, m_temp.b.l); 177 return; 178 179ASL16: 180 @m_temp.b.h = read_operand(0); 181 @m_temp.b.l = read_operand(1); 182 m_temp.w = set_flags<uint16_t>(CC_NZVC, m_temp.w, m_temp.w, m_temp.w << 1); 183 @eat(hd6309_native_mode() ? 0 : 1); 184 @write_operand(0, m_temp.b.h); 185 write_operand(1, m_temp.b.l); 186 return; 187 188ROL16: 189 @m_temp.b.h = read_operand(0); 190 @m_temp.b.l = read_operand(1); 191 m_temp.w = set_flags<uint16_t>(CC_NZV, rotate_left(m_temp.w)); 192 @eat(hd6309_native_mode() ? 0 : 1); 193 @write_operand(0, m_temp.b.h); 194 write_operand(1, m_temp.b.l); 195 return; 196 197DEC16: 198 m_temp.b.h = read_operand(0); 199 m_temp.b.l = read_operand(1); 200 m_temp.w = set_flags<uint16_t>(CC_NZVC, m_temp.w, 1, m_temp.w - 1); 201 eat(hd6309_native_mode() ? 0 : 1); 202 write_operand(0, m_temp.b.h); 203 write_operand(1, m_temp.b.l); 204 return; 205 206INC16: 207 m_temp.b.h = read_operand(0); 208 m_temp.b.l = read_operand(1); 209 m_temp.w = set_flags<uint16_t>(CC_NZVC, m_temp.w, 1, m_temp.w + 1); 210 eat(hd6309_native_mode() ? 0 : 1); 211 write_operand(0, m_temp.b.h); 212 write_operand(1, m_temp.b.l); 213 return; 214 215TST16: 216 m_temp.b.h = read_operand(0); 217 m_temp.b.l = read_operand(1); 218 set_flags(CC_NZV, m_temp.w); 219 eat(hd6309_native_mode() ? 0 : 1); 220 eat(is_register_addressing_mode() ? 0 : 1); 221 return; 222 223CLR16: 224 eat(hd6309_native_mode() ? 0 : 1); 225 m_cc &= ~CC_NZVC; 226 m_cc |= CC_Z; 227 write_operand(0, 0x00); 228 write_operand(1, 0x00); 229 return; 230 231SUB8: 232 m_temp.b.l = read_operand(); 233 regop8() = set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l); 234 return; 235 236CMP8: 237 m_temp.b.l = read_operand(); 238 set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l); 239 return; 240 241SBC8: 242 m_temp.b.l = read_operand(); 243 regop8() = set_flags(CC_NZVC, regop8(), m_temp.b.l, regop8() - m_temp.b.l - (m_cc & CC_C ? 1 : 0)); 244 return; 245 246AND8: 247 m_cc &= ~CC_V; 248 regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() & read_operand()); 249 return; 250 251BIT8: 252 m_cc &= ~CC_V; 253 set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() & read_operand()); 254 return; 255 256EOR8: 257 m_cc &= ~CC_V; 258 regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() ^ read_operand()); 259 return; 260 261ADC8: 262 m_temp.b.l = read_operand(); 263 regop8() = set_flags(add8_sets_h() ? CC_HNZVC : CC_NZVC, regop8(), m_temp.b.l, regop8() + m_temp.b.l + (m_cc & CC_C ? 1 : 0)); 264 return; 265 266OR8: 267 m_cc &= ~CC_V; 268 regop8() = set_flags(CC_NZ, (uint8_t)0, regop8(), regop8() | read_operand()); 269 return; 270 271ADD8: 272 m_temp.b.l = read_operand(); 273 regop8() = set_flags(add8_sets_h() ? CC_HNZVC : CC_NZVC, regop8(), m_temp.b.l, regop8() + m_temp.b.l); 274 return; 275 276ADD16: 277 @m_temp.b.h = read_operand(0); 278 @m_temp.b.l = read_operand(1); 279 regop16().w = set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w + m_temp.w); 280 eat(hd6309_native_mode() ? 0 : 1); 281 return; 282 283SUB16: 284 @m_temp.b.h = read_operand(0); 285 @m_temp.b.l = read_operand(1); 286 regop16().w = set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w - m_temp.w); 287 eat(hd6309_native_mode() ? 0 : 1); 288 return; 289 290CMP16: 291 @m_temp.b.h = read_operand(0); 292 @m_temp.b.l = read_operand(1); 293 set_flags(CC_NZVC, regop16().w, m_temp.w, regop16().w - m_temp.w); 294 eat(hd6309_native_mode() ? 0 : 1); 295 return; 296 297LD8: 298 regop8() = read_operand(); 299 set_flags(CC_NZV, regop8()); 300 return; 301 302LD16: 303 @regop16().b.h = read_operand(0); 304 @regop16().b.l = read_operand(1); 305 set_flags(CC_NZV, regop16().w); 306 if (®op16() == &m_s) 307 m_lds_encountered = true; 308 return; 309 310ST8: 311 write_ea(set_flags(CC_NZV, regop8())); 312 return; 313 314ST16: 315 @write_operand(0, regop16().b.h); 316 @write_operand(1, regop16().b.l); 317 set_flags(CC_NZV, regop16().w); 318 return; 319 320NOP: 321 eat(hd6309_native_mode() ? 0 : 1); 322 return; 323 324SYNC: 325 // SYNC stops processing instructions until an interrupt request happens. 326 // This doesn't require the corresponding interrupt to be enabled: if it 327 // is disabled, execution continues with the next instruction. 328 eat(3); 329 330 while(!m_nmi_asserted && !m_firq_line && !m_irq_line) 331 { 332 // massaging the PC this way makes the debugger's behavior more 333 // intuitive 334 m_pc.w--; 335 336 @eat_remaining(); 337 338 // unmassage... 339 m_pc.w++; 340 } 341 return; 342 343DAA: 344 daa(); 345 eat(hd6309_native_mode() ? 0 : 1); 346 return; 347 348ORCC: 349 m_cc |= read_operand(); 350 eat(hd6309_native_mode() ? 0 : 1); 351 return; 352 353ANDCC: 354 m_cc &= read_operand(); 355 eat(1); 356 return; 357 358SEX: 359 m_q.r.d = set_flags<uint16_t>(CC_NZ, (int8_t) m_q.r.b); 360 eat(hd6309_native_mode() ? 0 : 1); 361 return; 362 363BRANCH: 364 @m_temp.b.l = read_opcode_arg(); 365 eat(1); 366 if (branch_taken()) 367 { 368 m_pc.w += (int8_t) m_temp.b.l; 369 } 370 return; 371 372LBRANCH: 373 @m_temp.b.h = read_opcode_arg(); 374 @m_temp.b.l = read_opcode_arg(); 375 eat(1); 376 if (branch_taken()) 377 { 378 m_pc.w += m_temp.w; 379 eat(hd6309_native_mode() ? 0 : 1); 380 } 381 return; 382 383BSR: 384 @m_temp.b.l = read_opcode_arg(); 385 m_ea.w = m_pc.w + (int8_t) m_temp.b.l; 386 @eat(hd6309_native_mode() ? 2 : 3); 387 goto GOTO_SUBROUTINE; 388 389LBSR: 390 @m_temp.b.h = read_opcode_arg(); 391 @m_temp.b.l = read_opcode_arg(); 392 m_ea.w = m_pc.w + (int16_t) m_temp.w; 393 @eat(hd6309_native_mode() ? 2 : 4); 394 goto GOTO_SUBROUTINE; 395 396JSR: 397 @eat(2); 398 goto GOTO_SUBROUTINE; 399 400GOTO_SUBROUTINE: 401 @write_memory(--m_s.w, m_pc.b.l); 402 @write_memory(--m_s.w, m_pc.b.h); 403 m_pc.w = m_ea.w; 404 return; 405 406RTS: 407 m_temp.w = 0x80; // RTS is equivalent to "PULS PC" 408 eat(hd6309_native_mode() ? 0 : 1); 409 set_regop16(m_s); 410 goto PULL_REGISTERS; 411 412ABX: 413 m_x.w += m_q.r.b; 414 eat(hd6309_native_mode() ? 0 : 2); 415 return; 416 417MUL: 418 mul(); 419 eat(hd6309_native_mode() ? 9 : 10); 420 return; 421 422RTI: 423 set_regop16(m_s); 424 m_temp.w = 0x01; // PULS CC 425 %PULL_REGISTERS; 426 m_temp.w = ((m_cc & CC_E) ? entire_state_registers() : partial_state_registers()) & ~0x01; 427 goto PULL_REGISTERS; 428 429CWAI: 430 @m_cc &= read_opcode_arg(); 431 @eat(2); 432 433 m_cc |= CC_E; 434 set_regop16(m_s); 435 m_temp.w = entire_state_registers(); 436 %PUSH_REGISTERS; 437 438 while((m_ea.w = get_pending_interrupt()) == 0) 439 { 440 // massaging the PC this way makes the debugger's behavior more 441 // intuitive 442 m_pc.w -= 2; 443 444 @eat_remaining(); 445 446 // unmassage... 447 m_pc.w += 2; 448 } 449 450 if (m_nmi_asserted) 451 m_nmi_asserted = false; 452 453 set_ea(m_ea.w); // need to do this to set the addressing mode 454 m_cc |= CC_I | (m_ea.w != VECTOR_IRQ ? CC_F : 0); 455 456 // invoke standard interrupt callback for MAME core 457 switch (m_ea.w) 458 { 459 case VECTOR_NMI: standard_irq_callback(INPUT_LINE_NMI); break; 460 case VECTOR_FIRQ: standard_irq_callback(M6809_FIRQ_LINE); break; 461 case VECTOR_IRQ: standard_irq_callback(M6809_IRQ_LINE); break; 462 default: break; 463 } 464 465 goto INTERRUPT_VECTOR; 466 467LEA_xy: 468 regop16().w = set_flags(CC_Z, m_ea.w); 469 eat(1); 470 return; 471 472LEA_us: 473 if (®op16() == &m_s) 474 m_lds_encountered = true; 475 regop16().w = m_ea.w; 476 eat(1); 477 return; 478 479PSHS: 480 @m_temp.w = read_opcode_arg(); 481 @eat(hd6309_native_mode() ? 2 : 3); 482 set_regop16(m_s); 483 goto PUSH_REGISTERS; 484 485PULS: 486 @m_temp.w = read_opcode_arg(); 487 @eat(hd6309_native_mode() ? 1 : 2); 488 set_regop16(m_s); 489 goto PULL_REGISTERS; 490 491PSHU: 492 @m_temp.w = read_opcode_arg(); 493 @eat(hd6309_native_mode() ? 2 : 3); 494 set_regop16(m_u); 495 goto PUSH_REGISTERS; 496 497PULU: 498 @m_temp.w = read_opcode_arg(); 499 @eat(hd6309_native_mode() ? 1 : 2); 500 set_regop16(m_u); 501 goto PULL_REGISTERS; 502 503SWI: 504 // doesn't use SOFTWARE_INTERRUPT label because SWI will 505 // inhibit IRQ/FIRQ 506 set_ea(VECTOR_SWI); 507 standard_irq_callback(M6809_SWI); 508 m_cc |= CC_E; 509 set_regop16(m_s); 510 m_temp.w = entire_state_registers(); 511 %PUSH_REGISTERS; 512 m_cc |= CC_I | CC_F; 513 goto INTERRUPT_VECTOR; 514 515SWI2: 516 set_ea(VECTOR_SWI2); 517 standard_irq_callback(M6809_SWI); 518 goto SOFTWARE_INTERRUPT; 519 520SWI3: 521 set_ea(VECTOR_SWI3); 522 standard_irq_callback(M6809_SWI); 523 goto SOFTWARE_INTERRUPT; 524 525SOFTWARE_INTERRUPT: 526 // used for SWI2/SWI3 and illegal/div0 on 6309 527 m_cc |= CC_E; 528 set_regop16(m_s); 529 m_temp.w = entire_state_registers(); 530 %PUSH_REGISTERS; 531 goto INTERRUPT_VECTOR; 532 533DIRECT: 534 @set_ea(((uint16_t)m_dp << 8) | read_opcode_arg()); 535 @eat(hd6309_native_mode() ? 0 : 1); 536 return; 537 538EXTENDED: 539 @set_ea_h(read_opcode_arg()); 540 @set_ea_l(read_opcode_arg()); 541 @eat(hd6309_native_mode() ? 0 : 1); 542 return; 543