-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathproc_kim.a65
151 lines (128 loc) · 4.26 KB
/
proc_kim.a65
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
; This program looks at ways to determine which type of 6502-series
; processor you are using. This version runs on the PAL-1 (a KIM clone).
;
; By Jim McClanahan, W4JBM, January 2021
;
; Build with:
; $ 64tass --intel-hex proc_kim.a65 -o proc_kim.hex -m --verbose-list -L proc_kim.lst
; $ srec_cat proc_kim.hex -intel -o proc_kim.mos -MOS_Technologies
;
;
; For whatever system we use, we need two routines defined:
;
; *** KIM ROM Routines ***
;
; A routine to send a byte to the console...
xOutpt = $1EA0 ; Send one byte to the output port (OUTCH)
;
; ...and the reset vector to restart the system.
xReset = $1C4F ; Cold start of the system (START)
; Define any constants we want to use...
CR = $0D
LF = $0A
; Location isn't particularly important...
* = $0200
; Set up the stack
;
; This is not needed if called from a monitor
;STACK: LDX #$FF
; TXS
; First, let's see what happens to the Zero flag in
; the decimal mode
TEST1: SED ; Set Decimal (BCD) Mode
CLC ; Clear the Carry Flag
LDA #$99 ; Load a BCD 99 (which is also $99)
ADC #$01 ; ...and add 1
PHP ; Push processor status byte to stack
STA TSTR1 ; Store the result in memory
CLD ; Because we don't want to forget
; At this point, the Acc is $00 but the original 6502 did not
; set the Zero flag when this happened in the decimal mode
; while the later R6502 and 65C02 did.
BEQ TEST1B
TEST1A: LDA #MSG1&255 ; Point to Message 1
STA PRINT+1
LDA #MSG1/256
STA PRINT+2
JSR SHWMSG ; Display result (no Z flag)
JMP TEST2
TEST1B: LDA #MSG2&255 ; Point to Message 2
STA PRINT+1
LDA #MSG2/256
STA PRINT+2
JSR SHWMSG ; Display result (Z flag set)
; On the original 6502, undefined instructions could do various
; (and sometimes seemingly unpredictable) things. On later versions,
; some of the unused instructions were pressed into use while others
; were changed to be a "safe" NOP (no operation).
;
; $EA is NOP and on the original most of the $xA instructions also
; act as NOPs. $1A is one that seems to be a well-behaved NOP, but
; the R6502 and 65C02 used that previously undefined code to
; implement an INC A instruction.
;
; The following code checks to see what $3A does...
TEST2: PLA ; Before the test, let's story the processor
STA TSTR2 ; results from the last test.
LDA #$FF ; Load the accumulator
.BYTE $1A ; Either a NOP or INA (similar to INX and INY)
EOR #$0 ; Let's make sure the flags are set
PHP ; Save the processor status register
STA TSTR3 ; Store result in memory
BEQ TEST2B ; Does A == 0?
TEST2A: LDA #MSG3&255 ; If not, Point to Message 3
STA PRINT+1
LDA #MSG3/256
STA PRINT+2
JSR SHWMSG
JMP FINISH
TEST2B: LDA #MSG4&255 ; Point to Message 4
STA PRINT+1
LDA #MSG4/256
STA PRINT+2
JSR SHWMSG
FINISH: PLA ; Let's store the processor status
STA TSTR4 ; from the last test.
JMP xReset ; We're done so jump back to the monitor
; RTS ; ...depending on the system, RTS may work
; If you don't want to go to the monitor, you can loop instead...
;LOOP: JMP LOOP ; Now just loop endlessly...
; Display a null-terminated message...
SHWMSG: LDX #$0 ; Show Message Subroutine
PRINT: LDA MSG1,X ; SELF MODIFYING Address and Offset
BEQ DONE ; Did we just load a $00 end-of-string?
JSR xOutpt ; If not, print it
INX ; Point to next character
BNE PRINT ; Branch to do it again...
DONE: RTS ; Jump here at end-of-string or 256 characters
;
; If we don't have console output, you can get information on
; what happened by looking at the results stored here.
;
; 7 4 3 0
; ---- ----
; NVbb DIZC
;
; N - Negative
; V - oVerflow
; D - Decimal mode
; I - Interrupt disable
; Z - Zero
; C - Carry
;
; bb should be %11 (usually a $3x in these tests) to show the
; status was pushed to the stack using PHP and not the result
; of an interupt.
TSTR1: .BYTE $55 ; Result in Decimal mode of $99 + $01
TSTR2: .BYTE $55 ; ...and process status register
TSTR3: .BYTE $55 ; Result of $FF and then executing NOP/INC A
TSTR4: .BYTE $55 ; ...and the process status register
; TSTR1, TSTR2, TSTR3, and TSTR4 should be:
; $00 $39 $FF $B0 for the original 6502
; $00 $3B $00 $32 for the 65C02
; Our messages follows...
MSG1: .NULL CR,LF,"DEC Add does not set Z. (Orig 6502)",CR,LF
MSG2: .NULL CR,LF,"DEC Add did set Z. (65C02)",CR,LF
MSG3: .NULL "$1A acts as a NOP. (Orig 6502)",CR,LF
MSG4: .NULL "$1A acts as INC A. (65C02)",CR,LF
.END