<<

ENHANCEMENT OF MC68000 SIMULATOR MACROS TO SUPPORT

FLOATING POINT NUMBER

______

A Thesis

Presented to the

Faculty of

San Diego State University

______

In Partial Fulfillment

of the Requirements for the Degree

Master of Science

in

Computer Science

______

by

Honey Walia

Spring 2012

iii

Copyright © 2012 by Honey Walia All Rights Reserved

iv

ABSTRACT OF THE THESIS

Enhancement of MC68000 Simulator Macros to Support Floating Point Number by Honey Walia Master of Science in Computer Science San Diego State University, 2012

The purpose of this thesis is to write macros to support floating point number for BSVC simulator. This simulator provides a runtime environment which simulates a family CPU system. This system is currently used at SDSU to teach machine organization and assembly language programming to students in CS237. This thesis provides significant enhancements to the functionality of the system, making it more valuable tool for classroom instruction.

v

TABLE OF CONTENTS

PAGE

ABSTRACT ...... iv LIST OF FIGURES ...... vii ACKNOWLEDGEMENTS ...... viii CHAPTER 1 INTRODUCTION ...... 1 1.1 BSVC History ...... 1 1.2 Motivation ...... 2 2 MOTOROLA 68000 ASSEMBLY LANGUAGE BACKGROUND ...... 3 2.1 The MC68000 Family ...... 3 2.2 Trap ...... 3 2.3 Macro ...... 4 2.4 Macro Preprocessor ...... 4 2.5 Trap 13 ...... 4 3 TRAP14 ...... 6 3.1 What are Floating Point Numbers? ...... 6 3.2 Storage Layout ...... 6 3.2.1 The Sign Bit ...... 7 3.2.2 The Exponent ...... 7 3.2.3 The Mantissa ...... 7 3.2.4 Putting it All Together ...... 8 3.3 The Problem ...... 8 3.4 The Solution ...... 8 3.4.1 Addition ...... 8 3.4.2 Subtraction ...... 9 3.4.3 Multiplication ...... 9 3.4.3.1 Code Snippet ...... 10 3.4.3.2 Special Case ...... 11

vi

3.4.3.3 Code Snippet ...... 11 3.4.4 Division ...... 13 3.4.5 Special Case ...... 14 4 FUTURE WORK DOUBLE PRECISION FLOATING POINT NUMBERS ...... 15 REFERENCES ...... 16 APPENDIX A BSVC SYSTEM ...... 17 B FLOAT I/O MACRO ...... 19 C TRAP 14.S ...... 24 D TRAP14 MACRO ...... 50 E TRAP14 DEMO PROGRAM ...... 57

vii

LIST OF FIGURES

PAGE

Figure 3.1. Floating-point representation...... 7

viii

ACKNOWLEDGEMENTS

I want to express my gratitude to my advisor Mr. Alan Riggins for giving me an opportunity to work on this thesis project and for his constant guidance, support and motivation throughout this project. I am grateful to Dr. Leland Beck, for trusting me with this project. I am also thankful to Professor Tunc Geveci for being on my committee and for his co-operation.

1

CHAPTER 1

INTRODUCTION

1.1 BSVC HISTORY BSVC is a microprocessor simulation framework written in C++ and TCL/TK. It simulates Motorola 68000 family of microprocessors. It was developed as a senior design project at North Carolina State University by Bradford W. Mott in 1993. Since then, many professors and students have been using BSVC and found it a very useful tool in courses based on the Motorola 68000 family (for different parts of simulator see Appendix A).. BSVC was originally written for Unix , however, it has been ported to windows. The Windows version has the same features as the Unix version except the Motorola 68000 simulator does not support the M68681 Dual UART. The Computer Science department of San Diego State University has been using BSVC for its undergraduate assembly class and has found BSVC to be a very useful tool. However input and output are not part of the assembly language. They need to be accomplished by the use of library functions. The original development of BSVC does not include input and output libraries. This made work requiring input and output impossible, which is inconvenient to both students and professors who are using the simulator. In 1998, Professor Marko Vuskovic at San Diego State University wrote a trap 15 that contained some I/O routines to handle input and output on a Unix system. Trap 15 was revised and expanded to include a complete set of I/O routines by Professor Sara Baase and Alan Riggins at San Diego State University [1]. The new library was renamed trap13 to distinguish it from Professor Vuskovic's work. In 2003, Alan Riggins ported the I/O routines to windows system. Before that any programming requiring input/output had to be done either at school, which is inconvenient to students, or using x-window to remote log in to the school server from a PC, which makes the remote connection very slow.

2

1.2 MOTIVATION The Motorola 68881 and Motorola 68882 were floating-point chips that were used in some computer systems in conjunction with the 68020 or 68030 CPUs. The addition of one of these chips added a floating point unit that could rapidly perform floating point math calculations. This was useful mostly for scientific and mathematical software. BSVC simulator does not support floating point numbers. Floating point numbers have a variety of practical uses and are a very important component to an assembly language. Without support for floating-point numbers, the BSVC simulator is incomplete and it is difficult for professors and students to program any floating-point number related programs. Because of this Professor Carl Eckberg at San Diego State University proposed to write a trap that would add floating- point number input/output, addition, subtraction, multiplication and division into the BSVC simulator. In 2004, Huijuan Yin, student at San Diego State University wrote a trap 14 to support floating point numbers. Trap 14, when given input greater than 7 digits before decimal point or greater than three digits after decimal point it failed. So, Professor Alan Riggins proposed to find a solution to support floating point calculations (32 bit- precision) for all valid inputs.

3

CHAPTER 2

MOTOROLA 68000 ASSEMBLY LANGUAGE BACKGROUND

2.1 THE MC68000 FAMILY Early computer systems were programmed using machine language which was slow and error prone. High level programming languages increase programmer productivity but compiled code is usually both larger and less efficient. The need for a language that can directly access machine instruction is obvious. Assembly language grew out of this need then. Assembly language programming is writing machine instructions in mnemonic form, using an assembler to convert these mnemonics into actual processor instructions and associated data. A microprocessor is a collection of circuits packaged on a small silicon chip [2]. Motorola 68000 is the first member of motorola family of 16- and 32-bit microprocessors and it is the successor to the and followed by the . The 68000 was initially released in 1982. The other family members include MC68020, MC 68030and MC 68040. There are separately sold auxiliary devices called available to MC 68000 processors. The MC68881 and MC68882 are two of them. They are separate chips designed to perform floating point operations in hardware [3].

2.2 TRAP Traps are in the class of internal exceptions and are generated by specific MC 68000 instructions. The TRAP execution is used to make a system call from a user program. The TRAP instruction is used to request that the operating system perform a task. The user program is suspended until the task has been performed and then continues normal execution when the operating system returns from the execution.

4

2.3 MACRO A macro is like a subroutine in that the macro consists of assembly instructions which are defined and associated with an identifier. A macro differs from a subroutine in that the call to a subroutine will transfer the program control to the subroutine section and returns to the calling program after execution is finished, while the call to macro will result in a code expansion in the place where the macro was called. Macros execute faster than subroutines, but take more memory if they are long and are called often. Macros play important roles in exception handlers. Macros are used to package the subroutines in the exception handler so the user program calls the macro instead of using the subroutine in the exception handler directly. For example, the macro cvt2a for trap13 packages the subroutine that converts a two's complement number to an ASCII string of trap13. To do the conversion, the user program just needs to call the macro cvt2a and pass the correct parameters without worrying about the details of the calling process. The macro must be defined before it can be used. The macros defined for trap 13 are stored in a file called iomacs.s. To use trap 13, this file has to be included in the user program.

2.4 MACRO PREPROCESSOR The BSVC simulator is in use at a number of universities, including San Diego State. It provides a superior environment for the development of 68k assembly language programs. It, however, lacks a macro preprocessor. To address this shortcoming, a group of students in Professor Nenad Marovac's Software Engineering class designed and developed a macro preprocessor for use with the BSVC simulator as part of a course project in 1998. The original macro preprocessor was revised and improved by Professor Vernor Vinge's Systems Programming class in the Fall 1999 semester. When the macro is invoked, the instructions contained in the definition of the macro are substituted for the macro call and this is called macro expansion. Macro expansion is done through the using of the macro preprocessor.

2.5 TRAP 13 Trap 13 was written to address the lack of input/output libraries for the BSVC simulator. Main entry the main entry is used to save registers and dispatch the handler to the special I/O function, therefore all calls to the I/O subroutine have to go through the main entry.

5

Init13 intializes the simulator device called M68681 Dual Universal Asynchronous Receiver/Transmitter(DUART). It resets the MR1A and MR2A pointers, sets the size of each character to be of 8 bits, sets the port mode to be normal, sets both receiver-clock and transmitter-clock to be 9600, and enables the transmitter and receiver. Instr gets an input string from the keyboard. It stops when the input character is a carriage return. It also limits the length of the string to 80 characters. If input exceeds 80 characters, it will still be output to the screen but will not be stored. Outstr outputs a string to the screen. It stops when the character it encounters is a null character. Cvta2 is used to convert an ASCII string to a two's complement number. Everything input from the keyboard is ASCII code. In ASCII code, digits 0 through 9 are stored as $30...$39. If you want to input a number, eg. 12, from keyboard, it will be represented as two ASCII characters ''1'' and ''2'' and the values stored in the memory will be $31 and $ 32 accordingly. The macro cvt2a takes the string from the keyboard, first checks to see if the first character is a sigh character such as ''-'' or ''+'', then subtracts $30 from each of the digit and multiplies by 10 repeatedly to get the value of the data. Cvt2a is used to convert the two's complement number back to an ASCII string. To output something to the screen, it has to be an ASCII string. For example, if you want to output something to the screen, it has to be an ASCII string. For Example, if you want to output a decimal value of ''12'' to the screen, it has to be sent as two ASCII characters ''1'' and ''2'' or $31 and $ 32. The ASCII code ''12'' is the form feed character often represented by ''\f''. The conversion algorithm is to keep dividing the number by 10, and for each remainder, subtract $30. If the number is negative sign is also added to the string [4].

6

CHAPTER 3

TRAP14

3.1 WHAT ARE FLOATING POINT NUMBERS? There are several ways to represent real numbers on computers. Fixed point places a radix point somewhere in the middle of the digits, and is equivalent to using integers that represent portions of some unit. For example, one might represent 1/100ths of a unit; if you have four decimal digits, you could represent 10.82, or 00.01. Another approach is to use rationals, and represent every number as the ratio of two integers. Floating-point representation - the most common solution - basically represents reals in scientific notation. Scientific notation represents numbers as a base number and an exponent. For example, 123.456 could be represented as 1.23456 × 102. In hexadecimal, the number 123.abc might be represented as 1.23abc × 162. Floating-point solves a number of representation problems. Fixed-point has a fixed window of representation, which limits it from representing very large or very small numbers. Also, fixed-point is prone to a loss of precision when two large numbers are divided. Floating-point, on the other hand, employs a sort of "sliding window" of precision appropriate to the scale of the number. This allows it to represent numbers from 1,000,000,000,000 to 0.0000000000000001 with ease.

3.2 STORAGE LAYOUT IEEE floating point numbers have three basic components: the sign, the exponent, and the mantissa. The mantissa is composed of the fraction and an implicit leading digit (explained below). The exponent base (2) is implicit and need not be stored. Figure 3.1 shows the layout for single (32-bit) and double (64-bit) precision floating- point values. The number of bits for each field are shown (bit ranges are in square brackets):

7

Sign Exponent Fraction Bias Single Precision 1 [31] 8 [30-23] 23 [22-00] 127 Double Precision 1 [63] 11 [62-52] 52 [51-00] 1023 Figure 3.1. Floating-point representation.

3.2.1 The Sign Bit The sign bit is as simple as it gets. 0 denotes a positive number; 1 denotes a negative number. Flipping the value of this bit flips the sign of the number.

3.2.2 The Exponent The exponent field needs to represent both positive and negative exponents. To do this, a bias is added to the actual exponent in order to get the stored exponent. For IEEE single-precision floats, this value is 127. Thus, an exponent of zero means that 127 is stored in the exponent field. A stored value of 200 indicates an exponent of (200-127), or 73. For reasons discussed later, exponents of -127 (all 0s) and +128 (all 1s) are reserved for special numbers. For double precision, the exponent field is 11 bits, and has a bias of 1023.

3.2.3 The Mantissa The mantissa, also known as the significand, represents the precision bits of the number. It is composed of an implicit leading bit and the fraction bits. To find out the value of the implicit leading bit, consider that any number can be expressed in scientific notation in many different ways. For example, the number five can be represented as any of these:

• 5.00 × 100 • 0.05 × 102 • 5000 × 10-3 In order to maximize the quantity of representable numbers, floating-point numbers are typically stored in normalized form. This basically puts the radix point after the first non-zero

digit. In normalized form, five is represented as 5.0 × 100. A nice little optimization is available to us in base two, since the only possible non- zero digit is 1. Thus, we can just assume a leading digit of 1, and don't need to represent it

8 explicitly. As a result, the mantissa has effectively 24 bits of resolution, by way of 23 fraction bits.

3.2.4 Putting it All Together So, to sum up: 1. The sign bit is 0 for positive, 1 for negative. 2. The exponent's base is two. 3. The exponent field contains 127 plus the true exponent for single-precision, or 1023 plus the true exponent for double precision. 4. The first bit of the mantissa is typically assumed to be 1.f, where f is the field of fraction bits [5].

3.3 THE PROBLEM In 2004, Huijuan Yin wrote macros for floating point number I/O and arithmetic calculations for BSVC simulator (for float I/O macro see Appendix B). But the macros failed to work for very big and very small floating point number. So, professor Alan Riggins proposed to study and modify macros written by Huijuan Yin.

3.4 THE SOLUTION After studying Huijuan Yin's written routines, it was clear that the code fails to retain the significant digits. The trap 14 routine when given input as very large or very small floating point number, it truncates the most significant digits instead of truncating the least significant digits (for trap 14.s see Appendix C). So, the solution was to work on retaining significant digits. The modified routine written for Trap14 addresses the problem (for trap 14 macro and trap 14 demo program see Appendix D, Appendix E). There are basically four arithmetic operations that TRAP14 supports as follows: • Addition • Subtraction • Multiplication • Division

3.4.1 Addition There are four steps between entering an input floating point number and getting the output as a floating point number.

9

1. Getting an input from user 2. Converting ASCII to floating point number format 3. Adding the floating point numbers 4. Converting floating point result to ASCII string to be displayed on screen to user Huijuan Yin code fails at step 2 when input is very big or very small floating point number. In the proposed solution for very big and very small floating point number, if the user enters more than 8 decimal digits than most significant 7 or 8 decimal digits are retained. So, what goes inside can be described with an example. • Let the first no. entered be: 2222222222211 • Let the second no. entered be: 33333333300 How the modified code handles inside: • The first number is taken as: 2222222 • The second number is taken as: 3333333 The count of lost significant digits in decimal is saved for later use. The numbers need to be aligned, after alignment we get • The first number is taken as: 2222222 • The second number is taken as: 33333 So, the addition algorithm actually works on above specified numbers. • The result after addition is: 2255555 Before the result of addition is output to screen, the count of lost decimal digits is postfixed to get the correct output. • Output displayed on screen: 2255555000000.000000

3.4.2 Subtraction Subtraction can be taken as an addition case only where first number entered is subtracted from second number entered.

3.4.3 Multiplication There are four steps between entering an input floating point number and getting the output as a floating point number. 1. Getting an input from user

10

2. Converting ASCII to floating point number format 3. Multiplication of the floating point numbers 4. Converting floating point result to ASCII string to be displayed on screen to user Huijuan Yin code fails at step 2 when input is very big or very small floating point number. In the proposed solution for very big and very small floating point number, if the user enters more than 8 decimal digits than most significant 7 or 8 decimal digits are retained. So, what goes inside can be described with an example. • Let the first no. entered be: 1000000011 • Let the second no. entered be: 1000000011 How the modified code handles inside: • The first number is taken as: 1000000 • The second number is taken as: 1000000 The count of lost significant digits in decimal is saved for later use. Huijuan Yin code fails at step 3 for some of the calculations where mantissa goes bigger than 24 bits. So, right shift is done to retain significant bits and mantissa of product is truncated to 24 significant bits.

3.4.3.1 CODE SNIPPET move.b #8,muul ;Walia.... code inserted to save significant digits btst.l #31,d0 bne kk09 move.b #7,muul btst.l #30,d0 bne kk09 move.b #6,muul btst.l #29,d0 bne kk09 move.b #5,muul btst.l #28,d0 bne kk09 move.b #4,muul btst.l #27,d0 bne kk09 move.b #3,muul

11

btst.l #26,d0 bne kk09 move.b #2,muul btst.l #25,d0 bne kk09 move.b #1,muul btst.l #24,d0 bne kk09 move.b #0,muul

kk09:

clr.l d5 ; Walia...... code inserted to get right exponent move.b muul,d5 ; and mantissa after multiplication add.w d5,EXPO(a0) lsr.l d5,d0 move.l d0,MANTI(a0)

3.4.3.2 SPECIAL CASE Huijuan Yin written routine to convert floating point to ASCII works good till exponent equals 30(in decimal). So, if exponent is greater than 30 ;logic needs to be applied. For each additonal 1(in decimal) increase in exponent we need to double the output. Example : If exponent equals 33, that means increase in exponent is 3 (in decimal). So output has to be doubled three times. If 2 is the output, in first step it will become 4, than 8 than 16. Hence 16 will be the correct output.

3.4.3.3 CODE SNIPPET clr.l d1 move.w #$51e0,d1 move.l d1,a1 move.b #4,d0 add.l #3,a1 clr.l d1 move.b (a1),counter cmpi.b #30,counter blt gd

12

subi.b #30,counter ;Walia... In multiplication we get the right ;floating point product in internal format ty: cvtfa mem2,pro ; but the macro to convert it to ASCII works cmpi.b #0,counter ;till exponent is 30(in decimal). blt gj ;So, it need to be checked and logic applied if ;exponent greater than 30 to get right product value. hjk: cmpi.b #0,counter beq gj lea pro,a1 tr: add.b #1,jkl cmpi.b #'.',(a1)+ bne tr subi.b #1,jkl move.b #0,d0 swap d0 move.b jkl,d1 move.b d1,d0 clr.l d1 clr.l d2 hdf: cvtaf pro,mem1 fadd mem1,mem1 cmpi.b #1,counter bne dd dd: move mem2,mem1 move.l #$51d3,d0 move.w d0,a1 move.l #$51e3,d0 move.w d0,a2 move.b (a2),d0 move.b d0,(a1) clr.l d7 cmpi.b #1,counter bne xcv move.b #2,d7

13

xcv: cvtfanew mem2,pro subi.b #1,counter move.b #0,jkl bra hjk

So, the multiplication algorithm actually works on above specified numbers. • The result after multiplication is: 999999200000 Before the result of multiplication is output to screen, the count of lost decimal digits is postfixed to get the correct output. • Output displayed on screen: 999999200000000000.000000

3.4.4 Division There are four steps between entering an input floating point number and getting the output as a floating point number. 1. Getting an input from user 2. Converting ASCII to floating point number format 3. Division of the floating point numbers 4. Converting floating point result to ASCII string to be displayed on screen to user Huijuan Yin code fails at step 2 when input is very big or very small floating point number. In the proposed solution for very big and very small floating point number, if the user enters more than 8 decimal digits than most significant 7 or 8 decimal digits are retained. So, what goes inside can be described with an example. • Let the first no. entered be: 4444444444001 • Let the second no. entered be: 1 How the modified code handles inside: • The first number is taken as: 4444444 • The second number is taken as: 1 The count of lost significant digits in decimal is saved for later use. So, the division algorithm actually works on above specified numbers. • The result after division is: 4444444

14

Before the result of division is output to screen, the count of lost decimal digits is postfixed to get the correct output. • Output displayed on screen: 4444444000000.000000

3.4.5 Special Case For very very small floting point numbers division. So, what goes inside can be described with an example. • Let the first no. entered be: .000000000002 • Let the second no. entered be .00000000001 How the modified code handles inside: • The first number is taken as: .2 • The second number is taken as: .1 The count of lost significant digits in decimal is saved for later use. So, the division algorithm actually works on above specified numbers. • The result after division will be: 2 Before the result of division is output to screen, the count of lost decimal digits is postfixed/prefixed to get the correct output. • Output displayed on screen: .200000

15

CHAPTER 4

FUTURE WORK DOUBLE PRECISION FLOATING POINT NUMBERS

In this thesis trap 14 is modified to get the correct results. However, there is still more work that need to be done to make BSVC simulator work more close to the real m68000 processor. Trap 14 works for 32-bit single precision floating-point numbers. Future work on making trap14 to work on double precision floating point-numbers need to be done.

16

REFERENCES

[1] A. Riggins. CS237 Machine organizations & assembly language programming. KB Books, San Diego, CA, 2003. [2] W. Ford and W. Topp. Assembly language and syatems programming for the M68000 family. Ones and Bartlett Publishers, Boston, MA, 1997 [3] Motorola. Programer's Reference Manual. Motorola Inc., Schaumburg, IL, 1992. [4] H. Yin. Enhancement of MC 68000 simulator. Master's thesis, San Diego State University, San Diego, CA, 2004. [5] S. Hollasch. IEEE Standard 754 Floating Point Numbers, 2005. http://steve.hollasch.net/cgindex/coding/ieeefloat.html, accessed Mar. 2012.

17

APPENDIX A

BSVC SYSTEM

18

BSVC Simulator System

The following table shows the parts of this simulator and the function of each part.

File Name Function 68kasm Assembler. Used to converts the assembly source file to machine code. Usage:68kasm -l filename.s or 68kasm -l filename.se Using this command will generate two files: filename.lis and filename.h68 where filename.h68 contains the machine code. MacroPP Macro Preprocessor. Used to do macro expansion. Usage: 68kpp filename.s Afilename.se will be generated. Serial.setup Simulator setup file. Used to initialize the simulator. trap13.s File that contains the I/O subroutines. trap14.s File that contains the floating-point number subroutines. setevt.s Exception handler file. Contains exception service subroutines. iomacs.s Contains macros definitions for subroutines for trap 13 and trap 14. evtmacs.s Contains the macro definition for using exception handlers. hexascmacs.s Contains the macro converting hex number to ASCII string.

19

APPENDIX B

FLOAT I/O MACRO

20

Float I/O Macro Documentation

This documentation file describes the I/O macros and arithmetic macros written for the floating point numbers. The macros were written by Huijuan Yin. Last Modified: Feb, 2012 by Honey Walia

*Macro definition: floatin Reads a line from the keyboard with restriction on input. There is one argument, the destination in memory for the line. Information is returned in D0.

The argument is the destination for the line. The characters are read from the keyboard and stored in memory in ASCII. The length of the string is placed in D0. You will be only allowed to input sign as the first character and only one sign will be allowed. You will be only allowed to input one period to indicate the fractional part.

Warning: Every character you type is read and counted. If you make a typo and then backspace, the backspace character is included.

*Macro definition: cvtaf Converts ascii to unpacked floating point number. There are two arguments, the address of the ASCII string to be converted and the address where the result will be stored to. The length of the string is taken from D0.

The first argument is the address of an ASCII string representing a floating point number. The second argument is the address of the resulting unpacked floating point number. The unpacked floating-point number requires 64-bit of storage.

*Macro Definition: cvtfa Converts the unpacked floating point number to ASCII. There are two arguments following cvtfa, the address of unpacked floating point number to be converted and the address of the resulting ASCII string. It also takes another parameter which is passed in through D0. D0 contains the number of digits after the period. The first argument is the address of the source unpacked floating point number to be converted. The second argument is the address of the destination ASCII string.

21

*Macro Definition: cvtfanew Converts the unpacked floating point number to ASCII. There are two arguments following cvtfanew, the address of unpacked floating point number to be converted and the address of the resulting ASCII string. It also takes another parameter which is passed in through D0. D0 contains the number of digits after the period.

The first argument is the address of the source unpacked floating point number to be converted. The second argument is the address of the destination ASCII string.

*Macro Definition: pack Converts the unpacked floating point number to packed floating point number. There is one argument, the address of the unpacked floating point number to be converted. The packed result is stored in D0 as a long word.

*Macro Definition: unpack Converts the packed floating point number to an unpacked floating point number. There is one argument, the address of the result unpacked floating point number which needs two long words. The packed floating point number is taken from D0.

*Macro Definition: fadd Add two unpacked floating point numbers. There are two arguments, the address of the source unpacked floating point number and the address of the destination unpacked floating point number. The result is stored in the destination address.

The first argument is the address of the source unpacked floating point number. The second argument is the address of the destination unpacked floating point number. The fadd adds the floating point number specified by the source and the floating point number specified by the destination. The result is stored in the destination. +

22

*Macro Definition: fsub Subtracts two unpacked floating point numbers. There are two arguments, the address of the source unpacked floating point number and the address of the destination unpacked floating point number. The result is stored at the second argument.

The first argument is the address of the source unpacked floating point number. The second argument is the address of the destination unpacked floating point number. The fsub subtracts the floating point number specified by the source from the floating point number specified by the destination. The result is stored in the destination. -

*Macro Definition: fmul Multiply two unpacked floating point numbers. There are two arguments, the address of the source unpacked floating point number and the address of the destination unpacked floating point number. The result is stored in the destination address.

The first argument is the address of the source unpacked floating point number. The second argument is the address of the destination unpacked floating point number. The fmul multiply the 24- bit mantissas of the floating-point numbers from both source and destination then generate a new 24-bit mantissa. The result is stored in the destination. *

Note: The multiplication of two 24-bit numbers will result a 48-bit number. With a 24-bit mantissa, the precision is lost.

*Macro Definition: fdiv Divides two unpacked floating point numbers. There are two arguments, the address of the source unpacked floating point number and the address of the destination unpacked floating point number. The result is stored at the second argument.

The first argument is the address of the source unpacked floating point number. The second argument is the address of the destination unpacked floating point number. The fdiv divides the floating point number specified by the destination by the floating point number specified

23 by the source. The division uses all the 24 bits of the mantissas from both source and destination numbers. The result is stored in the destination. *

24

APPENDIX C

TRAP 14.S

25

*======* * File: trap14.s * * Trap 14 Floating-point number input/output routines and floating-point * number arithmetic routines * By Huijuan Yin * Last Modified: Oct. 24, 2004 * Bug fixes, summer 2005, Alan Riggins * Last Modified: Feb. 24, 2012, Honey Walia

ORG $5200 ; Trap 14 Address

*------I/O Register Offsets:------

DUART equ $effc01 ; Dual Universal Asynchronous Receiver/Transmitter MR1A equ 0 ; Mode Register 1 Port A MR2A equ 0 ; Mode Register 2 Port A SRA equ 2 ; Status Register Port A CRA equ 4 ; Command Register Port A CSRA equ 2 ; Clock Select Register Port A TBA equ 6 ; Transmitter Buffer Port A RBA equ 6 ; Receiver Buffer Port A IMR equ 10 ; Interrupt Mask Register TBB equ $16 ; Transmitter Buffer Port B CRB equ $14 ; Command Register Port B MR1B equ $10 ; Mode Register 1 Port B MR2B equ $10 ; Mode Register 2 Port B SRB equ $12 ; Status Register Port B * *------Other important constants:------LINEFEED equ 10 ; LineFeed Character value CARR_RETURN equ 13 ; Carriage Return character value PERIOD equ 46 ZERO equ 48 ONE equ 49 NINE equ 57 PLUS equ 43 MINUS equ 45 THESIGN equ 0 EXPO equ 2 MANTI equ 4 * *------Main entry to the TRAP14 handler ------* * All I/O calls through trap 14 begin here. The particular * I/O function is dispatched based on the trap code, which * is a word size integer which is located in the caller * right after the trap #14 instruction. * main: link a6,#0 ; Establish argument pointer movem.l d1-d7/a0-a5,-(sp) ; Save registers (not D0) move.b d7,ttr ; Walia ... ttr value required for division

***HUIJAN has a bug somewhere. ***Not a good fix, but solves the problem. clr.l D3 ***Side effects, she relies on at least D1

26

clr.l D4 ***containing all zeros, other registers cleared ***for added security. clr.l D6 clr.l D7

move.l 6(a6),a0 ; Get the caller's PC clr.l d7 ; Fill d7 with zeros move.w 0(a0),d7 ; Get the trap code add.l #2,6(a6) ; Modify PC, so it points to * the next instruction asl.l #2,d7 ; Prepare offset for jump table * Dispatch handler to the particular * I/O function lea JMPTAB,a4 ; Get address of the jump table move.l 0(a4,d7.l),a4 jmp (a4) ; Go to I/O function exit: movem.l (sp)+,d1-d7/a0-a5 unlk a6 rte ; Exit the handler

* Jump table (contains entry points for I/O functions) JMPTAB dc.l init14,inflo,atoun,packfloat,unpackfloat,fadd,fmul,fdiv,ftoasc

* *------TRAP14 functions:------

* * Initialize the trap 14 handler: * init14: lea DUART,a1

move.b #%00010000,CRA(a1) ; Reset MR?A pointer move.b #%00100011,MR1A(a1) ; 8 data bits move.b #%00010111,MR2A(a1) ; Normal Mode move.b #%10111011,CSRA(a1) ; Set clock to 9600 move.b #%00000101,CRA(a1) ; Enable Rx and Tx bra exit

******************************************************* * Input a floating point number with 10 digit limit * * The length of chars before . is stored in LSW of d0 * The length of chars after . is stored in MSW of d0 ******************************************************* inflo: movea.l 10(A6),A0 movea.l 10(A6),A2 clr.l d1 ; Clear character counter clr.l d2 ; Clear decimel point counter clr.l d3 ; Clear sign bit register clr.l d4 ; Clear the fraction number counter inchr: btst #0,SRA+DUART ; Test Receive data register full beq.s inchr ; If not keep polling clr.l d0 ; Make sure that entire d0 is clear move.b RBA+DUART,D0 ; Read the character cmp.b #CARR_RETURN,D0 beq endln * * Check the sign of input string *

27

cmp.b #PLUS,D0 beq sign cmp.b #MINUS,D0 beq sign bra point sign: addi.l #1,d3 ; increase sign bit counter if input a + or - sign cmpi #1,d3 bgt inchr ; ignore extra sign cmpi #0,d1 ; ignore the sign if it's not the first input char bgt inchr bra store point: cmp.b #PERIOD,D0 bne count addi.l #1,d2 cmpi.b #1,D2 bgt inchr bra goput ; will not store the decimal point count: add.l #1,d1 cmpi.b #0,d2 beq store add.l #1,d4 store: move.b D0,(A0)+ ; store the character goput: jsr putc ; Echo the character bra inchr endln: move.b #LINEFEED,d0 jsr putc *Echo LF and CR move.b #CARR_RETURN,d0 jsr putc move.l d4,d0 swap d0 move.w d1,d0 move.l d3,d1 swap d1 move.w d2,d1 bra exit

********************************************** * convert ascii to unpacked floating number * ********************************************** atoun: move.b d2,diff ;Walia....diff & do value required for addition, ;subtraction, multiplication. swap d2 ;Walia ... doo value required for division. move.b d2,do move.b d5,doo

clr.l d2 move.l 10(a6),a1 ; get the string pointer move.l 14(a6),a2 ; get the result pointer move.b d0,total ; store the total length of the string swap d0 move.b d0,frag ; store the length of the frag part move.b d1,dots ; store the length of dots swap d1 move.b d1,signs ; store the length of the sign

28

* * Process sign * * move.b signs,d0 * cmpi.b #0,d0 * bgt a * bra b a: move.b (a1),d0 cmp.b #PLUS,d0 beq b cmp.b #MINUS,d0 beq b2 cmp.b #'.',d0 beq b3 bra b4 b: adda.l #1,a1 move.w #0,(a2)+ bra c b2: adda.l #1,a1 move.w #1,(a2)+ bra c b3: adda.l #1,a1 move.w #0,(a2)+ bra c b4: move.w #0,(a2)+ * * Process the whole number part * c: clr.l d6 ; d6 is going to contain the mantissa move.b total,d0 sub.b frag,d0 move.b d0,whole

cmpi.b #5,d5 ;Walia... div1,divd value required for division bne check1 move.b d0,div1 move.b d0,divd check1:cmpi.b #6,d5 ;Walia.... niv2,nivd value required for division bne check move.b d0,niv2 move.b d0,nivd check: ;Walia.... check block tracks whether whole number cmpi.b #8,whole ;can be stored as 8 decimal digits or 7 decimal digits blt y1 move.b #1,align

move.b #8,whole movea.l a1,a3 cmpi.b #32,(a3)+ bge y2 cmpi.b #37,(a3)+ bge y2 cmpi.b #38,(a3)+ bge y2 cmpi.b #38,(a3)+ bge y2 cmpi.b #38,(a3)+

29

bge y2 cmpi.b #33,(a3)+ bge y2 cmpi.b #32,(a3)+ bge y2 cmpi.b #36,(a3)+ bge y2 bra y1 y2: move.b #7,whole

y1: cmpi.b #0,align ; Walia .... y1,j1 block required for addition and cmpi.b #0,diff ;subtraction beq y111 move.b #7,whole j1: suba.l #1,a1 move.b #48,d3 move.b d3,(a1) subi.b #1,diff bne j1

y111: cmpi.b #0,do ;Walia..... wholeold, whole1, bhole2 bne ff1 ;stores original decimal digits no. sub.b whole,d0 move.b d0,wholeold

ff1: cmpi.b #2,do bne ff2 sub.b whole,d0 move.b d0,whole1

ff2: cmpi.b #3,do bne ff sub.b whole,d0 move.b d0,bhole2

ff: cmpi.b #5,d5 ; Walia .... ff block works on dividend..for division bne wq move.b div1,d6 move.b whole,d7 cmp.b d7,d6 blt ddr sub.b whole,d6 move.b d6,div1

wq: clr.l d6 ; Walia....wq block works on divisor..for division case cmpi.b #6,d5 bne ddr move.b #1,no move.b niv2,d6 move.b whole,d7 cmp.b d7,d6 blt ddr sub.b whole,d6 move.b d6,niv2

30

ddr jsr tobin cmpi.l #0,d0 beq c2 move.l #31,d7 s: btst d7,d0 ; d0 has the whole number part beq raise bra initset raise subi.l #1,d7 bra s initset move.l #23,d5 ; d5 hold the index of mantissa move.w d7,(a2)+ ; d7 hold the exponent setman bset d5,d6 change subi.l #1,d5 ; the whole number is over 24 bits blt mvm ; then move the mantissa subi.l #1,d7 cmpi.l #0,d7 blt d ; go process fraction part btst d7,d0 beq change bra setman c2 move.l #22,d5 ;fraction part starting from bit 22 move.w #0,(a2)+ * * Process the fraction part *

* This part we make the fraction part into at most three decimal number * The length is 23 at most d: clr.l d2 clr.l d3 clr.l d4

move.b frag,whole ;Walia..... code modified to save very small movea.l a1,a3 ;fraction part cmpi.b #8,whole blt ffj

cmpi.b #5,doo ;Walia..... code inserted for division case bne ttyu ;block asx,ttyu,asxx required for division asx: cmpi.b #'0',(a3)+ bne dds addi.l #1,d2 move.b d2,sghj bra asx

ttyu: cmpi.b #6,doo bne ffj

asxx: cmpi.b #'0',(a3)+ bne dds addi.l #1,d2 move.b d2,sghx

31

bra asxx

dds: sub.b d2,whole cmpi.b #0,d2 beq ffj clr.l d2 suba.l #1,a3 movea.l a3,a1

ffj: cmpi.b #8,whole blt bj move.b #8,whole

cmpi.b #32,(a3)+ bge uy cmpi.b #37,(a3)+ bge uy cmpi.b #38,(a3)+ bge uy cmpi.b #38,(a3)+ bge uy cmpi.b #38,(a3)+ bge uy cmpi.b #33,(a3)+ bge uy cmpi.b #32,(a3)+ bge uy cmpi.b #36,(a3)+ bge uy bra bj uy: move.b #7,whole bj: jsr tobin move.l d0,d2 ;the first 8 digit store in d2 move.b #8,d0 sub.b whole,d0 mt1 move.l d2,d7 asl.l #3,d2 asl.l #1,d7 add.l d7,d2 subi.b #1,d0 cmpi.b #0,d0 bgt mt1 bra chk4 dcon move.b #8,whole jsr tobin move.l d0,d2 sub.b #8,frag cmpi.b #8,frag bge dcon2 move.b frag,whole jsr tobin move.l d0,d3 move.b #8,d0 sub.b frag,d0 mt2 move.l d3,d7 asl.l #3,d3 asl.l #1,d7

32

add.l d7,d3 subi.b #1,d0 cmpi.b #0,d0 bgt mt2 *bra chk4 dcon2 move.b #8,whole jsr tobin move.l d0,d3 ******** ALAN subi.l #8,frag sub.b #8,frag cmpi.b #7,frag bge dcon3 move.b frag,whole jsr tobin move.l d0,d4 move.b #7,d0 sub.b frag,d0 mt3 move.l d4,d7 asl.l #3,d4 asl.l #1,d7 add.l d7,d4 subi.b #1,d0 cmpi.b #0,d0 bgt mt3 *bra chk4 dcon3 move.b #7,whole dcon4 jsr tobin move.l d0,d4

* * Here we are going to convert the ascii to fraction * if (d4*2)>10000000, d4 = d4-10000000 and d3=d3+1 * if (d3*2)>100000000, d3 = d3 - 100000000 and d2 = d2+1 * if (d2*1) > 100000000, set bit d5 of d6 otherwise decrease d5 chk4 cmpi.l #0,d4 ;check if d4 is 0 beq chk3 asl.l #1,d4 chk3 cmpi.l #0,d3 beq chk31 asl.l #1,d3 chk31 cmpi.l #10000000,d4 blt chk2 subi.l #10000000,d4 addi.l #1,d3 chk2 cmpi.l #0,d2 beq chk21 asl.l #1,d2 chk21 cmpi.l #100000000,d3 blt chk22 subi.l #100000000,d3 addi.l #1,d2 chk22 cmpi.l #100000000,d2 blt setf subi.l #100000000,d2

33

bset d5,d6 ; else set bit d5 in d6 setf subi.l #1,d5 cmpi.l #0,d5 blt mvm ; if d5<0, move mantissa to (a2) bra chk4 mvm move.l d6,(a2) move.l 14(a6),a2 ; get the result pointer movea.l a2,a0 jsr normalize leave bra exit

***************************************** * convert unpacked format to packed format ***************************************** packfloat: move.l 10(a6),a0 ;get the string pointer jsr normalize ; normalize the unpacked number ****************************************************************** **Bug fix by Alan

move.l 4(A0),D7 btst.l #23,D7 bne.s pnext clr.l D0 bra pack2 pnext:

******************************************************************** clr.l d0 clr.l d2 tst.w EXPO(a0) bne.s pack0 tst.l MANTI(a0) beq.s pack2 pack0:clr.l d2 move.w EXPO(a0),d0 addi.w #127,d0 tst.w THESIGN(a0) beq.s pack1 ori.w #$100,d0 pack1:swap d0 lsl.l #7,d0 move.l MANTI(a0),d2 andi.l #$7fffff,d2 or.l d2,d0 pack2: bra exit

***************************************** * convert packed format to unpacked format ***************************************** unpackfloat: move.l 10(a6),a0 ; a0 points to the result string clr.w THESIGN(a0) ; clear sign tst.l d0 bne.s unpack0 clr.w THESIGN(a0) ; clear sign clr.w EXPO(a0) ; clear exponent clr.w MANTI(a0) ; clear mantissa bra.s unpack2 unpack0:

34

bpl.s unpack1 ; set sign 0(+), 1(-) move.w #1,THESIGN(a0) unpack1: move.l d0,d1 andi.l #$7fffff,d1 ; mask the mantissa ori.l #$800000,d1 ; add hidden high order bit move.l d1,MANTI(a0) ; save high 1+23 bits of mant swap d0 lsr.w #7,d0 ; move exponent to LSB andi.w #$ff,d0 ; isolate exponent subi.w #127,d0 ; convert from excess 127 move.w d0,EXPO(a0) ; store exponent unpack2: bra exit

***************************************** * add two unpacked format float numbers ***************************************** fadd: move.l 10(a6),a0 ; a0 contain the first operand move.l 14(a6),a1 ; a1 contains the second operand fadd00: move.w EXPO(a0),d0 ; d0 contains the first exponent move.w EXPO(a1),d1 ; d1 contains the second exponent sub.w d1,d0 bmi.s fadd0 exg a1,a0 ; (a0) points to smaller value jsr shift move.w EXPO(a1),EXPO(a0) bra.s fadd1 fadd0:neg.w d0 jsr shift add.w d0,EXPO(a0) ;test the signs fadd1:tst.w THESIGN(a0) beq.s fadd2 neg.l MANTI(a0) fadd2:move.l MANTI(a0),d0 tst.w THESIGN(a1) beq.s fadd3 neg.l MANTI(a1) fadd3:move.l MANTI(a1),d1 add.l d0,d1 bge fadd4 ; if the result is positive, set sign word 0 neg.l d1 move.w #1,THESIGN(a0) bra.s fadd5 fadd4:move.w #0,THESIGN(a0) fadd5:move.l d1,MANTI(a0) move.l 14(a6),a1 ; a1 points to the second operand cmpa.l a0,a1 bne fadd6 bra fadd7 fadd6:move.l (a0)+,(a1)+ move.l (a0),(a1) fadd7:move.l 14(a6),a1 clr.l d0 move.w (a1),d0 beq fadd8 ori.w #$0008,4(a6) bra fadd9 fadd8:andi.w #$FFF7,4(a6) fadd9:move.l 4(a1),d0

35

beq fadd10 andi.w #$FFFB,4(a6) bra fadd11 fadd10:ori.w #$0004,4(a6) fadd11:bra exit ;otherwise exit

************************************************ * multiply two unpacked format float numbers ************************************************ fmul: move.l 10(a6),a0 ; a0 points to the first operand jsr normalize movea.l a0,a1 ; a1 now points to the first operand move.l 14(a6),a0 ; a0 points to the second operand jsr normalize move.w THESIGN(a1),d0 ; set the sign for the product eor.w d0,THESIGN(a0) move.w EXPO(a1),d0 add.w d0,EXPO(a0) move.l MANTI(a0),d0 move.l MANTI(a1),d1 jsr umul32

moveq #8,d2 fmul_1:lsl.l #1,d1 roxl.l #1,d0 dbra d2,fmul_1 move.b #8,muul ;Walia.... code inserted to save significant digits btst.l #31,d0 bne kk09 move.b #7,muul btst.l #30,d0 bne kk09 move.b #6,muul btst.l #29,d0 bne kk09 move.b #5,muul btst.l #28,d0 bne kk09 move.b #4,muul btst.l #27,d0 bne kk09 move.b #3,muul btst.l #26,d0 bne kk09 move.b #2,muul btst.l #25,d0 bne kk09 move.b #1,muul btst.l #24,d0 bne kk09 move.b #0,muul

kk09:

clr.l d5 ; Walia...... code inserted to get right exponent move.b muul,d5 ; and mantissa for multiplication add.w d5,EXPO(a0) lsr.l d5,d0 move.l d0,MANTI(a0) tst.l d0

36

bne fmul_2 move.w #0,THESIGN(a0) * start to set the N and Z of CCR fmul_2: clr.l d0 move.w (a0),d0 beq fmul2 ori.w #$0008,4(a6) bra fmul3 fmul2:andi.w #$FFF7,4(a6) fmul3:move.l 4(a0),d0 beq fmul4 andi.w #$FFFB,4(a6) bra fmul5 fmul4:ori.w #$0004,4(a6) fmul5: move.w EXPO(a0),expedia cmpi.w #24,expedia bra exit

*************************************************************** * Divide two unpacked format floating point numbers. * The quotient is returned in the second parameter *************************************************************** fdiv: move.b #1,ddiv move.l 14(a6),a1 ; a1 points to the second operand movea.l a1,a0 ; prepare for normalizing jsr normalize move.l 10(a6),a0 ; a0 points to the first operand jsr normalize move.w THESIGN(a0),d0 ; copy the sign of the divisor to d0 eor.w d0,THESIGN(a1) ; get the sign for quotient

move.w EXPO(a0),d0 ; copy the exponent of the divisor to d0 sub.w d0,EXPO(a1) ; get the exponent for the quotient

move.l MANTI(a0),d0 ; copy the mantissa of the divisor to d0 move.l MANTI(a1),d1 ; copy the mantissa of the dividend to d1 move.l #23,d3 ggg: clr.l d4 ; d4 is used to store the mantissa for quotient * * Get the whole number part * clr.l d2 ; d2 works as a counter fdiv1: cmp.l d0,d1 ; compare the mantissas beq fdiv2 blt fdiv3 sub.l d0,d1 bset d3,d4 bra fdiv1 fdiv2: move.l #$800000,MANTI(a1) ; set the mantissa for quotient bra fdiv6

* *Get the fraction part * fdiv3:

37

cmpi.l #0,d1 ; if d1 is 0, stop beq fdiv5 subi.l #1,d3 cmpi.l #0,d3 blt fdiv5 lsl.l #1,d1 ; shift mantisa dividend left 1 bit cmp.l d0,d1 beq fdiv4 blt fdiv3 sub.l d0,d1 bset d3,d4 cmpi.l #0,d3 beq fdiv5 bra fdiv3 fdiv4: bset d3,d4 fdiv5:

move.l d4,MANTI(a1) fdiv6: movea.l a1,a0 jsr normalize

* If the result is 0, set the sign to be 0 move.l MANTI(a1),d0 tst.l d0 bne fdiv_7 move.w #0,THESIGN(a1)

* start to set the N and Z of CCR fdiv_7: clr.l d0 move.w (a1),d0 beq fdiv7 ori.w #$0008,4(a6) bra fdiv8 fdiv7: andi.w #$FFF7,4(a6) fdiv8: move.l 4(a1),d0 beq fdiv9 andi.w #$FFFB,4(a6) bra fdiv10 fdiv9: ori.w #$0004,4(a6) fdiv10: bra exit

******************************************************************* * Convert unpacked float number to an ASCII string * The total number of chars is returned by D0 ******************************************************************* ftoasc:move.l 10(a6),a0 ; a0 points to the source number move.l 14(a6),a1 ; a1 points to the result string

move.b d0,num ;store precision

move.b d5,l1 swap d5 move.b d5,m1

clr.l d0

38

clr.l d5 clr.l d7 move.w THESIGN(a0),d0 beq ftoasc0 move.b #'-',(a1)+ ftoasc0: move.l MANTI(a0),d1 ; d1 contains the mantissa move.l d1,d3 ; d3 contains the mantissa move.w EXPO(a0),d0 ; d0 contains the exponent

move.w d0,expogreat ;Walia... expogreat & chav stores exponent move.w d0,chav

* beq ftoasc3 * blt ftoasc4 * to get the whole number part, we will shift the mantissa right * by 23-expo bits if exponent is greater than 0 ftoasc1: move.w #23,d2 ext.l d2 sub.w d0,d2 blt xxc lsr.l d2,d1 ; d1 contains the whole number xxc:

move.b #0,isgreat move.l d1,temp ;save the whole number for later

* * Start to process the fraction part * ftoasc2: move.w EXPO(a0),d0 add.w #9,d0

**** ALAN coded printed zero for values <= 2^-10 tst.w D0 BGE OKK NEG.W D0 LSR.L D0,D3 BRA NEXXT

OKK: lsl.l d0,d3 ; High order byte of d3 contains fraction

NEXXT: clr.l d1 ; d1 is to store the first 8 digits clr.l d2 ; d2 is to store the second 8 digits clr.l d7 ; d7 is to store the last 7 digits *break btst #31,d3 beq fg1 move.l #50000000,d1 *break fg1: btst #30,d3 beq fg2 addi.l #25000000,d1 *break fg2: btst #29,d3

39

beq fg3 addi.l #12500000,d1 * break fg3: btst #28,d3 beq fg4 addi.l #6250000,d1 * break fg4: btst #27,d3 beq fg5 addi.l #3125000,d1 * break fg5: btst #26,d3 beq fg6 addi.l #1562500,d1 * break fg6: btst #25,d3 beq fg7 addi.l #781250,d1 * break fg7: btst #24,d3 beq fg8 addi.l #390625,d1 * break fg8: beq fg9 addi.l #50000000,d2 addi.l #195312,d1 fg9: btst #22,d3 beq fg10 addi.l #25000000,d2 addi.l #97656,d1 fg10: btst #21,d3 beq fg11 addi.l #12500000,d2 addi.l #48828,d1 fg11: btst #20,d3 beq fg12 addi.l #625000,d2 addi.l #24414,d1 fg12: btst #19,d3 beq fg13 addi.l #3125000,d2 addi.l #12207,d1 fg13: btst #18,d3 beq fg14 addi.l #51562500,d2 cmpi.l #100000000,d2 bge sk1 addi.l #6103,d1 bra fg14 sk1: addi.l #6104,d1 ; 6104= 6103 + 1 subi.l #100000000,d2 fg14: btst #17,d3 beq fg15 addi.l #75781250,d2 cmpi.l #100000000,d2 bge sk2 addi.l #3051,d1 bra fg15 sk2: addi.l #3052,d1 ; 3052 = 3051 + 1 subi.l #100000000,d2 fg15: btst #16,d3

40

beq fg16 addi.l #87890625,d2 cmpi.l #100000000,d2 bge sk3 addi.l #1525,d1 bra fg16 sk3: addi.l #1526,d1 ; 1526 = 1525+ 1 subi.l #100000000,d2 fg16: btst #15,d3 beq fg17 addi.l #5000000,d7 addi.l #93945312,d2 cmpi.l #100000000,d2 bge sk4 addi.l #762,d1 bra fg17 sk4: addi.l #763,d1 ; 763 = 762 + 1 subi.l #100000000,d2 fg17: btst #14,d3 beq fg18 addi.l #2500000,d7 addi.l #46972656,d2 cmpi.l #100000000,d2 bge sk5 addi.l #381,d1 bra fg18 sk5: addi.l #382,d1 ; 382 =381 + 1 subi.l #100000000,d2

fg18: btst #13,d3 beq fg19 addi.l #1250000,d7 addi.l #73486328,d2 cmpi.l #100000000,d2 bge sk6 addi.l #190,d1 bra fg19 sk6: addi.l #191,d1 ; 191 = 190 + 1 subi.l #100000000,d2 fg19: btst #12,d3 beq fg20 addi.l #625000,d7 addi.l #36743164,d2 cmpi.l #100000000,d2 bge sk7 addi.l #95,d1 bra fg20 sk7: addi.l #96,d1 ; 96 = 95 + 1 subi.l #100000000,d2 fg20: btst #11,d3 beq fg21 addi.l #312500,d7 addi.l #68371582,d2 cmpi.l #100000000,d2 bge sk8 addi.l #47,d1 bra fg21 sk8: addi.l #48,d1 ; 48 = 47 + 1 subi.l #100000000,d2

41

fg21: btst #10,d3 beq fg22 addi.l #156250,d7 addi.l #84185791,d2 cmpi.l #100000000,d2 bge sk9 addi.l #23,d1 bra fg22 sk9: addi.l #24,d1 ; 24 = 23 + 1 subi.l #100000000,d2 fg22: btst #9,d3 beq pp addi.l #5078125,d7 cmpi.l #10000000,d7 bge sk10 addi.l #92092895,d2 cmpi.l #100000000,d2 bge sk11 addi.l #11,d1 bra pp sk10: addi.l #92092896,d2 cmpi.l #100000000,d2 bge sk11 addi.l #11,d1 bra pp sk11: addi.l #12,d1 ; 12 = 11 + 1 subi.l #100000000,d2

* * Process precision * pp: cmpi.b #23,num ;if precision is 23 digits or bigger, set it to be 23 bge fw cmpi.b #16,num ;if the precision > 16 but < 23 digits, need to process d7 blt chd2 move.b #21,d0 sub.b num,d0 move.l #5,d5 cmpi.b #-1,d0 ble chd71 chd7: move.l d5,d6 asl.l #3,d6 asl.l #1,d5 add.l d6,d5 dbra d0,chd7 chd71:add.l d5,d7 cmpi.l #10000000,d7 blt fw subi.l #10000000,d7 addi.l #1,d2 cmpi.l #100000000,d2 blt fw subi.l #100000000,d2 addi.l #1,d1 cmpi.l #100000000,d1 blt fw subi.l #100000000,d1 move.b #1,isgreat

42

bra fw * process d2 chd2: cmpi.b #8,num blt chd1 move.b #14,d0 sub.b num,d0 move.l #5,d5 cmpi.b #-1,d0 ble chd22 chd21:move.l d5,d6 asl.l #3,d6 asl.l #1,d5 add.l d6,d5 dbra d0,chd21 chd22:add.l d5,d2 cmpi.l #100000000,d2 blt fw subi.l #100000000,d2 addi.l #1,d1 cmpi.l #100000000,d1 blt fw subi.l #100000000,d1 move.b #1,isgreat bra fw

* process d1

**** ALAN chd1: move.b #6,d0 chd1: moveq #6,D0 sub.b num,d0 move.l #5,d5 cmpi.b #-1,d0 ble chd12 chd11:move.l d5,d6 asl.l #3,d5 asl.l #1,d6 add.l d6,d5 dbra d0,chd11 chd12:add.l d5,d1 cmpi.l #100000000,d1 blt fw subi.l #100000000,d1 move.b #1,isgreat

* *Convert the whole number part to string * fw:

subi.w #23,expogreat blt fw1 cmpi.w #0,expogreat bne fw1 move.w #1,expogreat fw1: move.l temp,d0 cmpi.b #0,isgreat beq fto addi.l #1,d0 fto: move.b #10,length jsr cvt2a jsr strip

43

*move.l temp,d0 lea string,a2 move.l d0,d6 subi.l #1,d6 ;d6 contains exponant-1,used as counter ftoasc1a: move.b (a2)+,(a1)+ dbra d6,ftoasc1a clr.l d0

tp: move.b wholeold,d0 ;Walia.... code inserted to print out cmpi.b #2,ttr ;significant 0's(in decimal)before decimal point bne t1 add.b whole1,d0 add.b bhole2,d0

t1: cmpi.b #0,d0 beq sad cmpi.b #1,no beq sad move.b #'0',(a1)+ subi.b #1,d0 bra t1 sad: cmpi.b #1,m1 bne tj ee: cmpi.b #0,l1 bne tj subi.b #1,l1 move.b #'0',(a1)+ bra ee tj: move.b #0,m1 clr.l d0 move.b div1,d0 move.b niv2,d6 cmp.b d6,d0 blt yut clr.l d6 sub.b niv2,d0 hjg: cmpi.b #0,d0 beq yut move.b #'0',(a1)+ subi.b #1,d0 bra hjg

yut: clr.l d7 move.b sghx,d7 sub.b sghj,d7 move.b d7,sghx move.b sghx,cala cmpi.b #0,sghx bge fg26 suba.l #1,a1 ccv: move.b (a1),(a3)+ suba.l #1,a1 addi.b #1,sghx cmpi.b #0,sghx blt ccv move.b #'0',(a1)+ move.b #'.',(a1)+ suba.l #1,a3

44

jkg: move.b (a3)+,(a1)+ addi.b #1,cala move.b #1,gogo cmpi.b #0,cala blt jkg yu:

* * Convert the fraction part to string * fg26: move.l d1,d0 move.b #8,length jsr cvt2a move.l #6,d6 * 7 to 6 lea string,a2 fto2j: cmpi.b #1,gogo beq ppk

cmpi.b #0,sghx bgt ppk cmpi.b #0,sghx blt ppk move.b #'.',(a1)+ movea.l a1,a5

ppk: move.b #0,gogo move.b (a2)+,(a1)+ subi.b #1,sghx dbra d6,fto2j move.b #0,sghx

ggh:

* make a1 point to the end of the string cmpi.b #23,num ble fg27 move.b #23,num fg27: move.b num,d1 move.b #6,d1 ext.w d1 ext.l d1 adda.l d1,a5 movea.l a5,a1

* d0 contains the length of the string ftoasc6: move.l a1,d0 move.l 14(a6),d4 sub.l d4,d0 bra exit

***** subroutine ***********************************************

45

putc: btst #2,SRA+DUART ; Test Transmit data register empty beq.s putc ; If not keep polling move.b d0,TBA+DUART ; Transmit the character putcx: rts

* * Convert ascii to 2's complement * (M68000 has no longword multipication instructions.) tobin: move.l d2,-(sp) clr.l d2 ; for next digit clr.l d0 ; for 2's comp value move.b whole,d1 tst.b d1 bmi aext ; bad count beq aext ; bad count digi: move.b (a1)+,d2 ; get ascii digit sub.b #'0',d2 ; get decimal digit * mulu.l #10,d0 ; 10*current value (mustsimulate) move.l d0,d4 ; save current value asl.l #3,d0 ; 8*current value asl.l #1,d4 ; 2*current value add.l d4,d0 ; 10*current value add.l d2,d0 ; add new digit sub.w #1,d1 ; decrement counter bne digi aext: clr.l d4 move.l (sp)+,d2 rts

* * Convert 2's complement to ascii * (M68000 has no longword multipication or division instructions.) * cvt2a: movem.l d1-d7/a1,-(sp) clr.l d1 ; for counter lea string,a1 ; string pointer move.b length,d1 ; string length, counter adda.l d1,a1 ; end of string move.b #0,bad

sd: cmpi.w #24,chav blt gh cmpi.b #7,bad beq gh lsl.l #1,d0 addi.b #1,bad subi.w #1,chav bra sd gh: move.l d0,d2 ; 2's comp integer bge cvt neg.l d2 ; get absolute value cvt: move.l d2,d3 * divu.l #10,d3 ; simulated clr.l d4 move.w d3,d4 ; lsw of dividend, msw cleared swap d3 ext.l d3 ; msw of dividend

46

divu.w #10,d3 ; remainder and msw/10 swap d3 ; msw/10 and remainder clr.l d5 move.w d3,d5 ; remainder swap d5 ; remainder*2^16 add.l d5,d4 ; remainder*2^16 + lsw divu.w #10,d4 ; (rem + lsw)/10 swap d4 clr.w d4 swap d4 ; clear remainder for lsw clr.w d3 ; msw/10 in left half add.l d4,d3 ; result v/10 move.l d3,d4 ; v/10 * mulu.l #10,d3 ; 10*(v/10) (must simulate) move.l d3,d5 ; save v/10 asl.l #3,d3 ; 8*(v/10) asl.l #1,d5 ; 2*(v/10) add.l d5,d3 ; 10*(v/10) sub.l d3,d2 ; v - 10*(v/10) addi.b #'0',d2 ; get char code for digit move.b d2,-(a1) ; store digit cmpi.b #1,m1 bne rt subi.b #1,l1 rt: move.l d4,d2 ; new v = v/10 sub.w #1,d1 ; decrement counter bne cvt movem.l (sp)+,d1-d7/a1 cvtext: rts

******* strip leading zeros ************ strip: movem.l d2/a1-a4,-(SP) *break lea string,a1 ; a1 points to source byte to move movea.l a1,a4 ; copy start to get length of new string movea.l a1,a2 ; A2 points to destination byte. movea.l a1,a3 ; A3 indicates end of string clr.l d2 move.b length,d2 ext.l d2 adda.l d2,a3 cmpa.l a1,a3 ; if string is 0 length or less ble nadaMCR cmpi.b #'-',(a1) bne loopMCR adda.l #1,a1 ; found a minus sign, skip over it adda.l #1,a2 loopMCR: cmpa a1,a3 ; quit condition beq doneMCR cmpi.b #'0',(a1) bne nextMCR ; move A1 down until we hit a nonzero digit adda.l #1,A1 bra loopMCR nextMCR: cmpa a1,a3 ; quit condition beq doneMCR move.b (a1)+,(a2)+ ; move digits following leading zeros bra nextMCR doneMCR: suba.l a4,a2 move.l a2,d0

47

tst.l d0 ;if the number was all zeros, return one zero. bgt outMCR move.b #$30,(a4) move.l #1,d0 bra outMCR nadaMCR: move.l #0,d0 outMCR: movem.l (SP)+,d2/a1-a4 rts

**** shift ******** shift: movem.l d1/d2,-(sp) clr.l d1 move.l MANTI(a0),d2 ;load mantissa move.w d0,d1 ; examine exponent correction bmi.s shift1 ; shift left bne.s shift0 ; shift right bra.s shift3 ; no shift shift0: asr.l #1,d2 ; shift mantissa right subq.w #1,d1 ; repeat until count is zero bne shift0 and.l #$ffffff,d2 ; clear high order byte bra shift2 ; prepare to return shift1: asl.l #1,d2 ; shift mantissa left addq.w #1,d1 ; repeat until count is zero bne shift1 shift2: move.l d2,MANTI(a0) ; store mantissa shift3: movem.l (sp)+,d1/d2 rts

**** normalize ****** normalize: movem.l d0/d1,-(sp) moveq #1,d0 move.l MANTI(a0),d1 bne.s normal0 clr.w d0 bra.s normal1 normal0: subq.w #1,d0 asl.l #1,d1 bcc.s normal0 addq.w #8,d0 normal1: add.w d0,EXPO(a0) jsr shift movem.l (sp)+,d0/d1 rts

***** 32 bit unsigned multiplication ******** * parameters are passed by register d0 and d1 * the 64-bit result is returned in registers d0 and d1 umul32: movem.l d2-d4,-(sp) move.l d1,d2 move.l d1,d3 move.l d0,d4 swap d3 ; (d3) = a.low || a.high swap d4 ; (d4) = b.low || b.high mulu d0,d1 ; (d1) = a.low * b.low mulu d3,d0 mulu d4,d2 mulu d4,d3

48

* add up the partial procuts moveq #0,d4 swap d1 add.w d0,d1 addx.l d4,d3 add.w d2,d1 addx.l d4,d3 swap d1 ; put (d1) into its final form clr.w d0 swap d0 clr.w d2 swap d2 add.l d2,d0 add.l d3,d0 movem.l (sp)+,d2-d4 rts

***** 32 bit division ******** udiv32: movem.l d2-d4,-(sp) clr.l d3 udiv1: cmp.l d0,d1 blo.s udiv5 move.l d0,d2 clr.l d4 move.w #$10,ccr udiv2: cmp.l d2,d1 ; test divisor > dividend blo.s udiv3 ; if yes, this step is done roxl.l #1,d4 ; shift temp quotient left tst.l d2 ; test for another shift bmi.s udiv4 ; if bit31=1, don't undo shift lsl.l #1,d2 ; shift divisor to next test bra.s udiv2 ; keep going udiv3: lsr.l #1,d2 ; undo the last shift udiv4: sub.l d2,d1 ; subtract shifted divisor add.l d4,d3 ; add temp quotient to d3 bra.s udiv1 ; go back for another division udiv5: move.l d3,d0 ; put the quotient in d0 movem.l (sp)+,d2-d4 rts

***** data ***************** signs: ds.b 1 dots: ds.b 1 whole: ds.b 1 frag: ds.b 1 total: ds.b 1 string: ds.b 20 length: dc.b 20 one1: ds.b 8 temp: ds.l 1 temps: ds.w 1 ;temp sign for div tempe: ds.w 1 ;temp exp for div tempm: ds.l 1 ;temp mantissa for div divexp: ds.b 2 num: ds.b 1 isgreat: dc.b 0 expogreat: ds.b 1 diff: ds.b 1 align: dc.b 0

49 wholeold: dc.b 0 do: dc.b 0 whole1: dc.b 0 bhole2: dc.b 0 expedia: ds.w 1 l1 dc.b 0 m1 dc.b 0 bad: dc.b 0 chav: ds.w 1 div1: dc.b 0 divd: dc.b 0 niv2: dc.b 0 nivd: dc.b 0 ddiv: dc.b 0 muul: dc.b 0 no dc.b 0 sghj: dc.b 0 sghx: dc.b 0 cala: dc.b 0 gogo: dc.b 0 doo: dc.b 0 ttr: dc.b 0 rvb: dc.b 0

end

50

APPENDIX D

TRAP14 MACRO

51

* File: /home/ma/cs237/bsvc/iomacs.s * I/O initialization and macro definitions for use with 68kpp. * Macros by Alan Riggins and Sara Baase * Trap14 calls added by Huijuan Hyun, Summer 2004. * Code modified for I/O in packed format by Alan Riggins * Last modified: August, 2005 by Alan Riggins * Last modified: Feburary, 2012 by Honey Walia * * Trap code definitions, etc. * .INIT13 equ $0000 *Initialize I/O (SCI) .INIT14 equ $0000 .INSTR equ $0001 *Input a line from keyboard .INFLO equ $0001 .INCHR equ $0002 *Input a character from keyboard .ATOUN equ $0002 *convert string to unpack floating number .UNTOPA equ $0003 .OUTCHR equ $0003 *Output a character to screen .PATOUN equ $0004 .ADD equ $0005 *Add two floating point numbers .OUTSTR equ $0004 *Output a string .MUL equ $0006 *Multiply two floating point numbers .DIV equ $0007 .CVTA2 equ $0005 *Convert ascii to 2's complement .FTOA equ $0008 .CVT2A equ $0006 *Convert 2's complement to ascii VEC13 equ (32+13)*4 *Trap 13 vector address VEC14 equ (32+14)*4 ADDR13 equ $5000 *Trap 13 handler address ADDR14 equ $5200 LINEFEED equ 10 *LineFeed Character value CARR_RETURN equ 13 *CarriageReturn Character value *

MEM_BUF EQU $51D0 **MODIFIED BY ALAN R., buffer for pack/unpack MEM_BUF2 EQU $51E0 ** Extra buffer MEM_BUF3 EQU $51F0

initIO macro move.l #ADDR13,VEC13 trap #13 dc.w .INIT13 endm initF macro move.l #ADDR14,VEC14 trap #14 dc.w .INIT14 endm floatin macro * destination pea \1 trap #14 dc.w .INFLO adda.l #4,sp tst.l d0 endm cvtaf macro * source, destination pea MEM_BUF pea \1 trap #14

52

dc.w .ATOUN adda.l #8,sp

pack MEM_BUF move.l D0,\2 endm pack macro * source clr.l D0 pea \1 trap #14 dc.w .UNTOPA adda.l #4,sp endm unpack macro * destination pea \1 trap #14 dc.w .PATOUN adda.l #4,sp endm fadd macro * source,destination move.l D0,MEM_BUF3 *save D0 move.l \1,D0 *unpack first number unpack MEM_BUF move.l \2,D0 unpack MEM_BUF2 pea MEM_BUF2 pea MEM_BUF trap #14 dc.w .ADD adda.l #8,sp pack MEM_BUF2 move.l D0,\2 move.l MEM_BUF3,D0 endm fsub macro * source,destination move.l D0,MEM_BUF3 *save D0 move.l \1,D0 unpack MEM_BUF move.l \2,D0 unpack MEM_BUF2 move.w MEM_BUF,d0 bchg #0,d0 move.w d0,MEM_BUF pea MEM_BUF2 pea MEM_BUF trap #14 dc.w .ADD adda.l #8,sp pack MEM_BUF2 move.l D0,\2 move.l MEM_BUF3,D0 endm fmul macro * source,destination **handle sign clr.b MEM_BUF3 move.l \1,MEM_BUF btst.b #7,MEM_BUF beq.s fmnxt\@ addi.b #1,MEM_BUF3

53 fmnxt\@: move.l \2,MEM_BUF btst.b #7,MEM_BUF beq.s fmcnt\@ addi.b #1,MEM_BUF3

fmcnt\@: move.l \1,D0 unpack MEM_BUF move.l \2,D0 unpack MEM_BUF2 pea MEM_BUF2 pea MEM_BUF trap #14 dc.w .MUL adda.l #8,sp pack MEM_BUF2 btst.b #0,MEM_BUF3 beq.s fmout\@ movem.l D7,-(SP) moveq #31,D7 bset.l D7,D0 movem.l (SP)+,D7 fmout\@: move.l D0,\2 endm fdiv macro * source,destination **handle sign clr.b MEM_BUF3 move.l \1,MEM_BUF btst.b #7,MEM_BUF beq.s fdnxt\@ addi.b #1,MEM_BUF3 fdnxt\@: move.l \2,MEM_BUF btst.b #7,MEM_BUF beq.s fdcnt\@ addi.b #1,MEM_BUF3 fdcnt\@: move.l \1,D0 unpack MEM_BUF move.l \2,D0 unpack MEM_BUF2 pea MEM_BUF2 pea MEM_BUF trap #14 dc.w .DIV adda.l #8,sp pack MEM_BUF2 btst.b #0,MEM_BUF3 beq.s fdout\@ movem.l D7,-(SP) moveq #31,D7 bset.l D7,D0 movem.l (SP)+,D7 fdout\@: move.l D0,\2 endm cvtfa macro * source,destination move.l D0,MEM_BUF3 * SAVE # of digits to print move.l \1,D0

54

unpack MEM_BUF pea \2 * pea \1 pea MEM_BUF move.l MEM_BUF3,D0 *RESET # of digits to print trap #14 dc.w .FTOA adda.l #8,sp endm cvtfanew macro * source,destination ;Walia... modified for multiplication move.l D0,MEM_BUF3 * SAVE # of digits to print move.l \1,D0 pea \2 * pea \1 pea MEM_BUF move.l MEM_BUF3,D0 *RESET # of digits to print trap #14 dc.w .FTOA adda.l #8,sp endm

lineout macro * source pea \1 trap #13 dc.w .OUTSTR adda.l #4,sp endm linein macro * destination pea \1 trap #13 dc.w .INSTR adda.l #4,sp tst.l d0 endm cvta2 macro * source,numDigits move.w \2,-(sp) pea \1 trap #13 dc.w .CVTA2 adda.l #6,sp endm cvt2a macro * destination,numDigits move.w \2,-(sp) pea \1 trap #13 dc.w .CVT2A adda.l #6,sp endm stripp macro movem.l A1-A4,-(SP) lea \1,A1 * A1 points to source byte to move movea.l A1,A4 * copy start to get length of new string movea.l A1,A2 * A2 points to destination byte. movea.l A1,A3 * A3 indicates end of string adda.l \2,A3

55

cmpa.l A1,A3 * if string is 0 length or less BLE nadaMCR\@ cmpi.b #'-',(A1) BNE loopMCR\@ adda.l #1,A1 * found a minus sign, skip over it adda.l #1,A2 loopMCR\@: cmpa A1,A3 * quit condition BEQ doneMCR\@ cmpi.b #'0',(A1) BNE nextMCR\@ * move A1 down until we hit a nonzero digit adda.l #1,A1 BRA loopMCR\@ nextMCR\@: cmpa A1,A3 * quit condition BEQ doneMCR\@ move.b (A1)+,(A2)+ * move digits following leading zeros BRA nextMCR\@ doneMCR\@: suba.l A4,A2 move.l A2,D0 tst.l D0 *if the number was all zeros, return one zero. BGT outMCR\@ move.b #$30,(A4) move.l #1,D0 BRA outMCR\@ nadaMCR\@: move.l #0,D0 outMCR\@: movem.l (SP)+,A1-A4 endm fset macro link A6,#-80 movem.l A0-A2/D1-D2,-(SP) movea.l A6,A1 suba.l #80,A1 *stack ptr for buffer movea.l A1,A0 lea \1,A2 flpp\@: move.b (A2)+,(A0)+ bne flpp\@ movea.l A1,A0 clr.l D1 clr.l D2 cmpi.b #'-',(A0) bne fslp\@ adda.l #1,A0 fslp\@: addq.l #1,D1 cmpi.b #'.',(A0) beq.s ffnd\@ tst.b (A0) beq.s fnpd\@ adda.l #1,A0 bra fslp\@ ffnd\@: addq.l #1,D2 addq.l #1,D1 move.b 1(A0),(A0)+ bne ffnd\@ subq #1,D2 move.w D2,D0 swap D0 subq #2,D1 move.w D1,D0 bra fcvt\@

56 fnpd\@: move.l D1,D0 subq.l #1,D0 fcvt\@: cvtaf (A1),D0 movem.l (SP)+,A0-A2/D1-D2 unlk A6 move.l D0,\2 endm fdump macro link A6,#-80 movem.l D0/A1-A2,-(SP) movea.l A6,A1 suba.l #80,A1 movea.l A1,A2 moveq #5,D0 cvtfa \1,(A1) adda.l D0,A1 clr.b (A1) lineout (A2) movem.l (SP)+,D0/A1-A2 unlk A6 endm dump macro link A6,#-80 movem.l D0/A1-A2,-(SP) movea.l A6,A1 suba.l #80,A1 movea.l A1,A2 move.l \1,D0 cvt2a (A1),#12 stripp (A1),#12 adda.l D0,A1 clr.b (A1) lineout (A2) movem.l (SP)+,D0/A1-A2 unlk A6 endm

57

APPENDIX E

TRAP14 DEMO PROGRAM

58

*------* Programmer: Huijuan Yin * Assignment or Title: I/O Demo for bsvc, floating point routines. * Filename: trap14demo.s * Date completed: October, 2004 * Date modified: Feburary, 2012 Honey Walia *------* ORG $0 DC.L $3000 * Stack pointer value after a reset DC.L start * Program counter value after a reset ORG $3000 * Start at location 3000 Hex * #minclude C:\bsvc\system\iomacs.s #minclude C:\bsvc\system\evtmacs.s

* * Register use * D0 length of input line * D1 user's response to query * A1 address of end of line (for inserting 0) * start: initIO * Initialize (required for I/O) initF setEVT

lineout stars * Output heading lineout title lineout title2 lineout stars con1: lineout skipln lineout addnum lineout prmpt1 floatin buffer * Get input

clr.l d2 move.b d0,total1 ; store the total length of the string move.b d0,d2 swap d0 move.b d0,frag1 ; store the length of the frag part sub.b d0,d2 move.b d2,whole1 move.l d1,sd21

lineout skipln lineout prmpt2 floatin buffer1

clr.l d2 move.b d0,total2 ; store the total length of the string move.b d0,d2 swap d0 move.b d0,frag2 ; store the length of the frag part sub.b d0,d2 move.b d2,whole2 move.l d1,sd22

59

clr.l d0 clr.l d2 move.b whole2,d2 move.b whole1,d0

cmp.b d2,d0 ;Walia... bigger number is passed as first number bge g1

sub.b d0,d2 move.b d2,diffe ;Walia... diffe value helps in aligning numbers

clr.l d0 clr.l d1 move.b frag2,d0 swap d0 move.b total2,d1 move.b d1,d0 move.l sd22,d1 clr.l d2

cvtaf buffer1,mem1

clr.l d0 clr.l d1 move.b frag1,d0 swap d0 move.b total1,d1

move.b d1,d0 move.l sd21,d1 move.b #1,d2 swap d2 move.b diffe,d2

cvtaf buffer,mem2 bra g2

g1: sub.b d2,d0 move.b d0,diffe clr.l d0 clr.l d1 move.b frag1,d0 swap d0 move.b total1,d1

move.b d1,d0 move.l sd21,d1 clr.l d2 cvtaf buffer,mem1 clr.l d0 clr.l d1 move.b frag2,d0 swap d0 move.b total2,d1 move.b d1,d0 move.l sd22,d1 move.b #1,d2 swap d2 move.b diffe,d2

60 cvtaf buffer1,mem2 g2: fadd mem1,mem2 beq mada bra mada2 mada: bra mada4 mada2:bpl mada3

bra mada4 mada3: mada4: move.b #13,d0 cvtfa mem2,sum lea sum,a1 adda.l d0,a1 clr.b (a1) lineout answer con2: lineout skipln lineout skipln lineout subnum lineout prmpt1 clr.l d0 clr.l d1 clr.l d2 floatin buffer * Get input clr.l d2

move.b d0,total1 ; store the total length of the string move.b d0,d2 swap d0 move.b d0,frag1 ; store the length of the frag part sub.b d0,d2 move.b d2,whole1 move.l d1,sd21

lineout skipln lineout prmpt2 floatin buffer1

clr.l d2 move.b d0,total2 ; store the total length of the string move.b d0,d2 swap d0 move.b d0,frag2 ; store the length of the frag part sub.b d0,d2 move.b d2,whole2 move.l d1,sd22

clr.l d0 clr.l d2 move.b whole2,d2 move.b whole1,d0

cmp.b d2,d0 ;Walia...... bigger number is passed as first number bge g3

sub.b d0,d2 move.b d2,diffe ;Walia...... diffe helps in aligning numbers

clr.l d0 clr.l d1

61 move.b frag2,d0 swap d0 move.b total2,d1 move.b d1,d0 move.l sd22,d1 clr.l d2

cvtaf buffer1,mem1 clr.l d0 clr.l d1 move.b frag1,d0 swap d0 move.b total1,d1 move.b d1,d0 move.l sd21,d1 move.b #1,d2 swap d2

move.b diffe,d2

cvtaf buffer,mem2 bra g4

g3: sub.b d2,d0 move.b d0,diffe clr.l d0 clr.l d1 move.b frag1,d0 swap d0 move.b total1,d1

move.b d1,d0 move.l sd21,d1 clr.l d2 cvtaf buffer,mem1 clr.l d0 clr.l d1 move.b frag2,d0 swap d0 move.b total2,d1

move.b d1,d0 move.l sd22,d1 move.b #1,d2 swap d2 move.b diffe,d2

cvtaf buffer1,mem2

g4: fsub mem1,mem2

beq mads bra mads2 mads: bra mads4 mads2: bpl mads3

bra mads4 mads3: mads4: move.b #13,d0

62 cvtfa mem2,dif lea dif,a1 adda.l d0,a1 clr.b (a1) lineout ans2 q2: con3: lineout skipln lineout skipln lineout mulnum lineout prmpt1 clr.l d0 clr.l d1 clr.l d2

floatin buffer * Get input clr.l d2 move.b d0,total1 ; store the total length of the string move.b d0,d2 swap d0 move.b d0,frag1 ; store the length of the frag part

sub.b d0,d2 move.b d2,whole1 move.l d1,sd21

lineout skipln lineout prmpt2 floatin buffer1 clr.l d2 move.b d0,total2 ; store the total length of the string move.b d0,d2 swap d0 move.b d0,frag2 ; store the length of the frag part sub.b d0,d2 move.b d2,whole2 move.l d1,sd22

clr.l d0 clr.l d2 move.b whole2,d2 move.b whole1,d0

cmp.b d2,d0 bge g5

move.b #0,diffe ;Walia...... alignment is not required so diffe value is 0

clr.l d0 clr.l d1

move.b frag2,d0 swap d0 move.b total2,d1 move.b d1,d0 move.l sd22,d1 clr.l d2 move.b #2,d2 swap d2 move.b #0,d2

cvtaf buffer1,mem1

63 clr.l d0 clr.l d1 move.b frag1,d0 swap d0 move.b total1,d1 move.b d1,d0 move.l sd21,d1 move.b #3,d2 swap d2 move.b diffe,d2 cvtaf buffer,mem2 bra g6

g5: sub.b d2,d0 move.b #0,diffe clr.l d0 clr.l d1 move.b frag1,d0 swap d0 move.b total1,d1

move.b d1,d0 move.l sd21,d1 clr.l d2 move.b #2,d2 swap d2 move.b #0,d2

cvtaf buffer,mem1

clr.l d0 clr.l d1 move.b frag2,d0 swap d0 move.b total2,d1 move.b d1,d0 move.l sd22,d1 move.b #3,d2 swap d2 move.b diffe,d2

cvtaf buffer1,mem2

g6: fmul mem1,mem2

beq madm bra madm2 madm: bra madm4 madm2: bpl madm3

bra madm4 madm3:

madm4: clr.l d1 move.w #$51e0,d1 move.l d1,a1 move.b #4,d0 add.l #3,a1 clr.l d1 move.b (a1),counter

64 cmpi.b #30,counter blt gd subi.b #30,counter ;Walia... In multiplication we get the right ;floating point product in internal format ty: cvtfa mem2,pro ; but the macro to convert it to ASCII works cmpi.b #0,counter ;till exponent is 30(in decimal). blt gj ;So, it need to be checked and logic applied if ;exponent greater than 30 to get right product value. hjk: cmpi.b #0,counter beq gj lea pro,a1 tr: add.b #1,jkl cmpi.b #'.',(a1)+ bne tr subi.b #1,jkl move.b #0,d0 swap d0 move.b jkl,d1 move.b d1,d0 clr.l d1 clr.l d2 hdf: cvtaf pro,mem1 fadd mem1,mem1 cmpi.b #1,counter bne dd dd: move mem2,mem1 move.l #$51d3,d0 move.w d0,a1 move.l #$51e3,d0 move.w d0,a2 move.b (a2),d0 move.b d0,(a1) clr.l d7 cmpi.b #1,counter bne xcv move.b #2,d7 xcv: cvtfanew mem2,pro subi.b #1,counter move.b #0,jkl bra hjk gd: move.b #13,d0 clr.l d7 move.b #2,d7 cvtfa mem2,pro gj: lea pro,a1 adda.l d0,a1 clr.b (a1) lineout ans3 q3: con4: lineout skipln lineout skipln

65 lineout divnum lineout prmpt1 clr.l d0 clr.l d1 clr.l d2 clr.l d5 floatin buffer * Get input move.b #5,d5

cvtaf buffer,mem2 lineout skipln lineout prmpt2 clr.l d0 clr.l d1 clr.l d2 clr.l d5 floatin buffer move.b #6,d5

cvtaf buffer,mem1 clr.l d0 clr.l d1 clr.l d2 clr.l d5

fdiv mem1,mem2

beq madd bra madd2 madd: bra madd4 madd2: bpl madd3

bra madd4 madd3:

madd4: move.b #13,d0 cvtfa mem2,div lea div,a1 adda.l d0,a1 clr.b (a1) lineout ans4 q4: lineout bye

* * Storage declarations mem1: ds.l 4 mem2: ds.l 4 title: dc.b '*** Welcome to the I/O trap/macro demo ***',0 stars: dc.b '***************************************************************',0 title2: dc.b '***Arithmetic operations of two floating point numbers***',0 addnum: dc.b '**** Add two numbers ****',0 subnum: dc.b '**** Subtract two numbers ****',0 mulnum: dc.b '**** Multiply two numbers ****',0 divnum: dc.b '**** Divide two numbers ****',0 prmpt1: dc.b 'Please enter the first floating point number:',0 prmpt2: dc.b 'Please enter the second floating point number:',0 hgfdjk: ds.b 50

66 buffer: ds.b 12 buffer1:ds.b 12 yuiotr: ds.b 50 answer: dc.b 'The sum of the two numbers is: ' sum: ds.b 40 ans2: dc.b 'The difference of the two number is: ' dif: ds.b 40 ans3: dc.b 'The product of the two number is: ' pro: ds.b 40 ans4: dc.b 'The quotient of the two number is: ' div: ds.b 40 query: dc.b 'Do you want to add more (y/n)?',0 query2: dc.b 'Do you want to sub more (y/n)?',0 query3: dc.b 'Do you want to multiply more (y/n)?',0 query4: dc.b 'Do you want to divide more (y/n)?',0 bye: dc.b 'The program is finished.',0 skipln: dc.b 0 bool ds.b 20 ha: dc.b '',0 ha2: dc.b '',0 ha3: dc.b '',0 frag1: ds.b 1 total1: ds.b 1 frag2: ds.b 1 total2: ds.b 1 whole1: ds.b 1 whole2: ds.b 1 sd21: ds.l 1 sd22: ds.l 1 diffe: ds.b 1 counter:ds.b 1 jkl: ds.b 1 iop: dc.b 0

end