Learn Multi platform 6309 Assembly Programming...
With Secret stuff!
The 6809 was pretty good... and
Hitachi decided they wanted to make their own version  the 6309!
However, they decided they could do better, and added a ton of
extra commands and registers to the chip!... the 6309 has an extra
2 eight bit registers, for a total of 32 bits!
Rather strangely they forgot to tell anyone, and it was much later
that anyone found out about all the extra functionality!


Useful Resources

If
you
want to learn 6309 get the 6309
cheatsheet It contains all the 6809 and 6309 opcodes.



We'll be using
Macroassembler AS for our assembly in these tutorials... VASM is
an assembler which supports rarer CPU's like 6309 and 65816 and
many more, and also supports multiple syntax schemes...
You can get the source and documentation for AS from the
official website HERE 
What is the 6309 and what are 8
'bits' You can skip this if you know about binary and Hex
(This is a copy of the same section in the Z80 tutorial)
The 6309 is an 8Bit processor with a 16 bit Address bus!... it has two 8
bit accumulators, A and B, that can be combined to make up one 16 bit
accumulator D (AB)
What's 8 bit... well, one 'Bit' can be 1 or 0
four bits make a Nibble (015)
two nibbles (8 bits) make a byte (0255)
two bytes (16 bits) make a word (065535)
And what is 65535? well that's 64 kilobytes ... in computers Kilo is 1024,
because four bytes is 1024 bytes
64 kilobytes is the amount of memory a basic 8bit system can access
the 6309 is 8 bit so it's best at numbers less than 256... it can do
numbers up to 65535 too more slowly... and really big numbers will be much
harder to do!  we can design our game round small numbers so these limits
aren't a problem.

You probably
think 64 kilobytes doesn't sound much when a small game now
takes 8 gigabytes, but that's 'cos modern games are sloppy,
inefficient, fat and lazy  like the basement dwelling
losers who wrote them!!!
6309 code is small, fast, and super efficient  with ASM you can
do things in 1k that will amaze you! 
Numbers in Assembly can be represented in different ways.
A 'Nibble' (half a byte) can be represented as Binary (00001111) ,
Decimal (015) or Hexadecimal (0F)... unfortunately, you'll need to
learn all three for programming!
Also a letter can be a number... Capital 'A' is stored in the
computer as number 65!
Think of Hexadecimal as being the number system invented by someone wit h
15 fingers, ABCDEF are just numbers above 9!
Decimal is just the same, it only has 1 and 0.
In this guide, Binary will shown with a % symbol... eg %11001100 ...
hexadecimal will be shown with & eg.. &FF.
Assemblers will
use a symbol to denote a hexadecimal number, some use $FF or #FF
or even 0x, but this guide uses &  as this is how
hexadecimal is represented in CPC basic
All the code in this tutorial is designed for compiling with
WinApe's assembler  if you're using something else you may need
to change a few things!
But remember, whatever compiler you use, while the text based
source code may need to be slightly different, the compiled
"BYTES' will be the same! 

Decimal 
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
... 
255 
Binary 
0000 
0001 
0010 
0011 
0100 
0101 
0110 
0111 
1000 
1001 
1010 
1011 
1100 
1101 
1110 
1111 

11111111 
Hexadecimal 
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
A 
B 
C 
D 
E 
F 

FF 
Another way to think of binary is think what each digit is 'Worth'
... each digit in a number has it's own value... lets take a look at
%11001100 in detail and add up it's total
Bit position 
7 
6 
5 
4 
3 
2 
1 
0 
Digit Value (D) 
128 
64 
32 
16 
8 
4 
2 
1 
Our number (N) 
1 
1 
0 
0 
1 
1 
0 
0 
D x N 
128 
64 
0 
0 
8 
4 
0 
0 
128+64+8+4= 204
So %11001100 = 204
! 
If a binary number is small, it may be shown as %11 ... this is the
same as %00000011
Also notice in the chart above, each bit has a number, the bit on
the far right is no 0, and the far left is 7... don't worry about it
now, but you will need it one day!
If you ever get confused, look at Windows
Calculator, Switch to 'Programmer Mode' and it has binary
and Hexadecimal view, so you can change numbers from one form to
another!
If you're an Excel fan, Look up the functions DEC2BIN and DEC2HEX...
Excel
has all the commands to you need to convert one thing to the
other! 

But wait! I said a Byte could go from 0255 before, well what
happens if you add 1 to 255? Well it overflows, and goes back to 0!...
The same happens if we add 2 to 254... if we add 2 to 255, we will
end up with 1
this is actually usefull, as if we want to subtract a number, we
can use this to work out what number to add to get the effect we want
Negative number 
1 
2 
3 
5 
10 
20 
50 
254 
255 
Equivalent Byte value 
255 
254 
253 
251 
246 
236 
206 
2 
1 
Equivalent Hex Byte Value 
FF 
FE 
FD 
FB 
F6 
EC 
CE 
2 
1 

All these number types can be confusing,
but don't worry! Your Assembler will do the work for you!
You can type %11111111 , &FF , 255 or 1
... but the assembler knows these are all the same thing!
Type whatever you prefer in your ode and the assembler will work
out what that means and put the right data in the compiled code! 
The 6309 Registers
Compared to the 6502, the 6309 is seriously powerful  and even gives the
Z80 something to think about!

8 Bit 
16 Bit 
24 Bit 
32 Bit 
Use cases 
accumulator A 
A 



8 Bit Accumulator 
accumulator B 
B 



8 Bit Accumulator 
accumulator E 
E





accumulator F 
F





16Bit Accumulator D

A 
B 


A+B combined to make a 16 bit Double
accumulator 
16Bit Accumulator W 
E 
F



E+F combined to make a 16 bit Word
accumulator 
32Bit Accumulator Q 
A

B

E

F

A+B+E+F combined to make a 32 bit Quad
accumulator 
Condition Code Register 
CCR 



Flags 
Mode Register 
MD 




Zero Register (fixed) 
0
/ Z




Transfer Value 
V 


Fixed Value... accessible via TFR only
survives reset! 
Indirect X 
X 


Indirect Register 
Indirect Y 
Y 


Indirect Register

User Stack Pointer 
U 


User Stack 
Hardware Stack Pointer 
S 


Stack 
Program Counter 
PC 


Running Command 
Direct Page 
DP 



Zero page is relocatable on 6309 


MD: 0IFN
CC: EFHINZVC

Name 
Meaning 
0

/0

Division By Zero 
I

IL

Illegal instruction Exception 
F 
FM

FIRQ pushes all registers (1=on) 
N

NM

Native mode (1=on) 
E 
Entire Flag 
Regular/Fast Interrupt flag

F 
FIRQ Mask 
Fast Interrupt Flag

H 
Half Carry 
Bit 3/4 carry for BCD

I 
IRQ Mask 
Interrupt Flag

N 
Negative 

Z 
Zero 

V 
oVerflow 

C 
Carry 


note E and F cannot be pushed with PSHS ...
you must use PSHSW and PULSW (W=E+F)
The Direct page is like the 6502 Zero Page, however
it does not need to be at zero!
We can load A with a value, then TFR A,DP to set the direct
page... we need to tell the assembler where the direct page is,
otherwise some commands may malfunction, we do this with ASSUME
dpr:$xx  this is called SETDP on some assemblers 

Like the 68000, the 6309 is BIG
ENDIAN... this means a 16 bit pair stored to an address like $6000
will save the high byte to $6000, and the low byte to $6001
Special Memory addresses on the 6309
Unlike the 6502, The 6309 has full 16 bit Stack pointers, U and S....
the 'Zero Page' (AKA Direct Page) can also be re positioned
Like the 6502, there are a variety of
'Interrupt Vectors' with fixed addresses...
Address 
Vector
(Address) 
Registers
Autopushed onto stack 
$FFF2 
SWi 3
Vector

D,X,Y,U,DP,CC 
$FFF4 
SWI 2
Vector

D,X,Y,U,DP,CC 
$FFF6 
FIRQ Vector 
CC (E
flag cleared)

