@@ -448,3 +448,70 @@ TEST_CASE("16 bit arithmetic carries") {
448448 }
449449 }
450450}
451+
452+ TEST_CASE (" JSL jumps long" ) {
453+ w65816_t cpu;
454+ w65816_desc_t desc = {};
455+ uint64_t pins = w65816_init (&cpu, &desc);
456+
457+ // skip RESET
458+ pins &= ~(W65816_RW | W65816_RES);
459+ cpu.PINS = pins;
460+
461+ // Test code: JSL $123456
462+ uint8_t memory[] = {
463+ 0x22 ,
464+ 0x56 ,
465+ 0x34 ,
466+ 0x12 ,
467+ };
468+
469+ // Set initial PC to 0x0000, PBR to 0x00
470+ cpu.PC = 0x0000 ;
471+ cpu.PBR = 0x00 ;
472+ cpu.S = 0x01FF ; // Stack pointer
473+ // CPU reads first instruction
474+ pins |= W65816_RW | W65816_VPA | W65816_VDA;
475+
476+ static std::vector<uint8_t > stack;
477+
478+ int cycle = 0 ;
479+
480+ // Run for 8 cycles (JSL takes 8 cycles according to W65C816S datasheet)
481+ while (cycle < 8 ) {
482+ if (pins & W65816_RW) {
483+ // memory read
484+ uint32_t full_addr = W65816_GET_ADDR (pins);
485+ uint8_t bank = (full_addr >> 16 ) & 0xFF ;
486+ uint16_t addr = full_addr & 0xFFFF ;
487+
488+ if (bank == 0 && addr < sizeof (memory)) {
489+ W65816_SET_DATA (pins, memory[addr]);
490+ }
491+ else {
492+ W65816_SET_DATA (pins, 0xEA ); // NOP
493+ }
494+ }
495+ else {
496+ // writes push to the stack
497+ stack.push_back ((pins >> 16 ) & 0xFF );
498+ }
499+
500+ pins = w65816_tick (&cpu, pins);
501+ cycle++;
502+ }
503+
504+ CAPTURE (stack.size ());
505+ CAPTURE (cpu.PBR );
506+ CAPTURE (cpu.PC );
507+ // After JSL $123456, we expect:
508+ // - PBR = 0x12
509+ // - PC = 0x3456
510+ CHECK (cpu.PBR == 0x12 );
511+ CHECK (cpu.PC == 0x3456 );
512+ // and the return address (0x000003) is pushed to the stack
513+ REQUIRE (stack.size () == 3 );
514+ CHECK (stack[0 ] == 0x00 ); // PBR
515+ CHECK (stack[1 ] == 0x00 ); // PCH
516+ CHECK (stack[2 ] == 0x03 ); // PCL
517+ }
0 commit comments