Showing posts with label 6809. Show all posts
Showing posts with label 6809. Show all posts

Wednesday, November 24, 2021

Retrocomputing Basic Implementations

Here is a summary of a number of Basic implementations that I have come across and worked with as part of my retrocomputing hobby. Many of these were ported by me or others to different platforms from the ones they were originally written for (for example, single board computers based on the 6502, 6809, Z80, and 68000 microprocessors). These are all found on my github  account.

Name Developer Platform Code size Comments
Enhanced Basic (68000) Lee Davison 68000 14K Full-featured Basic for 68K platform
Tiny Basic for the 68000 Gordon Brandly 68000 4K Derived from and similar to Palo Alto Tiny Basic.
Enhanced Basic (6502) Lee Davison 6502 11K Full-featured Basic for 6502 platform.
Microsoft Basic for 6502 Microsoft Apple 2, Commodore, KIM-1, OSI, and others 8K Basic used on several early 6502-based microcomputers.
Tiny Basic for 6502 Tom Pitman 6502 3K Originally published in Dr. Dobbs Journal.
Apple 1 Basic Steve Wozniak 6502 (Apple 1) 4K Basic for the Apple 1, later expanded into Apple 2 Integer Basic.
BBC Basic 2 for Acorn Atom/BBC Computer Roger Wilson (Acorn Computer) 6502-based Acorn Atom and BBC Computers 16K Basic for the Acorn Atom and BBC Computers.
Tiny Basic for 6800 Tom Pitman 6800 2K My version runs on the Heathkit ETA-3400.
Tiny Basic for 6809 Tom Pitman 6809 2K 6809 port of 6800 version.
TSC Micro BASIC PLUS Technical Systems Consultants 6809 4K Similar to Tiny Basic.
Sinclair ZX81 Basic John Grant and Steve Vickers, Nine Tiles Networks and Sinclair Research Sinclair ZX80/ZX81, Timex 1000 8K Basic for the Sinclair ZX81 computer.

Sunday, April 14, 2019

A 6809 Single Board Computer: Instruction Trace/Step Function

In my JMON monitor for the 6502, I implemented a trace or step function where you can execute code one instruction at a time and see the results of execution on the CPU registers. This is very useful for debugging, particularly as this implementation supports stepping through ROM code, something that can't be done with breakpoints.

For my 6809 single board computer I wondered if I could do the same for the 6809 processor. After some thought, it looked feasible, although more challenging as the 6809 has a larger and more complex instruction set than the 6502.

The basic idea is to take the instruction to be executed and store it in a buffer in RAM. The values of all CPU registers from the previous instruction trace are restored and the instruction is executed. A jump instruction is placed right after the traced instruction that goes back to the trace program. After execution, the new register values can be displayed and saved. This allows running code that is in ROM, as it gets copied to RAM when executed.

To implement this requires knowing the length of each instruction, as they can vary on the 6809 from one to five bytes depending on the instruction and addressing mode. From my previously written disassembler I already had code that could determine the instruction length and even disassemble it.

A wrinkle in this approach is handling instructions which cause a change in the flow of execution, such as a JMP (jump) instruction which would not return if simply executed in the buffer. We need to handle this instruction as a special case. We can examine the destination address and update the saved program counter accordingly. We don't need to actually execute it since it changes no other registers than the PC. We do need to check for and handle both direct (8 bit) and extended (16-bit) jump instructions. For direct, the destination address needs to be calculated by combining the instruction operand with the current value of the direct page (DP) register.

Jump to subroutine (JSR) in another special case. Here we need to push the return address on the stack (using the saved value of the stack pointer that we trace with) and then calculate the new PC value.

Similarly, we can handle BRA/LBRA and BSR/LBSR like JMP and JSR but the effective address needs to be calculated by adding the offset to the current PC value. Again we don't need to execute the instruction, just update the new PC value.

The interrupt related instructions SYNC, CWAI, SWI, SWI2, and SWI3 can all be simulated by pushing registers on the stack and setting the PC to the appropriate interrupt vector.

RTS and RTI are simulated by pulling registers (in the case of RTI) or just the PC (for RTS) off the stack. One wrinkle is that in the 6809 we need to check the E (Entire) flag in the condition code register to know of we should restore all registers from the stack.

Conditional branches are a little more tricky. They can transfer control to two different places depending on whether the condition is true or not. These are handled by writing into the execution buffer both the instruction being traced as well as different jumps depending on whether the branch is taken or not. The branch destinations can update the PC accordingly. The code in the buffer looks like below:

XXXX XX 03           Bxx $03 (Taken)         ; Instruction being traced
XXXX 7E XX XX        JMP BranchNotTaken
XXXX 7E XX XX Taken  JMP BranchTaken

We execute the instruction in the buffer and let it perform the test. We need to handle all the possible branch instructions, both short and long versions.

TFR (transfer) and EXG (exchange) instructions are okay to run except the cases where the source or destination is the PC. We need to handle those cases manually since it would otherwise change the flow of control.

Similarly, PSHS/PHSU and PULS/PULU could potentially include the PC in the list of registers pushed or pulled. Currently I just check for this case, remove the PC from the list of registers, and warn the user in this case that it is not fully handled yet.

Indexed addressing poses a challenge: we need to handle an instruction that changes flow of control like JMP 1,X with an arbitrary index addressing mode. It might also produce side effects in the case of instructions like JMP 1,X++. These are handled using a trick: instead of JMP, we run a LEAU instruction with the same indexed operand. Then we examine value of U, which should be the new PC. Currently the code can't handle addressing modes that change the U register like JMP ,U++.

