[ บทความ : FP11 ]

วันก่อนผมเอา Lib11 มาให้ดูเป็นตัวอย่างไปแล้ว .. .พอดี ผมไปเจอไฟล์ Fp11 เข้า เลยเอามาขึ้น web ให้นำไปใช้กันครับ ... หน้าที่ของ FP11 คือ เพิ่มความสามารถเรื่อง floating point (ตัวเลขแบบทศนิยม) ให้แก่ไมโครคอนโทรลเลอร์ 68hc11 นั่นเอง รายละเอียดของไฟล์ FP11.ASM เป็นดังนี้ครับ
**********************************************************************
*                  Floating Point Package 22/1/86                    *
*                   written by R.Soja, Motorola                      *
**********************************************************************
* All floating point routines use                                    *
* two, 3-byte operands located in RAM at OP1,OP2                     *
* Each is  organised as: 7 bit exponent + 1 sign bit (2's complement)*
*                        15 bit mantissa + 1 sign bit                *
*                        (15 bit positive notation)                  *
*                        Sign bit is always is always MSBit          *
*                                                                    *
* Routines implemented:                                              *
*                      1. Addition         MAD  (FADD)  OP1+OP2      *
*                      2. Subtraction      MSB  (FSUB)  OP1-OP2      *
*                      3. Division         MDV  (FDIV)  OP1/OP2      *
*                      4. Multiplication   MML  (FMUL)  OP1*OP2      *
*                                                                    *
* On exit from routine, OP1 contains result, OP2 is destroyed        *
*                                                                    *
* Two conversion routines are also included:                         *
* FLOATINT converts FP number in OP1 to unsigned integer in ACCD     *
* INTFLOAT converts unsigned integer in ACCD to FP number in OP1     *
*                                                                    *
**********************************************************************
*
*    Constants
SYSRAM   EQU 0
START    EQU $E000           For EVM board.
*
*    OP1, OP2 in RAM
*
         ORG SYSRAM
MANT1    RMB 2
EXP1     RMB 1
MANT2    RMB 2
EXP2     RMB 1
*
         ORG START
MAD      EQU *               OP1 + OP2 => OP1
FADD     EQU *
         BSR ALIGN
         BVS FADDEX          If exponent difference too great, return.
         LDAA MANT1          Put sign bit of mantissa 1 in X reg.
         ANDA #$80
         XGDX
         LDAA MANT1
         EORA MANT2
         BMI SUBMANT         If signs are same
         BSR GETABS          then add positive  parts of mantissas.
         ADDD MANT2
         BPL FADD1           if MSBit of result set, then result has
         INC EXP1            overflowed, so increment exponent, while
         BVC FADD2           limiting value to upper bound.
         DEC EXP1
         LDD #$7FFF
         BRA FADD1
FADD2    LSRD
FADD1    STX MANT2           Save sign bit
         STD MANT1           and result, prior to
         BSR NORM            normalising it.
FADDEX   RTS                 Return to calling program segment.
SUBMANT  BSR GETABS          If signs are different,
         SUBD MANT2          then subtract positive parts of mantissas.
         BSR CONVFP          Change 2s compl result to floating point format
         BRA FADD1           and store result (X contains corrected sign bit)
*
GETABS   BCLR MANT2,#$80     Clear sign bits in MANT2
         LDD MANT1           and MANT1 in ACCD
         ANDA #$7F
         RTS
*
MSB      EQU *               OP1 - OP2 => OP1
FSUB     EQU *
         LDAA MANT2
         ADDA #$80           Negate sign of mantissa 2
         STAA MANT2          and perform addition
         BRA FADD
*
ALIGN    CLRA
         LDAB EXP1
         SUBB EXP2
         BPL POS             If EXP1 OP1
FDIV     EQU *
         LDD MANT2
         BEQ MAXRES          Trap divide by 0
         LDAA MANT1
         EORA MANT2
         BMI FDIV1           If signs are same
         LDY #0              then result sign is positive
         BRA FDIV2
FDIV1    LDY #$8000          else result sign is negative
FDIV2    LDAB EXP1
         SUBB EXP2
         BVC FDIV3           If V bit set then its an under/overflow, so
         STAA MANT1          !  update result sign
         BCC MINRES          !  If C bit clear then force result to min limit
         BRA MAXRES          !  else force result to max limit, retaining sign
FDIV3    STAB EXP1           Save result exponent.
         JSR GETABS          Load ACCD with +ive part of MANT1
         LDX MANT2           and X with +ive part of MANT2
         IDIV
         STX MANT1           Store integer part of result in ACCD
         LDX MANT2           and reload denominator.
         FDIV
         XGDX                Get result into ACCD
COMBINE  TST MANT1
         BNE COMBINE1
         TST MANT1+1
         BEQ FDIV5           If non-zero integer part then
COMBINE1 INC EXP1            combine it with fractional part
         CLC                 and adjust exponent accordingly
         ROR MANT1
         ROR MANT1+1
         RORA
         RORB
         BRA COMBINE
FDIV5    LSRD                Clear sign bit of adjusted result
         STY MANT2
         ADDD MANT2          Update sign bit
         BRA NORM3           and store result, checking for -0
*
MAXRES   BSET MANT1,#$7F     Maximise MSbyte of mantissa, retaining sign.
         LDD #$FF7F          Maximise LSbyte of mantissa, and exponent.
         STD MANT1+1
         RTS
*
MINRES   CLRA                Result = 0
         CLRB
         STD MANT1
         CLR EXP1
         RTS
*
MML      EQU *               OP1 * OP2 => OP1
FMUL     EQU *
         LDAB EXP1           First, add exponents.
         ADDB EXP2
         BVC FMUL1           If V bit is set then its an under/overflow, so
         STAA MANT1          !  update result sign
         BCS MINRES          !  If C bit set then force result to min limit
         BRA MAXRES          !  else force result to max limit, retaining sign
FMUL1    STAB EXP1           Store result exponent.
         LDAA MANT1          Evaluate result sign, and
         EORA MANT2          put it in X reg
         XGDX
         BCLR MANT1,#$80     Make both operands positive
         BCLR MANT2,#$80
         BSR CONVFPI         Convert MANT1,MANT2 to unsigned integer format
*                            !and return with result sign + MANT1 in Y reg
         LDAA MANT1          multiply MSbytes of mantissas.
         LDAB MANT2
         MUL
         XGDX                Save 1st partial result in X
         LDAA MANT1+1        Cross multiply.
         LDAB MANT2
         MUL
         ADCA #0             Round up and
         TAB
         CLRA                restore weighting of partial result (in ACCD)
         STX MANT1           Add 1st and 2nd partial results
         ADDD MANT1
         XGDX                Store updated partial result.
         STY MANT1           Restore MANT1
         LDAA MANT1          Cross multiply again.
         LDAB MANT2+1
         MUL
         ADCA #0             Round up again.
         TAB
         CLRA                Correctly weighted 3rd partial result now in ACCD
         STX MANT1           so add it to stored partial result.
         ADDD MANT1
         BSR CONVIFP         Convert integer in ACCD to FP format,and store.
*                            Multiplication of LS bytes is unnecessary, as
*                            the result will always overflow if both non-zero.
         RTS                 Return to calling program.
*
CONVFPI  EQU *               Enter with +ive MANT1,MANT2: result sign in X reg
         LSL MANT1+1         De-normalise both operands.
         ROL MANT1
         LSL MANT2+1
         ROL MANT2
         LDD MANT1
         CPX #0              Add result sign bit to ACCD
         BPL FPI1
         ORAB #1
FPI1     XGDY                and save result sign+operand 1 in Y.
         RTS
*
CONVIFP  EQU *
         LDX #0
         STX MANT2
         STD MANT1           Temporarily store result.
         XGDY                Move result sign bit
         LSRD
         ROR MANT2           to MANT2 before
         LDD MANT1
         LSRD
         JSR NORM            normalising result mantissa.
IFP2     RTS                 Return with result stored in MANT1.
*
FLOATINT EQU *
         CLRB
         LDAA EXP1           If exponent <= 0
         BGT FLTINT1         then clear ACCD and return.
         CLRA
         RTS
FLTINT1  CLRA                else
         LSL MANT1+1         adjust mantissa, destroying sign bit
         ROL MANT1
FLTINT2  LSL MANT1+1         then move mantissa into ACCD
         ROL MANT1
         ROLB
         ROLA
         DEC EXP1
         BNE FLTINT2         until exponent = 0
         RTS
*
INTFLOAT EQU *               On entry, unsigned integer in ACCD
         LDX #0              Initialise result mantissa
         STX MANT1
         INX
         STX EXP1            and exponent.
INTFLT1  LSRD                Move integer to F.P. mantissa
         ROR MANT1
         ROR MANT1+1
         INC EXP1            adjusting exponent with every shift.
         CPD #0
         BNE INTFLT1         When no more bits in ACCD
         ROR MANT1           clear sign bit as integer was always >=0
         ROR MANT1+1
         RTS
*

เรียบเรียง : ศุภชัย บุศราทิจ ( Supachai Budsaratij)
e-mail : raek@se-ed.net
วันที่ทำการปรับปรุง : ๒๙ ก.ย. ๒๕๔๓