$FFF8 
IRQ Vector 
D,X,Y,U,DP,CC 
$FFFA 
SWI 1
Vector 
D,X,Y,U,DP,CC 
$FFFC 
NMI Vector 
D,X,Y,U,DP,CC 
$FFFE 
RESET
Vector 
NA 
The 6309 Addressing Modes
The 6502 has 11 different addrssing modes... many have no comparable
equivalent on the Z80
Inherent Addressing 
Commands that don't take a parameter 
ABX 
Register Addressing 
Commands that only use register 
TFR A,DP 
Immediate Addressing 
Direct Address of command 
ADDA #$10
ADDD #$1000 
Direct Page addressing 
Read from DP (zero page) 
ADDA $10 
Extended Direct addressing 
Read from an address 
ADDA $1234 
Extended Indirect Addressing 
Read from the address specified... then get the value from that
address 
ADDA [$1234] 
Indexed Addressing 
Uses a 2nd setting byte  allows for Autoinc 
,R
offset,R
label,pcr
,R+
,R
[] 
Indexed Addressing: Zero Offset 
Just use the address in the register 
LDA ,Y
LDA 0,Y
LDA Y 
Indexed Addressing: 5 bit offset 
16 to +15 offset 
LDA 1,Y 
Indexed Addressing: Constant offset from base register 
8 / 16 bit offset from X,Y,U,S ... Can be negative or positive 
LDA 1000,Y 
Indexed Addressing: Constant Offset From PC 
8 / 16 bit offset from PC 
LDA $10,PC 
Program counter relative 
PCR is like PC, but is calculated by the assembler 
ADDA label,PCR 
Indirect with constant offset from base register 
Load from the address in the register + offset 
LDA [1,X] 
Accumulator offset from Base register 
Add accumulator (A/B/D) to a X,Y,U,S (not PC) 
LDA B,Y 
Indirect Accumulator offset from Base register 
Load from the address made up of a X,Y,U,S Plus the accumulator 
LD [B,Y] 
AutoIncrement 
Add 1 or 2 to the register 
ADDA ,X+
ADDA ,X++ 
AutoDecrement 
Subtract 1 or 2 from the register 
ADDA ,X
ADDA ,X 
Indirect AutoIncrement 
Load from the address in Register, then add 1 or 2 
ADDA [,X+]
ADDA [,X++] 
Indirect AutoDecrement 
Subtract 1 or 2 then Load from the address in Register 
ADDA [,X]
ADDA [,X] 
Program relative 
Offset to PC 
BRA label 
Hints
Saving a byte on return:
Rather than returning, if your last command is a pop, just pop the PC with
your other registers:
PULS B , X , PC
Addresses, Numbers and Hex... 6309 notification
We'll be using VASM for our assembler, but most other 6502
assemblers use the same formats... however coming from Z80, they can be a
little confusing, so lets make it clear which is which!
Prefix 
Example 
Z80 equivalent 
Meaning 
# 
#16384 
16384 
Decimal Number 
#% 
#%00001111 
%00001111 
Binary Number 
#$ 
#$4000 
&4000 
Hexadecimal number 
#' 
#'a 
'a' 
ascii value 

12345 
(16384) 
decimal memory address 
$ 
$4000 
(&4000) 
Hexadecimal memory address 
Missing Commands!
Commands we don't have, but might want!
DEX/DEY/INX/INY 
Tfr X,D ;replace X with Y if required
DecB ;or IncB as required
Tfr D,X ;replace X with Y if required 

CLC 
AndCC #%11111110 

SEC 
OrCC #%00000001 

DeX

LEAX 1,X





Lesson
1  Getting started with 6309
Lets learn the basics of using 6309... We'll take a look at
the new registers, and some of the new commands.

The 6809 devtools
support 6309 
6309_Lesson_1.asm




6309 supports
everything 6809 does... so we'll only cover the new stuff here!
If you don't know 6809 yet, please see these
tutorials!

New Registers!
The 6809's two 8 bit registers have been doubled!
As well as the old A and B, we now have E and F! 

Of course, The 16 bit D register is still made up of A+B, but we
now have another 16 bit pair known as W
W is made up of E+F


All 4 8 bit registers are combined in some cases to make one 32
bit quad, known as Q
Q is made up of A+B+E+F


There are a few more weird and wonderful registers!
0 (or z in asw) is a hardwired zero, we can use it as a substitute
for a regsiter, to get a zero value, or 'discard' the result of a
command.
V is a 16 bit register referred to as the 'Transfer Value'. We
can't set it directly like E and F, but we can move values into
it. Also, strangely, it keeps its value after a reboot!
The final register is MD  the MoDe register. We can turn on bit 0
to enable Native 6309 mode, though we can use all the new commands
without doing so!. Turning on native mode alters the way the
interrupts work.


Here are the results.


Commands using the
new registers like E and F often take an extra byte than the
ones using A and B.
You should still prioritize the original registers where you
can, and just use the new ones as an alternative to the zero
page, or to reduce push pops.


Many of the previous maths commands can now be used with the new
registers.
We can use Clear, Inc and Dec... and these now even work with the
D register.
The new registers also work with ADD and SUB


Here are the results.


We have new ADDR and SUBR commands, which will add and subtract
one register from/to another. The destination is on the right.
ADCR and SBCR provide similar functions, but add and subtract the
carry as well
Unfortunately we dont have a 32 bit add or subtract command which
works with Q, but we can use the 16 bit commands to effect a 32
bit add or subtract via the carry.


Here are the results


Lesson
2  Shifts, Compares and logical ops
The 6309 adds lots of new commands, and adds new supported
registers to old ones... lets see what we can do now!

The 6809 devtools
support 6309 
6309_Lesson_2.asm



Rotation and shifts
We now have 16 bit rotate
and shift commands, which work with the D and W registers.
ROR and ROL shift between the
16 bits of the register, plus the carry as a 17th bit
We do not, however, have any that work with the 32 bit Q 

Here are the results


We have new logical shift commands for unsigned 16 bit numbers.
We now have LSRD and LSRW
Strangely, while we have a LSLD, we do not have
a LSLW, however "ADDR W,W" will add W to itself giving the same
effect.


