Volver a la página principal.DOCUMENTACIÓN TÉCNICA: Ensamblador para 65816 (1ª parte)
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
4.00 Native Mode Registers:
4.01 · Accumulator
4.02 · X,Y Index Registers
4.03 · Direct Page Register (D)
4.04 · Stack Pointer (S)
4.05 · Program Bank Register (PBR)
4.06 · Data Bank Register (DBR)
4.07 · Status Register:
4.07.1 · Emulation Bit E: Hidden Bit
4.07.2 · Sixteen BIT User Registers
4.07.3 · Index Register Select
4.07.4 · Accumulator/Memory Select
4.08 · Setting Status Register Bits
5.00 65816 Emulation Mode Programming Model:
5.01 · Emulation Mode Registers
6.00 Relocating the Stack and Direct Page
7.00 Addressing Modes:
7.01 · New 65816 Specific Addressing Modes
7.02 · Addressing Mode Descriptions
Appendix A: 65816 Instruction Set
Appendix B: Composite Instruction List
Appendix C: IC Pinouts
Ir a la segunda parte del artículo
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.
=============
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".
=====================
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.
Miscellaneous:
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
=================================3.01 Processor Status Register (P)====================
4.00 Native Mode Registers
====================4.01 AccumulatorAlthough 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.
4.02 X,Y Index RegistersThe 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.
4.03 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.
4.04 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.
4.05 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.
4.06 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.
4.07 Status RegisterThe 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.
4.07.1 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.
4.07.2 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.
4.07.3 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.
4.07.4 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.
4.08 Setting Status Register BitsTwo 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.
===================================
5.00 65816 Emulation Mode Programming Model
===================================5.01 Emulation Mode RegistersEmulation Mode Processor Status Register (P)
--------------------------------------------
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.
================================
6.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.
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:
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.
=================
7.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.
7.01 New 65816 Specific Addressing Modes7.02 Addressing Mode DescriptionsProgram 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.
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:
Using Absolute Indexed Indirect addressing it could be written in half the bytes and cycles:
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.
Ir a la segunda parte del artículoVolver a la página principal.