In sim65, simulator memory access to a 64 KB array is implemented via functions
defined in src/sim65/memory.h and src/sim65/memory.c.
In the old version, the types for both content bytes (8 bits), content words
(16 bits), regular addresses (16 bits), and zero-page addresses (8 bits) were
all given as bare 'unsigned'.
This lead to several cases of address overrun (e.g., when an instruction wraps
around from address 0xffff to 0x0000) when running the simulator against a
stress test (specifically, the 65x02 test suite). To protect from this, and to
more properly express the bit width of the types involved which is a good idea
anyway, we start using the fixed-width types provided by 'stdint.h'.
In the process, we also change the MemReadByte macro to a full function call.
This may impact performance (by a small amount), but it improves memory safety,
as cases where the address is accidentally expressed as a value exceeding 0xffff
are handled by wrap-around (as it is in the actual hardware), rather than causing
access outside of the Mem[] array where the 64 KB of simulated RAM resides.
The reason for this patch is twofold.
(1) It is a partial patch for issue #2539.
Several issues brought to the surface by running the 65x02 testsuite are
eliminated by these changes. In the discussion about this issue, it was
concluded that it is a Good Idea to use the stdint-types, both for the
simulated CPU registers and for the memory. This patch addresses the
memory-part of that change.
(2) It is a precursor patch for issue #2355.
For that issue, we will implement a memory-mapped timer register. This will
make handling of memory access in the simulator a bit more complex.
Having proper functions with the proper types in place will help to make the
timer register patch easier.
The BIT #imm instruction behaves differently from the BIT instruction with other
addressing modes, in that it does /not/ set the N and V flags according to the
value of its operand. It only sets the Z flag, in accordance to the value of
(A & operand).
This is corroborated in two ways:
- The 65x02 test suite;
- Documentation about BIT #imm such as http://www.6502.org/tutorials/65c02opcodes.html
This patch implements the correct behavior for BIT with immediate addressing.
The patched version passes the 65x02 test suite for 65C02 opcode 0x89.
Branch instructions, when taken, take three or four cycles,
depending on whether a page is crossed by the branch.
The proper check to determine whether the extra cycle must be added
is the target address of the branch vs the address immediately
following the branch.
In the former version of the BRANCH instruction handler, the target
address was incorrectly checked vs the address of the branch instruction
itself.
The corrected behavior was verified against a real 6502 (Atari) and
the 65x02 testsuite.
The JMP (ind) bug is present in the 6502 which is emulated by both the "6502" and "6502X"
emulation targets of sim65; specifically, the OPC_6502_6C handler. In the old code, the
bug-exhibiting code was not executed when the target was set to 6502X, which is incorrect.
the patch removes the (CPU == CPU_6502) check, which made no sense.
The JMP (ind) bug was actually fixed in the 65c02. Indeed, the OPC_65C02_6C opcode handler
has code that implements the 'right' behavior.