Here are the results


We have new Arithmetic shift commands for signed 16 bit numbers.
We now have ASRD and ASRW
Strangely, while we have a ASLD, we do not have
a ASLW, however "ADDR W,W" will add W to itself giving the same
effect. 

Here are the results


Tests and compares
We have TST and CMP commands for the new 8 and 16 bit registers.
These commands work the same as usual.
TST will set the Zero and Negative flags based on the contents of
a register.
CMP will set the flags like a subtraction, but will not change the
tested register.
Unfortunately these commands cannot work with the 32 bit Q
register. 

Here are the results 

Logical Operations
We have some new logical operations!
EOR, AND and OR now can work with the 16 bit D register (but not
the W one)
We now also have commands which work with register to register
values. The first specified register will be processed with the
second, and the result stored in the second register.


Here are the results


We have some new commands which perform an operation with an
Immediate value and the address in a register + an offset,
changing the byte at the effective address.
EIM will Eor an Immediate with Memory
AIM will And an Immediate with Memory
OIM will Or an Immediate with Memory
TIM will Test an Immediate with Memory  setting the flags like
logical operation AND


Here are the results.


More Maths Operations
We have a few other useful commands which perform Bit operations
SEXW will Sign EXtend 16 bit W into a 32 bit value Q (effectively
filling D with the top bit of W)
NEGD will negate the 16 bit D register  however there is no
command to negate the W register.
We also have a COMplement command, which will flip the bits of a
register, this works on all the 8 and 16 bit registers, but the 32
bit Q cannot be flipped in a single command


Here are the results


Lesson
3  More new commands!
Lets take a look at the last of the new 6309 commands.

The 6809 devtools
support 6309 
6309_Lesson_3.asm



Push and Pull Commands
The PSH and PUL commands do
not work with the new E and F registers (and by implication W)
The only way to backup and restore these registers via the stack
are using the 4 new commands.
PSHSW will Push W onto the S stack.
PULSW will Pull W off the S stack.
PSHUW will Push W onto the U stack.
PULUW will Pull W off the U stack. 

Here are the results


Bulk transfer commands
The 6309 adds some impressive new bulk transfer commands...
these give functions like LDIR on the Z80, or MVN on the 65816.
The TFM command allows us to transfer from one register to
another, with a variety of Increment and Decrement options (4 in
total)
TFM r1+,r2+ will copy W bytes from the address in r1 to the
address in r2, incrementing both after each byte.
TFM r1,r2 will copy W bytes from the address in r1 to the
address in r2, decrementing both after each byte.


Here are the results!
We copied 4 bytes to the right, then 4 bytes to the left.


We have two more slightly strange options
TFM r1+,r2 will copy W bytes from the address in r1 to the
address in r2, incrementing only the source after each byte
TFM r1,r2+ will copy W bytes from the address in r1 to the
address in r2, incrementing only the destination after each byte
These could be usedful for transferring a block of data to, or
from, a memory mapped hardware port. 

Here are the results, first we transferred 89,AB,CD,EF to $7104
(leaving only EF visible)
Then we transferred 89 four times. 

Multiplication and Division
We have a new 16/32 bit
Multiply command!
MULD will multiply D by either an immediate or memory
value  alas we can't multiply by the w register.
DIVQ is the opposite, this divides the 32 bit
value in Q by the specified value, putting the whole number result
in W, and the remainder in D
DIVD is the opposite of the original MUL
command, this divides the 16 bit value in D, putting the whole
number result in B and the remainder in A 

Here is the results! 

ASW seems to not assembly the DIVD command
correctly, it seems to store the immediate value as a 16 bit
value, causing the command to end up as 4 bytes, rather than the
apparently correct 3.


Bit Test and Set
There are a set of special new commands for bit manipulation on
the 6309:
LDBT Load Memory Bit into Register Bit
STBT Store value of a Register Bit into Memory
BAND Logically AND Register Bit with Memory Bit
BOR Logically OR Memory Bit with Register Bit
BEOR ExclusiveOR Register Bit with Memory Bit
BITD Bit Test Accumulator D with Memory Word
Value
BIEOR ExclusivelyOR Register Bit with Inverted
Memory Bit
BIOR Logically OR Register Bit with Inverted
Memory Bit
These have an odd format:
CMD Reg.Bit, Address.Bit
Where Reg and Address are the source/destination (Depending on the
command), and Bit is the source and destination bit numbers (07)
Unfortunately, it seems they are not emulated
properly  the 3 register options A,B,CC are mixed
up (I think the assembler is doing them right), so we won't
be covering them in detail here. 

 
Buy my Assembly programming book on Amazon in Print or Kindle!
Available worldwide! Search 'ChibiAkumas' on your local Amazon website!
Click here for more info!
