BigEd wrote:
So, by the end - just before the end - of the second cycle of the branch, when the offset byte has just arrived, are the flags not yet ready?
it's a bit different, here an example of how the LDA # instruction works:
Cycle 0: Load OPCode from memory (at PC), and update PC to the address of the next OPCode
Cycle 1: Load the value from memory (at PC - 1) into A, and END the Instruction
you can see a lot of stuff happening at the same time...
the "END" basically just means that next cycle the counter is set back to 0, so that it can load the OPCode and update the PC for the next instruction.
here another example with a single cycle instruction (DEX):
Cycle 0: Load OPCode from memory (at PC), and update PC to the address of the next OPCode
Cycle 1: Decrement X, SKIP Cycle 0 of the next instruction, load the OPCode for the next instruction and update the PC to the address of the OPcode after that, and finally END the instruction
basically SKIP just means that the current cycle does the same thing as the Cycle 0 of the next instruction plus whatever the current instruction wants to do in the last cycle. it combines them into one.
this also sets the Cycle counter to 1 for the next instruction, since it already loaded the Opcode and updated the PC.
this is what breaks the Branch as DEX updates the flags and the X Register on the same cycle as it loads the next opcode, which in case of the branch is the same cycle it checks for the flags.
BigEd wrote:
I'm wondering if you could speculatively add the offset to the PC, and then at the last instant a mux will select between the incremented PC and the destination PC.
I think i see what you mean....
Cycle 0: Load OPCode from memory (at PC), and update PC to the address of the next OPCode
Cycle 1: Check for Flags, and load from Memory (PC - 1, IE the Operand) into a temprary Register
Cycle 2: (not taken) END the Instruction, and SKIP Cycle 0 of the next Instruction
Cycle 2: (taken) Load PC + TEMP into the PC, and END the instruction
making it 2 cycles long when not taken, and 3 cycles when taken.
it's similar to what i planned to do, i wanted to load the Operand on the last cycle after the branch is taken, but in the end it has the same cycle count so it doesn't really matter. it just saves a memory access everytime a branch is not taken...
Cycle 0: Load OPCode from memory (at PC), and update PC to the address of the next OPCode
Cycle 1: Check for Flags
Cycle 2: (not taken) END the Instruction, and SKIP Cycle 0 of the next Instruction
Cycle 2: (taken) Load from Memory (PC - 1, IE the Operand), add that to the PC, and finally END the Instruction
after doing these changes it got much further, now it got stuck at 0x3573.
which i again can only guess what it means.
Code:
trap_vs
3554 : 70fe > bvs * ;failed overflow set
trap_mi
3556 : 30fe > bmi * ;failed minus (bit 7 set)
trap_eq
3558 : f0fe > beq * ;failed equal (zero)
355a : c94a cmp #'J' ;registers loaded?
trap_ne
355c : d0fe > bne * ;failed not equal (non zero)
355e : e053 cpx #'S'
trap_ne
3560 : d0fe > bne * ;failed not equal (non zero)
3562 : c04f cpy #('R'-3)
trap_ne
3564 : d0fe > bne * ;failed not equal (non zero)
3566 : 48 pha ;save a,x
3567 : 8a txa
3568 : 48 pha
3569 : ba tsx ;sp -4? (return addr,a,x)
356a : e0fb cpx #$fb
trap_ne
356c : d0fe > bne * ;failed not equal (non zero)
356e : adff01 lda $1ff ;propper return on stack
3571 : c909 cmp #hi(jsr_ret)
trap_ne
3573 : d0fe > bne * ;failed not equal (non zero)
it looks like it checks some stack stuff?
it got stuck at the last compare, and acording to that code it compared 0x09 to 0xBA (the value in 0x01FF), which were supposed to be equal to eachother, but the value 0x09 is on 0x01FE...
I tested the PUSH and PULL Instructions again but they seem fine. even when i transfer the SP to X directly after a PUSH/PULL it works perfectly fine and transfers the correct value.
i also tested JSR and RTS and the SP is the correct value, so when i start at 0x00, do a JSR and then a RTS, it's back at 0x00. same with all PUSH/PULL Instructions if one of each is done in a sequence.
so there must be something else breaking...