Skip to content

Commit d74ff14

Browse files
committed
[fix] JSL instruction
Fixes #17
1 parent e6b52e0 commit d74ff14

File tree

3 files changed

+77
-10
lines changed

3 files changed

+77
-10
lines changed

src/chips/w65c816s.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,13 +1240,13 @@ uint64_t w65816_tick(w65816_t* c, uint64_t pins) {
12401240
/* JSL a */
12411241
case (0x22<<4)|0: _VPA();_SA(c->PC++);break;
12421242
case (0x22<<4)|1: _VPA();_SA(c->PC++);c->AD=_GD();break;
1243-
case (0x22<<4)|2: _VDA(c->DBR);_SA((_GD()<<8)|c->AD);break;
1244-
case (0x22<<4)|3: _VDA(0);_SAD(_SP(_S(c)),c->PBR);_WR();break;
1245-
case (0x22<<4)|4: _SA(_SP(_S(c)--));c->AD=(_GD()<<8)|c->AD;break;
1246-
case (0x22<<4)|5: _VPA();_SA(c->PC++);break;
1247-
case (0x22<<4)|6: _VDA(0);c->PBR=_GD();_SAD(_SP(_S(c)--),c->PC>>8);_WR();break;
1248-
case (0x22<<4)|7: _VDA(0);_SAD(_SP(_S(c)--),c->PC);_WR();break;
1249-
case (0x22<<4)|8: c->PC=c->AD;_FETCH();break;
1243+
case (0x22<<4)|2: _VDA(0);c->AD=(_GD()<<8)|c->AD;_SAD(_SP(_S(c)),c->PBR);_WR();break;
1244+
case (0x22<<4)|3: _SA(_SP(_S(c)--));break;
1245+
case (0x22<<4)|4: _VPA();_SA(c->PC);break;
1246+
case (0x22<<4)|5: _VDA(0);c->PBR=_GD();_SAD(_SP(_S(c)--),c->PC>>8);_WR();break;
1247+
case (0x22<<4)|6: _VDA(0);_SAD(_SP(_S(c)--),c->PC);_WR();break;
1248+
case (0x22<<4)|7: c->PC=c->AD;_FETCH();break;
1249+
case (0x22<<4)|8: assert(false);break;
12501250
/* AND d,s */
12511251
case (0x23<<4)|0: _VPA();_SA(c->PC++);break;
12521252
case (0x23<<4)|1: c->AD=_GD();break;

src/codegen/w65c816s_gen.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -731,11 +731,11 @@ def i_jsrx(o):
731731
def i_jsl(o):
732732
cmt(o,'JSL')
733733
# write Program Bank Register to stack
734-
o.t('_VDA(0);_SAD(_SP(_S(c)),c->PBR);_WR();')
734+
o.to('_VDA(0);c->AD=(_GD()<<8)|c->AD;_SAD(_SP(_S(c)),c->PBR);_WR();')
735735
# put SP on addr bus, next cycle is a junk read
736-
o.t('_SA(_SP(_S(c)--));c->AD=(_GD()<<8)|c->AD;')
736+
o.t('_SA(_SP(_S(c)--));')
737737
# read bank of target address
738-
o.t('_VPA();_SA(c->PC++);')
738+
o.t('_VPA();_SA(c->PC);')
739739
# write PC high byte to stack
740740
o.t('_VDA(0);c->PBR=_GD();_SAD(_SP(_S(c)--),c->PC>>8);_WR();')
741741
# write PC low byte to stack

src/tests/cputest.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)