A final challenge is PCR relative index addressing. If we move the instruction to the buffer to execute it, the PC relative address is now wrong. I thought about this, and it should be possible to adjust the offset based on the difference between the original instruction location and the address of the buffer where it will be run. This would get a little complicated, so I didn't implement it (yet). For now I just ignore it and display a message at run time that it is not supported.

After working out most of the logic as pseudocode, I implemented and debugged it. I started with the basic instructions and then added all of the special cases, testing them one at a time. Once done, I tested it with some smaller complete programs.

Finally, I was able to integrate it into the "combined" ROM which also contains the ASSIST09 monitor, disassembler, and Microsoft Basic. I added the trace command as a new ASSIST09 "T" command. It took some shuffling but I was able to just get them all to fit in the 8K ROM.

It hasn't been tested exhaustively, and it can't run BASIC because it uses some PC relative instructions, but it seems to work quite well. Here is some sample output:

>T D000
D000  81 30        CMPA  #$30 
PC=D002 A=FF B=FF X=FFFF Y=FFFF S=FFDF U=FFFF DP=FF CC=11111000 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D002  25 04        BCS   $D008 
PC=D004 A=FF B=FF X=FFFF Y=FFFF S=FFDF U=FFFF DP=FF CC=11111000 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D004  81 3C        CMPA  #$3C 
PC=D006 A=FF B=FF X=FFFF Y=FFFF S=FFDF U=FFFF DP=FF CC=11111000 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D006  25 C0        BCS   $CFC8 
PC=D008 A=FF B=FF X=FFFF Y=FFFF S=FFDF U=FFFF DP=FF CC=11111000 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D008  30 1F        LEAX  $1F ,X
PC=D00A A=FF B=FF X=FFFE Y=FFFF S=FFDF U=FFFF DP=FF CC=11111000 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D00A  34 50        PSHS  U,X
PC=D00C A=FF B=FF X=FFFE Y=FFFF S=FFDB U=FFFF DP=FF CC=11111000 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D00C  0F 41        CLR   $41 
PC=D00E A=FF B=FF X=FFFE Y=FFFF S=FFDB U=FFFF DP=FF CC=11111000 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D00E  CE C0 E7     LDU   #$C0E7 
PC=D011 A=FF B=FF X=FFFE Y=FFFF S=FFDB U=C0E7 DP=FF CC=01111110 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D011  0F 42        CLR   $42 
PC=D013 A=FF B=FF X=FFFE Y=FFFF S=FFDB U=C0E7 DP=FF CC=01111110 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT  
D013  33 4A        LEAU  $0A ,U
PC=D015 A=FF B=FF X=FFFE Y=FFFF S=FFDB U=C0F1 DP=FF CC=01011001 (EFHINZVC)
PRESS TO CONTINUE, TO QUIT 

References

  1. https://github.com/jefftranter/6809/tree/master/sbc/trace
  2. https://github.com/jefftranter/6809/tree/master/sbc/combined
  3. https://github.com/jefftranter/6809/tree/master/sbc/disasm
  4. https://github.com/jefftranter/6502/tree/master/asm/jmon

Saturday, April 13, 2019

A 6809 Single Board Computer: The MC6839 Floating Point ROM



Implementing floating point math was a challenge with 8-bit microprocessors. The early version of BASIC for the 6502-based Apple 1 and Apple 2 series written by Steve Wozniak only supported 16-bit integer variables in order to keep the size down and achieve acceptable performance. Later, Applesoft BASIC was licensed from Microsoft which supported floating point variables. A significant amount of the code for Microsoft BASIC for 8-bit microprocessors was dedicated to floating point math. Some versions, loaded from tape, gave the user the option to leave out the sin/cos/tan trig functions to save space and free up some memory.

The 6809 supports instructions for 8-bit addition, subtraction, and division and some 16-bit math instructions. While more powerful than earlier processors like the 6502 and 6800, implementing floating point math was still a significant undertaking. Motorola saw an opportunity to offer a floating point math library as a standard product for the 6809. This was made more viable for two reasons:

  • An IEEE standard for floating point math formats appeared to be poised to become an industry standard.
  • The 6809 allowed writing position independent code, so a floating point library could be offered in binary form that would be independent of the memory map of the system it needed to run on.

Out of this came a product: the MC6839 Floating Point ROM. While essentially a software product, it was sold as hardware: an 8K ROM programmed with the floating point code. As well as the ROM, it included a programming manual almost 100 pages in length, describing how to use it.

The basic features of the library were:

  • An 8KB ROM which would run at any contiguous range of addresses.
  • All RAM used was relative to the stack pointer.
  • A well documented API that allowed operands to be passed in registers or via the stack.
  • Fully implemented the IEEE Standard for floating point math (at the time, still in draft form).
  • Support for the following operations: add, subtract, multiply, divide, remainder, square root, integer part, absolute value, negate, condition code compares, conversion between integer and floating point, and conversion between binary floating point and BCD.
  • Supported three precisions (4, 8, and 10 bytes) defined by the IEEE standard.
  • Supported the rounding modes, closure modes, and normalize modes defined by the standard.
  • Supported handling of exceptions (e.g. division by zero).

According to the source code it was written around 1980, with revisions up to at least 1982. The author names in the source code were Greg Stevens, Joel Boney, and G. Walker. In 1988 the source code was put in the public domain by Motorola, and can be found on the Internet as well as the binary for the ROM.

