-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path65816primer.html
More file actions
2779 lines (2243 loc) · 127 KB
/
65816primer.html
File metadata and controls
2779 lines (2243 loc) · 127 KB
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<html>
<head>
<title>65816 primer</title>
<link rel="stylesheet" type="text/css" href="./index.css" />
</head>
<body>
<table>
<tr>
<td>
<pre>
A 65816 Primer
[----------------------------------------------------------]
No republication or redistribution of the following is permitted without
the authors express written consent.
Table of Contents
------------------------------------------------------------------------
i Preface
1.00 Introduction
2.00 New 65816 Instructions
3.00 65816 Native Mode Programming Model
3.01 Native Mode Processor Status Register
3.10 Native Mode Registers
3.11 Accumulator:
3.12 X,Y Index Registers
3.13 Direct Page Register (D)
3.14 Stack Pointer (S)
3.15 Program Bank Register (PBR)
3.16 Data Bank Register (DBR)
3.20 Status Register
3.21 Emulation Bit E: Hidden Bit
3.22 Sixteen BIT User Registers
3.23 Index Register Select
3.24 Accumulator/Memory Select
3.30 Setting Status Register Bits
4.00 65816 Emulation Mode Programming Model
4.10 Emulation Mode Registers
5.00 Relocating the Stack and Direct Page
6.00 Addressing Modes
6.10 New 65816 Specific Addressing Modes
6.20 Addressing Mode Descriptions
7.00 Interrupts
7.10 Hardware Vectors
Appendix A: 65816 Instruction Set
Appendix B: Composite Instruction List
Appendix C: IC Pinouts
Disclaimer:
Some of the following information was referenced with various documents and
public documentation available for the Apple IIGS computer system and the
Super NES game console system via the world wide web and other user group
publications. No claim is made or intended against any copyrighted
information that may be contained within this document. The main
sub-content that could be construed as a copyright infringement, would be
the usage of mnemonic tables and the similarity of programming models.
Although these tables were built specifically for this project, it is
unclear what the legal status of mnemonic information is at present. Brett
Tabke 1997
This document is intended to aid those programming the 65816 Processor from
The Western Design Center. This chip is the basis for the Apple IIGS, the
Creative Micro Designs SuperCPU addon cartridge for the Commodore 64 & 128,
and the Super NES game console that are all based around the 65816 micro
processor.
------------------------------------------------------------------------
Preface
This document was pulled from several chapters of book project I had
started. I'd intended to publish a small booklet on programming the CMD
Super CPU cartridge detailing the operation of the 65816 - however, I have
been unable to acquire a release to republish some critical information.
So, the following is a few chapters that I feel are worthy of public
disclosure and distribution.
HTML Conversion Notes
This document was originally in IBM CG/ANSI format and the conversion to
HTML was marginal. Even with the file being fairly generic text, four
different browsers rendered it differently. Lynx 2.7 and Lynx 2.6 will not
render it the same - I tried to strike a happy medium - your mileage may
vary.
TOC
[ Image Jet ]
------------------------------------------------------------------------
1.00 Introduction
-----------------
Welcome to the world of 65816 programming. The 65816 is an advanced upgrade
to the vintage 6502 Central Processing Unit. The main new features include
full 24 bit addressing for direct memory access of up to 16 megabytes.
Additionally, the 65816 offers full 6502 emulation, new addressing modes,
full 16 bit user registers, and dozens of new instructions.
If you have been a 6502 programmer for long, the advantages of the 65816
will become clear very quick. Regardless of CPU operating speed (mhz) a the
65816 will operate a bit faster simply by the nature of the 16 bit user
registers. By using 16 bit registers for operations such as addition and
subtraction the 65816 also offers the programmer a substantial speed
increase.
The following document is not meant as a definitive guide to programming
the 65816, but rather a primer for those who are familiar with the 6502 and
wish to find the new 65816 (good) stuff.
The 65816 offers two primary modes of operation, Native 65816 Mode and 6502
emulation mode. The default power-up status of the processor is in 6502
emulation mode. Other than correcting a few bugs in the 6502, emulation
mode "looks and feels" just like a 6502.
There are a few notable differences between the 65816's emulation mode and
the original 6502. The 6502 opcodes that were unimplemented, are now
available as additional instructions on the 65816, thus they will not
produce the results they do on a stock NMOS 6502 CPU. The 65816 implements
ALL of the available 256 opcodes, whether in emulation or Native mode.
Also different between a 6502 and emulation mode is that the indirect jump
JMP ($XXXX) bug that caused the processor to retrieve the wrong data when
the low byte was $xx has been fixed.
While in emulation mode, the 65816's Direct (zero) Page register is set for
zero. The Stack pointer high byte is set for one (just as a 6502). The
Program and Data Bank Registers are initialized to zero. Timing of all
instructions is identical.
While in Native mode, the processor has full access to the 16 megabyte
address space via 24 bit addressing. Native mode also makes available
several new and extended processor registers. The 65816 has the ability to
relocate the Stack and Zero Page any where within the first 64k bank of
memory. For old Commodore 128 programmers, this will sound suspiciously
like the 128's Memory Management Units ability to relocate zero page and
the stack also - so it will be old hat from the start. (On a side note, it
will be interesting to program on CMD's Super CPU 128 - which will give you
a Relocatable Relocatable Zero Page and Stack. hmmm ;)
Native mode also opens up the world of 16 bit user registers. The
accumulator may be 8 or 16 bits and the XY index registers may also be 8 or
16 bits. The accumulator maybe seen in terms of two 8 bit registers with
one accessible and the other hidden, or as a full 16 bit register. While
the accumulator is set for 16 bits, memory is also treated in 16 bit (2
byte) fashion.
Two other new registers are the Data Bank Register and the Program Bank
register. The Program Bank Register functionally extends the program
counter out to 24 bits, while the Data Bank register allows code flow
control to branch or jump to points outside of the 6502's 64k address
space.
Lastly, while in Native mode the status register of the 65816 includes
several new bits. The old BRK bit is no longer needed as the 65816 has a
BRK hardware vector. The BRK bit is now replaced with the X bit to select
either 8 or 16 bit index registers. However while in emulation mode, the
BRK bit is still there. The old "reserved" bit 5 of the status register is
replaced with the 16/8 bit accumulator/memory select bit. There is also a
hidden emulation bit that is only accessible by exchanging it will the
carry flag.
Here is a run down of some of the new fun stuff:
* XYA registers can be 16 or 8 bits wide.
* Wow, two actual Block Move Memory instructions.
* New push/pull instructions phx,plx,phy,ply.
* New xfer instructions tyx,txy.
* Set or Reset any memory bit without loading the accumulator.
* INC and DEC the accumulator.
* JSR indirect, Branch Always, or Branch Long to 64k.
* Zero Page has been renamed to Direct Page. Like many strange things,
this will be totally confusing at first. The only thing you can do is,
"get over it and get on with it".
TOC
2.00 New 65816 Instructions:
----------------------------
There are some new instructions worthy of short detail:
New transfer instructions include:
TXY,TYX xfer between x and y.
TCD,TCD xfer between the accumulator and direct page pointer(D).
TCS,TSC xfer between the accumulator and stack pointer(S).
XBA exchange the low 8 bits (a) and the high 8 bits
of the accumulator.
XCE exchange the contents of the emulation bit (E) with
the contents of the carry flag (C).
New Stack pushes and pulls:
PHX,PHY,PLX,PLY push and pull the XY index registers.
PHB,PLB to push/pull the data bank register.
PHK to push the program bank register (no pull present)
PHD,PLD to push/pull the direct page register.
PEA to push effect absolute address.
PEI to push effective indirect address.
PER to push effective relative address.
Misc:
MVN Move block in negative direction.
MVP Move block in positive direction.
STZ Store a zero to any location.
BRA Branch always.
BRL Branch to any address in bank 0 (64k).
RTL Return Long. Pulls one more byte. (pc bank byte)
As you can see, there is plenty new to digest. The remainder of this
document will assume prior 6502 knowledge. Lets go.
TOC
------------------------------------------------------------------------
==========================================
3.00 65816 Native Mode Programming Model
==========================================
------------------------------------------------------------------------
Bits:23 15 7 0
/--------------------l-------------------\
IAccumulator (B) (A or C) Accumulator (A)I
\--------------------I-------------------/
/--------------------------\
I Data Bank Register (DBR) I
\--------------------------/
/--------------------l-------------------\
I X Index I Register (X) I
\--------------------I-------------------/
/--------------------l-------------------\
I Y Index I Register (Y) I
\--------------------I-------------------/
---------------------------/--------------------l-------------------\
| 0 0 0 0 0 0 0 0 I Direct I Page Pointer (D) I
---------------------------\--------------------I-------------------/
---------------------------/--------------------l-------------------\
| 0 0 0 0 0 0 0 0 I Stack I Pointer (S) I
---------------------------\--------------------I-------------------/
/---------------------------l--------------------l-------------------\
IProgram Bank Register(PBR) I Program I Counter (PC) I
\---------------------------I--------------------I-------------------/
===================================
3.01 Processor Status Register (P)
===================================
Bits 7 6 5 4 3 2 1 0
/---\
I e --- Emulation 0 = Native Mode
/---l---l---l---l---l---l---+---I
I n I v I m I x I d I i I z I c I
\-l-I-l-I-l-I-l-I-l-I-l-I-l-I-l-/
I I I I I I I \-------- Carry 1 = Carry
I I I I I I \------------- Zero 1 = Result Zero
I I I I I \---------- IRQ Disable 1 = Disabled
I I I I \------------- Decimal Mode 1 = Decimal, 0 = Binary
I I I \-------- Index Register Select 1 = 8-bit, 0 = 16-bit
I I \-------- Memory/Accumulator Select 1 = 8-bit, 0 = 16 bit
I \----------------------------- Overflow 1 = Overflow
\--------------------------------- Negative 1 = Negative
65816 Native Mode Programming Model
TOC
======================================
3.10 Native Mode Registers
======================================
3.11 Accumulator
-----------------
Although shown as a 16 bit register, it may be either 16 or 8 depending on
the status of bit 5 (memory/accumulator select) of the status register bit
designated M.
When in 8 bit mode (M=1) then the accessible low order 8 bit accumulator is
designated as A and the hidden but exchangeable is designated B. When in
full 16 bit accumulator mode (M=0) then the accumulator is designated as C.
3.12 X,Y Index Registers
-------------------------
The X and Y index registers are 8 or 16 bit selectable. When status
register bit 4 designated X is set to 1 then 8 bit registers are selected.
When set to 0 then 16 bit registers are selected.
TOC
3.13 Direct Page Register (D)
------------------------------
This register is formerly known as Zero Page. The Direct Page pointer
specifies where in the first bank of 64k Direct Page (zero page) will be
located. The Direct Page may be moved to ANY location within Bank 0.
The Bank byte (bits 16-23) is shown in a dashed line to represent the fact
that the Direct Page is always located within bank 0.
3.14 Stack Pointer (S):
-----------------------
Like the Direct (zero) Page Pointer, the Stack is now totally relocatable
within Bank 0 (first 64k) of memory. The Bank byte (bits 16-23) is shown in
a dashed line to represent the fact that the Stack is always located within
bank 0. While in Native Mode the stack is not restricted to 256 bytes in
length.
while in emulation mode (e=1) the stack is located at page 1.
TOC
3.15 Program Bank Register (PBR):
---------------------------------
Much like the DBR below, the Program Bank Register is used to specify
address's above and beyond the 6502 64k limit. The PBR is referred to as
the Bank Byte or the highest 8 bits of the Program Counter. Flow control
instructions such as JSR and JMP, may jump to full 23 bit address's. The
PBR is used to specify the highest order 8 bits of the effective address.
However; relative branches do not roll out of the current bank. Branch
commands that branch across $FFFF roll back into the current bank. Also;
program segments may not cross bank boundaries - the program counter goes
from $FFFF to $0000 during such and occurrence.
3.16 Data Bank Register (DBR):
------------------------------
Certain addressing modes take advantage of the 65816's ability to address
up to 16meg of data. Those modes that retrieve and store data to absolute
16 meg/(24 bit address's use the DBR as the top 8 bits of the effective
address. The DBR is also referred to as the Data Bank Byte. The term Bank
Byte is used so that High Byte still refers to bits 8-15 of a given
location or register.
When indexed addressing mode branch across 64k bank boundaries, DBR is
temporarily incremented.
TOC
3.20 Status Register
=====================
The status register bits 7,6,3,2,1,0 (nvdizc) function the same as the 6502
status register bits.
The B break bit is no longer needed to detect a BRK. Instead a new hardware
vector has been implemented to direct code flow to a OS ROM handler in the
same way as an IRQ. However, while in emulation mode (E=1) BRK and the B
bit work as a 6502 does.
3.21 Emulation Bit E: Hidden Bit
--------------------------------
The emulation status bit E specifies whether the processor is in 6502
emulation mode or Native 65816 mode. 1=emulation. The processor powers up
in default 6502 emulation mode. When in 6502 emulation mode, the processor
is functionally a 6502. With the exceptions of un implemented opcodes, all
other opcodes perform identically to their true 6502 counter parts. In
emulation mode, the stack is defined as page one, direct page is defined as
page zero, and the Data Bank and Program Bank bytes are set to zero. The
additional 65816 opcodes are also available in emulation mode.
The emulation status bit is a hidden or phantom bit that is not directly
set, tested, or cleared. Therefore, a new instruction is used to exchange
the values of the carry bit and the emulation bit (XCE:eXchange Carry with
emulation bit). After exchanging, the carry can be tested to determine the
previous status of the E bit.
To switch to Native Mode use the following:
clc ;clear carry to zero.
xce ;exchange (swap) carry with the emulation bit.
To return to Emulation mode:
sec ;set carry to one.
xce ;exchange (swap) carry with the emulation bit.
TOC
3.22 Sixteen BIT User Registers
--------------------------------
The main advantage of the 65816 over the 6502 is that the Accumulator and
the XY index registers can be toggle between 8 and 16 bits wide. The width
of the Accumulator and the XY registers are independently selectable. Thus
you may select any combination of either:
16 bit accum. m=0 - 16 bit XY regs x=0
16 bit accum. m=0 - 8 bit XY regs x=1
8 bit accum. m=1 - 16 bit XY regs x=0
8 bit accum. m=1 - 8 bit XY regs x=1
When the accumulator is switched from or to 16 bits, the high order byte is
retained in either direction.
When the XY registers are switched from 16 bits to 8 bits, the high byte
(bits 8-15) are lost. When switching the XY registers to 16 bits, the high
byte becomes a zero.
TOC
3.23 Status Bit 4 X: Index Register Select
-------------------------------------------
Bit 4 of the status register selects either 8 bit or 16 bit XY index
register operation. When x=1 (8 bit), the XY registers function identically
to the 6502 index registers.
When x=0 (16 bit), both the X and Y registers become 16 bits wide. All
operations involving the X and Y registers act on all 16 bits of the index
register.
When switching from 8 to 16 or 16 to 8 bit index register, the high byte of
either X or Y will be come zero.
While in emulation mode (E=1) bit 4 is the B BRK flag bit.
TOC
3.24 Status Bit 5: Accumulator/Memory Select
---------------------------------------------
Bit 5 specifies whether the accumulator will be treated as an 8 bit or 16
bit register. When in 16 bit mode (m=0) all operations involving the
accumulator will act upon 16 bits of data. Such as, when in 16 bit mode, a
standard load (lda $1000) will load the load by ($1000) in the low order 8
bits of the accumulator and load ($1001) into the high order of the
accumulator.
When switching the accumulator from 16 to 8 or from 8 to 16 bits, the high
byte is perfectly retained. While in 8 bit mode, the high byte of the
accumulator (B) maybe exchanged with the low byte with the XBA instruction.
While in emulation mode, bit 5 is not present.
TOC
3.30 Setting Status Register Bits
----------------------------------
Two new instructions have been added to 65816 Native mode to set and reset
bits of the status register. The two instructions are SEP (set processor
status bits) and REP (reset processor status bits). They both use a single
byte operand to specify which bits should be set or reset. For example to
set bit 4 of the status register to 1 for 8 bit registers:
SEP #%00010000 ;set bit 4.
Or to clear bit 4 for 16 bit XY index registers:
REP #%00010000 ;reset (clear) bit 4.
You may set or reset more than 1 bit at a time. For example, to set both 16
bit accumulator/memory and 16 bit XY registers use the following:
REP #%00110000 ;set 16 bit accum/xy registers.
------------------------------------------------------------------------
=============================================
4.00 65816 Emulation Mode Programming Model I
=============================================
------------------------------------------------------------------------
Bits:23 15 7 0
--------------------l-------------------\
|Accumulator (B) (C) Accumulator (A)I
--------------------I-------------------/
/--------------------------\
I Data Bank Register (DBR) I
\--------------------------/
/-------------------\
I X Index Register I
\-------------------/
/-------------------\
I Y Index Register I
\-------------------/
---------------------------l--------------------l-------------------\
| 0 0 0 0 0 0 0 0 I Direct I Page Pointer (D) I
---------------------------I--------------------I-------------------/
---------------------------l--------------------l-------------------\
| 0 0 0 0 0 0 0 0 I 0 0 0 0 0 0 0 1 I Stack Pointer (S) I
---------------------------I--------------------I-------------------/
/---------------------------l--------------------l-------------------\
IProgram Bank Register(PBR) I Program I Counter (PC) I
\---------------------------I--------------------I-------------------/
4.10 Emulation Mode Registers
=============================
TOC
Emulation Mode Processor Status Register (P)
--------------------------------------------
Bits 7 6 5 4 3 2 1 0
/---\
I e --- Emulation 1 = 6502 Emulation Mode
/---l---l---l---l---l---l---+---I
I n I v I I b I d I i I z I c I
\-l-I-l-I---I-l-I-l-I-l-I-l-I-l-/
I I I I I I \-------- Carry 1 = Carry
I I I I I \------------- Zero 1 = Result Zero
I I I I \---------- IRQ Disable 1 = Disabled
I I I \------------- Decimal Mode 1 = Decimal, 0 = Binary
I I \------------ Break Instruction 1 = BRK caused IRQ
I I
I \----------------------------- Overflow 1 = Overflow
\--------------------------------- Negative 1 = Negative
65816 Emulation Mode Programming Model.
TOC
The above 6502 emulation mode Programming Model shows some interesting
features of the 65816 while in emulation mode. Even though 16 bit index
registers are not available in emulation mode, you can still do the
following:
* Relocate Direct Page.
* Use the stack addressing modes.
* Swap the lower A accumulator with the hidden B accumulator.
* The Program and Data Bank Registers can be changed.
* Use the new instructions.
Things lost or changed in Emulation mode verses Native mode:
* The ability to use 16 bit user registers. The M and X bits of the
status register are returned to their 6502 form.
* The utility of the Block Move instructions. Block Move instructions
use the index registers to specify the source and destination
address's of a move - with only 8 bits available in emulation mode,
you can only move data within zero page because the high byte will
always be zero.
* Zero page addressing "wraps" in emulation mode, whereas in Native mode
it rolls into the next page.
* The stack pointer is ALWAYS on page one.
When switching from emulation to native mode the processor replaces the B
BREAK flag and bit 5 with the 65816 M and X flags, and sets them to one.
This leaves the index registers and accumulator/memory into 8 bit mode
(which is the same as emulation mode). The remaining bits in the status
register are unchanged. The stack pointer remains at page one.
When switching from native mode into emulation mode; the M and X status
register bit disappear, putting the accumulator and index registers at 8
bit. The X and Y low bytes are retained, but the high bytes are lost. The
accumulator low and high bytes are retained. (of course the high byte is
hidden but accessible with the XBA instruction). The stack pointer is
returned to eights bits with the high byte forced to one and the high byte
is lost.
I think that after you work with the 65816 in emulation mode you will
realize that it is not about what you lose over native mode, but how much
you gain over a 6502. The fact that all of the extra opcodes and
instructions are still available even in emulation mode, makes for a
powerful processor even without the 16 bit registers.
------------------------------------------------------------------------
TOC
5.00 Relocating the Stack and Direct Page:
------------------------------------------
On power-up, the Stack is set to page one and the direct page (Zero Page)
to page zero. When in emulation mode (E=1) the Stack is initialized to Page
one, and Zero page is initialized to Page zero to emulate the default
status of the 6502.
Relocating the Direct Page (formerly known as Zero Page) is accomplished by
use of the PLD:pull direct page instruction.
LDA #$5900 ; lda with immediate 16 bit data.
PHA ; on the stack with 16 bits.
PLD ; pull it back into the direct page register.
Always keep in mind that PLD pulls 16 bits (2 bytes) off the stack. You may
also use the TCD:transfer C register to Direct page register. (the C
register refers to the Accumulator as 16 bits)
LDA #$5900 ; load 16 bit accum with immediate 16 bit data.
TCD ; transfer accum to direct page register.
Although you generally will want to keep Direct Page starting on an even
256 page boundary (low byte zero), you can specify a low byte address at
any 1-255 value. However all of the Direct Page (zero page) addressing
modes will add one clock cycle to the execution time if the low byte of the
direct page register is other than zero.
While in emulation mode, a direct page addressing mode where the index
rolls out of direct page will wrap around to the beginning of the direct
page, just as a 6502 does. For example:
LDX #$2C
LDA ($E0,X)
Would yield an effective address of $0C and not $10C.
While in Native mode, a direct page addressing mode where the index rolls
out of direct page will wrap into the next page of memory. Using the
example from above would yield the expected $10C effect address.
For those old Commodore 128 programmers, the concept of a relocatable
Direct Page is nothing new - we've been tweaking it on the MMU for years.
However; relocating zero page to something other than a page boundary has
some strong implications for the right style of code.
The power behind changing the direct page, is the same as 6502 zero page
addressing has always been. You can save bytes by using direct page
addressing (zero page) modes and acquire faster execution times as well. It
will take some time to find the best ways to program with a relocated
direct page, but once mastered, you wont get along with out.
TOC
------------------------------------------------------------------------
------------------------------------------------------------------------
=======================
6.00 Addressing Modes
=======================
All 6502 and 65C02 addressing modes and opcodes are supported in 65816
Native mode. Nine other new addressing modes are also supported in both
emulation and Native mode. However; there are a few notable addressing
differences between 816 Native mode and its 6502 counter part.
While in emulation mode there is no page wraparound when using Zero Page
Indexed addressing from a base address+index that "rolls over" $FF. While
in Native 65816 mode indexes can be 16 bits, so if the base address+index
rolls over into the next page the proper effective address in generated.
With 16 bit index registers, a direct page addressing mode where indexing
rolls over $FFFF the effective address roll back into the current bank not
into the next bank (ie:lda $20,x where x is $FFFF will result in an
effective address of $1F).
When using absolute indexed addressing where the base address is $FF01 to
$FFFF an index value that would cause the eFFective address to roll over
$FFFF would result in the next ram bank being accessed. Whereas on a 6502
there would be a wrap around into zero page.
Remember that when index registers are 16 bit, that absolute indexed X or
absolute indexed Y can now reach up to a full 64k! (ie: lda $6000,y where
y=$2000 would result in an effective address of $8000).
The 85618 also fixed the 6502 indirect JMP bug. A JMP ($12FF) now yields
the proper address of $12FF-$1300.
TOC
6.10 New 65816 Specific Addressing Modes:
-----------------------------------------
New Mode Name Example
-------------------------------------------------------
Program Counter Relative Long BRL $1234
Stack Relative LDA 15,S
Stack Relative Indirect Indexed Y LDA (9,S),Y
Block Move MVP 0,0
Absolute Long LDA $123456
Absolute Long Indexed X LDA $123456,X
Absolute Indexed Indirect JMP ($1234,X)
Absolute Indirect Long JMP [$1234]
Direct Page Indirect LDA ($12)
Direct Page Indirect Long LDA [$12]
Direct Page Indirect Long Indexed Y LDA [$77],Y
6.20 Addressing Mode Descriptions
----------------------------------
Program Counter Relative Long: BRL #$44
Program Counter Relative Long extends the range of the branch instructions
from the standard -127/+128 to 64k (+32767/-32768). Thus; the operand of
the BRL branch command is 16 bits. This address mode will help enormously
when writing relocatable code.
Stack Relative: LDA 7,S
Stack Relative addressing uses the Stack Pointer as a base address and then
adds the one byte user supplied operand as an offset into the stack. The S
specifies that this mode is Stack addressing via the stack pointer.
When using Stack Relative Addressing you should keep in mind that the Stack
Pointer will always point to the NEXT available spot on the stack. Thus, an
operand of one will retrieve the last item pushed onto the stack. An
operand of zero maybe useful to get another copy of the last thing PULLED
off the stack - but, of course, if an interrupt hits, then you would be in
trouble as the stack is manipulated via the interrupt routine.
Stack Relative Indirect Indexed Y: LDA ($22,S),Y
This addressing mode, locates and indirect address that points to the base
data located elsewhere (same as zero page indirect indexed). This two byte
instruction starts with the current location of the stack, then adds the
first operand, and finally adds in the Y index as and offset.
The value of this addressing mode is that suppose you have an address you
pushed onto the stack, by using this mode you can easily reach to where the
data was located.
10 LDY #0
20 LDA (1,S),Y ; get the address 16 bits
30 TAX ; save it in x
40 LDY #2
50 LDA (1,S),Y ; get a second address
In the example above, we start with the current stack pointer location as
the base address. In line 20 we load from an offset of one (1,S) and then
add in the offset to give the effective address. The above assumes we are
in 16 bit index and 16 bit accumulator mode.
Block Move: MVP 0,0
This is a major new addressing mode used by two instructions on the 65816.
The two new instructions Block Move Positive and Block Move Negative can
move up to 64K of data from one memory location to another. To setup a
move, the accumulator is loaded with the number of bytes to copy, the X
register is loaded with source address, and the Y register holds the
destination address. Then issue the Block move instruction and data is
moved at 7 cycles per byte.
Absolute Long: LDA $123456
Absolute Long is used to locate any data within the 16 bit address space of
the 65816. The operand is three bytes (24 bits long). The main usage of
this addressing mode is to temporarily override the contents of the DBR
Data Bank Register for the execution of the single instruction. If standard
absolute addressing is used, then the bank byte is concatenated to the
address from the DBR.
Absolute Long Indexed X: LDA $123456,X
Absolute Long Indexed starts with the base operand and then adds the X
index value to create an effective address. This is the same as 6502
Absolute Indexed X, except the base operand is 24 bits wide. Note that the
actual order of bytes is Opcode, low byte, high byte, bank byte and that it
is up to the assembler to arrange the bytes in this order.
Absolute Indexed Indirect JMP ($1234,X)
Absolute Indexed Indirect is a three byte instruction that creates the
effective address by starting with the specified operand and then adding in
the index value. Old 6502 programmers will recognize the following command
lookup and execute example:
SEC
SBC "0" ; subtract ascii zero off accumulator.
ASL ; times two into a table.
TAX ; into x as offset into word table.
LDA TABLE,X ; get command address byte.
STA PTR ; save in indirect pointer.
LDA TABLE+1,X ; get table command address high byte.
STA PTR+1 ; save in pointer high byte.
JMP (PTR) ; jump to command.
TABLE .WORD RUT1,RUT2,RUT3,...
PTR .BYTE 0,0
Using Absolute Indexed Indirect addressing it could be written in half the
bytes and cycles:
SEC
SBC "0" ; subtract ascii zero off accumulator.
ASL ; times two into a table.
TAX ; into x as index into word table.
JMP (TABLE,X) ; jump to command.
TABLE .WORD RUT1,RUT2,RUT3,...
A JMP Indexed Indirect [JMP ($1234,x)] assumes that the operand address is
in the current program bank. A JMP indirect [JMP ($1234)] assumes that the
operand address is in BANK ZERO.
Absolute Indirect Long JMP [$1234]
This addressing mode will form and effective address from the location
pointed to by the operand.
Direct Page Indirect LDA ($12)
This instruction is two bytes long. The operand points to a 16 bit Direct
Page (zero page) pointer that will form the effective address. For example,
if the Direct Page pointer is $70, then the low byte with come from $70,
and the high byte from $71, and the Bank Byte from $72. The bank byte will
be the current data bank register.
Direct Page Indirect Long LDA [$12]
This instruction is two bytes long. The operand points to a 24 bit Direct
Page (zero page) pointer that will form the effective address. For example,
if the Direct Page pointer is $70, then the low byte with come from $70,
the high byte from $71, and the Bank Byte from $72. The bank byte will
temporarily override the data bank register.
Direct Page Indirect Long Indexed Y LDA [$77],Y
This instruction in two bytes long and allows you to temporarily reach into
any memory bank. The operand is a direct page (zero page) pointer. The
address located at the direct page offset is three bytes long. First is the
low byte, then high byte, followed by the bank byte of the base effect
address. The Y index register is then added to this three byte destination
address to form the effective address. Square brackets are used to denote
that the address is a full 24 bit address and not a simple 16 bit address.
TOC
------------------------------------------------------------------------
7.00 Interrupts
---------------
There are some quirks to 65816 interrupts that you should consider. If you
are going to be writing native 65816 code you should give some
consideration to how your interrupt routine is going to be handled. If you
have written custom a IRQ routine that assumes Native mode, then your
considerations are minor. However, if you are writing Native mode 65816
code with 16 bit accumulator and/or 16 bit index registers, and you are
using a stock kernal IRQ that assumes emulation mode, then you must do some
coding to handle the discrepancies. In 6502 emulation mode, and IRQ pushes
the program counter high, then pc low, and finally the status register on
to the stack. When in Native mode an IRQ starts by stacking the following:
Program Counter Bank (PBR)
Program Counter High
Program Counter Low
Status Register
Next; the status register decimal mode bit (d) is cleared (setting binary
mode), and the IRQ flag is set (non NMI only). Finally, the program bank
(PBR) is set to zero and the 65816 jumps through the IRQ hardware vector.
The implications are that if the 65816 is running in emulation mode in a
ram bank other than Bank zero, then the program bank is going to be lost
(not good). There are two solutions to the problem. One is never to run in
emulation mode outside of Ram Bank zero. Second; you could save off the
current program bank value somewhere in Ram before running in emulation
mode beyond Bank Zero.
One thing that is unclear at this point, is if the CMD Super CPU can even
handle a Native Mode IRQ. Native Mode features a new hardware vector table:
TOC
7.10 Hardware Vectors:
----------------------
Native Mode 6502 Emulation Mode
-----------------------------------------
IRQ $FFEE-$FFEF IRQ/BRK $FFFE-$FFFF
RESET $FFFC-$FFFD
NMI $FFEA-$FFEB NMI $FFFA-$FFFB
ABORT $FFE8-$FFE9 ABORT $FFF8-$FFF9
BRK $FFE6-$FFE7
COP $FFE5-$FFE6 COP $FFF4-$FFF5
Notice that there is a separate BRK vector for Native mode, and no need to
poll bit 5 for the brk flag. However when running in emulation mode,
remember that bit 5 is still the BRK flag, and your IRQ will still need to
check for the source of the IRQ.
While in Native mode, a BRK instruction is two bytes. The Zero BRK opcode
followed by an optional "signature" byte. This way, you can detect what BRK
caused the vector to be taken for multiple BRK's while debugging.
COP is for a coprocessor interrupt. (see the instruction COP)
Notice in Native mode where the IRQ vector destinations are...hmm
When an IRQ is triggered, the current instruction is completed before the
interrupt is processed. This "interrupt latency" may be up to 7 clock
cycles. If you are running a time critical IRQ you may want to examine the
WAI:wait for interrupt instruction whereby you can stop the processor until
and interrupt occurs.
The ABORT vector listed above is taken when the 65816's Abort pin is pulled
low. This pin is only available on the 65816.
TOC
------------------------------------------------------------------------
------------------------------------------------------------------------
================================
Appendix A: 65816 Instruction Set
================================
------------------------------------------------------------------------
------------------------------------------------------------------------
Syntax Conventions:
addr two byte address.
addr/const two byte value: either an address or a constant.
const one- or two-byte constant.
destbk 64k bank to which string will be moved.
dp one-byte direct page offset (6502 zero page).
label label of code in same 64K bank as instruction.
long three-byte address (includes bank byte)
nearlabel label of code close enough to instruction to be
reachable by a one-byte signed offset.
sr one-byte stack relative offset.
srcebk 64k bank from which string will be moved.
Flags
Bits 76543210
nvmxdizc
e
n - negative.
v - overflow.
m - 8/16 memory/accumulator.
x - 8/16 bit index registers.
d - decimal mode.
i - irq enable disable.
z - zero result.
c - carry.
e - emulation.
------------------------------------------------------------------------
ADC Add with carry.
When using 16 bit accumulator mode, as expected, a carry will be properly
rolled over from bit 7 to bit 8 when generated by the operation. (ie: $FF+4
= $0103 with 1 in high byte an 3 in low byte of the accumulator.) Thus
carry need only be cleared when the low order bytes are added. Manual
checking for carry above bit 15 will still have to be done just as when in
8 bit accumulator mode.
When in 16 bit mode, the low-order bits are located in the effective
address, and the high order bits are located in the effective address plus
one.
Flags Altered nv----zc
n Set if most-significant bit of result is set.
v Set if signed overflow.
z Set if result is zero.
c Set if overflow.
Addressing Mode Syntax Opcode Bytes Cycles Ref
----------------------------------------------------------------------
Immediate ADC #const 69 2* 2 | 1
Absolute ADC addr 6D 3 4 | 1
Absolute Long ADC long 6F 4 5 | 1
Direct Page ADC dp 65 2 3 | 1,2
Direct Page Indirect ADC (dp) 72 2 5 | 1,2
Direct Page Indirect Long ADC [dp] 67 2 6 | 1,2
Absolute Indexed,X ADC addr,X 7D 3 4 | 1,3
Absolute Long Indexed,X ADC long,X 7F 4 5 | 1
Absolute Indexed,Y ADC addr,Y 79 3 4 | 1,3
Direct Page Indexed,X ADC dp,X 75 2 4 | 1,2
DP Indexed Indirect,X ADC (dp,X) 61 2 6 | 1,2
DP Indirect Indexed,Y ADC (dp),Y 71 2 5 | 1,2,3
DP Indirect Long Indexed,Y ADC [dp],Y 77 2 6 | 1,2
Stack Relative ADC sr,S 63 2 4 | 1
SR Indirect Indexed,Y ADC (sr,S),Y 73 2 7 | 1
-----------------------------------------------------------------------
* Add 1 byte if m=0 (16-bit memory/accumulator).
1 Add 1 cycle if m=0 (16-bit memory/accumulator).
2 Add 1 cycle if low byte of Direct Page register is <>0.
3 Add 1 cycle if adding index crosses a page boundary.
AND And Accumulator with Memory
Logically ANDs the data located at the effective address
specified by the operand and the accumulator.
If in 16 bit accumulator mode (m=0) Data ANDed from memory is
16 bits wide, the low byte is the effective address and the high
byte is the effective address+1.
Flags Altered n-----z-