Homemade Floating Point Interpreter for 6502

The CI-2 is a homemade floating point simple interpreter language by hand assembling for my 6502 computer PERSEUS-8 and PERSEUS-9.

Similar projects worth following
I have a dream. It is to build a floating-point computer programming system by myself. Here is a description of the challenge. Currently, there are already many programming languages in existence, and precision floating point arithmetic and function value calculation have been put to practical use. Here, I would like to take a method that I find easy to create, without being bound by standardized specifications. The concepts are as follows.
(1) The development environment will be completed only on PERSEUS-8 without using any other computer. This is to re-evaluate the value of a computer that has toggle switches as its user interface.
(2) Attempt to implement elementary functions such as sine, exponential, etc. in order to make it somewhat practical.
The assembly code of the system is shown in the attached file (ASSEMBLY_CODE_CI-2_V2_0_0.pdf).
(3) As an application program, I will try to program signal processing, which has been widely used from the 1970s to the present computers.

1. System requirements

The CPU of the computer to be run is the 6502, which was widely used about 45 years ago. The total memory requirement for the system and user area is 16kB. The user interface uses a RS232C serial terminal. Figure 1 shows the execution of this interpreter CI-2 (Computation Interpreter -2).

                                                Fig.1  Floating point interpreter CI-2 running on my 6502 computer PERSEUS-8

2. Language specification

The language specifications are listed in the following. This specification was not defined exactly at the beginning, but was the result of trial and error. The details of the language specification are shown in the attached file (Specification of Floating Point Computation Interpreter CI-2 V2_0.pdf).

    The numeric values were set to 32-bit single-precision floating-point type. In order to simplify the conversion of ASCII code to numbers, BCD notation was used instead of binary. Therefore, the number of significant digits and the numerical range are inferior to those of general single-precision arithmetic systems. In order to avoid parsing, variables and instructions were defined as single letters of the alphabet. The formula uses RPN (Reverse Polish Notation). This is also to avoid parsing.

    There are three one-dimensional array variables:)X,)Y,)Z. The arguments range from 0 to 255. This alone occupies 3kB of memory. There is no statement equivalent to a FOR loop, but I decided to use a conditional branch and a jump to the specified line number instead. Therefore, it is not suitable for large-scale programming.

    The following is an example of programming description and its execution. The line number 230 ‘N)X=N P K** M/)S’ is ‘X(N)=sin((K*P*N)/M)’ in a typical language description. The line number 480 ‘L M?< 445!’ means ‘if L<M then go to 445’. Command ‘@’ from the terminal is the display of the program list, and command ‘!’ is to execute the program.

    The upper limit of the user program area is set by manually writing to the zero-page area only at the first startup so that it can be varied according to the memory capacity of the system. In PERSEU-8, the memory limit is $1FFF, so type 130$=31 in the direct mode pointer variable. This will set the upper byte $1F of the upper memory limit address in the register $0082. In PERSEUS-8, the user memory area is 4 kB, so the maximum number of characters in a user program is approximately 3840

3. Software configuration 

Figure 2 shows the block diagram of this interpreter system. The system will wait for one line of input after startup. After inputting a single line from the serial interface, it analyzes it one character at a time from the left of the line buffer. Here, if a line number is detected at the beginning of a line, the process moves to the line editor. If no line number is detected, parse one character at a time as direct execution mode. This ‘MAIN LOOP’ process is mapped from address $E8F0 in the assembly code. If it is a number, it is converted to BCD and stored in the floating point register. This ‘GET FLOATING POINT’ process is mapped from address $E0F7 in the assembly code. If it is an arithmetic operator or a command, it moves to the respective processing routine. If a ‘CR’ code is detected, perform the assignment and register value display, and return to waiting for one-line input. This ‘END LINE’ process is mapped from address $EDB9 in the assembly code.

    Program execution is performed by setting the execution flag upon detection of a ‘! ‘ code and the execution flag is set. Once the execution flag is raised, a single line of analysis is executed from the beginning of the program area. In the case of a conditional branch statement, the line with the line number...

Read more »

Specification of Floating Point Computation Interpreter CI-2 V2_0.pdf

Specification and quick manual of the Floating Point Interpreter CI-2

Adobe Portable Document Format - 34.56 kB - 07/31/2023 at 10:35



Assembly code of the interpreter

Adobe Portable Document Format - 2.05 MB - 07/31/2023 at 10:34



Programming and execution example

Adobe Portable Document Format - 11.87 kB - 03/20/2023 at 23:39



Assembly code of the interpreter

Adobe Portable Document Format - 406.31 kB - 03/14/2023 at 04:25


Specification of Floating Point Computation Interpreter CI-2 V1_5.pdf

Specification and quick manual of the Floating Point Interpreter CI-2

Adobe Portable Document Format - 34.46 kB - 03/14/2023 at 04:25