I came across the code and decided to try it out on my 6809 single board computer. There is a programming example in the manual that finds the roots to quadratic equations of the form ax^2 + bx +c = 0 using the classic formula -b +/- sqrt(b^2 - 4ac) / 2a

I typed in the example and adapted it to the lwasm assembler. The program uses a standard set of macro instructions to set up the parameters in the correct calling sequences for the ROM. These macros make the code much more readable and were easily ported to the lwasm assembler. I needed to make a few changes in order to make the example a complete runnable program. When run, and with the S record file for the MC6839 ROM also loaded into memory, I was able to get the example to run and produce the correct results. The code is on my github account.

Since I had the source, I took a look at whether I could assemble it. It would take some effort because the original source required a special Motorola "structured assembler" that I have not been able t find any information about. It has a number of structured programming macros for things like looping and conditionals. Given some time this could be reversed engineering by looking at the binary file.

I also found that the source does not quite match the binary (the former has a 1980 copyright date and the latter 1982). Without having a known good binary that corresponds to the source code, porting would be a challenge, so I set any further work on this aside for now.

The MC6839 Floating Point ROM was Motorola's first foray into this type of binary ROM product. The data sheet lists the product as "preliminary" and according to one source it was never actually offered as a product.

Later processors, like the 68000 series, would support floating point math in hardware using either a separate dedicated chip or on-board floating point unit (FPU). These still use (as do modern computers, including your smart phone) the IEEE standard for floating point math.

References

  1. https://github.com/jefftranter/6809/tree/master/sbc/mc6839
  2. http://github.com/brouhaha/fp09
  3. http://www.colorcomputerarchive.com/updates/2017
  4. http://www.classiccmp.org/pipermail/cctalk/2017-March/033678.html
  5. http://www.classiccmp.org/pipermail/cctech/2016-June/019519.html
  6. http://www.colorcomputerarchive.com/coco/Documents/Manuals/Hardware/MC6839%20Floating-point%20ROM%20Manual.pdf

Tuesday, February 12, 2019

6809 Single Board Computer: TSC Micro Basic Plus

On the hunt for interesting software that could run on my 6809 Single Board Computer, I came across a small BASIC interpreter.

Originally written for the 6800 processor to run on systems like the Southwest Technical Products SWTPC, Micro Basic Plus was developed by Technical Systems Consultants in 1976 and cost $15.95 for the manual and listing. A cassette tape was $6.95 and paper tape was $6.00. The original version can be found here  and had this marketing blurb about it:


TSC Micro Basic Plus

This is the most complete small Basic available to micro users. Statements include: PRINT, INPUT, READ, DATA, RESTORE, IF ... THEN, GOTO, GOSUB, LET, ON ...GOTO, ON ...GOSUB, RETURN, FOR (with + and - step), NEXT, DIM (single and double dimensioned arrays up to 98 by 98), REM and END. There are also several functions available which include TAB and SPC (for output formatting), RND, ABS, SGN and exponentiation. The commands available to the user are LIST, SCRATCH, RUN, and MONITOR. But the list does not stop here. MICRO BASIC PLUS also includes a complete line editor ability to have multiple statements per line, direct execution of most statements, large arithmetic range (integer only -99999 to +99999), and a very simple load and dump procedure for saving the user's BASIC program on paper tape or cassette and then reloading it at a later time. Also included is an EXTERNAL statement which allows the user to write 6800 machine language subroutines to be called during BASIC program execution.

You are probably thinking all this sounds great, but if the less extensive versions of small BASIC require 23K of memory then this version must require 5 or 6K because the capability is doubled. Well here is the icing on the cake. MICRO BASIC PLUS resides in a fraction over 3K which means that in a 4K system you still have room for a 30 to 60 line BASIC program. For more complex programs, we recommend a system with 8K or more of memory.

One more plus... you not only receive a complete manual and hex dump of the program, but also the fully commented source listing! This is a great aid for learning programming techniques as well as enabling you to alter the program should you so desire.


I found a 6809 port here,  developed by Drexel University to run on their 6809 Single Board Computer. It looks to have been a straight port from 6800 to 6809 mnemonics with the input/output routines adapted to their hardware and monitor.

I ported it to my board, using ASSIST09 monitor routines for i/o. I had it up and running in an evening, and made a few improvements after that. It supports most common BASIC keywords including ON/GOTO and ON/GOSUB and one and two dimensional arrays.

Overall, though, the language is pretty limited as compared to other BASICs with support for integer math only and no string variables at all. This is not surprising given that it is only a little of 3 Kilobytes in size! It is not too different in capabilities from Apple 1 BASIC originally written by Steve Wozniak and later expanded into Integer BASIC for the Apple ][.

I tried a few sample programs and they ran quite well. I made an enhancement it to show full error messages rather than just numbers (which increases the size by another 1/2 K or so). The code is here.

For running real BASIC programs I think I will stick to the port of Microsoft BASIC for the Color Computer, but this is an interesting little program.

Friday, February 8, 2019

A 6809 Single Board Computer: Cross-Compilers under Linux


Assembling code by hand is possible, but for any program of non-trivial size, cross-compilation is the way to go, even for 8-bit processors like the 6809. When working with my 6809 single board computer I went looking for a suitable cross-assembler. My requirements were to support the 6809, run on Linux, and be freely available. I came across three suitable programs, which I'll briefly describe here.

AS9 Assembler

Home page: http://home.hccnet.nl/a.w.m.van.der.horst/m6809.html

Documentation: http://home.hccnet.nl/a.w.m.van.der.horst/as11v2.pdf

This code is apparently derived from the original and official Motorola cross-assembler circa 1981. Written in very old pre-ANSI standard C, it was modified by a number of people over the years, and this version was last modified Albert van der Horst in 2004 to compile under Linux. I had no trouble building it under Ubuntu Linux.

As the official Motorola assembler, it follows the Motorola documentation. It seems pretty comprehensive, and supports the 6800, 6809, 68HC11, and some other chips in the 68xx series.

I have used this as my primary cross-assembler to develop or port the 6809 code I've been working on. The S-record files it generates are happily accepted by the ASSIST09 monitor's Load command.

Here is a sample output listing:

0005 7000                            ORG     $7000           ; Start address
0006                         
0007 7000 86 12              START:  LDA     #$12
0008 7002 c6 34                      LDB     #$34
0009 7004 8e 56 78                   LDX     #$5678
0010 7007 1e 89                      EXG     A,B
0011 7009 12                         NOP
0012 700a 12                         NOP
0013 700b 39                         RTS

The only quirk I encountered is a known issue where it can produce invalid warnings about comments. I worked around this when needed by disabling warnings with a command line option.

ASM6809 Assembler

Home page: https://www.6809.org.uk/asm6809

Documentation: https://www.6809.org.uk/asm6809/doc/asm6809.shtml

This is a portable cross assembler targeting the Motorola 6809 and Hitachi 6309 written by Ciaran Anscomb. It features arbitrarily complex expressions (with most C-style operators available), forward references, macro expansion and conditional assembly. Output formats are: raw binary, DragonDOS binary, Color Computer RS-DOS or "DECB" binary, Motorola S record, and Intel HEX.

Written in C, it is licensed under the GPL and is actively being maintained with the latest version being 2.11 released on 2018-07-27.

I downloaded the source and was able to build it with no problems simply by running the configure script, make, and sudo make install.

Trying it on my 6809 disassembler program (about 2000 lines of code), the only issues I encountered were that it didn't accept labels with a colon at the end and it didn't like one symbol I used that started with a dot. After making appropriate changes, the code built fine. It even warns that some long branches fit in eight bits and could have used short branches, so I modified them and made the code a little smaller. I did notice that it generated slightly different code than the as9 assembler had, where it picked a different (more efficient) indexed addressing mode that could use a 5-bit displacement.

Here is a sample listing:
                     
7000                          ORG     $7000           ; Start address
                      
7000  8612            START   LDA     #$12
7002  C634                    LDB     #$34
7004  8E5678                  LDX     #$5678
7007  1E89                    EXG     A,B
7009  12                      NOP
700A  12                      NOP
700B  39                      RTS

It generated a Motorola S record (RUN) file, but the ASSIST09 firmware did not like to load it. Investigation showed that it was producing S record files with invalid checksums. I made a code fix to the source for this. It also doesn't produce the S9 record at the end of the file that ASSIST09 wants to see, unless you have an END directory specifying that start address.

LWTOOLS

Home page: http://lwtools.projects.l-w.ca/

Documentation: http://lwtools.projects.l-w.ca/manual/manual.html

LWTOOLS is a set of cross-development tools for the Motorola 6809 and Hitachi 6309 microprocessors. It supports a number of output formats including raw binary, Motorola S record, Color Computer binaries, and a proprietary object file format that supports linking.

It is implemented in C and is actively maintained. I used version 4.16 that was released in December 2018.

It supports a number of platforms. I was able to build it with no issues on Ubuntu Linux. It installs a number of tools including lwasm, lwlink, lwar, and lwobjdump.

Here is a sample output listing:

                      (          ex1.asm):00005                 ORG     $7000           ; Start address
                      (          ex1.asm):00006         
7000 8612             (          ex1.asm):00007         START   LDA     #$12
7002 C634             (          ex1.asm):00008                 LDB     #$34
7004 8E5678           (          ex1.asm):00009                 LDX     #$5678
7007 1E89             (          ex1.asm):00010                 EXG     A,B
7009 12               (          ex1.asm):00011                 NOP
700A 12               (          ex1.asm):00012                 NOP
700B 39               (          ex1.asm):00013                 RTS

I only tried the assembler, using my disassembler program again. It didn't like items in FCB directives to be separated by any white space, only commas. It also didn't a like symbol starting with "." Other than that it assembled it fine, and generated a S record file which I successfully loaded and ran on the single board computer.

For advanced development work where you might want to assemble multiple files and link them, this looks like a good choice for a toolset. A 6809-based C compiler I have tried, CMOC, uses it as it's cross-assembler.

Summary

All three of these cross-assemblers look adequate for basic 6809 assembly language programming hosted on a Linux desktop. With a few changes I was able to get same source code for my disassembler to build with all three assemblers.

Tuesday, February 5, 2019

A 6809 Single Board Computer: Disassembler and Thoughts on the 6809


As a project to use my 6809 SBC and learn more about 6809 assembly language programming, I wrote a disassembler that can run on the board. The design was loosely based on the one I did for the 6502.

While straightforward in principle, a disassembler for the 6809 is a little more challenging that for the 6502 for a number of reasons:
  • It supports many instructions.
  • Some instructions have unique operand formats (e.g. TFR/EXG, PSH/PULS).
  • There are many (24) different indexed addressing modes.
  • The instruction length can change based on the indexed addressing mode being used.
  • Some instructions are two bytes long, prefixed by $10 or $11 (the so-called page 2 and page 3 op codes).
Implementation was pretty straightforward. I used lookup tables for a number of things including op codes, instruction types, addressing modes, and mnemonics. I strove to make the code readable and avoided any tricks that might increase efficiency slightly at the expense of clarity.

It is mostly portable. It uses ASSIST09 monitor routines for i/o, but other than that could be used on other systems with minor changes.

I implemented over a few evenings, building it up in pieces. It took some time (but less than I expected) to handle all the index addressing modes and to correctly handle the differing instruction lengths and page 2/3 instructions.

My basic approaches for testing and debug were:
  1. Test low level functions, like PrintString, on their own with some test code.
  2. "Desk check" complex code on paper to try to verify the logic, use of registers, etc.
  3. Build it up in stages and confirm them working before adding on (e.g. initially just display hex bytes)
When I ran into bugs I used the "desk check" method as well as making use of breakpoints when running the code to see what it was doing at various steps. Having a working monitor to run, display and change memory and registers, etc. was a requirement and ASSIST09 worked well for that. Downloading new versions of code over the serial port only took a few seconds.

I initially ran it standalone, but at the end I was able to also support installing it as an external command in the ASSSIST09 monitor, so you can run it by typing U (for unassemble). ASSIST09 has calls to add new commands, so it can be done without changing the code in ROM.

Here is some sample output (disassembling the start of the ASSIST09 ROM code):

>U F800
F800  30 8D 68 BE  LEAX  $68BE ,PCR
F804  1F 10        TFR   X,D
F806  1F 8B        TFR   A,DP
F808  97 9D        STA   $9D 
F80A  33 84        LEAU  ,X
F80C  31 8C 35     LEAY  $35 ,PCR
F80F  EF 81        STU   ,X++
F811  C6 16        LDB   #$16 
F813  34 04        PSHS  B
F815  1F 20        TFR   Y,D
F817  E3 A1        ADDD  ,Y++
F819  ED 81        STD   ,X++
F81B  6A E4        DEC   ,S
F81D  26 F6        BNE   $F815 
F81F  C6 0D        LDB   #$0D 
F821  A6 A0        LDA   ,Y+
F823  A7 80        STA   ,X+
F825  5A           DECB
F826  26 F9        BNE   $F821 
F828  31 8D F7 D4  LEAY  $F7D4 ,PCR
F82C  8E 20 FE     LDX   #$20FE 
F82F  AC A1        CMPX  ,Y++
F831  26 02        BNE   $F835 
F833  AD A4        JSR   ,Y
PRESS SPACE TO CONTINUE, Q TO QUIT 

With a little more 6809 assembly language programming experience under my belt, it is interesting to compare it to the other 8-bit processor I am most familiar with, the 6502. Let me list a few thoughts here.

Having two accumulators is very handy. Often one is being used as an accumulator for some form of data, but another may be needed for indexing or as a parameter to calling another routine. Surprisingly, I also found myself using the 16-bit D register (which uses A and B) because I needed 16-bit data. Some functions, like addition and subtraction, are supported on the D register, but many only have 8-bit versions which you need to combine using several instructions to work on 16 bits of data.

Two index registers is also handy (the 6502 has two, but the 6809's predecessor the 6800 only had one). But I found in practice that I rarely needed a second one. Having 16-bit index registers, unlike the 8-bit registers of the 6502, was much more convenient as you often find you are using them to store addresses.

The 6502 typically makes the programmer heavily use addresses in the first 256 bytes of memory (page 0). Some key instructions and addressing modes can only work with page zero. For that reason, these tend to become valuable real estate and you can run out of them or run into collisions between different uses of them. In contrast, the 6809 has a more orthogonal instruction set and all relevant instructions can work with full 16-bit addresses. It does have direct mode (8-bit addresses) but with the Direct Page register you can have them work with any page of memory, not just page zero. I did not use this feature (the ASSIST09 monitor does) but I can see it being useful when you wanted to optimize the size of your code.

In general the 6809 is more orthogonal than the 6502, with few limitations on the addressing modes or operands of instructions. Unlike the 6502 you can push, pull, transfer, or exchange any registers. The push and pull (PSHS/PSHU/PULS/PULU) instructions are particularly nice in that you can push or pull a set of registers in one instruction. The order of push and pull is defined, so that you do not have to ensure that the order is correct in your code (provided you push and pull the same list of registers). There are two stack pointers, but I only used one. And of course, the 16-bit stack pointer is much more reasonable than the 8-bit stack on the 6502 that is fixed in page 1 of memory.

Transfer (TFR) and Exchange (EXG) are two other instructions which are very handy for moving registers around without any restrictions. The 6502 had some limitations on what registers you could transfer and had no equivalent to EXG.

The 6809 introduced a MULtiply instruction, which sounded at the time like a luxury for assembly language programmers. I actually used it in an early version of my disassembler program when I needed to multiply the offset to a table by 4 and get a 16-bit result. I felt it was overkill using a multiply to do this, and later did it using two shifts (you can easily implement a 16-bit shift of the D register using two instructions: ASLB, ROLA).

The 6809 has many more addressing modes than the 6502, with 24 variations of indexed addressing. I think it is unlikely that assembly language programmers would use the majority of these as just a few of them generally suffice. I suspect the original intention may have been to help support compilers of high-level languages that could use these.

One quirk with indexed addressing that could confuse programmers is that the 5, 8, and 16 b-t offset modes consider the offset to be signed. So, for example, the 5 bit offsets are not 0 to 31 but rather -16 to 15. If you have a lookup table of 256 elements, for example, and expect the 8-bit offset indexed addressing mode to access all of them starting from an offset of zero, you will be surprised when values of $80 and higher don't read the table entries you expected. I ran into this, and solved it by using 16-bit offset in this case.

One instruction that you could easily overlook is LEA (Load Effective Address). It might not seem particularly useful, essentially removing one level of indirection. In fact it is very useful, and is the key to a lot of efficient programming as it can make use of all of the indexed addressing modes and make code position independent.

The 6809 supports position independent code (PIC). The ASSIST09 monitor, for example, is fully position independent. It is not particularly hard to write PIC code, and I made some effort to try this in the disassembler. Mostly it is a matter of using branches rather than jumps and using the PCR (program counter relative) addressing mode when working with addresses. I did leave the memory locations in RAM used by the program at fixed addresses. One annoyance is that as code gets larger during development 8-bit branches often fail and need to be converted to long branches. Unlike some assemblers, the one I was using did not automatically select short or long branches as needed.

Overall, the 6809 is quite a pleasant processor to program, with more instructions, more and larger registers than the 6502. Of course, it is not really a fair comparison as it came a generation later and could make use of advanced in technology that allowed a more complex chip. The 6800 was of the same vintage as the 6502. In fact, the decision to use the 6502 over the 6800 in a number of early computers was based on cost. Compared to the $300 price tag of the 6800, the 6502 sold for $25. The Apple 1 was originally designed to use a 6800, but was converted to the 6502 when Steve Wozniak learned about it. The schematic diagram for the Apple 1 still listed the circuit changes needed on the board to use a 6800.

Sunday, January 27, 2019

A 6809 Single Board Computer


As well as the 6502, 6800, and 68000 chips, another CPU I used early in my career was the Motorola 6809, the more powerful successor to the 6800. Having completed some retrocomputing projects with the other chips, I start looking for a project where I could play with this CPU for nostalgia purposes.

I soon came across a Single Board Computer design by Grant Searle. A five or six chip design, it has serial i/o and can run a version of Microsoft BASIC that he adapted from the version in the Radio Shack Color Computer.

The basic specs are a 6809 processor running at just under 2 MHz, 32K of static RAM, 16K of EPROM, and a 6850 ACIA-based serial port.

The design is simple, potentially buildable on a breadboard, and had been reproduced by other people, so I decided to give it a try.

I entered my own schematic using the EasyEDA web-based CAD software. This would make it easier to make design changes and potentially a printed circuit board (PCB).

I made a few small changes in my version of the board:

  • Used a 6-pin connector for a standard FTDI USB to serial breakout board and omitted any RS-232 line driver/receiver circuitry. I also omitted the optional hardware handshaking circuit.
  • Added a simple power on reset circuit to the pushbutton reset.
  • Added a power on LED.
  • Provided a jumper to select USB or external power source.
  • Added a 32-pin header with access to most signals, for future expansion and to help with debug.

The system can plug into a computer's USB port where it shows up as a serial port. It is powered by USB (taking about 230 mA of current) and you communicate with it using a terminal emulator.

The provided BASIC is a port of Microsoft Extended BASIC for the 6809-based Radio Shack Color Computer. A disassembly of it was published in two books. In Grant Searle's port, all code and commands that were not applicable (e.g. graphics, sound, cassette tape i/o) were removed. It is just under 10KB in size. Pretty typical of Microsoft BASIC of the era, it has a few quirks, e.g. available memory i available from the variable MEM rather than a function FRE(). Extended Color Computer BASIC has some additional commands that are useful like RENUMber, additional math functions, PRINT USING, TRON/TROFF and even EDIT to support editing program lines. Apparently this was the last version of Microsoft BASIC that Bill Gates personally worked on. You can find online copies of books on the Colour Computer and its version of BASIC.

I took the BASIC firmware and got it to build under Linux using the as09 cross-assembler with no warnings. I found and fixed a small typo that might have affected the PRINT USING command.

I breadboarded the CPU, clock, and reset circuit on a solderless breadboard. Then I got the 6809 to free run by forcing all the data lines all low. I decided not to breadboard the entire circuit as it would be quite tedious to do so, wouldn't fit on my small breadboard, and the design looked stable and had been verified by others, so I opted to move directly to a PCB layout.

I made a PCB layout from EasyEDA (using the autorouter). Once it looked good, I ordered some PCBs from JLPCB, a partner of EasyEDA which offers PCBS for as little as $2 per board.

There are high quality double-sided boards with plated-through holes, silkscreened, solder masked and even electrically tested. They are built in about one day and arrive in about 5 business days. With the availability of suppliers like this, it really doesn't make sense to etch your own boards at home.


I had found and orders the remaining parts I needed on Ebay. Some, like the Motorola 68B50 and 68B09, are readily available as new old stock (NOS).


I programmed the firmware onto a 27C128 EPROM using my UV eraser and programmer.


Once the boards arrived, I build one up, starting with the power, then clock and reset circuits. Everything checked out and before long BASIC was up and running!

I read some books on Color Computer BASIC to review the commands, played with the commands and tested some old programs. Here is an example, a little horoscope program I wrote in BASIC some time again, which ran with some minor changes:

           YOUR HOROSCOPE
           --------------

THE PROGRAM GENERATES A PERSONAL
HOROSCOPE. I NEED SOME INFORMATION
ABOUT YOUR DATE AND LOCATION OF BIRTH.
I WILL THEN GENERATE AN ANALYSIS BASED
ON YOUR ASTROLOGICAL DATA.

WHAT IS YOUR FIRST NAME? Fred
YOUR YEAR OF BIRTH (E.G. 1980)? 1980
YOUR MONTH OF BIRTH (1=JAN)? 6
DAY OF THE MONTH (1-31)? 21
COUNTRY OF BIRTH? Canada
IN WHAT CITY? Ottawa
CALCULATING HOROSCOPE...PLEASE WAIT.

Fred, YOUR ASTROLOGICAL SIGN IS:
CANCER.

HERE IS MY ANALYSIS:

AT TIMES YOU ARE EXTROVERTED, AFFABLE,
SOCIABLE, WHILE AT OTHER TIMES YOU ARE
INTROVERTED, WARY, RESERVED.

YOU WORRY ABOUT YOUR HEALTH AS YOU GET
OLDER.

YOU ARE CONCERNED ABOUT THE HEALTH OF
AN AGING RELATIVE.

GENERATE ANOTHER HOROSCOPE (Y/N)? 

Looking for machine language monitors, I found source code for the ASSIST09 program that Motorola offers for their 6809-based development ports. I got it to cross-assemble under Linux, and modified it to work with the 6850 ACIA instead of what the Motorola hardware used. With a little debugging, I got it running. It works well, and provides most feature you want for development and debug, including memory display and change, register display and change, running and breakpoints, and generating and loading Motorola S record files. here is a sample session:

ASSIST09
>D 1000 20

      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  
1000 45 41 4C 49 53 54 49 43 2E 22 20 3A 20 90 00 10  EALISTIC." : ...
1010 56 2F 26 87 20 22 54 48 45 20 42 49 52 54 48 44  V/&. "THE BIRTHD
>R
PC-F842 A-00 B-00 X-20FE Y-F002 U-60C2 S-6051 CC-F4 DP-00 
PC-
>M 1000
45-55
>P 1000 100F
S13100055414C49535449432E22203A2090001014
S9030000FC
>

I am able to cross-assemble code on a Linux computer and then load the S record file onto the board via the serial port. This is much more efficient than erasing and burning EPROMs.


Note that for uploading you need to add delays due to no hardware handshaking. I use the ascii-xfr program on Linux to do this, as well as the minicom terminal emulator.

I wrote a couple of example programs that run with the ASSIST09 monitor, using it's SWI functions for i/o.

Next, I combined BASIC and ASSIST09 into one EPPROM. It comes up in ASSIST09 but you can get to BASIC using the "G D000" command. This offers the ability to play with BASIC or machine language without swapping EPROMs.

ASSIST09
>G D000
6809 EXTENDED BASIC
(C) 1982 BY MICROSOFT

OK
10 FOR I = 1 TO 10
20 PRINT I,
30 NEXT I
RUN
 1               2               3               4               5
 6               7               8               9               10
OK

I have built up a second board and am just waiting to receive a second 68B09 chip to complete it. I have a few programming projects in mind to work on, and some code (like a small C compiler) that I want to look at.

If you want to give this a design a try, I encourage you to do so. Feel free to use my PCB design files if you wish, or just breadboard it up.

References


  1. Grant's 6-chip 6809 Computer: http://searle.hostei.com/grant/6809/Simple6809.html
  2. My git code with firmware and other software: https://github.com/jefftranter/6809/tree/master/sbc
  3. EasyEDA project: https://easyeda.com/tranter/6809-Single-Board-Computer
  4. AS9 assembler: http://home.hccnet.nl/a.w.m.van.der.horst/m6809.html

Sunday, July 9, 2017

Building a 68000 Single Board Computer - 6809 to 68000 Assembly Language Source Translator

Unlike Intel, which made a decision to keep a high level of compatibility in their x86 processor line, from the 8086 through 286, 386, 486, and Pentium and beyond, Motorola made a clean break when they introduced the 68000. It didn't offer any software compatibility with their earlier processors like the 6800 and 6809.

However, Motorola offered a tool to help programmers port their source code from the 6809 to 68000 microprocessor. The tool, written in Pascal, was intended to do about 90% of the work of translation.

I was able to find a copy of this tool at http://www.retro.co.za/68000/XLATE09/ and try it out. It includes the tool (both executable and source code), documentation, and some sample files.

I was able to run the original trans09.com executable under using the dosbox MS-DOS emulator. I was also able to run it under Windows 10, but I got a number of errors that I had to ignore.

The tool was written in Pascal. It didn't specify which compiler it was targetted at, but it looks like pretty standard Pascal. I was able to compile it using the Free Pascal compiler under Linux with the addition of one line: "Uses Crt;". I made a few other changes to remove warnings about unused variables. The data files used by the program also needed to be renamed to lower case as Linux is case sensitive.

The tool ran quite well, working as described. Much of the translation rules are contained in data files which can be modified. It also uses some small routines which need to be assembled separately.

M6809 to M68000 Source Code Translator     Version 1.2
Systems Engg, E. Kilbride, Scotland
Motorola Inc. Copyright 1986

   Code in       Code out         Errors         Warnings
      17             23              0               4

The basic approach is to map the 6809 registers to corresponding 68000 registers, e.g. A to D0, B to D1, D to D2, X to A0, and Y to A1. It converts 6809 instructions to corresponding 68000 versions, e.g. LDA to MOVE, and points out possible problem areas, like where the behavior of the overflow flag may be different. Some instructions cannot be converted at all. The intention is that this might do about 90% of the conversion and a programmer would need to do the rest.

Here is a sample conversion, first the 6809 code:

* Sample input program
NULL     EQU   0
         CMPA  #9
         BLS   CB1HX1           branch if number is 0-9
         ADDA  #7               number is 10-15 so add 7 to make it A-F

CB1HX1   ADDA  #'0              add the ASCII offset
         RTS

OP1HEX   PSHS   A               save the binary number
         BSR    CB1HEX          convert the number to its ASCII equivalent
         LBSR   OPCHAR          and output it to the system terminal
         PULS   A,PC            restore the binary number and exit
         EXG    A,B             save the l.s. ASCII character in B; original 8-bit number to A
         LSRA                   shift the m.s. half byte into the l.s half byte
         LSRA
         LSRA
         LSRA
         NOP
         RTS                    leave the m.s. ASCII character in A

And now the resulting 68000 version generated by the tool:

*++       ******   STUB EXTERNAL REFERENCES  ******

                  XREF ..DIN,..DOUT,..JSR,..RTS,..CTOX,..CREP
                  XREF ..DPR,..DPW,..CLRAB,..MUL,..INIT,..VREP
          
* Sample input program
NULL      EQU 0                 
          CMP.B #9,D0           
          BLS CB1HX1            branch if number is 0-9
          ADD.B  #7,D0          number is 10-15 so add 7 to make it A-F

CB1HX1    ADD.B  #'0',D0        add the ASCII offset
          BSR ..RTS              

OP1HEX    MOVEM.L D0,-(A6)      save the binary number
          BSR CB1HEX            convert the number to its ASCII equivalent
          BSR OPCHAR            and output it to the system terminal
          MOVEM.L (A6)+,D0      restore the binary number and exit
          MOVE.L (A6)+,A3       
          JMP (A3)              
          EXG.L  D0,D1          save the l.s. ASCII character in B; original 8-
*                               bit number to A
          LSR.B #1,D0           shift the m.s. half byte into the l.s half byte
** WARNING **                      * V-BIT CLEARED *
          LSR.B #1,D0            
** WARNING **                      * V-BIT CLEARED *
          LSR.B #1,D0            
** WARNING **                      * V-BIT CLEARED *
          LSR.B #1,D0            
** WARNING **                      * V-BIT CLEARED *
          NOP                    
          BSR ..RTS             leave the m.s. ASCII character in A

To actually use this tool you may need to modify it and/or the data files to work with your particular 68000 cross-assembler. For example, the VASM assembler I use does not like the stub routine names starting with two dots like "..RTS" but will accept them with only one dot (e.g. ".RTS").

I've put my test files and notes here: https://github.com/jefftranter/68000/tree/master/xlate09

I don't know if anyone used this tool to port any significant programs for the 6809 to 68000, but it is a rather interesting tool and the concept could be applicable to other processors. It is also an alternative approach to emulation, which is often use but has a different set of tradeoffs (like performance).

Thursday, April 5, 2012

Nostalgic Musing on CPUs

The first processor I learned was the 6502 on an Ohio Scientific Superboard computer. My main resource for learning was the book Programming a Microcomputer: 6502 by Caxton Foster, which was written for the KIM-1 computer but was pretty generic. I wrote a disassembler, a simple assembler, and some games. Later I got an Apple //e and did some more 6502 programming with it, along with BASIC, and Pascal.

Ohio Scientific Superboard


I used a 6800 in university and at a summer job at the university working on an embedded data acquisition system. The graduate student writing the code had no source code, he just typed in the bytes and burned them into an EEPROM! I adapted my disassembler in BASIC from the 6502 to the 6800 to disassemble the EEPROMs and make a hardcopy of the code.

At school I also used a 6800 cross-assembler on a minicomputer for labs on a small KIM-1 like single board computer. I remember it had a minor bug - it assembled the NOP instruction wrong! In a CS course I did a little assembler programming on a mainframe that had 60 bit words - I believe it was a CDC Cyber.

When I started working in the mid 80's I worked on developing equipment for manufacturing testing. It was all custom and used Motorola processors. It started with the 6800 but mostly used 6809 for new development by that time. The 6809 was a big improvement over the 6800 having more registers and addressing modes. You had 16-bit registers and could write position independent code. It could even do an 8-bit multiply! I spent many hours programming EEPROMs or waiting for them to be erased under an ultra violet light so I could test my latest version of code.

Then the 68000 came out and it was an embarrassment of riches to have 16 32-bit registers and a MOVE instruction that could move from anywhere to anywhere. It ran at a blazing 8MHz! I didn't actually do much assembler programming on the 68000 because by then we were mostly using higher level languages like C and Pascal (and a language called Concurrent Euclid that you probably haven't heard of). 

I still have a soft spot in my heart for the 6502 as all the programming I did on it was done for fun. It was the first processor I learned, and it has an elegant simplicity to it.

Actually, I wasn't entirely correct when I said I first learned the 6502. Some time when I was under 10 years old my father introduced me to the CARDIAC computer: CARDboard Illustrative Aid to Computation.  The short book and cardboard model was a hypothetical processor that taught how processors work at the fundamental level. It was a simple CPU with 10 instructions and the student used the cardboard model to execute instructions in a program himself. Copies of the booklet and computer are available on the Internet. Even the original cardboard CARDIAC is still available.

Cardiac Computer
Accompanying Booklet

I remember at the time I found it hard to resolve the wide gap between this explanation of a computer with what I saw in the media, such as the robot in Lost In Space or computer on Star Trek. I was also given a book called The How And Why Wonder Book Of Robots And Electronic Brains that probably set some unrealistic expectations about computers too.

 

On my to do list is to write a simulator for the CARDIAC, probably graphical in C++ using the Qt toolkit.