2075 lines
75 KiB
Plaintext
2075 lines
75 KiB
Plaintext
|
||
|
||
|
||
|
||
|
||
|
||
DR6502
|
||
======
|
||
|
||
|
||
|
||
|
||
|
||
|
||
A 6502 Software and Hardware Execution Simulator System
|
||
=======================================================
|
||
|
||
|
||
|
||
|
||
|
||
|
||
with Code Debugging
|
||
===================
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Using a Symbolic Assembler/Disassembler
|
||
=======================================
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
By: M.J.Malone
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
====================================================================
|
||
DR 6502 AER 201S Engineering Design 6502 Execution Simulator
|
||
====================================================================
|
||
|
||
Simulator Manual By: M.J.Malone
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Contents Page
|
||
-------- ----
|
||
|
||
1) Introduction 1
|
||
|
||
2) Simulator Modes of Operations 4
|
||
|
||
3) Stopped Mode Simulator Command Options 6
|
||
|
||
4) After The CRASH: Simulator Command Options 8
|
||
|
||
5) DRSYM and Debugging with the Symbolic Assembler/Disassembler 10
|
||
|
||
6) Explanation of Commands 12
|
||
|
||
7) Extended Instruction Set for the 65C02 and Rockwell R65C02 22
|
||
|
||
8) Differences Between DR6502 and the R6502, 65C02 and R65C02 23
|
||
|
||
9) DR 6502 Support Files 25
|
||
|
||
10) References 26
|
||
|
||
Appendix A: OpCode Alignment 27
|
||
|
||
Appendix B: Merging with EDIT/Blackbeard 30
|
||
|
||
Appendix C: Hardware Simulator Diagrams 31
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
DR6502 - A 6502 Software and Hardware Execution Simulator System
|
||
==================================================================
|
||
|
||
with Code Debugging Using a Symbolic Assembler/Disassembler
|
||
===========================================================
|
||
|
||
|
||
|
||
|
||
1) Introduction
|
||
===============
|
||
|
||
|
||
What is the Simulator and how does it work?
|
||
-------------------------------------------
|
||
The 6502 is a digital circuit. Its reactions to logic levels
|
||
in interior registers and external memory locations are fixed. If
|
||
the logic levels are all known in advance then the operations of the
|
||
6502 are determined. The simulator, using the same information as
|
||
in a project target computer, traces the execution the 6502 would
|
||
take. The simulator is a piece of software that runs on an IBM
|
||
compatible computer. The simulator is programmed with the
|
||
instruction set of the 6502. The task of tracing the movements a
|
||
6502 would make through a piece of code is tackled in the same way
|
||
as any other computational problem. The fact that the IBM does not
|
||
use the 6502 as its central processor is not relevant.
|
||
|
||
The hardware simulator is an interface card and cable that
|
||
plugs into the 6502 socket on an aerospace project board. The
|
||
simulator software, if informed about the presence of the hardware
|
||
card, uses it to perform reads and writes on the target computer's
|
||
memory. This causes data to actually be read from and written to
|
||
I/O ports allowing software debugging while the project hardware is
|
||
present.
|
||
|
||
|
||
Memory Management
|
||
-----------------
|
||
The simulator is a compiled BASIC program. It uses BASIC
|
||
variables to keep track of the processor registers and flags. The
|
||
program 'grabs' a 160K chunk of a 512K IBM computer's high memory.
|
||
Note that the operating system of the IBM is not consulted about the
|
||
allocation of this memory and problems can occur. If you have only
|
||
256K the area of memory used simply does not exist. If you have a
|
||
large number of memory resident programs that push the simulator
|
||
code up into this area then the code will corrupt itself and will
|
||
once again not work. 64K of that memory is used to record all of
|
||
the data in the 64K address space of the 6502 if the hardware
|
||
simulator card is not present. Another 64K is used to hold a status
|
||
number for each memory location that indicates whether the memory is
|
||
allocated, whether it is EPROM or RAM if it is RAM, whether a value
|
||
has been written to it or not. This status number will also
|
||
indicate if the corresponding memory location is to be found in the
|
||
IBM's simulated 6502 address space or found via the hardware card on
|
||
the target computer. This makes partial hardware simulation easy
|
||
where some of the memory elements are accessed by the hardware board
|
||
and others are assumed to be in the simulated address space. One
|
||
example of this is EPROM emulation where the simulator accesses the
|
||
real RAM and VIA on the target but looks to the IBM memory for the
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 2
|
||
|
||
program. The last 32K is used for internal variables and data. As
|
||
a result, to run the simulator a system must have at least 373K of
|
||
the lower 640K free:
|
||
|
||
DR 6502 Code 85K
|
||
Extra Data 160K
|
||
512-640K Unused 128K
|
||
-------------------------
|
||
Total Required: 373K
|
||
|
||
Included among the files on the DR6502 disk is a program 'MM.COM'
|
||
which will tell the user how a system's memory is allocated. To run
|
||
DR6502 it must respond with more than 373K free. If not, the
|
||
AUTOEXEC.BAT and CONFIG.SYS files must be altered to remove some of
|
||
the memory resident utilities or a RAM drive. Also included are two
|
||
handy memory management utilities, 'MARK.COM' and 'RELEASE.COM' to
|
||
mark a spot in memory and then later to release any memory resident
|
||
utilities added after the mark.
|
||
|
||
|
||
The Procedure: What do you have to do to make it run?
|
||
-----------------------------------------------------
|
||
|
||
As explained in the 'QIKSTART.DOC' file, the command line to
|
||
use in assembling 'myfile.asm' with TASM is as follows.
|
||
|
||
tasm -65 -b -l -fff myfile.asm myfile.bin myfile.lst <enter>
|
||
|
||
Note on Options: -65 : Assemble for the 6502
|
||
-b : Binary file output
|
||
-l : List the symbol table
|
||
-fff: Fill unassigned spaces of the EPROM with $FF
|
||
|
||
After the program is assembled, to produce a symbol file for
|
||
DR6502, the user must run DRSYM.EXE as follows:
|
||
|
||
drsym <enter>
|
||
|
||
The user must next provide the name of the listing file, in this
|
||
case 'myfile'. DRSYM produces a file 'myfile.sym' that can be read
|
||
by DR6502. The user would next execute the DR6502 CONFIG program
|
||
(if a different memory configuration is to be used):
|
||
|
||
config <enter>
|
||
|
||
The user then provides a description of the memory elements in the
|
||
system. When the EPROM is input, the CONFIG program will as for the
|
||
name of the binary file, in this case 'myfile'. After the
|
||
configuration is complete, the CONFIG program will automatically
|
||
execute the DR6502 program. To run DR6502 with the same
|
||
configuration as before and with a binary file of the same name and
|
||
with a current or no symbol file then type:
|
||
|
||
dr6502 <enter>
|
||
|
||
The simulation begins.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 3
|
||
|
||
The Simulation: What does DR6502 do when it runs?
|
||
-------------------------------------------------
|
||
|
||
The simulator constructs an exact memory map of your target
|
||
system with RAM, EPROM and VIA. The simulator then reads your .BIN
|
||
program file produced by TASM into the spaces allocated as EPROM.
|
||
(Note that the .BIN file is the form of your software that is ready
|
||
to be burned on an EPROM and installed on your target system so the
|
||
simulation will be exact.) The program then simulates the start up
|
||
and running of the processor. Several run time error conditions are
|
||
checked such as reads or writes to unallocated memory (not occupied
|
||
by a chip), attempted writes to ROM space, reads from RAM spaces
|
||
that were never set etc. Regular CPU crashes are recognized by the
|
||
occurrence of undefined opcodes.
|
||
|
||
When using the hardware simulator option, the RST, NMI, IRQ, SO
|
||
and RDY signals are monitored in the hardware and are obeyed by the
|
||
simulator. When used entirely in software, a simulated IRQ
|
||
frequency is available (Search /Option 'i'/).
|
||
|
||
The simulator is called a symbolic code simulator because it
|
||
will read a ??.SYM file for each EPROM present in your simulated
|
||
computer and will create a reverse symbol table. This table is then
|
||
used in the 'P' program option and 'D' assembly code to allow the
|
||
user to operate with the symbols that were used in the source code.
|
||
This makes viewing and editing the code (Option 'P') much easier.
|
||
With symbol information present, program outputs produced under
|
||
Option 'D' could be combined back into the original assembly code to
|
||
incorporate changes made during simulation sessions.
|
||
|
||
|
||
Other Benefits of the Hardware Simulator System
|
||
-----------------------------------------------
|
||
|
||
Once again, the hardware simulator is made up of two
|
||
components, an interface card and cable that plugs into an IBM
|
||
mother board slot and the DR6502 program. The copy of DR6502 given
|
||
out to all students is capable of operating in either hardware or
|
||
software mode. If a student wishes to construct a hardware
|
||
simulator card to use on their MS-DOS machine at home, the
|
||
schematics are given in the notes. In addition to simulating the
|
||
operation of the 6502 on the target board with DR6502, the interface
|
||
card can be used to run diagnostics.
|
||
The programs 'RAMTEST' and 'EPRMTEST' are used to test the RAM
|
||
and EPROM chips respectively. The program 'EEPROM' can be used with
|
||
the interface card to program electrically erasable, programmable
|
||
read only memories or EEPROMs of the XL2864A type or equivalent. By
|
||
installing the chip on your target computer board, plugging in the
|
||
interface cable to your 6502 processor socket and running one of the
|
||
above mentioned programs, all of these services are available
|
||
through the interface card.
|
||
Because students sometimes wish to test chips outside their
|
||
board or would like to test their VIA chips, an auxiliary board is
|
||
provided with ZIF (zero insertion force) sockets that uses a project
|
||
computer board as its base. The board has been specially wired to
|
||
allow testing of RAM, EPROM, and VIA or programming of EEPROMs.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 4
|
||
|
||
2) Simulator Modes of Operations
|
||
================================
|
||
|
||
The program can run in one of four modes given by the
|
||
combinations of user output/no output and break point set/no break
|
||
point set. Each of the four modes gives a different amount of user
|
||
feedback and executes instructions at a different speed.
|
||
|
||
Screen Output:
|
||
When the simulator reports to the screen after every program
|
||
step, the execution is quite slow in comparison to the speed of a
|
||
6502. To speed up the execution of the program, the user has the
|
||
option to suppress screen printing thereby saving a great deal of
|
||
time. Note that any time screen output is selected, the history
|
||
file (DR_6502.HST) is updated as per its user selected output
|
||
option. When the screen output is suppressed, the history file is
|
||
not written to either. (Search /Option 'H'/)
|
||
|
||
Trace Controlled Screen Output:
|
||
The simulator has a control option (Search /Option 't'/) where
|
||
the screen output is enabled and disabled based on the position of
|
||
execution in the subroutine calling tree. This option is called the
|
||
trace option because it can be used to trace the execution of a
|
||
particular routine, performing all of the calculations in
|
||
subroutines without displaying them. The speed of execution of the
|
||
simulator is not effected whether operating under the trace mode or
|
||
not however as the trace option changes execution modes, the speed
|
||
changes accordingly.
|
||
|
||
Break Point Set:
|
||
If the 'processor' encounters the one user selected break point
|
||
address during any memory access (OpCode fetch, read, write etc) the
|
||
simulation will stop and await user prompting. If there is no break
|
||
point set then no check of addresses will be done. (Search /Option
|
||
'b'/)
|
||
|
||
|
||
Mode 1: Break Point and No Output
|
||
---------------------------------
|
||
The fastest execution occurs when a break point has been set
|
||
and no output is selected. In this mode the 'processor' blasts
|
||
along at maximum speed scanning for the ` key which indicates
|
||
switching back to full user output. Without user input the program
|
||
will run 'silently' until the breakpoint address is reached. At
|
||
maximum, the program is currently capable of simulating about 166
|
||
MCPS (machine cycles per second) or one second of 6502 CPU time in
|
||
about 1.67hr of XT (8Mhz) execution time which is 1/6000th real
|
||
speed. With delay loops disabled, this mode can move very rapidly
|
||
though the program, executing about one page of assembly source code
|
||
per second. Since most every computer owned by students is many
|
||
times faster than an XT, the simulation will be that much faster on
|
||
their machine at home. If the break point address is reached, the
|
||
program will switch to Mode 4: Stopped Mode.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 5
|
||
|
||
Mode 2: No Output, No Break Point
|
||
---------------------------------
|
||
The program still scans for the ` key because with no break
|
||
point this is the only means of returning the program to full output
|
||
mode. Since the program will run indefinitely in this mode, the
|
||
user needs to know at what stage the program is so that it may be
|
||
stopped near points of interest. The program prints the current
|
||
program counter value to the screen after each program step to let
|
||
the user know where the program is. This mode runs at about 118
|
||
MCPS, that is 70% of the speed of mode 1.
|
||
|
||
|
||
Mode 3: Full Output
|
||
-------------------
|
||
In this mode the program prints the values of all registers
|
||
after every program step. If there is a break point set then the
|
||
current fetch and program addresses will be compared to the break
|
||
point address at each program step. If the program reaches the
|
||
break point address it will go into Mode 4: Stopped Mode. Running
|
||
with full output with or without a breakpoint is very slow but still
|
||
faster than the average human is able to absorb the information
|
||
flipping past on the screen. For this reason the program builds a
|
||
DR_6502.HST history file on disk that records any program steps that
|
||
are displayed on the screen. In this mode the simulator executes
|
||
about 16 MCPS or about 1/10th the speed of mode 1 including all disk
|
||
and screen output. In this mode the program is scanning for user
|
||
input. To transfer to modes 1 or 2 press the ` key. To stop the
|
||
execution (go to Mode 4: Stopped Mode) press the 's' key (stands
|
||
for 'STOP').
|
||
|
||
|
||
Mode 4: Stopped Mode
|
||
--------------------
|
||
|
||
In this mode the program does not execute program steps but
|
||
waits for user input. To go back to each of the other modes from
|
||
mode 4, the user must input:
|
||
|
||
Mode 1: Enter a [new] break point address. Press the ` key.
|
||
Mode 2: Press the ` key.
|
||
Mode 3: Press the 'g' key (stands for GO)
|
||
|
||
To remain in stopped mode but advance by one program step, the
|
||
user can press the 's' key (stands for STEP). The other command
|
||
options available are explained in the next section.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 6
|
||
|
||
3) Stopped Mode Simulator Command Options
|
||
=========================================
|
||
|
||
Since there are several avenues open to the user under the
|
||
stopped mode, no command prompt is displayed but the program will
|
||
react to keystrokes. The following is a list of the keystrokes and
|
||
the commands they initiate. The more complete description of what
|
||
each of the commands does is given in below. The reader can use a
|
||
word search or find option searching for /Option 'x'/ where x is the
|
||
keystroke to be searched.
|
||
|
||
|
||
Key | Function
|
||
====================================================================
|
||
|
|
||
b | Set the break point address
|
||
|
|
||
t | Trace on, Full screen output for this level subroutine
|
||
| only. Screen output is disabled upon JSR and is
|
||
| re-enabled after the matching RTS is executed.
|
||
|
|
||
T | Trace off
|
||
|
|
||
d | Dump memory data to a disk file in hex, TASM or block
|
||
| format
|
||
|
|
||
R | Read a disk data file in block format into memory
|
||
|
|
||
* D | Dump Disassembled Program to a Disk file in TASM format
|
||
|
|
||
p | Poke values into memory (good for simulating I/O, sensors)
|
||
|
|
||
* P | (Re)Program: Disassembles a Page of Program Memory and
|
||
| Offers the following sub-menu
|
||
|
|
||
| Key Function
|
||
| ==========================================================
|
||
| u move Up a line in the program
|
||
| d move Down a line in the program
|
||
| c Change the code - begin reprogramming in assembly
|
||
| code
|
||
| s Save current page
|
||
| r Reread current page discarding any changes
|
||
| + read and disassemble the next memory page of the
|
||
| program
|
||
| p read and disassemble a different Page
|
||
| m Make space for new assembly code to be inserted
|
||
| i Symbol information
|
||
| a Assign a Symbol
|
||
| l Label current line with a symbol
|
||
| b toggle display of Branch line labels
|
||
| n modify Notepad
|
||
| q Quit Program module - do not save the current page
|
||
|
|
||
|
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 7
|
||
|
||
m | Monitor an address (variable)
|
||
|
|
||
r | Change the contents of the processor Registers including
|
||
| the flags
|
||
|
|
||
v | View memory in hex dump format to the screen
|
||
|
|
||
n | Display and edit the notepad
|
||
|
|
||
l | List a text file to the screen - copy to notepad
|
||
| f - find text
|
||
| ESC - quit
|
||
|
|
||
h | History, display the short history that is maintained in
|
||
| memory
|
||
|
|
||
H | Change the history file and short history format
|
||
|
|
||
! | RESET the processor - all memory remains
|
||
|
|
||
i | Set interrupt frequency (Available only in software
|
||
| simulation mode)
|
||
|
|
||
e | End the simulation - Check DR_6502.HST for a log of that
|
||
| run
|
||
|
|
||
? | HELP - List the Keystrokes available to the user
|
||
|
|
||
====================================================================
|
||
* Segments contained in the second overlay. Upon initiating the
|
||
command the simulator will stop for a few moments to transfer in
|
||
'OVERLAY1.EXE'. These segments of the program utilize the symbol
|
||
information if present to enhance their operation. Please see
|
||
section 5) DRSYM and the Symbolic Debugging.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 8
|
||
|
||
4) After The CRASH: Simulator Command Options
|
||
=============================================
|
||
|
||
After the simulator has flagged some condition that would lead
|
||
to a malfunction of a real 6502 system, the mode of operations
|
||
changes to the post crash analysis. The user has many option
|
||
available to analyze memory and processor status to discover where
|
||
things went wrong. The user also has the option to direct the
|
||
simulator to return to normal operations after some adjustments to
|
||
registers or data has been made. The following is a list of
|
||
commands available in the post crash analysis.
|
||
|
||
|
||
Key | Function
|
||
====================================================================
|
||
|
|
||
d | Dump memory data to a disk file in hex, TASM or block
|
||
| format
|
||
|
|
||
* D | Dump Disassembled Program to a Disk file in TASM format
|
||
|
|
||
p | Poke values into memory (good for simulating I/O, sensors)
|
||
|
|
||
* P | (Re)Program: Disassembles a Page of Program Memory and
|
||
| Offers the following sub-menu
|
||
|
|
||
| Key Function
|
||
| ==========================================================
|
||
| u move Up a line in the program
|
||
| d move Down a line in the program
|
||
| c Change the code - begin reprogramming in assembly
|
||
| code
|
||
| s Save current page
|
||
| r Reread current page discarding any changes
|
||
| + read and disassemble the next memory page of the
|
||
| program
|
||
| p read and disassemble a different Page
|
||
| m Make space for new assembly code to be inserted
|
||
| i Symbol information
|
||
| a Assign a Symbol
|
||
| l Label current line with a symbol
|
||
| b toggle display of Branch line labels
|
||
| n modify Notepad
|
||
| q Quit Program module - do not save the current page
|
||
|
|
||
|
|
||
r | Change the contents of the processor Registers including
|
||
| the flags
|
||
|
|
||
v | View memory in hex dump format to the screen
|
||
|
|
||
n | Display and edit the notepad
|
||
|
|
||
h | History, display the short history that is maintained in
|
||
| memory
|
||
|
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 9
|
||
|
||
H | Change the history file and short history format
|
||
|
|
||
! | RESET the processor - all memory remains
|
||
|
|
||
e | End the simulation - Check DR_6502.HST for a log of that
|
||
| run
|
||
|
|
||
? | HELP - List the Keystrokes available to the user
|
||
|
|
||
j | Jump Start the simulation - Direct the simulator to resume
|
||
|
|
||
====================================================================
|
||
* Segments contained in the second overlay. Upon initiating the
|
||
command the simulator will stop for a few moments to transfer in
|
||
'OVERLAY1.EXE'. These segments of the program utilize the symbol
|
||
information if present to enhance their operation. Please see
|
||
section 5) DRSYM and the Symbolic Debugging.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 10
|
||
|
||
5) DRSYM and Debugging with the Symbolic Assembler/Disassembler
|
||
================================================================
|
||
|
||
DRSYM is a very short program that reads the symbol table
|
||
printed in ASC II at the end of the TASM list file and turns it into
|
||
a packed binary file for input into DR6502. DRSYM also excludes
|
||
from the list of symbols it produces, any symbols that appear
|
||
anywhere in the assembly code as constant arguments in the format
|
||
'#symbol'. The reasons for this will be explained later. If
|
||
another assembler is used other than TASM, a different DRSYM program
|
||
will need to be programmed. For this reason both the BASIC source
|
||
code and compiled code for DRSYM have been provided so that the user
|
||
may alter the program to read the list file from their favorite
|
||
assembler.
|
||
With the symbol information and the machine code the simulator
|
||
is able to recreate your assembly code fairly closely. The two
|
||
program modules that use this ability are the 'D' dump assembly code
|
||
to disk file and the 'P' (re)program assembly code modules.
|
||
|
||
|
||
'D' Dump Assembly Code Option
|
||
-----------------------------
|
||
|
||
The 'D' dump code option is quite straight forward. The
|
||
simulator looks at the section of memory to be disassembled and
|
||
dumped to the disk and inserts labels whenever it finds a match
|
||
between an address reference and a label value.
|
||
|
||
Constants
|
||
Labels are not substituted in the case of constant references
|
||
since there may be times when #$01 is used as the 'number 1', 'bit
|
||
zero set' or 'true' each with a different label. It would be
|
||
impossible for the simulator to determine which usage of the #$01
|
||
was intended in a particular piece of code. Since constants are
|
||
never substituted for, there is no need for constant labels to
|
||
appear in the symbol table. For this reason, DRSYM does not record
|
||
constants labels in the symbol table in the .SYM file.
|
||
|
||
Address with No Symbol
|
||
References to addresses that do not have a corresponding label
|
||
but are only a few bytes offset from a label will be recorded as
|
||
'label+offset' assuming a multibyte storage data structure. For
|
||
example, if 'Register_0' where assigned the value of $00 in the
|
||
source assembly code and no label were assigned to the address
|
||
$01, it is very likely that references to the address $01 would
|
||
actually be written in the code as 'Register_0 + 1' where
|
||
Register_0 is in this case a multibyte piece of data. If
|
||
contents of address $01 had absolutely nothing to do with the
|
||
contents of address $00 then, as dictated by good programming
|
||
style, $01 should have been assigned a label that explained its
|
||
purpose such as 'Register_1' or 'Temp'.
|
||
|
||
Though these rules may not seem to make sense when stated,
|
||
experimentation has found, on average, this set of rules produces
|
||
code that is closest to the original assembly source code. It is
|
||
very possible that the code reproduced by DR6502 will be identical
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 11
|
||
|
||
to the original source code with the omission of the comments. The
|
||
dump module is not interactive, the output of the symbolic
|
||
disassembly goes directly to the user specified disk filename. The
|
||
output of the dump option is easily incorporated into the original
|
||
source code to reflect reprogramming done in the 'P' (re)program
|
||
code option.
|
||
|
||
|
||
'P' (re)Program Code Option
|
||
---------------------------
|
||
|
||
The 'P' (re)program code option is an interactive symbolic
|
||
assembler/disassembler based on a machine language page of assembly
|
||
code. As with the 'D' dump option the 'P' option disassembles
|
||
starting at a user specified memory address inserting address labels
|
||
in the same manner as described above. The disassembled code is
|
||
displayed on the screen and the user can move up and down through
|
||
the page. The user can inquire about label information, assign a
|
||
new label or label the current memory address indicated by the line
|
||
the cursor is currently on. The user can modify the code and use
|
||
labels to specify any arguments including constant arguments (like
|
||
#True for #$01).
|
||
|
||
**** In fact the user need not start with any real code at all! ****
|
||
|
||
By assembling a file with one instruction, and the reset vector, the
|
||
user can start the simulator with no actual program present. The
|
||
'P' option could be used as an interactive, line by line assembler,
|
||
inputting labels as necessary developing code on the fly. Though
|
||
this is definitely not a good programming practice, it is very
|
||
useful if the user just wants to try something out, preferably that
|
||
will code out to less than 256 bytes of machine code or about 100
|
||
lines of assembly code. After the code has been programmed or
|
||
reprogrammed in the case of repairing a bug, the page must be saved
|
||
back to the memory of the simulated 6502.
|
||
Using the 'P' option, it is possible to work on your code in
|
||
the simulator at a near source code level provided symbol
|
||
information is provided. It is convenient and wise to use the 'D'
|
||
option to record to disk, for later reference, any changes made to a
|
||
section of the assembly code. Search /Option 'D'/ or /Option 'P'/
|
||
for specific information on how each option is used.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 12
|
||
|
||
6) Explanation of Commands
|
||
===========================
|
||
|
||
Option 'b'
|
||
----------
|
||
Often the user would like the code to run to a certain point
|
||
and then stop. DR6502 allows the user to set a break point address
|
||
and whenever that address is used in a memory fetch of any sort,
|
||
including data, the simulator will stop and display the current
|
||
status of the simulated processor. This can be used to make the
|
||
program execute to a certain address by specifying the code address
|
||
you wish the program to stop at. The user can monitor the data
|
||
traffic to a VIA port by setting the break point to be the address
|
||
of the VIA port. In this case whenever a read or a write is done to
|
||
the port the simulator would stop and display the status.
|
||
|
||
|
||
Option 't' and Option 'T'
|
||
-------------------------
|
||
The 't' trace option modifies the screen output of the
|
||
simulator. The 'b' option allows the user to execute until a
|
||
certain address. Often, the user wants to execute a routine that
|
||
calls a number of subroutines. In this case the user may only be
|
||
interested in monitoring the execution of the program when it is in
|
||
the high level routine and not when it jumps into the lower level
|
||
subroutines. When the trace option is initialed at a particular
|
||
point in the subroutine call tree, DR6502 automatically switches to
|
||
no output mode (as initiated by the ' option) when executing
|
||
subroutines at nesting levels lower and switches back to full output
|
||
mode for subroutines of a equal or higher nesting level. This
|
||
allows the user to view only the higher level logic. The 'T' cancel
|
||
trace option, cancels the current trace mode.
|
||
|
||
|
||
Option 'm'
|
||
----------
|
||
The 'm' monitor a variable option allows the user to constantly
|
||
monitor the contents of a memory location. The value is displayed
|
||
in the status area next to the 6502 register values. This option
|
||
can be used to monitor a memory location that is used by the code as
|
||
a variable or it can be used to monitor in a memory location
|
||
corresponding to a VIA port. The user is given the option of
|
||
selecting a two byte display where the memory location specified and
|
||
the one following are interpreted as a 16 bit variable.
|
||
|
||
|
||
Option 'r'
|
||
----------
|
||
The 'r' modify registers option allows the user to modify the
|
||
processor .A, .X, .Y, .SP, .PC and .R registers. This option can be
|
||
used to correct for data or stack errors recognized in the program.
|
||
As the user is testing their individual subroutines, they may wish
|
||
to place the break point at the RTS, set data register initial
|
||
values and then set the program counter to begin the routine.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 13
|
||
|
||
Option 'j'
|
||
----------
|
||
Presumably if the crash was not too bad and a little adjustment
|
||
of the registers will fix it (including possibly the program
|
||
counter) then the program will allow you to attempt to jump-start
|
||
the simulation again. This may be attempted as many times as the
|
||
user wishes.
|
||
|
||
***** WARNING ***** An infinite loop is NOT a crash if it is
|
||
composed of valid 6502 instructions, so be careful.
|
||
|
||
Option '!'
|
||
----------
|
||
The '!' reset option performs the same function on the
|
||
simulator as the reset button on the target microprocessor board.
|
||
The user is given the option of changing the type of 6502 processor
|
||
simulated.
|
||
|
||
|
||
Option 'h'
|
||
----------
|
||
The 'h' history option displays a short history of the last 9
|
||
instructions that the processor has executed. The user will
|
||
probably find this most helpful after the simulation has stopped at
|
||
a break point to discover by what manner it came to arrive at the
|
||
break point.
|
||
|
||
|
||
Option 'H' and the History File
|
||
-------------------------------
|
||
As stated earlier, the simulator writes to a history file
|
||
whenever full screen output is selected. The format of the file can
|
||
be controlled by the 'H' history file mode option. The first choice
|
||
is full output including disassembled code, all registers, program
|
||
counter before and after and the monitored variable address and
|
||
value (if selected) at every program step. The second choice is
|
||
every line output with the disassembled code only. The last option
|
||
is nesting output that writes to the history file only on the
|
||
occurrence of JSR, RTS, BRK, RTI and the hardware interrupt.
|
||
The first choice is most useful if extensive checking of the
|
||
flow of data through the registers is desired. The disadvantage of
|
||
full output mode is that it requires a lot of disk storage space for
|
||
the DR_6502.HST file. The second mode is best for simple tracing of
|
||
the program execution. This mode requires less disk space yet still
|
||
provides enough information to help debug the program. The third
|
||
option allows the user to check that subroutines are nested properly
|
||
and called when expected. This mode saves a great deal on disk
|
||
space (and runs faster too) by cutting out a lot of the unnecessary
|
||
information not required for high level debugging.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 14
|
||
|
||
Sample output from mode 1:
|
||
|
||
Addr Op Args Mn Addr Mode A X Y SP PC PC NV BDIZC Variable
|
||
-----------------------------------------------------------------------------
|
||
F001 A2 FF LDX #const (2) 00 FF 00 00 F001=>F003 10100100 0080=#$????
|
||
F003 9A TXS (2) 00 FF 00 FF F003=>F004 10100100 0080=#$????
|
||
F004 58 CLI (2) 00 FF 00 FF F004=>F005 10100000 0080=#$????
|
||
NOP Cruise $F005-$F009
|
||
F009 EA NOP (10) 00 FF 00 FF F009=>F00A 10100000 0080=#$????
|
||
F00A A9 FF LDA #const (2) FF FF 00 FF F00A=>F00C 10100000 0080=#$????
|
||
F00C 8D 00 02 STA addr (4) FF FF 00 FF F00C=>F00F 10100000 0080=#$????
|
||
F00F A9 02 LDA #const (2) 02 FF 00 FF F00F=>F011 00100000 0080=#$????
|
||
F011 85 81 STA zpage (3) 02 FF 00 FF F011=>F013 00100000 0080=#$????
|
||
F013 A9 00 LDA #const (2) 00 FF 00 FF F013=>F015 00100010 0080=#$????
|
||
F015 85 80 STA zpage (3) 00 FF 00 FF F015=>F017 00100010 0080=#$0200
|
||
F017 A9 55 LDA #const (2) 55 FF 00 FF F017=>F019 00100000 0080=#$0200
|
||
F019 8D 01 02 STA addr (4) 55 FF 00 FF F019=>F01C 00100000 0080=#$0200
|
||
F01C A9 01 LDA #const (2) 01 FF 00 FF F01C=>F01E 00100000 0080=#$0200
|
||
-----------------------------------------------------------------------------
|
||
|
||
Sample output from mode 2: (Note: this is the default mode on start up)
|
||
|
||
Addr Op Args Mn Addr Mode
|
||
---------------------------------------------------------------------------
|
||
F001 A2 FF LDX #const (2)
|
||
F003 9A TXS (2)
|
||
F004 58 CLI (2)
|
||
NOP Cruise $F005-$F009
|
||
F009 EA NOP (10)
|
||
F00A A9 FF LDA #const (2)
|
||
---------------------------------------------------------------------------
|
||
|
||
Sample output from mode 3:
|
||
|
||
Addr Op Args Mn
|
||
---------------------------------------------------------------------------
|
||
F020 20 00 F8 JSR dest (6)
|
||
F812 60 RTS (6)
|
||
---------------------------------------------------------------------------
|
||
|
||
|
||
Other History File Entries
|
||
--------------------------
|
||
|
||
Certain conditions including errors and warnings produce
|
||
notations in the history file. The following are several such
|
||
example entries.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 15
|
||
|
||
Sample RESET Entry:
|
||
|
||
Each time the simulator is RESET the following appears in the
|
||
history file:
|
||
|
||
--------------------------------------------------------------------------
|
||
RESET ====> $FFFC
|
||
Reset Vector = $F000
|
||
F000 78 SEI (2) **** Note this depends on your first instruction
|
||
--------------------------------------------------------------------------
|
||
|
||
|
||
Sample Stopped Mode Entry
|
||
|
||
Each time the user presses the 's' key whether to stop
|
||
execution or to step execution by one step the value of all
|
||
registers is written to the history file.
|
||
|
||
-------------------------------------------------------------------------
|
||
Time=000000.000042 million cycles
|
||
Registers:
|
||
Acc=$01
|
||
Xreg=$FF
|
||
Yreg=$00
|
||
SP=$00
|
||
PC=$F01E
|
||
N V 1 B D I Z C
|
||
0 0 1 0 0 0 0 0
|
||
------------------------------------------------------------------------
|
||
|
||
|
||
Sample NOP Special Execution Entry
|
||
Often a program will contain large areas that contain nothing
|
||
but NOP no operation instructions. Since these instructions do not
|
||
modify memory, registers or program flow, they are given a special
|
||
notation in the history file to save space.
|
||
|
||
-----------------------------------------------------------------------
|
||
NOP Cruise $F005-$F009
|
||
F009 EA NOP (10) 00 FF 00 FF F009=>F00A 10100000 0080=#$????
|
||
-----------------------------------------------------------------------
|
||
|
||
|
||
Option 'i'
|
||
----------
|
||
In software simulation mode, there is no target computer to
|
||
provide NMI or IRQ signals. The simulator provides an option where
|
||
one interrupt signal can be simulated at a user defined frequency
|
||
(period given in clock cycles). This 'signal' can be blocked by the
|
||
interrupt flag in the processor status register. This 'signal' can
|
||
be blocked by the interrupt flag in the processor status register
|
||
and uses the IRQ jump vector so it is a close simulation of the IRQ
|
||
function of the processor.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 16
|
||
|
||
Option 'e'
|
||
----------
|
||
The 'e' end option allows the user to end the simulation
|
||
session. The history file maintained on the disk is closed and the
|
||
simulator returns the use stopped or crashed mode.
|
||
|
||
|
||
The 'n' Notepad Option
|
||
----------------------
|
||
A minor deficiency in the DR6502 program was the necessity for
|
||
the user to constantly be making note of addresses so that they may
|
||
be correctly input to another option of the program etc. Such minor
|
||
note taking has been taken care of by the 'n' option where the user
|
||
is given four lines at the top of the screen (used for errors and
|
||
warnings only) to make notes of any kind. This area of the screen
|
||
is not erased after the user exits the notepad option and may stay
|
||
for quite a while. The contents of the note pad can always be
|
||
called up again if they are erased.
|
||
|
||
|
||
The 'l' List Text File Option
|
||
-----------------------------
|
||
Sometimes the user would like to check a text file for
|
||
information necessary to the debugging of the code under testing.
|
||
Commonly the user would like check the source or listing files from
|
||
the assembly code but this option allows any text file to be
|
||
examined including this documentation file for DR6502.
|
||
The reading of the text file is one way, forward only, with one
|
||
line read for each keystroke. The 'f' key in this mode invokes a
|
||
find or search function. The <ESC> ends this option. On exiting
|
||
this option the user is allowed the option to copy the portion of
|
||
the file displayed into the notepad so that it may be edited and
|
||
redisplayed. Note: there is no facility to copy the contents of the
|
||
notepad back to the file or to a different file so this cannot be
|
||
used for file editing.
|
||
|
||
|
||
Option 'v'
|
||
----------
|
||
The 'v' view memory option allows the user to display portions
|
||
of the 6502 virtual memory to the screen. With this option the user
|
||
can check the data values at any point in the execution of the
|
||
program code. The memory is listed beginning at a user supplied
|
||
address and then the user has the option of paging up and down
|
||
through the memory using the 'u' and 'd' keys.
|
||
|
||
|
||
Option 'd'
|
||
----------
|
||
The 'd' dump data option is conceptually equivalent to the 'v'
|
||
view option. The dump option allows the user to dump the contents
|
||
the 6502 virtual memory to a disk file in hex format for later
|
||
inspection or merging into a TASM source file. This allows the user
|
||
to take data generated by 6502 commands and incorporate it into the
|
||
source code. The 'd' option dumps a section of memory to a disk
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 17
|
||
|
||
file in one of two formats, either in hex format:
|
||
|
||
F000 A9 00 8D 00 02 CD ........
|
||
|
||
for easy (?) interpretation later or in 'TASM' format:
|
||
|
||
.ORG $F000
|
||
.BYTE $A9,$00,$8D,$00,$02,$CD,....
|
||
|
||
for easy merging with the program source code to make it a data
|
||
table. (see Appendix A)
|
||
|
||
The user may also record the data in a 'block' format in the
|
||
data file. The block format is useful for recording memory values
|
||
to be read back into memory later using the 'R' option. The format
|
||
of a 'block' file is as follows:
|
||
|
||
4096
|
||
0, 1, 2, 3, 4, 5, 6, 7
|
||
8, 9, 10, 11, 12, 13, 14, 15
|
||
-1, 0, 0, 0, 0, 0, 0, 0
|
||
|
||
The first number '4096' corresponds to the address in memory,
|
||
in this case $1000 at the beginning of the data block. The numbers
|
||
that follow, in rows of 8, are the values of the memory locations
|
||
sequentially following the beginning address of the data block. The
|
||
last line must begin with a -1 followed by 7 other numbers. All
|
||
numbers (except the -1) must be in the range 0-255.
|
||
|
||
|
||
Option 'R'
|
||
----------
|
||
The 'R' read data option inputs data from disk files into the
|
||
6502 ram memory in a block format (see Option 'd', 'block' output as
|
||
described above). The data file may be produced by DR6502 by the
|
||
'd' option or may be created by a user with a text editor. See the
|
||
'd' option above for details on the format.
|
||
|
||
|
||
Option 'p'
|
||
----------
|
||
The 'p' poke option allows the user to directly write to RAM
|
||
spaces within the 6502 virtual memory map. The user supplies a
|
||
start address and fills in the values in that and successive
|
||
locations by separating the figures with spaces. The user can
|
||
prefix the data with '$' or '%' to indicate hexidecimal format or
|
||
binary format respectively. If no prefix is included, the data is
|
||
assumed to be decimal. Once a prefix is attached to the first
|
||
figure, all other figures input on that line are assumed to be in
|
||
the same format and no further prefixes are required. For example,
|
||
typing:
|
||
|
||
$7f 6a f2 00 37
|
||
|
||
would place $7F in the specified memory location and $F2, $00 and
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 18
|
||
|
||
$37 int and no further prefixes are required. For example, typing:
|
||
|
||
$7f 6a f2 00 37
|
||
|
||
would place $7F in the specified memory location and $F2, $00 and
|
||
$37 in the next 3 memory locations.
|
||
|
||
|
||
Option 'D'
|
||
----------
|
||
The 'D' dump program option is used to dump a disassembled copy
|
||
of the program in a user specified memory range to disk. If symbol
|
||
information is read into DR6502 then the disassembled listing will
|
||
contain symbolic representations for any address references in
|
||
arguments. This allows the user to make changes in the code
|
||
permanent. (See Appendix B: Merging with EDIT/Blackbeard to
|
||
recognize the possibilities here)
|
||
|
||
|
||
Option 'P'
|
||
----------
|
||
|
||
The 'P' (re)program option reads, disassembles and displays 256
|
||
bytes or one page of program code starting at a user selected
|
||
address. The user may then move a cursor '=>' up and down ('u' and
|
||
'd') line by line through the disassembled page. The user may quit
|
||
the 'P' (re)program option with the 'q' key. The '+' key causes the
|
||
simulator to read the Next page of assembly code. If the user would
|
||
like to look at a different part of the code, the 'p' causes the
|
||
simulator to read a new page of code starting at a user specified
|
||
address. Using these commands and the 'u' and 'd' commands this is
|
||
similar to a 'view code' mode however there are other subcommand
|
||
options that allow the user to alter the program at the assembly
|
||
language level.
|
||
|
||
The 'c' change suboption allows the user to input lines of
|
||
assembly code as opcodes and operands. Note that labels and macros
|
||
are not allowed since this is a line by line assembly process. Be
|
||
warned that the change suboption overwrites the bytes of code that
|
||
were in the locations prior to changing. If the change requires
|
||
more than a simple substitution or if the user is not certain that
|
||
the opcode alignment will be preserved after the change then the
|
||
make space option (described below) should be used first.
|
||
|
||
All editing of the code is done in a buffer so that if
|
||
mistakes are made in changes to the code, the actual 6502 memory map
|
||
can be read again to retrieve the original program. The 's' save
|
||
subcommand saves the current page of assembly code back into the
|
||
6502 virtual memory. This does not make the change permanent (to
|
||
the binary file) but will remain for the rest of the session with
|
||
the simulator. If the user would like to make program changes made
|
||
in the simulator permanent then consult the 'D' option of the
|
||
Stopped Mode commands.
|
||
|
||
If the user has made changes to the program in the buffer and
|
||
would like to discard them and reread the program from the 6502
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 19
|
||
|
||
virtual memory then the 'r' reread option is available. This will
|
||
discard any changes that may have been made in 'c' change operations
|
||
but will not discard changes that have been saved with the 's' save
|
||
option. If a virgin copy of the program is required then the user
|
||
must exit the simulator and start over so that the .BIN file can be
|
||
reread.
|
||
|
||
The simulator is capable of reading a file of symbol
|
||
information if one is produced using DRSYM. Whether a file has been
|
||
input or not the user can 'a' assign values to new symbols or 'l'
|
||
label the current memory address with a symbol (as with branch
|
||
labels). The user can search the list of symbols for 'i'
|
||
information, either the symbol assigned to an address or the address
|
||
represented by an symbol. Users may prefer to see or not to see the
|
||
branch line labels in the assembly code and these can be toggled on
|
||
and off by the 'b' option.
|
||
|
||
The user is able to make notes in the notepad with the 'n'
|
||
suboption of the 'P' option. This is the same notepad as is
|
||
accessed from the stopped status screen and is very useful for
|
||
making note of address, labels or diagnostic states.
|
||
|
||
When the user has found that an error has been made and some
|
||
code has been omitted, the 'c' change suboption is not sufficient.
|
||
The user must first open up a space in the program for the omitted
|
||
code to be inserted. The 'm' make space option does just this.
|
||
Here is a graphical representation of the 'make space' process
|
||
|
||
|
||
Program Start Addr > ============= =============
|
||
| | | |
|
||
| | | |
|
||
| A | | A |
|
||
| | | |
|
||
Cut ____|___________| |___________|
|
||
Here | | | |
|
||
| | | NOP Filler|
|
||
| B | Slide down ____|___________|
|
||
| | to here | |
|
||
| | | |
|
||
Program End Addr > ============= | B |
|
||
| | | |
|
||
| | | |
|
||
=============
|
||
|
||
|
||
............. End of Eprom .............
|
||
|
||
Process in Brief:
|
||
|
||
1) Program sections (A+B) are searched for address references to the
|
||
B section (JMPs, JSRs, Branches, Data access like LDA, STA etc).
|
||
The references are adjusted to reflect the relocation of the B
|
||
section of the program.
|
||
Two possible error conditions can arise during this
|
||
adjustment. Relative branches have a maximum length of 128
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 20
|
||
|
||
bytes. If a relative branch forward or backward crosses the cut
|
||
line and the added length of the branch due to the inserted
|
||
section exceeds the maximum length of a branch then an error is
|
||
counted and the branch is recorded as Bxx $FE. This will result
|
||
in an endless loop if the branch is taken but will also be easier
|
||
to find if you have to change it. Absolute addresses must fall
|
||
into the range of $0000-$FFFF. If the user has miscalculated and
|
||
tries to make so much space that the end of the B section of the
|
||
code is pushed off the end of the EPROM space (past $FFFF) then
|
||
another error will occur. If an absolute address plus the offset
|
||
of the move exceeds $FFFF then these are counted as errors and the
|
||
address is recorded as $0000. This would happen for references to
|
||
the part of B that is pushed off the end of the EPROM.
|
||
If any symbol information has been input into DR6502, either
|
||
with a .SYM file at the beginning of the session of during the
|
||
session with the 'a' assign symbol or 'l' label current address
|
||
commands, then these symbols are adjusted as well. The code will
|
||
automatically adjust all address labels that fall into the range
|
||
of code being moved.
|
||
Since labels used to represent constants (as opposed to those
|
||
used to represent addresses) are not present in the symbol table
|
||
as created by DRSYM, the DR6502 system attempts to shield the user
|
||
from the following problem. In the rare instance that the user
|
||
has used the 'a' assign symbol to assign a symbol used as a
|
||
constant AND has assembly code on the zero page AND uses the 'm'
|
||
make space option to move it, the following can be a problem.
|
||
There is the possibility that constant symbols may be confused for
|
||
address labels. If for instance the code being moved was in the
|
||
range $0060-$0090 and a constant label like 'Bit_7_set = $80' is
|
||
assigned by the user during the simulator session, then DR6502
|
||
will mistakenly adjust this label's value interpreting it as an
|
||
address. This has NO EFFECT on the actual code since in the
|
||
memory of the 6502, TASM has already removed the symbols from the
|
||
machine code. This also has NO EFFECT on the disassembled outputs
|
||
produced by DR6502 in the 'D' or 'P' options since constant
|
||
arguments are never substituted for. In the 'D' option however,
|
||
at the beginning of the file produced, DR6502 writes out the
|
||
values of all the symbols in the form of assembly language
|
||
assignment statements. (This allows the 'D' dumped code to be
|
||
reassembled directly if the user desires.) In the list of
|
||
assignments the label 'Bit_7_set = ...' will have an adjusted
|
||
address.
|
||
|
||
2) The slide is performed, regardless of any errors that were
|
||
encountered. The simulator was programmed assuming the user knows
|
||
what they are doing, allowing users who know what they are doing
|
||
to do some very unusual things. If one of the errors mentioned
|
||
above occurs and you were not anticipating it then it may be best
|
||
to end the session and start again with a virgin copy of the
|
||
binary code.
|
||
|
||
3) The space opened up is then filled with NOP instructions. Since
|
||
NOP instructions are one byte long, they can be replaced in the
|
||
'c' change option in reprogramming the code without worrying about
|
||
the opcode alignment. The simulator is optimized to execute a
|
||
memory space filled with NOP instructions very quickly so the user
|
||
need not worry about opening up a little more space than is
|
||
required by the code to be inserted.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 21
|
||
|
||
The 'm' make space subcommand requires the user to input the
|
||
first and last program space addresses to define the space A+B. The
|
||
address of the first opcode of section B is input to define the
|
||
position of the cut. The new address of the first opcode of section
|
||
B is input to define the offset of the relocation. Spaces can only
|
||
be created by this method. If a data table is present then care
|
||
must be taken that it has been handled in one of the ways as
|
||
described below.
|
||
|
||
Address references are CORRECTED for the new location of the
|
||
relocated part of the code but ONLY within a user specified
|
||
'program' area. Herein lies another problem. A program is a thin
|
||
line of opcode alignment; shift by one byte and a program starts
|
||
looking like a random stream of bytes. (See Appendix A for an
|
||
explanation/definition of opcode alignment) Given a valid program
|
||
opcode address as a starting point, a program can be traced and
|
||
address references to the area of relocated code can be adjusted.
|
||
If the program encounters a 'data' space half way through the
|
||
'program' space it is not trivial for the program to determine where
|
||
the data space ends and the program space resumes since op-code
|
||
misalignment can make programs look like data and coincidental data
|
||
may appear to be a program. As a result, if this relocate option of
|
||
DR6502 is to be used one of three arrangements must be used. NOTE:
|
||
the described options are only necessary if DATA (.BYTE or .WORD)
|
||
directives have been included in the eprom.
|
||
|
||
One option is to put user data tables that are to be burned
|
||
into the eprom at the beginning of the eprom before the program
|
||
code. In this case, the user specified 'program' space defined for
|
||
the purposes of address reference adjustments would be specified
|
||
from after the data table to the end of the program. (Note NOT the
|
||
end of the eprom! If the user hopes to create a blank space in the
|
||
program space then the end of the program cannot be specified as the
|
||
last address of the eprom or the memory shift will result in
|
||
'spillage' off the high end of the eprom.)
|
||
|
||
A second option is to put the data directly after the program.
|
||
In this case two things are necessary. First the data must be
|
||
defined as part of the program space so that it is relocated along
|
||
with the code instead of being overwritten. This will also make
|
||
sure that address references to the data table will be corrected.
|
||
At least one non-opcode byte must appear between the program and the
|
||
data table so that when DR6502 encounters this byte it will know a
|
||
data table has started and it will not attempt to interpret any
|
||
bytes that follow as opcodes or operands. Any non-opcode byte would
|
||
do just fine.
|
||
|
||
A third option is to put the data table at the very highest
|
||
address of the eprom, leaving a space between the end of the program
|
||
and the beginning of the data. In this case when defining the
|
||
'program' section, do not include the data. The relocated program
|
||
will move closer to the data when slid toward higher memory to make
|
||
room for more program lines.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 22
|
||
|
||
7) Extended Instruction Set for the 65C02 and Rockwell R65C02
|
||
=============================================================
|
||
|
||
With the development of the AER 201S computer board, which uses
|
||
the 65C02, it became more necessary for DR6502 to handle the
|
||
extended CMOS instruction set. Since the R65C02 is commonly
|
||
available, the specialty Rockwell instructions may also be
|
||
required. The following instructions were therefore added:
|
||
|
||
Branch Bit Reset (R65C02):
|
||
BBR0 zpage,rel ; BBR1, BBR2, BBR3, BBR4, BBR5, BBR6, BBR7
|
||
|
||
Branch Bit Set (R65C02):
|
||
BBS0 zpage,rel ; BBS1, BBS2, BBS3, BBS4, BBS5, BBS6, BBS7
|
||
|
||
BRanch Always (65C02):
|
||
BRA rel
|
||
|
||
PusH/PulL X and Y (65C02):
|
||
PHX, PHY, PLX, PLY
|
||
|
||
Reset memory bit (R65C02):
|
||
RMB0 zpage ; RMB1, RMB2, RMB3, RMB4, RMB5, RMB6, RMB7
|
||
|
||
Set Memory Bit (R65C02):
|
||
SMB0 zpage ; SMB1, SMB2, SMB3, SMB4, SMB5, SMB6, SMB7
|
||
|
||
STore #$00 Zero into a memory location (65C02):
|
||
STZ address mode
|
||
|
||
Test and Reset Bits (65C02):
|
||
TRB address mode
|
||
|
||
Test and Set Bits (65C02):
|
||
TSB address mode
|
||
|
||
Note that no accurate number of clock cycles durations were
|
||
available for the R65C02 instructions so estimates were used based
|
||
on other 6502 instructions.
|
||
|
||
The simple indirect (zpage) address mode was also added for memory
|
||
fetches as per the 65C02 standard. The special address/argument
|
||
structure of the BBSx and BBRx of zpage,rel is also supported.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 23
|
||
|
||
8) Differences Between DR6502 and the R6502, 65C02 and R65C02
|
||
=============================================================
|
||
|
||
Reference 3, Hendrix, details some anomalies in the operation
|
||
of the 6502 in Chapter 6 'Quirks, Bugs and Other Oddities of the
|
||
6502' which will be mentioned shortly. The simulator was not
|
||
programmed intentionally to imitate any of these problems in the
|
||
6502.
|
||
When using the add or subtract instructions in decimal mode on
|
||
the NMOS 6502, the Negative flag, Overflow flag and Zero flags are
|
||
not valid. On the 65C02 they are valid however the instructions
|
||
require one more clock cycle. In the simulator they are valid,
|
||
regardless of 6502 version simulated and the execution clock cycles
|
||
used are correct for the type of processor selected. If the
|
||
simulator is used to simulate an NMOS 6502 using the add and
|
||
subtract in decimal mode and makes use of the N, V or Z flags, the
|
||
simulation will not match the real (errant) execution of the NMOS
|
||
6502.
|
||
When using the indirect jump with a the address of a page (ie:
|
||
ending with $FF), an NMOS 6502 does not fetch the high byte of the
|
||
jump vector from the first byte of the next page but incorrectly
|
||
from the first byte of the current page. In NMOS 6502 mode, the
|
||
simulator flags JMP ($xxFF) as an error because on a 6502 it leads
|
||
to an incorrect jump. It is assumed that no program is designed to
|
||
exploit this error. The 65C02 does the jump correctly requiring an
|
||
addition clock cycle as does the simulator in 65C02 and R65C02 mode.
|
||
The unimplemented opcodes on the NMOS 6502 do unpredictable
|
||
things, sometimes crashing the CPU. The unimplemented opcodes on
|
||
the 65C02 and R65C02 are taken as NOP instructions. All
|
||
unimplemented NMOS 6502, 65C02 and R65C02 instructions are
|
||
interpreted as crash codes by the simulator since it is assumed a
|
||
user will never use an invalid code in the intended program.
|
||
The 6502 has no such thing as an idle bus cycle. In all cycles
|
||
there must be either a read from or a write to memory. The NMOS
|
||
6502, 65C02 and R65C02 all perform an extraneous read when executing
|
||
a absolute indexed addressing mode. The NMOS 6502 reads the next
|
||
byte after the instruction's argument, sometimes causing an error
|
||
with I/O devices that are sensitive to having their port memory
|
||
location read. The 65C02 and R65C02 both read the last byte of the
|
||
present instruction with less chance of such an error. The
|
||
simulator does not perform any extraneous reads.
|
||
The NMOS 6502 does not modify the decimal mode flag in the
|
||
processor status register in a reset operation or an interrupt. The
|
||
65C02 and R65C02 does clear the decimal mode flag in these two
|
||
cases. The simulator clears the decimal flag for all resets
|
||
regardless of the processor chosen. The simulator clears the
|
||
decimal flag on interrupts only in the case of 65C02 and R65C02
|
||
processors.
|
||
The NMOS 6502 requires 7 machine cycles to perform an absolute
|
||
indexed read/modify/write operator type instruction such as INC, ASL
|
||
or ROR. The 65C02 and R65C02 requires only 6 cycles to do the same
|
||
instructions in that particular addressing mode. The simulator uses
|
||
the correct number of cycles in each case.
|
||
The NMOS 6502 does not save any information on receiving a
|
||
reset signal. The 65C02 and R65C02 saves information on reset
|
||
consistent with an interrupt signal. The simulator does not save
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 24
|
||
|
||
any information on reset regardless of which processor it is
|
||
emulating.
|
||
In read/modify/write operator instructions such as DEC, LSR or
|
||
ROL there is an 'idle' bus cycle during the modify operation. As
|
||
mentioned above there is no such thing as an idle cycle for the
|
||
6502, either a read or a write must be performed. In the case of
|
||
these type of instructions, either a read or a write is performed in
|
||
the modify cycle to the address that will be written to on the
|
||
following cycle. Once again, unnecessary reads or writes can cause
|
||
problems with peripheral ports. The simulator does not do the
|
||
extraneous read or write.
|
||
|
||
Summary
|
||
-------
|
||
All of the above cases where the simulator deviates from the
|
||
processors, the instances are rare or the true behaviour is
|
||
undesirable. Any other deviations from the simulation of the actual
|
||
behaviour of the processor chosen is an error in the simulator.
|
||
Though not many such errors are likely to exist in the program,
|
||
there are undoubtedly a few left. Such errors will be fixed as soon
|
||
as they are identified by a user or a user supplies a minimum length
|
||
program (5-10 lines) and the simulator commands that will cause the
|
||
error every time.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 25
|
||
|
||
9) DR 6502 Support Files
|
||
========================
|
||
|
||
List of Files Necessary to the Operation of the Simulator
|
||
---------------------------------------------------------
|
||
DR6502.EXE - Main executable code of the simulator
|
||
OVERLAY1.EXE - Second module of the simulator program
|
||
CONFIG.EXE - Creates Memory Map 'CONFIG' files for your target
|
||
BLANK.BAS - A file used to initialize the 6502 virtual memory
|
||
CINST.SET - 6502, 65C02 and R65C02 Instruction sets
|
||
DRSYM.EXE - Symbol table preparation program
|
||
DRSYM.BAS - The BASIC source code for DRSYM.EXE
|
||
MM.COM - Utility to display memory allocation
|
||
MARK.COM - A memory resident utility whose purpose is to
|
||
mark a point in memory
|
||
RELEASE.COM - A memory utility used to release all memory
|
||
resident programs added after the last mark
|
||
in memory
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 26
|
||
|
||
10) References
|
||
==============
|
||
|
||
1) Commodore 64 Reference Manual, Chapter 5: Machine Language,
|
||
pp209-259
|
||
|
||
2) The Transactor, Volume 4, Issue 05, pp52-53 (Reprinted in your
|
||
handouts)
|
||
|
||
3) Steven P. Hendrix, The 6502, 65C02 and 65816 Handbook, Weber
|
||
Systems Inc., Cleveland, Ohio, 1986, pp221-227
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 27
|
||
|
||
Appendix A: OpCode Alignment
|
||
============================
|
||
|
||
Note that the 65C02 will not necessarily have the same problems
|
||
as a 6502 with opcode alignment, it will have worse problems
|
||
actually. Please read on and the differences will be explained.
|
||
So you aren't quite clear on what exactly I mean by opcode
|
||
alignment. Consider this question: How many groves are there in the
|
||
average phonograph record? The answer is one (or maybe two - one on
|
||
each side). This is a very unique condition if you think about it:
|
||
Put the needle down anywhere and the record will always play the
|
||
same series of songs. A few years back there was at least one
|
||
novelty record made where there were two groves, two possible series
|
||
of songs depending on the original placement of the needle on the
|
||
record. This record is conceptually similar to an assembly program,
|
||
where the songs represent the instructions in the program. The
|
||
series of songs played depends on the starting point on the record,
|
||
whether grove one or two is chosen. There are only two possible
|
||
'programs' available to the listener. Only the radial starting
|
||
point in the record determines what portion of two 'programs' are
|
||
played. An assembly language program however is more closely
|
||
comparable to a Snakes and Ladders game with rich interconnections
|
||
than to the sequential nature of a recording.
|
||
I know, you are saying hold on now, I have only one program, I
|
||
used the assembler, where is this other program you are talking
|
||
about? Well you are absolutely right, you have only one program: in
|
||
assembly. In machine code it is just numbers in an EPROM. Try
|
||
looking at machine code even when you know what is supposed to be
|
||
there: the program is not obvious. The key point is recognizing
|
||
what bytes represent opcodes and what bytes represent operands. To
|
||
the human eye opcodes, 'pop' out from inspection. A9 - LDA; 8D -
|
||
STA; 20 - JSR Your brain sees these and recognizes the pattern. The
|
||
6502 is not blessed with this ability to 'see' what are opcodes and
|
||
what are not. All it knows is the next byte it fetches will be an
|
||
opcode, then the operands, then another opcode. Where you start
|
||
determines what the 6502 interprets as the first instruction and the
|
||
course of the program from then on. Using an assembler assures that
|
||
opcodes will be in the right spot at the right time and things will
|
||
go just fine, provided no .BYTE directives are placed in the middle
|
||
of a piece of code. The problem arises when the user starts hacking
|
||
around with a piece of software with a tool like DR6502. If the
|
||
code has an error or if the user messes up the program, an operand
|
||
may be fetched instead of an opcode and all of a sudden the 6502 is
|
||
executing a very different program.
|
||
So just how many of these alternate universe programs are there
|
||
in a given piece of machine code? Well, if you have 4k of code, if
|
||
we take 35-50% of those bytes to be opcodes and the rest operands
|
||
then there are a good 2000 possible alternate universes that your
|
||
6502 could fall into. There is some good news and some bad news.
|
||
These alternate programs are very unstable (and erratic) and they
|
||
usually do one of two things after a few opcode fetches. They
|
||
either crash (that's the good news, because you know you have a
|
||
problem) after fetching an bad opcode or they fall back in line with
|
||
the proper opcode alignment and things go back to normal. This is
|
||
very bad since you may have a 'mysterious' error that you have no
|
||
idea what is going on with. Now what are the probabilities for all
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 28
|
||
|
||
of this? Of all the 256 opcodes, about 151 correspond to valid
|
||
opcodes, about 35 crash the CPU outright and the other 70 or so are
|
||
weird combinations of incrementing and adding with strange flag
|
||
results. In a real 6502 system, the CPU has a (151+70)/256 chance
|
||
of continuing to execute. Upon the completion of each opcode there
|
||
is the chance that the proper opcode stream may be rejoined. The
|
||
chance therefore of an outright crash is low. The bottom line: this
|
||
is bad news.
|
||
Someone, in a stroke of genius, said lets make the 65C02
|
||
better. Lets make all of the undefined opcodes behave as NOP's.
|
||
The 65C02 can NEVER crash. After hopping into the wrong opcode
|
||
alignment, the 65C02 will execute a maximum of two undefined opcodes
|
||
in a row before rejoining the proper opcode alignment. The
|
||
difficulty is that the 65C02 has a great number more defined opcodes
|
||
so a 'strange' program will execute for a long time before hitting
|
||
an undefined opcode, executing a NOP and rejoining the proper opcode
|
||
stream (possibly). If you are operating DR6502 and have used only
|
||
regular 6502 instructions then you should use DR6502 in 6502 mode.
|
||
This will cause the simulator to object to a wider array of mistakes
|
||
and more quickly.
|
||
The overall landscape of a section of machine code if compared
|
||
to a record would have a great many possible paths threading near
|
||
the intended opcode path. The alternate paths would be short lived
|
||
in general and would most frequently rejoin the main path but would
|
||
occasionally dead end in a crash. The Snakes and Ladders
|
||
interpretation necessary when considering loops in the real code and
|
||
accidental branches, JMPs, RTS, JSR statements in the parallel codes
|
||
would not look very different since a quick count gives only
|
||
(8+1+2+2)=13 program counter modifying opcodes out of the 151 legal
|
||
codes. If the proportion is the same for the illegal 70 or so codes
|
||
then the chances of an accidental jump is only about 1 in 10. These
|
||
instances are catastrophes since the destination (by Murphy's Law)
|
||
is nearly always a pure data space where there is no opcode line to
|
||
be rejoined and the results can be very erratic.
|
||
|
||
In summary: How do you get off track and how to avoid it? The
|
||
easiest way is to push data into the stack in a subroutine and
|
||
forget to pull it off again before executing an RTS (frightfully
|
||
common error). Mishandling interrupts, etc could be a real problem
|
||
usually in the misbalance of the stack and return addresses. Doing
|
||
little tricks like using the address pushed on the stack after a JSR
|
||
in a calculation and returning the wrong number to the stack or
|
||
using calculated JMPs using a push and RTS method and messing up the
|
||
address etc would do it too. If you use DR6502 you could do it in
|
||
one careless p-poke command or not watching what you are doing while
|
||
using the P-program command. The best way to avoid the alignment
|
||
problem is knowing it exists and being very careful of the stack and
|
||
changes to the program.
|
||
|
||
An exercise: If you want to see what an alternate universe
|
||
program looks like, invoke the P-program function on DR6052 with a
|
||
program loaded. If your code starts at $E000 try giving DR6502 the
|
||
page start address of $E000+a random number that does not correspond
|
||
to an opcode address and observe the results. 105/256 opcodes will
|
||
show up as .BYTE directives which means you have no idea what a real
|
||
6502 would do. 70% of the time it will do something, with some
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 29
|
||
|
||
operands and lead to another opcode fetch. 30% of the time
|
||
(anything $x2 or $xF is usually a crash) it will lead to a crash.
|
||
DR6502 traps all undefined opcodes as errors and halts execution.
|
||
|
||
The 65C02 was improved to define all undefined opcopes to be
|
||
NOPs so that alternate program streams will never crash the system.
|
||
As pointed out before, the alternate program lines that rejoin the
|
||
main program line are more mysterious and dangerous than ones that
|
||
crash the computer outright. DR6502 still considers all
|
||
non-allocated 65C02 opcodes as crashes and halts the 'processor'.
|
||
This is done because in the actual program such codes should never
|
||
occur and when they do it is a sure sign that something is wrong.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
page 30
|
||
|
||
Appendix B: Merging with EDIT/Blackbeard
|
||
========================================
|
||
|
||
You have probably found yourself reading this because you have
|
||
a section of 'invented' assembly that you made up to patch a bug
|
||
found while using DR6502 in one file and your original code in
|
||
another file. The merging process is a simple one:
|
||
|
||
|
||
1) edit the original file
|
||
2) ctrl-F2 to switch to window #2 (see Windows-Switch-window#2 in
|
||
ESC help menus)
|
||
3) ctrl-n to select a new file for window #2 (see Files-Newfile in
|
||
help) and enter the filename of the 'invented' section of code.
|
||
4) 'Copy' the desired section of the code from the 'invented' file
|
||
using f1 to mark the top of the range, f2 to mark the line after
|
||
the end of the range, f3 to copy this range into the paste
|
||
buffer. (transfer smaller blocks if the whole block is too large
|
||
for the paste buffer - shift f9 clears the paste buffer)
|
||
5) ctrl-f1 to switch back to window#1 where the original source code
|
||
is.
|
||
6) Cursor to the line that the range is to be inserted before and
|
||
press f7.
|
||
7) Make what ever other changes are necessary and
|
||
8) ctrl-z to save!
|
||
|