Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ext/imgui
Submodule imgui updated 129 files
14 changes: 7 additions & 7 deletions src/chips/w65c816s.h
Original file line number Diff line number Diff line change
Expand Up @@ -1240,13 +1240,13 @@ uint64_t w65816_tick(w65816_t* c, uint64_t pins) {
/* JSL a */
case (0x22<<4)|0: _VPA();_SA(c->PC++);break;
case (0x22<<4)|1: _VPA();_SA(c->PC++);c->AD=_GD();break;
case (0x22<<4)|2: _VDA(c->DBR);_SA((_GD()<<8)|c->AD);break;
case (0x22<<4)|3: _VDA(0);_SAD(_SP(_S(c)),c->PBR);_WR();break;
case (0x22<<4)|4: _SA(_SP(_S(c)--));c->AD=(_GD()<<8)|c->AD;break;
case (0x22<<4)|5: _VPA();_SA(c->PC++);break;
case (0x22<<4)|6: _VDA(0);c->PBR=_GD();_SAD(_SP(_S(c)--),c->PC>>8);_WR();break;
case (0x22<<4)|7: _VDA(0);_SAD(_SP(_S(c)--),c->PC);_WR();break;
case (0x22<<4)|8: c->PC=c->AD;_FETCH();break;
case (0x22<<4)|2: c->AD=(_GD()<<8)|c->AD;break;
case (0x22<<4)|3: _VDA(0);_SAD(_SP(_S(c)--),c->PBR);_WR();break;
case (0x22<<4)|4: _VPA();_SA(c->PC++);break;
case (0x22<<4)|5: _VDA(0);c->PBR=_GD();_SAD(_SP(_S(c)--),c->PC>>8);_WR();break;
case (0x22<<4)|6: _VDA(0);_SAD(_SP(_S(c)--),c->PC);_WR();break;
case (0x22<<4)|7: c->PC=c->AD;_FETCH();break;
case (0x22<<4)|8: assert(false);break;
/* AND d,s */
case (0x23<<4)|0: _VPA();_SA(c->PC++);break;
case (0x23<<4)|1: c->AD=_GD();break;
Expand Down
8 changes: 4 additions & 4 deletions src/codegen/w65c816s_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,11 +730,11 @@ def i_jsrx(o):
#-------------------------------------------------------------------------------
def i_jsl(o):
cmt(o,'JSL')
# replace last A_ABS tick - build 16-bit address from middle and low byte
o.to('c->AD=(_GD()<<8)|c->AD;')
# write Program Bank Register to stack
o.t('_VDA(0);_SAD(_SP(_S(c)),c->PBR);_WR();')
# put SP on addr bus, next cycle is a junk read
o.t('_SA(_SP(_S(c)--));c->AD=(_GD()<<8)|c->AD;')
# read bank of target address
o.t('_VDA(0);_SAD(_SP(_S(c)--),c->PBR);_WR();')
# read bank byte of target address
o.t('_VPA();_SA(c->PC++);')
# write PC high byte to stack
o.t('_VDA(0);c->PBR=_GD();_SAD(_SP(_S(c)--),c->PC>>8);_WR();')
Expand Down
56 changes: 56 additions & 0 deletions src/tests/cputest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,3 +448,59 @@ TEST_CASE("16 bit arithmetic carries") {
}
}
}

TEST_CASE("JSL instruction correctly sets PBR and PC") {
w65816_t cpu;
w65816_desc_t desc = {};
uint64_t pins = w65816_init(&cpu, &desc);

// skip RESET
pins &= ~(W65816_RW | W65816_RES);
cpu.PINS = pins;

// Test code: JSL $123456
// This tests that the middle byte ($34) is not lost
uint8_t asm_code[] = {
0x22, 0x56, 0x34, 0x12, // JSL $123456
};

// Memory for storing the code
uint8_t memory[0x10000] = {0};
memcpy(memory, asm_code, sizeof(asm_code));

// Set initial PC to 0x0000, PBR to 0x00
cpu.PC = 0x0000;
cpu.PBR = 0x00;
cpu.S = 0x01FF; // Stack pointer

int cycle = 0;

// Run for 8 cycles (JSL takes 8 cycles according to W65C816S datasheet)
while (cycle < 8) {
if (pins & W65816_RW) {
// memory read
// Get the full 24-bit address (bank:address)
uint32_t full_addr = W65816_GET_ADDR(pins);
uint8_t bank = (full_addr >> 16) & 0xFF;
uint16_t addr = full_addr & 0xFFFF;

// Read from our test memory
if (bank == 0 && addr < sizeof(memory)) {
W65816_SET_DATA(pins, memory[addr]);
} else {
W65816_SET_DATA(pins, 0xEA); // NOP
}
}

pins = w65816_tick(&cpu, pins);
cycle++;
}

// After JSL $123456, we expect:
// - PBR = 0x12
// - PC = 0x3456
CAPTURE(cpu.PBR);
CAPTURE(cpu.PC);
CHECK(cpu.PBR == 0x12);
CHECK(cpu.PC == 0x3456);
}
Loading