View all 11 files

  • CI-2 project log

    Mitsuru Yamada08/10/2021 at 13:00 0 comments

    1. The article was first posted on Aug. 6, 2021

    2. Revised on Aug. 10, 2021

         Corrected mistake in Fig. 3.

    3. Revised on Sep. 4, 2021

        Updated the assembly code to Ver. 1.1.0. The exponent part is always set to zero when the result of an operation is zero.

        As an application example, Fast Fourier Transform program and execution example were added to the attachment.

        Added single lowercase letters to variable names.

    4. Revised on Nov. 4, 2021

        Added  Chapter 11, "Making ROMs of the interpreter" to the Details.

    5. Revised on Dec. 31, 2021, Jan. 4, 2022

        To the Details, added programming & execution example, Fig. 7 "Calculation of natural logarithm function" and corrected Fig. 6.

    6. Revised on Jan. 24, 2022

        To the Details, inserted new chapter 10, "Application example", new Fig. 9.

        Added maximum operating clock frequency value to the chapter "Making ROMs of the interpreter".

    7.  Revised on Mar. 5, 2022

        To the Details chapter 10, added video link "Homemade Floating Point Interpreter computes FFT".

    8. Revised on Apr. 9, 2022

        Updated assembly code version to Ver. 1.2.0, for bug fix for square root function argument zero.

    9. Revised on May 13, 2022

        Added Fig. 6 for square root calculation and Fig. 7 for sine function calculation to chapter 6 "Elementary functions".

    10. Revised on May 14, 2022

        Added handling of negative arguments to the description of the exponential function calculation in Chapter 6.

    11. Revised on Nov. 30, 2022

        Added the demo video for executing of an application program of calculating planet positions in Chapter 11. 

    12. Revised on Dec. 13, 2022

        Updated the assembly code of the attachment to version 1.4.1, resolving a bug that caused an error in the function calculation for every 256 characters of the user program. 

        A description of the defects found so far and the assembly code version updates that resolved them were added to Chapter 9.

    13. Revised on Feb. 2, 2023

        Corrected Fig. 2 in Chapter 3.

        Added Fig. 5.1 for multiplication flowchart, and Fig. 5.2 for division flowchart in Chapter 5.

    14. Revised on Feb. 7, 2023

        The variable names in Fig. 9 were modified to match the comments in the source code.

    15. Revised on Mar. 14, 2023

        Updated the assembly code of the attachment to version 1.5.0, allow user program area limit to be set and correct normalize bug when the mantissa part is zero.

        Added Fig. 12 of PROM programmer in Chapter 12.

    16. Revised on Mar. 21, 2023

        Added Video 3 to introduce updating the interpreter by using the PROM programmer.

        Correct the power spectrum at zero of execution example in Chapter 2.

    17. Revised on Aug. 01, 2023

        Added program loading command using parallel interface, updated assembly code version to Ver. 2.0.0

        Added Chapter 8 "program loading" and moved up subsequent chapter numbers.

View project log

Enjoy this project?



don.ware wrote 09/23/2021 at 14:04 point

As always, this is an excellent presentation from you. I will have to sit quietly and study it further. Thanks !

  Are you sure? yes | no

Mitsuru Yamada wrote 09/24/2021 at 00:38 point

Thank you very much. It's quite difficult to explain these software. If I give too many detailed explanations, many people will probably not find it interesting to read. This time, I focused on the main points I wanted to convey.

  Are you sure? yes | no

zpekic wrote 09/05/2021 at 02:41 point

Super cool project! I was toying with the idea of creating a BCD floating point component using my microcode language / compiler. I have some experience with floating point as I recreated the Texas Instruments calculator chip based on another project. Even bigger challenge would be to re-create a AMD Am9511 FPU accelerator core!

On the side code, I also wonder about using 10's complement for exponent, as it is different than the mantissa format. I am bit familiar with BCD and I wrote a add/sub ALU with binary/decimal, actually very similar to 6502 patent (with D bit). Wouldn't it be better to use bit 7 and bit 6 as signs in the exponent byte, which would still leave exponent in 00-39 range.

  Are you sure? yes | no

Mitsuru Yamada wrote 09/05/2021 at 06:55 point

Thank you for your advice. At first, I considered allocating three bytes for the mantissa part and one byte for the exponent part in the same format. That was simple, but in order to make the number of digits in the mantissa part as large as possible, considering the generation of elementary functions, etc., I placed the sign bit of the mantissa in the exponent byte. 

Then 7 bits are the exponent, which can be done in three ways: the signed absolute value same as the mantissa part, the complement, or a positive number in offset form. There are three possible ways to do this: a signed absolute value like the mantissa part, the complement, or a positive number in offset form. I started with the complement for now, and realized halfway through that it was a bit of a hassle, but I ended up completing it this way. 

Since It often need to compare the exponents in the normalization before floating-point addition and subtraction, and to add and subtract exponents in multiplication and division, I think a format that allows me to do this simply is probably the best. So, in general, I think an offset method is used for the exponent part instead of the complement.

  Are you sure? yes | no

zpekic wrote 09/08/2021 at 04:03 point

So your offset for exponent is 50, everything below 50 is negative, and over 50 positive exponent? This is trick used to spare the exponent sign. I wonder if same could be applied to mantissa too, and use offset 0.5 to represent zero, and that way save the mantissa sign too. Of course, the problem is that negative number would be represented weirdly. Probably not a good idea, never seen such encoding :-)

  Are you sure? yes | no

Paul Fernquist wrote 08/10/2021 at 04:08 point

The exponent is 1's complement . The mantissa is 2's complement. Calling them a complement is a little strange,  to me. I designed a floating point divide instruction for a mainframe many many years ago so  my memory is a little fuzzy. Sounds like a fun learning experience..

  Are you sure? yes | no

Mitsuru Yamada wrote 08/10/2021 at 06:51 point

Thank you for your comment. The exponent part is used by converting 8 bits of BCD (Binary Coded Decimal), which is specific to this CPU, to 7 bits. The example values are +39(BCD)='0111001', +1(BCD)='0000001', 0(BCD)='0000000', -1(BCD)='1111001', -39(BCD)='1000001', which is different from the general 2's complement and 1's complement. I think the lower 4 bits are probably better described as 10's complement. I'd like to consider how to explain it better.

Figure 3 was wrong and has been corrected. I apologize for the error.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates