1mod alu; 2mod bits; 3mod disassemble; 4mod flags; 5mod flow; 6mod load; 7 8use crate::Spc700; 9use crate::traits::BusInterface; 10use jgenesis_common::num::{GetBit, SignBit}; 11 12fn fetch_operand<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) -> u8 { 13 let operand = bus.read(cpu.registers.pc); 14 cpu.registers.pc = cpu.registers.pc.wrapping_add(1); 15 16 log::trace!("Fetched operand from PC={:04X}: {operand:02X}", cpu.registers.pc.wrapping_sub(1)); 17 18 operand 19} 20 21macro_rules! invalid_cycle { 22 ($cpu:expr) => { 23 panic!("Invalid cycle for opcode {:02X}: {}", $cpu.state.opcode, $cpu.state.cycle) 24 }; 25} 26 27use invalid_cycle; 28 29macro_rules! impl_read_immediate { 30 ($name:ident, (|$registers:ident, $value:ident| $body:block)) => { 31 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 32 cpu.final_cycle(); 33 34 let $value = fetch_operand(cpu, bus); 35 let $registers = &mut cpu.registers; 36 $body 37 } 38 }; 39} 40 41use impl_read_immediate; 42 43macro_rules! impl_read_register_indirect { 44 ($index:ident, $name:ident, (|$registers:ident, $value:ident| $body:block)) => { 45 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 46 match cpu.state.cycle { 47 1 => { 48 bus.idle(); 49 } 50 2 => { 51 cpu.final_cycle(); 52 53 let address = u16::from_le_bytes([cpu.registers.$index, cpu.direct_page_msb()]); 54 let $value = bus.read(address); 55 let $registers = &mut cpu.registers; 56 $body 57 } 58 _ => invalid_cycle!(cpu), 59 } 60 } 61 }; 62} 63 64use impl_read_register_indirect; 65 66macro_rules! impl_read_register_indirect_postinc { 67 ($index:ident, $name:ident, (|$registers:ident, $value:ident| $body:block)) => { 68 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 69 match cpu.state.cycle { 70 1 => { 71 bus.idle(); 72 } 73 2 => { 74 let address = u16::from_le_bytes([cpu.registers.$index, cpu.direct_page_msb()]); 75 let $value = bus.read(address); 76 let $registers = &mut cpu.registers; 77 $body 78 } 79 3 => { 80 cpu.final_cycle(); 81 82 bus.idle(); 83 cpu.registers.$index = cpu.registers.$index.wrapping_add(1); 84 } 85 _ => invalid_cycle!(cpu), 86 } 87 } 88 }; 89} 90 91use impl_read_register_indirect_postinc; 92 93macro_rules! impl_read_direct_page { 94 ($name:ident, (|$registers:ident, $value:ident| $body:block)) => { 95 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 96 match cpu.state.cycle { 97 1 => { 98 cpu.state.t0 = fetch_operand(cpu, bus); 99 } 100 2 => { 101 cpu.final_cycle(); 102 103 let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]); 104 let $value = bus.read(address); 105 let $registers = &mut cpu.registers; 106 $body 107 } 108 _ => invalid_cycle!(cpu), 109 } 110 } 111 }; 112} 113 114use impl_read_direct_page; 115 116macro_rules! impl_read_direct_page_indexed { 117 ($index:ident, $name:ident, (|$registers:ident, $value:ident| $body:block)) => { 118 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 119 match cpu.state.cycle { 120 1 => { 121 cpu.state.t0 = fetch_operand(cpu, bus); 122 } 123 2 => { 124 bus.idle(); 125 } 126 3 => { 127 cpu.final_cycle(); 128 129 let address_lsb = cpu.state.t0.wrapping_add(cpu.registers.$index); 130 let address = u16::from_le_bytes([address_lsb, cpu.direct_page_msb()]); 131 let $value = bus.read(address); 132 let $registers = &mut cpu.registers; 133 $body 134 } 135 _ => invalid_cycle!(cpu), 136 } 137 } 138 }; 139} 140 141use impl_read_direct_page_indexed; 142 143macro_rules! impl_read_absolute { 144 ($name:ident, (|$registers:ident, $value:ident| $body:block)) => { 145 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 146 match cpu.state.cycle { 147 1 => { 148 cpu.state.t0 = fetch_operand(cpu, bus); 149 } 150 2 => { 151 cpu.state.t1 = fetch_operand(cpu, bus); 152 } 153 3 => { 154 cpu.final_cycle(); 155 156 let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1]); 157 let $value = bus.read(address); 158 let $registers = &mut cpu.registers; 159 $body 160 } 161 _ => invalid_cycle!(cpu), 162 } 163 } 164 }; 165} 166 167use impl_read_absolute; 168 169macro_rules! impl_read_absolute_indexed { 170 ($index:ident, $name:ident, (|$registers:ident, $value:ident| $body:block)) => { 171 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 172 match cpu.state.cycle { 173 1 => { 174 cpu.state.t0 = fetch_operand(cpu, bus); 175 } 176 2 => { 177 cpu.state.t1 = fetch_operand(cpu, bus); 178 } 179 3 => { 180 bus.idle(); 181 } 182 4 => { 183 cpu.final_cycle(); 184 185 let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1]) 186 .wrapping_add(cpu.registers.$index.into()); 187 let $value = bus.read(address); 188 let $registers = &mut cpu.registers; 189 $body 190 } 191 _ => invalid_cycle!(cpu), 192 } 193 } 194 }; 195} 196 197use impl_read_absolute_indexed; 198 199macro_rules! impl_read_indexed_indirect { 200 ($name:ident, (|$registers:ident, $value:ident| $body:block)) => { 201 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 202 match cpu.state.cycle { 203 1 => { 204 cpu.state.t0 = fetch_operand(cpu, bus); 205 } 206 2 => { 207 bus.idle(); 208 } 209 3 => { 210 let address_lsb = cpu.state.t0.wrapping_add(cpu.registers.x); 211 let address = u16::from_le_bytes([address_lsb, cpu.direct_page_msb()]); 212 cpu.state.t1 = bus.read(address); 213 } 214 4 => { 215 let address_lsb = cpu.state.t0.wrapping_add(cpu.registers.x).wrapping_add(1); 216 let address = u16::from_le_bytes([address_lsb, cpu.direct_page_msb()]); 217 cpu.state.t2 = bus.read(address); 218 } 219 5 => { 220 cpu.final_cycle(); 221 222 let address = u16::from_le_bytes([cpu.state.t1, cpu.state.t2]); 223 let $value = bus.read(address); 224 let $registers = &mut cpu.registers; 225 $body 226 } 227 _ => invalid_cycle!(cpu), 228 } 229 } 230 }; 231} 232 233use impl_read_indexed_indirect; 234 235macro_rules! impl_read_indirect_indexed { 236 ($name:ident, (|$registers:ident, $value:ident| $body:block)) => { 237 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 238 match cpu.state.cycle { 239 1 => { 240 cpu.state.t0 = fetch_operand(cpu, bus); 241 } 242 2 => { 243 bus.idle(); 244 } 245 3 => { 246 let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]); 247 cpu.state.t1 = bus.read(address); 248 } 249 4 => { 250 let address_lsb = cpu.state.t0.wrapping_add(1); 251 let address = u16::from_le_bytes([address_lsb, cpu.direct_page_msb()]); 252 cpu.state.t2 = bus.read(address); 253 } 254 5 => { 255 cpu.final_cycle(); 256 257 let address = u16::from_le_bytes([cpu.state.t1, cpu.state.t2]) 258 .wrapping_add(cpu.registers.y.into()); 259 let $value = bus.read(address); 260 let $registers = &mut cpu.registers; 261 $body 262 } 263 _ => invalid_cycle!(cpu), 264 } 265 } 266 }; 267} 268 269use impl_read_indirect_indexed; 270 271macro_rules! impl_read_op { 272 (@inner immediate, $($rest:tt)*) => { 273 impl_read_immediate!($($rest)*); 274 }; 275 (@inner x_indirect, $($rest:tt)*) => { 276 impl_read_register_indirect!(x, $($rest)*); 277 }; 278 (@inner x_indirect_postinc, $($rest:tt)*) => { 279 impl_read_register_indirect_postinc!(x, $($rest)*); 280 }; 281 (@inner direct_page, $($rest:tt)*) => { 282 impl_read_direct_page!($($rest)*); 283 }; 284 (@inner direct_page_x, $($rest:tt)*) => { 285 impl_read_direct_page_indexed!(x, $($rest)*); 286 }; 287 (@inner direct_page_y, $($rest:tt)*) => { 288 impl_read_direct_page_indexed!(y, $($rest)*); 289 }; 290 (@inner absolute, $($rest:tt)*) => { 291 impl_read_absolute!($($rest)*); 292 }; 293 (@inner absolute_x, $($rest:tt)*) => { 294 impl_read_absolute_indexed!(x, $($rest)*); 295 }; 296 (@inner absolute_y, $($rest:tt)*) => { 297 impl_read_absolute_indexed!(y, $($rest)*); 298 }; 299 (@inner indirect_x, $($rest:tt)*) => { 300 impl_read_indexed_indirect!($($rest)*); 301 }; 302 (@inner indirect_y, $($rest:tt)*) => { 303 impl_read_indirect_indexed!($($rest)*); 304 }; 305 ([$($am:tt -> $name:ident),* $(,)?] $rest:tt) => { 306 $( 307 impl_read_op!(@inner $am, $name, $rest); 308 )* 309 } 310} 311 312use impl_read_op; 313 314macro_rules! impl_x_y { 315 ($write:expr, $name:ident, (|$registers:ident, $operand_l:ident, $operand_r:ident| $body:block)) => { 316 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 317 match cpu.state.cycle { 318 1 => { 319 bus.idle(); 320 } 321 2 => { 322 let address = u16::from_le_bytes([cpu.registers.y, cpu.direct_page_msb()]); 323 cpu.state.t0 = bus.read(address); 324 } 325 3 => { 326 let address = u16::from_le_bytes([cpu.registers.x, cpu.direct_page_msb()]); 327 cpu.state.t1 = bus.read(address); 328 } 329 4 => { 330 cpu.final_cycle(); 331 332 let $operand_l = cpu.state.t1; 333 let $operand_r = cpu.state.t0; 334 let $registers = &mut cpu.registers; 335 let value = $body; 336 337 if $write { 338 let address = u16::from_le_bytes([cpu.registers.x, cpu.direct_page_msb()]); 339 bus.write(address, value); 340 } else { 341 bus.idle(); 342 } 343 } 344 _ => invalid_cycle!(cpu), 345 } 346 } 347 }; 348} 349 350use impl_x_y; 351 352macro_rules! impl_dp_dp { 353 ($write:expr, $name:ident, (|$registers:ident, $operand_l:ident, $operand_r:ident| $body:block)) => { 354 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 355 match cpu.state.cycle { 356 1 => { 357 cpu.state.t0 = fetch_operand(cpu, bus); 358 } 359 2 => { 360 let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]); 361 cpu.state.t1 = bus.read(address); 362 } 363 3 => { 364 cpu.state.t2 = fetch_operand(cpu, bus); 365 } 366 4 => { 367 let address = u16::from_le_bytes([cpu.state.t2, cpu.direct_page_msb()]); 368 cpu.state.t3 = bus.read(address); 369 } 370 5 => { 371 cpu.final_cycle(); 372 373 let $operand_l = cpu.state.t3; 374 let $operand_r = cpu.state.t1; 375 let $registers = &mut cpu.registers; 376 let value = $body; 377 378 if $write { 379 let address = u16::from_le_bytes([cpu.state.t2, cpu.direct_page_msb()]); 380 bus.write(address, value); 381 } else { 382 bus.idle(); 383 } 384 } 385 _ => invalid_cycle!(cpu), 386 } 387 } 388 }; 389} 390 391use impl_dp_dp; 392 393macro_rules! impl_dp_imm { 394 ($write:expr, $name:ident, (|$registers:ident, $operand_l:ident, $operand_r:ident| $body:block)) => { 395 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 396 match cpu.state.cycle { 397 1 => { 398 cpu.state.t0 = fetch_operand(cpu, bus); 399 } 400 2 => { 401 cpu.state.t1 = fetch_operand(cpu, bus); 402 } 403 3 => { 404 let address = u16::from_le_bytes([cpu.state.t1, cpu.direct_page_msb()]); 405 cpu.state.t2 = bus.read(address); 406 } 407 4 => { 408 cpu.final_cycle(); 409 410 let $operand_l = cpu.state.t2; 411 let $operand_r = cpu.state.t0; 412 let $registers = &mut cpu.registers; 413 let value = $body; 414 415 if $write { 416 let address = u16::from_le_bytes([cpu.state.t1, cpu.direct_page_msb()]); 417 bus.write(address, value); 418 } else { 419 bus.idle(); 420 } 421 } 422 _ => invalid_cycle!(cpu), 423 } 424 } 425 }; 426} 427 428use impl_dp_imm; 429 430macro_rules! impl_memory_to_memory_op { 431 (@inner x_y, $($rest:tt)*) => { 432 impl_x_y!(true, $($rest)*); 433 }; 434 (@inner x_y_no_write, $($rest:tt)*) => { 435 impl_x_y!(false, $($rest)*); 436 }; 437 (@inner dp_dp, $($rest:tt)*) => { 438 impl_dp_dp!(true, $($rest)*); 439 }; 440 (@inner dp_dp_no_write, $($rest:tt)*) => { 441 impl_dp_dp!(false, $($rest)*); 442 }; 443 (@inner dp_imm, $($rest:tt)*) => { 444 impl_dp_imm!(true, $($rest)*); 445 }; 446 (@inner dp_imm_no_write, $($rest:tt)*) => { 447 impl_dp_imm!(false, $($rest)*); 448 }; 449 ([$($am:tt -> $name:ident),* $(,)?] $rest:tt) => { 450 $( 451 impl_memory_to_memory_op!(@inner $am, $name, $rest); 452 )* 453 } 454} 455 456use impl_memory_to_memory_op; 457 458macro_rules! impl_modify_accumulator { 459 ($name:ident, (|$registers:ident, $value:ident| $body:block)) => { 460 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 461 cpu.final_cycle(); 462 bus.idle(); 463 464 let $value = cpu.registers.a; 465 let $registers = &mut cpu.registers; 466 cpu.registers.a = $body; 467 } 468 }; 469} 470 471use impl_modify_accumulator; 472 473macro_rules! impl_modify_direct_page { 474 ($name:ident, (|$registers:ident, $value:ident| $body:block)) => { 475 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 476 match cpu.state.cycle { 477 1 => { 478 cpu.state.t0 = fetch_operand(cpu, bus); 479 } 480 2 => { 481 let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]); 482 cpu.state.t1 = bus.read(address); 483 } 484 3 => { 485 cpu.final_cycle(); 486 487 let $value = cpu.state.t1; 488 let $registers = &mut cpu.registers; 489 let value = $body; 490 491 let address = u16::from_le_bytes([cpu.state.t0, cpu.direct_page_msb()]); 492 bus.write(address, value); 493 } 494 _ => invalid_cycle!(cpu), 495 } 496 } 497 }; 498} 499 500use impl_modify_direct_page; 501 502macro_rules! impl_modify_direct_page_indexed { 503 ($index:ident, $name:ident, (|$registers:ident, $value:ident| $body:block)) => { 504 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 505 match cpu.state.cycle { 506 1 => { 507 cpu.state.t0 = fetch_operand(cpu, bus); 508 } 509 2 => { 510 bus.idle(); 511 } 512 3 => { 513 let address_lsb = cpu.state.t0.wrapping_add(cpu.registers.$index); 514 let address = u16::from_le_bytes([address_lsb, cpu.direct_page_msb()]); 515 cpu.state.t1 = bus.read(address); 516 } 517 4 => { 518 cpu.final_cycle(); 519 520 let $value = cpu.state.t1; 521 let $registers = &mut cpu.registers; 522 let value = $body; 523 524 let address_lsb = cpu.state.t0.wrapping_add(cpu.registers.$index); 525 let address = u16::from_le_bytes([address_lsb, cpu.direct_page_msb()]); 526 bus.write(address, value); 527 } 528 _ => invalid_cycle!(cpu), 529 } 530 } 531 }; 532} 533 534use impl_modify_direct_page_indexed; 535 536macro_rules! impl_modify_absolute { 537 ($name:ident, (|$registers:ident, $value:ident| $body:block)) => { 538 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 539 match cpu.state.cycle { 540 1 => { 541 cpu.state.t0 = fetch_operand(cpu, bus); 542 } 543 2 => { 544 cpu.state.t1 = fetch_operand(cpu, bus); 545 } 546 3 => { 547 let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1]); 548 cpu.state.t2 = bus.read(address); 549 } 550 4 => { 551 cpu.final_cycle(); 552 553 let $value = cpu.state.t2; 554 let $registers = &mut cpu.registers; 555 let value = $body; 556 557 let address = u16::from_le_bytes([cpu.state.t0, cpu.state.t1]); 558 bus.write(address, value); 559 } 560 _ => invalid_cycle!(cpu), 561 } 562 } 563 }; 564} 565 566use impl_modify_absolute; 567 568macro_rules! impl_modify_op { 569 (@inner accumulator, $($rest:tt)*) => { 570 impl_modify_accumulator!($($rest)*); 571 }; 572 (@inner direct_page, $($rest:tt)*) => { 573 impl_modify_direct_page!($($rest)*); 574 }; 575 (@inner direct_page_x, $($rest:tt)*) => { 576 impl_modify_direct_page_indexed!(x, $($rest)*); 577 }; 578 (@inner absolute, $($rest:tt)*) => { 579 impl_modify_absolute!($($rest)*); 580 }; 581 ([$($am:tt -> $name:ident),* $(,)?] $rest:tt) => { 582 $( 583 impl_modify_op!(@inner $am, $name, $rest); 584 )* 585 } 586} 587 588use impl_modify_op; 589 590macro_rules! impl_registers_op { 591 ($name:ident, |$registers:ident| $body:block) => { 592 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 593 cpu.final_cycle(); 594 bus.idle(); 595 596 let $registers = &mut cpu.registers; 597 $body 598 } 599 }; 600} 601 602use impl_registers_op; 603 604macro_rules! impl_long_registers_op { 605 ($name:ident, |$registers:ident| $body:block) => { 606 pub(crate) fn $name<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 607 match cpu.state.cycle { 608 1 => { 609 bus.idle(); 610 } 611 2 => { 612 cpu.final_cycle(); 613 bus.idle(); 614 615 let $registers = &mut cpu.registers; 616 $body 617 } 618 _ => invalid_cycle!(cpu), 619 } 620 } 621 }; 622} 623 624use impl_long_registers_op; 625 626impl_registers_op!(nop, |_registers| {}); 627 628pub fn execute<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 629 if cpu.state.stopped { 630 bus.idle(); 631 return; 632 } 633 634 if cpu.state.cycle != 0 { 635 execute_cycle(cpu, bus); 636 637 if cpu.state.cycle != 0 { 638 cpu.state.cycle += 1; 639 } 640 641 return; 642 } 643 644 // Cycle 0: Fetch operand 645 cpu.state.opcode = fetch_operand(cpu, bus); 646 cpu.state.cycle = 1; 647 648 if log::log_enabled!(log::Level::Trace) { 649 let instr_str = disassemble::instruction_str(cpu.state.opcode); 650 log::trace!( 651 "Fetched opcode from PC={:04X}: {:02X} ({instr_str})", 652 cpu.registers.pc.wrapping_sub(1), 653 cpu.state.opcode 654 ); 655 } 656} 657 658macro_rules! opcode_table { 659 ( 660 $cpu:expr, 661 $bus:expr, 662 { $($opcode:literal => $($module:ident)?::$op_fn:ident $(($arg:expr))?),* $(,)? } 663 ) => { 664 match $cpu.state.opcode { 665 $( 666 $opcode => $($module::)?$op_fn($cpu, $bus $(, $arg)?), 667 )* 668 } 669 } 670} 671 672fn execute_cycle<B: BusInterface>(cpu: &mut Spc700, bus: &mut B) { 673 opcode_table!(cpu, bus, { 674 0x00 => ::nop, 675 0x01 => flow::tcall(0), 676 0x02 => bits::set1(0), 677 0x03 => flow::bbs(0), 678 0x04 => alu::or_dp, 679 0x05 => alu::or_abs, 680 0x06 => alu::or_xind, 681 0x07 => alu::or_indx, 682 0x08 => alu::or_imm, 683 0x09 => alu::or_dp_dp, 684 0x0A => bits::or1, 685 0x0B => bits::asl_dp, 686 0x0C => bits::asl_abs, 687 0x0D => load::push_psw, 688 0x0E => bits::tset1, 689 0x0F => flow::brk, 690 0x10 => flow::bpl, 691 0x11 => flow::tcall(1), 692 0x12 => bits::clr1(0), 693 0x13 => flow::bbc(0), 694 0x14 => alu::or_dpx, 695 0x15 => alu::or_absx, 696 0x16 => alu::or_absy, 697 0x17 => alu::or_indy, 698 0x18 => alu::or_dp_imm, 699 0x19 => alu::or_x_y_ind, 700 0x1A => alu::decw, 701 0x1B => bits::asl_dpx, 702 0x1C => bits::asl_a, 703 0x1D => alu::dec_x, 704 0x1E => alu::cmp_x_abs, 705 0x1F => flow::jmp_absx_ind, 706 0x20 => flags::clrp, 707 0x21 => flow::tcall(2), 708 0x22 => bits::set1(1), 709 0x23 => flow::bbs(1), 710 0x24 => alu::and_dp, 711 0x25 => alu::and_abs, 712 0x26 => alu::and_xind, 713 0x27 => alu::and_indx, 714 0x28 => alu::and_imm, 715 0x29 => alu::and_dp_dp, 716 0x2A => bits::or1_cpl, 717 0x2B => bits::rol_dp, 718 0x2C => bits::rol_abs, 719 0x2D => load::push_a, 720 0x2E => flow::cbne_dp, 721 0x2F => flow::bra, 722 0x30 => flow::bmi, 723 0x31 => flow::tcall(3), 724 0x32 => bits::clr1(1), 725 0x33 => flow::bbc(1), 726 0x34 => alu::and_dpx, 727 0x35 => alu::and_absx, 728 0x36 => alu::and_absy, 729 0x37 => alu::and_indy, 730 0x38 => alu::and_dp_imm, 731 0x39 => alu::and_x_y_ind, 732 0x3A => alu::incw, 733 0x3B => bits::rol_dpx, 734 0x3C => bits::rol_a, 735 0x3D => alu::inc_x, 736 0x3E => alu::cmp_x_dp, 737 0x3F => flow::call, 738 0x40 => flags::setp, 739 0x41 => flow::tcall(4), 740 0x42 => bits::set1(2), 741 0x43 => flow::bbs(2), 742 0x44 => alu::eor_dp, 743 0x45 => alu::eor_abs, 744 0x46 => alu::eor_xind, 745 0x47 => alu::eor_indx, 746 0x48 => alu::eor_imm, 747 0x49 => alu::eor_dp_dp, 748 0x4A => bits::and1, 749 0x4B => bits::lsr_dp, 750 0x4C => bits::lsr_abs, 751 0x4D => load::push_x, 752 0x4E => bits::tclr1, 753 0x4F => flow::pcall, 754 0x50 => flow::bvc, 755 0x51 => flow::tcall(5), 756 0x52 => bits::clr1(2), 757 0x53 => flow::bbc(2), 758 0x54 => alu::eor_dpx, 759 0x55 => alu::eor_absx, 760 0x56 => alu::eor_absy, 761 0x57 => alu::eor_indy, 762 0x58 => alu::eor_dp_imm, 763 0x59 => alu::eor_x_y_ind, 764 0x5A => alu::cmpw, 765 0x5B => bits::lsr_dpx, 766 0x5C => bits::lsr_a, 767 0x5D => load::mov_x_a, 768 0x5E => alu::cmp_y_abs, 769 0x5F => flow::jmp_abs, 770 0x60 => flags::clrc, 771 0x61 => flow::tcall(6), 772 0x62 => bits::set1(3), 773 0x63 => flow::bbs(3), 774 0x64 => alu::cmp_a_dp, 775 0x65 => alu::cmp_a_abs, 776 0x66 => alu::cmp_a_xind, 777 0x67 => alu::cmp_a_indx, 778 0x68 => alu::cmp_a_imm, 779 0x69 => alu::cmp_dp_dp, 780 0x6A => bits::and1_cpl, 781 0x6B => bits::ror_dp, 782 0x6C => bits::ror_abs, 783 0x6D => load::push_y, 784 0x6E => flow::dbnz_dp, 785 0x6F => flow::ret, 786 0x70 => flow::bvs, 787 0x71 => flow::tcall(7), 788 0x72 => bits::clr1(3), 789 0x73 => flow::bbc(3), 790 0x74 => alu::cmp_a_dpx, 791 0x75 => alu::cmp_a_absx, 792 0x76 => alu::cmp_a_absy, 793 0x77 => alu::cmp_a_indy, 794 0x78 => alu::cmp_dp_imm, 795 0x79 => alu::cmp_x_y_ind, 796 0x7A => alu::addw, 797 0x7B => bits::ror_dpx, 798 0x7C => bits::ror_a, 799 0x7D => load::mov_a_x, 800 0x7E => alu::cmp_y_dp, 801 0x7F => flow::reti, 802 0x80 => flags::setc, 803 0x81 => flow::tcall(8), 804 0x82 => bits::set1(4), 805 0x83 => flow::bbs(4), 806 0x84 => alu::adc_dp, 807 0x85 => alu::adc_abs, 808 0x86 => alu::adc_xind, 809 0x87 => alu::adc_indx, 810 0x88 => alu::adc_imm, 811 0x89 => alu::adc_dp_dp, 812 0x8A => bits::eor1, 813 0x8B => alu::dec_dp, 814 0x8C => alu::dec_abs, 815 0x8D => load::mov_y_imm, 816 0x8E => load::pop_psw, 817 0x8F => load::mov_dp_imm, 818 0x90 => flow::bcc, 819 0x91 => flow::tcall(9), 820 0x92 => bits::clr1(4), 821 0x93 => flow::bbc(4), 822 0x94 => alu::adc_dpx, 823 0x95 => alu::adc_absx, 824 0x96 => alu::adc_absy, 825 0x97 => alu::adc_indy, 826 0x98 => alu::adc_dp_imm, 827 0x99 => alu::adc_x_y_ind, 828 0x9A => alu::subw, 829 0x9B => alu::dec_dpx, 830 0x9C => alu::dec_a, 831 0x9D => load::mov_x_sp, 832 0x9E => alu::div, 833 0x9F => bits::xcn, 834 0xA0 => flags::ei, 835 0xA1 => flow::tcall(10), 836 0xA2 => bits::set1(5), 837 0xA3 => flow::bbs(5), 838 0xA4 => alu::sbc_dp, 839 0xA5 => alu::sbc_abs, 840 0xA6 => alu::sbc_xind, 841 0xA7 => alu::sbc_indx, 842 0xA8 => alu::sbc_imm, 843 0xA9 => alu::sbc_dp_dp, 844 0xAA => bits::mov1_c_bit, 845 0xAB => alu::inc_dp, 846 0xAC => alu::inc_abs, 847 0xAD => alu::cmp_y_imm, 848 0xAE => load::pop_a, 849 0xAF => load::mov_xind_postinc_a, 850 0xB0 => flow::bcs, 851 0xB1 => flow::tcall(11), 852 0xB2 => bits::clr1(5), 853 0xB3 => flow::bbc(5), 854 0xB4 => alu::sbc_dpx, 855 0xB5 => alu::sbc_absx, 856 0xB6 => alu::sbc_absy, 857 0xB7 => alu::sbc_indy, 858 0xB8 => alu::sbc_dp_imm, 859 0xB9 => alu::sbc_x_y_ind, 860 0xBA => load::movw_ya_dp, 861 0xBB => alu::inc_dpx, 862 0xBC => alu::inc_a, 863 0xBD => load::mov_sp_x, 864 0xBE => alu::das, 865 0xBF => load::mov_a_xind_postinc, 866 0xC0 => flags::di, 867 0xC1 => flow::tcall(12), 868 0xC2 => bits::set1(6), 869 0xC3 => flow::bbs(6), 870 0xC4 => load::mov_dp_a, 871 0xC5 => load::mov_abs_a, 872 0xC6 => load::mov_xind_a, 873 0xC7 => load::mov_indx_a, 874 0xC8 => alu::cmp_x_imm, 875 0xC9 => load::mov_abs_x, 876 0xCA => bits::mov1_bit_c, 877 0xCB => load::mov_dp_y, 878 0xCC => load::mov_abs_y, 879 0xCD => load::mov_x_imm, 880 0xCE => load::pop_x, 881 0xCF => alu::mul, 882 0xD0 => flow::bne, 883 0xD1 => flow::tcall(13), 884 0xD2 => bits::clr1(6), 885 0xD3 => flow::bbc(6), 886 0xD4 => load::mov_dpx_a, 887 0xD5 => load::mov_absx_a, 888 0xD6 => load::mov_absy_a, 889 0xD7 => load::mov_indy_a, 890 0xD8 => load::mov_dp_x, 891 0xD9 => load::mov_dpy_x, 892 0xDA => load::movw_dp_ya, 893 0xDB => load::mov_dpx_y, 894 0xDC => alu::dec_y, 895 0xDD => load::mov_a_y, 896 0xDE => flow::cbne_dpx, 897 0xDF => alu::daa, 898 0xE0 => flags::clrv, 899 0xE1 => flow::tcall(14), 900 0xE2 => bits::set1(7), 901 0xE3 => flow::bbs(7), 902 0xE4 => load::mov_a_dp, 903 0xE5 => load::mov_a_abs, 904 0xE6 => load::mov_a_xind, 905 0xE7 => load::mov_a_indx, 906 0xE8 => load::mov_a_imm, 907 0xE9 => load::mov_x_abs, 908 0xEA => bits::not1, 909 0xEB => load::mov_y_dp, 910 0xEC => load::mov_y_abs, 911 0xED => flags::notc, 912 0xEE => load::pop_y, 913 0xEF => flow::stop, 914 0xF0 => flow::beq, 915 0xF1 => flow::tcall(15), 916 0xF2 => bits::clr1(7), 917 0xF3 => flow::bbc(7), 918 0xF4 => load::mov_a_dpx, 919 0xF5 => load::mov_a_absx, 920 0xF6 => load::mov_a_absy, 921 0xF7 => load::mov_a_indy, 922 0xF8 => load::mov_x_dp, 923 0xF9 => load::mov_x_dpy, 924 0xFA => load::mov_dp_dp, 925 0xFB => load::mov_y_dpx, 926 0xFC => alu::inc_y, 927 0xFD => load::mov_y_a, 928 0xFE => flow::dbnz_y, 929 0xFF => flow::stop, 930 }); 931}