📄 lb1sf68.asm
字号:
subl d0, d1 /* d1 = a - (a/b)*b */ movel d1, d0 rts#endif /* L_umodsi3 */#ifdef L_modsi3 .text .proc .globl SYM (__modsi3)SYM (__modsi3): movel sp@(8), d1 /* d1 = divisor */ movel sp@(4), d0 /* d0 = dividend */ movel d1, sp@- movel d0, sp@- PICCALL SYM (__divsi3) addql IMM (8), sp movel sp@(8), d1 /* d1 = divisor */#ifndef __mcoldfire__ movel d1, sp@- movel d0, sp@- PICCALL SYM (__mulsi3) /* d0 = (a/b)*b */ addql IMM (8), sp#else mulsl d1,d0#endif movel sp@(4), d1 /* d1 = dividend */ subl d0, d1 /* d1 = a - (a/b)*b */ movel d1, d0 rts#endif /* L_modsi3 */#ifdef L_double .globl SYM (_fpCCR) .globl $_exception_handlerQUIET_NaN = 0xffffffffD_MAX_EXP = 0x07ffD_BIAS = 1022DBL_MAX_EXP = D_MAX_EXP - D_BIASDBL_MIN_EXP = 1 - D_BIASDBL_MANT_DIG = 53INEXACT_RESULT = 0x0001UNDERFLOW = 0x0002OVERFLOW = 0x0004DIVIDE_BY_ZERO = 0x0008INVALID_OPERATION = 0x0010DOUBLE_FLOAT = 2NOOP = 0ADD = 1MULTIPLY = 2DIVIDE = 3NEGATE = 4COMPARE = 5EXTENDSFDF = 6TRUNCDFSF = 7UNKNOWN = -1ROUND_TO_NEAREST = 0 | round result to nearest representable valueROUND_TO_ZERO = 1 | round result towards zeroROUND_TO_PLUS = 2 | round result towards plus infinityROUND_TO_MINUS = 3 | round result towards minus infinity| Entry points: .globl SYM (__adddf3) .globl SYM (__subdf3) .globl SYM (__muldf3) .globl SYM (__divdf3) .globl SYM (__negdf2) .globl SYM (__cmpdf2) .text .even| These are common routines to return and signal exceptions. Ld$den:| Return and signal a denormalized number orl d7,d0 movew IMM (INEXACT_RESULT+UNDERFLOW),d7 moveq IMM (DOUBLE_FLOAT),d6 PICJUMP $_exception_handlerLd$infty:Ld$overflow:| Return a properly signed INFINITY and set the exception flags movel IMM (0x7ff00000),d0 movel IMM (0),d1 orl d7,d0 movew IMM (INEXACT_RESULT+OVERFLOW),d7 moveq IMM (DOUBLE_FLOAT),d6 PICJUMP $_exception_handlerLd$underflow:| Return 0 and set the exception flags movel IMM (0),d0 movel d0,d1 movew IMM (INEXACT_RESULT+UNDERFLOW),d7 moveq IMM (DOUBLE_FLOAT),d6 PICJUMP $_exception_handlerLd$inop:| Return a quiet NaN and set the exception flags movel IMM (QUIET_NaN),d0 movel d0,d1 movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7 moveq IMM (DOUBLE_FLOAT),d6 PICJUMP $_exception_handlerLd$div$0:| Return a properly signed INFINITY and set the exception flags movel IMM (0x7ff00000),d0 movel IMM (0),d1 orl d7,d0 movew IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7 moveq IMM (DOUBLE_FLOAT),d6 PICJUMP $_exception_handler|=============================================================================|=============================================================================| double precision routines|=============================================================================|=============================================================================| A double precision floating point number (double) has the format:|| struct _double {| unsigned int sign : 1; /* sign bit */ | unsigned int exponent : 11; /* exponent, shifted by 126 */| unsigned int fraction : 52; /* fraction */| } double;| | Thus sizeof(double) = 8 (64 bits). || All the routines are callable from C programs, and return the result | in the register pair d0-d1. They also preserve all registers except | d0-d1 and a0-a1.|=============================================================================| __subdf3|=============================================================================| double __subdf3(double, double);SYM (__subdf3): bchg IMM (31),sp@(12) | change sign of second operand | and fall through, so we always add|=============================================================================| __adddf3|=============================================================================| double __adddf3(double, double);SYM (__adddf3):#ifndef __mcoldfire__ link a6,IMM (0) | everything will be done in registers moveml d2-d7,sp@- | save all data registers and a2 (but d0-d1)#else link a6,IMM (-24) moveml d2-d7,sp@#endif movel a6@(8),d0 | get first operand movel a6@(12),d1 | movel a6@(16),d2 | get second operand movel a6@(20),d3 | movel d0,d7 | get d0's sign bit in d7 ' addl d1,d1 | check and clear sign bit of a, and gain one addxl d0,d0 | bit of extra precision beq Ladddf$b | if zero return second operand movel d2,d6 | save sign in d6 addl d3,d3 | get rid of sign bit and gain one bit of addxl d2,d2 | extra precision beq Ladddf$a | if zero return first operand andl IMM (0x80000000),d7 | isolate a's sign bit ' swap d6 | and also b's sign bit '#ifndef __mcoldfire__ andw IMM (0x8000),d6 | orw d6,d7 | and combine them into d7, so that a's sign ' | bit is in the high word and b's is in the ' | low word, so d6 is free to be used#else andl IMM (0x8000),d6 orl d6,d7#endif movel d7,a0 | now save d7 into a0, so d7 is free to | be used also| Get the exponents and check for denormalized and/or infinity. movel IMM (0x001fffff),d6 | mask for the fraction movel IMM (0x00200000),d7 | mask to put hidden bit back movel d0,d4 | andl d6,d0 | get fraction in d0 notl d6 | make d6 into mask for the exponent andl d6,d4 | get exponent in d4 beq Ladddf$a$den | branch if a is denormalized cmpl d6,d4 | check for INFINITY or NaN beq Ladddf$nf | orl d7,d0 | and put hidden bit backLadddf$1: swap d4 | shift right exponent so that it starts#ifndef __mcoldfire__ lsrw IMM (5),d4 | in bit 0 and not bit 20#else lsrl IMM (5),d4 | in bit 0 and not bit 20#endif| Now we have a's exponent in d4 and fraction in d0-d1 ' movel d2,d5 | save b to get exponent andl d6,d5 | get exponent in d5 beq Ladddf$b$den | branch if b is denormalized cmpl d6,d5 | check for INFINITY or NaN beq Ladddf$nf notl d6 | make d6 into mask for the fraction again andl d6,d2 | and get fraction in d2 orl d7,d2 | and put hidden bit backLadddf$2: swap d5 | shift right exponent so that it starts#ifndef __mcoldfire__ lsrw IMM (5),d5 | in bit 0 and not bit 20#else lsrl IMM (5),d5 | in bit 0 and not bit 20#endif| Now we have b's exponent in d5 and fraction in d2-d3. '| The situation now is as follows: the signs are combined in a0, the | numbers are in d0-d1 (a) and d2-d3 (b), and the exponents in d4 (a)| and d5 (b). To do the rounding correctly we need to keep all the| bits until the end, so we need to use d0-d1-d2-d3 for the first number| and d4-d5-d6-d7 for the second. To do this we store (temporarily) the| exponents in a2-a3.#ifndef __mcoldfire__ moveml a2-a3,sp@- | save the address registers#else movel a2,sp@- movel a3,sp@- movel a4,sp@- #endif movel d4,a2 | save the exponents movel d5,a3 | movel IMM (0),d7 | and move the numbers around movel d7,d6 | movel d3,d5 | movel d2,d4 | movel d7,d3 | movel d7,d2 || Here we shift the numbers until the exponents are the same, and put | the largest exponent in a2.#ifndef __mcoldfire__ exg d4,a2 | get exponents back exg d5,a3 | cmpw d4,d5 | compare the exponents#else movel d4,a4 | get exponents back movel a2,d4 movel a4,a2 movel d5,a4 movel a3,d5 movel a4,a3 cmpl d4,d5 | compare the exponents#endif beq Ladddf$3 | if equal don't shift ' bhi 9f | branch if second exponent is higher| Here we have a's exponent larger than b's, so we have to shift b. We do | this by using as counter d2:1: movew d4,d2 | move largest exponent to d2#ifndef __mcoldfire__ subw d5,d2 | and subtract second exponent exg d4,a2 | get back the longs we saved exg d5,a3 |#else subl d5,d2 | and subtract second exponent movel d4,a4 | get back the longs we saved movel a2,d4 movel a4,a2 movel d5,a4 movel a3,d5 movel a4,a3#endif| if difference is too large we don't shift (actually, we can just exit) '#ifndef __mcoldfire__ cmpw IMM (DBL_MANT_DIG+2),d2#else cmpl IMM (DBL_MANT_DIG+2),d2#endif bge Ladddf$b$small#ifndef __mcoldfire__ cmpw IMM (32),d2 | if difference >= 32, shift by longs#else cmpl IMM (32),d2 | if difference >= 32, shift by longs#endif bge 5f2:#ifndef __mcoldfire__ cmpw IMM (16),d2 | if difference >= 16, shift by words #else cmpl IMM (16),d2 | if difference >= 16, shift by words #endif bge 6f bra 3f | enter dbra loop4:#ifndef __mcoldfire__ lsrl IMM (1),d4 roxrl IMM (1),d5 roxrl IMM (1),d6 roxrl IMM (1),d7#else lsrl IMM (1),d7 btst IMM (0),d6 beq 10f bset IMM (31),d710: lsrl IMM (1),d6 btst IMM (0),d5 beq 11f bset IMM (31),d611: lsrl IMM (1),d5 btst IMM (0),d4 beq 12f bset IMM (31),d512: lsrl IMM (1),d4#endif3:#ifndef __mcoldfire__ dbra d2,4b#else subql IMM (1),d2 bpl 4b #endif movel IMM (0),d2 movel d2,d3 bra Ladddf$45: movel d6,d7 movel d5,d6 movel d4,d5 movel IMM (0),d4#ifndef __mcoldfire__ subw IMM (32),d2#else subl IMM (32),d2#endif bra 2b6: movew d6,d7 swap d7 movew d5,d6 swap d6 movew d4,d5 swap d5 movew IMM (0),d4 swap d4#ifndef __mcoldfire__ subw IMM (16),d2#else subl IMM (16),d2#endif bra 3b 9:#ifndef __mcoldfire__ exg d4,d5 movew d4,d6 subw d5,d6 | keep d5 (largest exponent) in d4 exg d4,a2 exg d5,a3#else movel d5,d6 movel d4,d5 movel d6,d4 subl d5,d6 movel d4,a4 movel a2,d4 movel a4,a2 movel d5,a4 movel a3,d5 movel a4,a3#endif| if difference is too large we don't shift (actually, we can just exit) '#ifndef __mcoldfire__ cmpw IMM (DBL_MANT_DIG+2),d6#else cmpl IMM (DBL_MANT_DIG+2),d6#endif bge Ladddf$a$small#ifndef __mcoldfire__ cmpw IMM (32),d6 | if difference >= 32, shift by longs#else cmpl IMM (32),d6 | if difference >= 32, shift by longs#endif bge 5f2:#ifndef __mcoldfire__ cmpw IMM (16),d6 | if difference >= 16, shift by words #else cmpl IMM (16),d6 | if difference >= 16, shift by words #endif bge 6f bra 3f | enter dbra loop4:#ifndef __mcoldfire__ lsrl IMM (1),d0 roxrl IMM (1),d1 roxrl IMM (1),d2 roxrl IMM (1),d3#else lsrl IMM (1),d3 btst IMM (0),d2 beq 10f bset IMM (31),d310: lsrl IMM (1),d2 btst IMM (0),d1 beq 11f bset IMM (31),d211: lsrl IMM (1),d1 btst IMM (0),d0 beq 12f bset IMM (31),d112: lsrl IMM (1),d0#endif3:#ifndef __mcoldfire__ dbra d6,4b#else subql IMM (1),d6 bpl 4b#endif movel IMM (0),d7 movel d7,d6 bra Ladddf$45: movel d2,d3 movel d1,d2 movel d0,d1 movel IMM (0),d0#ifndef __mcoldfire__ subw IMM (32),d6#else subl IMM (32),d6#endif bra 2b6: movew d2,d3 swap d3 movew d1,d2 swap d2 movew d0,d1 swap d1 movew IMM (0),d0 swap d0#ifndef __mcoldfire__ subw IMM (16),d6#else subl IMM (16),d6#endif bra 3bLadddf$3:#ifndef __mcoldfire__ exg d4,a2 exg d5,a3#else movel d4,a4 movel a2,d4 movel a4,a2 movel d5,a4 movel a3,d5 movel a4,a3#endifLadddf$4: | Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and| the signs in a4.| Here we have to decide whether to add or subtract the numbers:#ifndef __mcoldfire__ exg d7,a0 | get the signs exg d6,a3 | a3 is free to be used#else movel d7,a4 movel a0,d7 movel a4,a0 movel d6,a4 movel a3,d6 movel a4,a3#endif movel d7,d6 | movew IMM (0),d7 | get a's sign in d7 ' swap d6 | movew IMM (0),d6 | and b's sign in d6 ' eorl d7,d6 | compare the signs bmi Lsubdf$0 | if the signs are different we have | to subtract#ifndef __mcoldfire__ exg d7,a0 | else we add the numbers exg d6,a3 |#else movel d7,a4 movel a0,d7 movel a4,a0 movel d6,a4 movel a3,d6 movel a4,a3#endif addl d7,d3 | addxl d6,d2 | addxl d5,d1 | addxl d4,d0 | movel a2,d4 | return exponent to d4 movel a0,d7 | andl IMM (0x80000000),d7 | d7 now has the sign
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -