;***************************************************************************************** ;IEEE 64 Bit Floating Point Library (c) 2003 M.Cibulski ; ;Basic Calculations ; ;***************************************************************************************** ;***************************************************************************************** ;Return AKKU as result of a binary operation ; ;Registers: ;AKKU floating point akkumulator ; ;***************************************************************************************** flt_binop_return_x: pop yh ;local variable ptr pop yl pop r16 ;save return adress pop r17 pop r0 ;remove FLT_Y from stack pop r0 pop r0 pop r0 pop r0 pop r0 pop r0 pop r0 pop r0 pop r0 push r17 ;restore return adress push r16 ret ;***************************************************************************************** ;Return FLT_Y as result of a binary operation ; ;Registers: ;AKKU floating point akkumulator ; ;***************************************************************************************** flt_binop_return_y: pop yh ;local variable ptr pop yl pop r16 ;save return adress pop r17 pop AKKU_S ;take FLT_Y as result pop AKKU_E1 pop AKKU_E2 pop AKKU_2 pop AKKU_3 pop AKKU_4 pop AKKU_5 pop AKKU_6 pop AKKU_7 pop AKKU_8 push r17 ;restore return adress push r16 ret ;***************************************************************************************** ;Subtraction ; ;AKKU = Y - AKKU ; ;***************************************************************************************** .CSEG flt_sub: f_chs r16 ;rjmp flt_add ;addition ;***************************************************************************************** ;Addition ; ;AKKUA = Y + AKKU ; ;***************************************************************************************** .CSEG flt_add: push yl push yh in yl ,spl in yh ,sph f_isnumber r16 ,flt_add_01 rjmp flt_binop_return_x flt_add_01: tst AKKU_E1 ;AKKU is Zero ? brne flt_add_02 ;no tst AKKU_E2 brne flt_add_02 ;no rjmp flt_binop_return_y flt_add_02: ldd r16 ,Y+FLT_Y_E1 ldd r17 ,Y+FLT_Y_E2 tst r16 ;FLT_Y is Zero ? brne flt_add_03 ;no tst r17 brne flt_add_03 ;no jmp flt_binop_return_x flt_add_03: cpi r16 ,high(FLT_E_NAN) ;FLT_Y is NAN ? brne flt_add_04 ;no cpi r17 ,low(FLT_E_NAN) brne flt_add_04 ;no flt_add_return_y: rjmp flt_binop_return_y ;yes flt_add_04: ;ldd r16 ,Y+FLT_Y_E1 ;ldd r17 ,Y+FLT_Y_E2 sub r17 ,AKKU_E2 ;calc difference of exponents sbc r16 ,AKKU_E1 brcc flt_add_ashift ;Y exponent bigger or equal, shift AKKU ldd r0 ,Y+FLT_Y_S ;swap X and Y std Y+FLT_Y_S ,AKKU_S mov AKKU_S ,r0 ldd r0 ,Y+FLT_Y_E1 std Y+FLT_Y_E1 ,AKKU_E1 mov AKKU_E1 ,r0 ldd r0 ,Y+FLT_Y_E2 std Y+FLT_Y_E2 ,AKKU_E2 mov AKKU_E2 ,r0 ldd r0 ,Y+FLT_Y_2 std Y+FLT_Y_2 ,AKKU_2 mov AKKU_2 ,r0 ldd r0 ,Y+FLT_Y_3 std Y+FLT_Y_3 ,AKKU_3 mov AKKU_3 ,r0 ldd r0 ,Y+FLT_Y_4 std Y+FLT_Y_4 ,AKKU_4 mov AKKU_4 ,r0 ldd r0 ,Y+FLT_Y_5 std Y+FLT_Y_5 ,AKKU_5 mov AKKU_5 ,r0 ldd r0 ,Y+FLT_Y_6 std Y+FLT_Y_6 ,AKKU_6 mov AKKU_6 ,r0 ldd r0 ,Y+FLT_Y_7 std Y+FLT_Y_7 ,AKKU_7 mov AKKU_7 ,r0 ldd r0 ,Y+FLT_Y_8 std Y+FLT_Y_8 ,AKKU_8 mov AKKU_8 ,r0 clr r0 ;exp_difference = -exp_difference com r17 com r16 adc r17 ,r0 adc r16 ,r0 flt_add_ashift: tst r16 ;more than 256 to shift brne flt_add_return_y ;AKKU too small (Zero) cpi r17 ,53 ;more than 52 to shift brcc flt_add_return_y ;AKKU too small (Zero) flt_add_06: add AKKU_E2 ,r17 ;take bigger exponent for result adc AKKU_E1 ,r16 clr r0 rjmp flt_add_ashift_chk flt_add_ashift8: mov r0 ,AKKU_8 mov AKKU_8 ,AKKU_7 ;shift A right 8 digits mov AKKU_7 ,AKKU_6 mov AKKU_6 ,AKKU_5 mov AKKU_5 ,AKKU_4 mov AKKU_4 ,AKKU_3 mov AKKU_3 ,AKKU_2 clr AKKU_2 subi r17 ,8 ;counter -8 flt_add_ashift_chk: ;shift A right cpi r17 ,8 ;8 or more digits brcc flt_add_ashift8 ;shift by 8 digits (move registers) tst r17 ;counter == 0 breq flt_add_noshift ;shifting completed flt_add_ashift1: lsr AKKU_2 ror AKKU_3 ror AKKU_4 ror AKKU_5 ror AKKU_6 ror AKKU_7 ror AKKU_8 ror r0 dec r17 ;counter -1 brne flt_add_ashift1 ;more to shift flt_add_noshift: tst r0 ;must round up ? brpl flt_add_shifted_noroundup ;no clr r0 ;add 1 to mantissa sec adc AKKU_8 ,r0 adc AKKU_7 ,r0 adc AKKU_6 ,r0 adc AKKU_5 ,r0 adc AKKU_4 ,r0 adc AKKU_3 ,r0 adc AKKU_2 ,r0 flt_add_shifted_noroundup: ldd r16 ,Y+FLT_Y_S ;sign of FLT_Y eor r16 ,AKKU_S ;sign of AKKU brmi flt_add_y_minus ;not equal, subtraction of absolute values flt_add_y_plus: ldd r1 ,Y+FLT_Y_8 add AKKU_8 ,r1 ldd r1 ,Y+FLT_Y_7 adc AKKU_7 ,r1 ldd r1 ,Y+FLT_Y_6 adc AKKU_6 ,r1 ldd r1 ,Y+FLT_Y_5 adc AKKU_5 ,r1 ldd r1 ,Y+FLT_Y_4 adc AKKU_4 ,r1 ldd r1 ,Y+FLT_Y_3 adc AKKU_3 ,r1 ldd r1 ,Y+FLT_Y_2 adc AKKU_2 ,r1 sbrs AKKU_2 ,5 ;overflow (0b00100000) rjmp flt_add_return_x ;no overflow lsr AKKU_2 ;shift right 1 digit ror AKKU_3 ror AKKU_4 ror AKKU_5 ror AKKU_6 ror AKKU_7 ror AKKU_8 ldi r16 ,low(1) ;exponent +1 add AKKU_E2 ,r16 ldi r16 ,high(1) adc AKKU_E1 ,r16 ldi r16 ,low(FLT_E_NAN) ;check for overflow ldi r17 ,high(FLT_E_NAN) cp AKKU_E2 ,r16 cpc AKKU_E1 ,r17 brcs flt_add_return_x ;exp < NANEXP, no overflow clr AKKU_S movw AKKU_E1:AKKU_E2 ,r17:r16 mov AKKU_2 ,r16 mov AKKU_3 ,r16 mov AKKU_4 ,r16 mov AKKU_5 ,r16 mov AKKU_6 ,r16 mov AKKU_7 ,r16 mov AKKU_8 ,r16 flt_add_return_x: rjmp flt_binop_return_x flt_add_y_minus: ldd AKKU_S ,Y+FLT_Y_S ;sign of FLT_Y ldd r1 ,Y+FLT_Y_8 sub r1 ,AKKU_8 mov AKKU_8 ,r1 ldd r1 ,Y+FLT_Y_7 sbc r1 ,AKKU_7 mov AKKU_7 ,r1 ldd r1 ,Y+FLT_Y_6 sbc r1 ,AKKU_6 mov AKKU_6 ,r1 ldd r1 ,Y+FLT_Y_5 sbc r1 ,AKKU_5 mov AKKU_5 ,r1 ldd r1 ,Y+FLT_Y_4 sbc r1 ,AKKU_4 mov AKKU_4 ,r1 ldd r1 ,Y+FLT_Y_3 sbc r1 ,AKKU_3 mov AKKU_3 ,r1 ldd r1 ,Y+FLT_Y_2 sbc r1 ,AKKU_2 mov AKKU_2 ,r1 brcc flt_add_no_chs ;no underflow, sign not changed com AKKU_8 ;negation com AKKU_7 com AKKU_6 com AKKU_5 com AKKU_4 com AKKU_3 com AKKU_2 clr r16 adc AKKU_8 ,r16 adc AKKU_7 ,r16 adc AKKU_6 ,r16 adc AKKU_5 ,r16 adc AKKU_4 ,r16 adc AKKU_3 ,r16 adc AKKU_2 ,r16 f_chs r16 ;change sign flt_add_no_chs: ldi r16 ,6 tst AKKU_2 breq flt_add_norm_8chk rjmp flt_add_norm1_chk flt_add_norm8: dec r16 breq flt_add_end_zero mov AKKU_3 ,AKKU_4 mov AKKU_4 ,AKKU_5 mov AKKU_5 ,AKKU_6 mov AKKU_6 ,AKKU_7 mov AKKU_7 ,AKKU_8 clr AKKU_8 ldi r17 ,low(8) ;exponent -8 sub AKKU_E2 ,r17 ldi r17 ,high(8) sbc AKKU_E1 ,r17 flt_add_norm_8chk: tst AKKU_3 ;highest 8 bit empty breq flt_add_norm8 ;shift left 8 digits (move registers) rjmp flt_add_norm1_chk flt_add_norm1: ldi r16 ,low(1) ;exponent -1 sub AKKU_E2 ,r16 ldi r16 ,high(1) sbc AKKU_E1 ,r16 lsl AKKU_8 ;shift right 1 digit rol AKKU_7 rol AKKU_6 rol AKKU_5 rol AKKU_4 rol AKKU_3 rol AKKU_2 flt_add_norm1_chk: bst AKKU_2 ,4 ;small mantissa without leading 1 brtc flt_add_norm1 tst AKKU_E1 ;check for small exponent (= zero result) brmi flt_add_end_zero brne flt_add_end tst AKKU_E2 brne flt_add_end flt_add_end_zero: clr AKKU_E1 clr AKKU_E2 clr AKKU_S clr AKKU_2 clr AKKU_3 clr AKKU_4 clr AKKU_5 clr AKKU_6 clr AKKU_7 clr AKKU_8 flt_add_end: rjmp flt_binop_return_x ;***************************************************************************************** ;Multiplication ; ;AKKU = Y * AKKU ; ;***************************************************************************************** .CSEG flt_mul: push yl push yh in yl ,spl in yh ,sph f_isnumber r16 ,flt_mul_01 rjmp flt_binop_return_x flt_mul_01: tst AKKU_E1 ;AKKU is Zero ? brne flt_mul_02 ;no tst AKKU_E2 brne flt_mul_02 ;no rjmp flt_binop_return_x flt_mul_02: ldd r16 ,Y+FLT_Y_E1 ldd r17 ,Y+FLT_Y_E2 tst r16 ;FLT_Y is Zero ? brne flt_mul_03 ;no tst r17 brne flt_mul_03 ;no rjmp flt_binop_return_y flt_mul_03: cpi r16 ,high(FLT_E_NAN) ;FLT_Y is NAN ? brne flt_mul_04 ;no cpi r17 ,low(FLT_E_NAN) brne flt_mul_04 ;no jmp flt_binop_return_y ;yes flt_mul_04: mov AKKUB_2 ,AKKU_2 mov AKKUB_3 ,AKKU_3 mov AKKUB_4 ,AKKU_4 mov AKKUB_5 ,AKKU_5 mov AKKUB_6 ,AKKU_6 mov AKKUB_7 ,AKKU_7 mov AKKUB_8 ,AKKU_8 ldi r16 ,1 ldi r17 ,0 clr AKKU_2 clr AKKU_3 clr AKKU_4 clr AKKU_5 clr AKKU_6 clr AKKU_7 clr AKKU_8 inc AKKU_8 ldd r0 ,Y+FLT_Y_8 ;A8 * B8 mul r0 ,AKKUB_8 tst r0 brpl flt_mul_no_a14 inc r1 flt_mul_no_a14: mov AKKU_8 ,r1 ;Results into A12:A13 ldd r0 ,Y+FLT_Y_7 ;A7 * B8 mul r0 ,AKKUB_8 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_8 ;A8 * B7 mul r0 ,AKKUB_7 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 tst AKKU_8 brpl flt_mul_no_a13 add AKKU_7 ,r16 adc AKKU_6 ,r17 flt_mul_no_a13: mov AKKU_8 ,AKKU_7 mov AKKU_7 ,AKKU_6 clr AKKU_6 ;Results into A11:A12 ldd r0 ,Y+FLT_Y_6 ;A6 * B8 mul r0 ,AKKUB_8 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_7 ;A7 * B7 mul r0 ,AKKUB_7 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_8 ;A8 * B6 mul r0 ,AKKUB_6 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 tst AKKU_8 brpl flt_mul_no_a12 add AKKU_7 ,r16 adc AKKU_6 ,r17 flt_mul_no_a12: mov AKKU_8 ,AKKU_7 mov AKKU_7 ,AKKU_6 clr AKKU_6 ;Results into A10:A11 ldd r0 ,Y+FLT_Y_5 ;A5 * B8 mul r0 ,AKKUB_8 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_6 ;A6 * B7 mul r0 ,AKKUB_7 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_7 ;A7 * B6 mul r0 ,AKKUB_6 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_8 ;A8 * B5 mul r0 ,AKKUB_5 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 tst AKKU_8 brpl flt_mul_no_a11 add AKKU_7 ,r16 adc AKKU_6 ,r17 flt_mul_no_a11: mov AKKU_8 ,AKKU_7 mov AKKU_7 ,AKKU_6 clr AKKU_6 ;Results into A9:A10 ldd r0 ,Y+FLT_Y_4 ;A4 * B8 mul r0 ,AKKUB_8 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_5 ;A5 * B7 mul r0 ,AKKUB_7 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_6 ;A6 * B6 mul r0 ,AKKUB_6 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_7 ;A7 * B5 mul r0 ,AKKUB_5 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_8 ;A8 * B4 mul r0 ,AKKUB_4 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 tst AKKU_8 brpl flt_mul_no_a10 add AKKU_7 ,r16 adc AKKU_6 ,r17 flt_mul_no_a10: mov AKKU_8 ,AKKU_7 mov AKKU_7 ,AKKU_6 clr AKKU_6 ;Results into A8:A9 ldd r0 ,Y+FLT_Y_3 ;A3 * B8 mul r0 ,AKKUB_8 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_4 ;A4 * B7 mul r0 ,AKKUB_7 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_5 ;A5 * B6 mul r0 ,AKKUB_6 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_6 ;A6 * B5 mul r0 ,AKKUB_5 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_7 ;A7 * B4 mul r0 ,AKKUB_4 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_8 ;A8 * B3 mul r0 ,AKKUB_3 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 tst AKKU_8 brpl flt_mul_no_a9 add AKKU_7 ,r16 adc AKKU_6 ,r17 flt_mul_no_a9: mov AKKU_8 ,AKKU_7 mov AKKU_7 ,AKKU_6 clr AKKU_6 ;Results into A7:A8 ldd r0 ,Y+FLT_Y_2 ;A2 * B8 mul r0 ,AKKUB_8 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_3 ;A3 * B7 mul r0 ,AKKUB_7 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_4 ;A4 * B6 mul r0 ,AKKUB_6 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_5 ;A5 * B5 mul r0 ,AKKUB_5 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_6 ;A6 * B4 mul r0 ,AKKUB_4 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_7 ;A7 * B3 mul r0 ,AKKUB_3 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ldd r0 ,Y+FLT_Y_8 ;A8 * B2 mul r0 ,AKKUB_2 add AKKU_8 ,r0 adc AKKU_7 ,r1 adc AKKU_6 ,r17 ;Results into A6:A7 ldd r0 ,Y+FLT_Y_2 ;A2 * B7 mul r0 ,AKKUB_7 add AKKU_7 ,r0 adc AKKU_6 ,r1 adc AKKU_5 ,r17 ldd r0 ,Y+FLT_Y_3 ;A3 * B6 mul r0 ,AKKUB_6 add AKKU_7 ,r0 adc AKKU_6 ,r1 adc AKKU_5 ,r17 ldd r0 ,Y+FLT_Y_4 ;A4 * B5 mul r0 ,AKKUB_5 add AKKU_7 ,r0 adc AKKU_6 ,r1 adc AKKU_5 ,r17 ldd r0 ,Y+FLT_Y_5 ;A5 * B4 mul r0 ,AKKUB_4 add AKKU_7 ,r0 adc AKKU_6 ,r1 adc AKKU_5 ,r17 ldd r0 ,Y+FLT_Y_6 ;A6 * B3 mul r0 ,AKKUB_3 add AKKU_7 ,r0 adc AKKU_6 ,r1 adc AKKU_5 ,r17 ldd r0 ,Y+FLT_Y_7 ;A7 * B2 mul r0 ,AKKUB_2 add AKKU_7 ,r0 adc AKKU_6 ,r1 adc AKKU_5 ,r17 ;Results into A5:A6 ldd r0 ,Y+FLT_Y_2 ;A2 * B6 mul r0 ,AKKUB_6 add AKKU_6 ,r0 adc AKKU_5 ,r1 adc AKKU_4 ,r17 ldd r0 ,Y+FLT_Y_3 ;A3 * B5 mul r0 ,AKKUB_5 add AKKU_6 ,r0 adc AKKU_5 ,r1 adc AKKU_4 ,r17 ldd r0 ,Y+FLT_Y_4 ;A4 * B4 mul r0 ,AKKUB_4 add AKKU_6 ,r0 adc AKKU_5 ,r1 adc AKKU_4 ,r17 ldd r0 ,Y+FLT_Y_5 ;A5 * B3 mul r0 ,AKKUB_3 add AKKU_6 ,r0 adc AKKU_5 ,r1 adc AKKU_4 ,r17 ldd r0 ,Y+FLT_Y_6 ;A6 * B2 mul r0 ,AKKUB_2 add AKKU_6 ,r0 adc AKKU_5 ,r1 adc AKKU_4 ,r17 ;Results into A4:A5 ldd r0 ,Y+FLT_Y_2 ;A2 * B5 mul r0 ,AKKUB_5 add AKKU_5 ,r0 adc AKKU_4 ,r1 adc AKKU_3 ,r17 ldd r0 ,Y+FLT_Y_3 ;A3 * B4 mul r0 ,AKKUB_4 add AKKU_5 ,r0 adc AKKU_4 ,r1 adc AKKU_3 ,r17 ldd r0 ,Y+FLT_Y_4 ;A4 * B3 mul r0 ,AKKUB_3 add AKKU_5 ,r0 adc AKKU_4 ,r1 adc AKKU_3 ,r17 ldd r0 ,Y+FLT_Y_5 ;A5 * B2 mul r0 ,AKKUB_2 add AKKU_5 ,r0 adc AKKU_4 ,r1 adc AKKU_3 ,r17 ;Results into A3:A4 ldd r0 ,Y+FLT_Y_2 ;A2 * B4 mul r0 ,AKKUB_4 add AKKU_4 ,r0 adc AKKU_3 ,r1 adc AKKU_2 ,r17 ldd r0 ,Y+FLT_Y_3 ;A3 * B3 mul r0 ,AKKUB_3 add AKKU_4 ,r0 adc AKKU_3 ,r1 adc AKKU_2 ,r17 ldd r0 ,Y+FLT_Y_4 ;A4 * B2 mul r0 ,AKKUB_2 add AKKU_4 ,r0 adc AKKU_3 ,r1 adc AKKU_2 ,r17 flt_mul_test: ;Results into A2:A3 clr r16 ldd r0 ,Y+FLT_Y_2 ;A2 * B3 mul r0 ,AKKUB_3 add AKKU_3 ,r0 adc AKKU_2 ,r1 adc r16 ,r17 ldd r0 ,Y+FLT_Y_3 ;A3 * B2 mul r0 ,AKKUB_2 add AKKU_3 ,r0 adc AKKU_2 ,r1 adc r16 ,r17 ;Result into A1:A2 ldd r0 ,Y+FLT_Y_2 ;A2 * B2 mul r0 ,AKKUB_2 add AKKU_2 ,r0 adc r16 ,r1 ldd r0 ,Y+FLT_Y_S eor AKKU_S ,r0 ;sign ldd r0 ,Y+FLT_Y_E2 add AKKU_E2 ,r0 ;add exponents ldd r0 ,Y+FLT_Y_E1 adc AKKU_E1 ,r0 ldi r17 ,low(0x03FF) ;subtract bias 0x3FF from exponent sub AKKU_E2 ,r17 ldi r17 ,high(0x03FF) sbc AKKU_E1 ,r17 lsr r16 ;shift right 4 digits ror AKKU_2 ror AKKU_3 ror AKKU_4 ror AKKU_5 ror AKKU_6 ror AKKU_7 ror AKKU_8 lsr r16 ror AKKU_2 ror AKKU_3 ror AKKU_4 ror AKKU_5 ror AKKU_6 ror AKKU_7 ror AKKU_8 lsr AKKU_2 ror AKKU_3 ror AKKU_4 ror AKKU_5 ror AKKU_6 ror AKKU_7 ror AKKU_8 lsr AKKU_2 ror AKKU_3 ror AKKU_4 ror AKKU_5 ror AKKU_6 ror AKKU_7 ror AKKU_8 sbrs AKKU_2 ,5 ;still overflow in AKKU_2 bit 5 ? rjmp flt_mul_check_bigexp ;no lsr AKKU_2 ;shift right one more digit ror AKKU_3 ror AKKU_4 ror AKKU_5 ror AKKU_6 ror AKKU_7 ror AKKU_8 ldi r16 ,low(1) ;exponent +1 add AKKU_E2 ,r16 ldi r16 ,high(1) adc AKKU_E1 ,r16 flt_mul_check_bigexp: ldi r16 ,low(FLT_E_NAN) ;check for overflow ldi r17 ,high(FLT_E_NAN) cp AKKU_E2 ,r16 cpc AKKU_E1 ,r17 brcs flt_mul_check_smallexp ;exp < NANEXP, no overflow clr AKKU_S ;return NAN movw AKKU_E1:AKKU_E2 ,r17:r16 mov AKKU_2 ,r16 mov AKKU_3 ,r16 mov AKKU_4 ,r16 mov AKKU_5 ,r16 mov AKKU_6 ,r16 mov AKKU_7 ,r16 mov AKKU_8 ,r16 rjmp flt_binop_return_x flt_mul_check_smallexp: tst AKKU_E1 ;check for small exponent (= zero result) brmi flt_mul_end_zero brne flt_mul_end tst AKKU_E2 brne flt_mul_end flt_mul_end_zero: clr AKKU_E1 ;return 0.0 clr AKKU_E2 clr AKKU_S clr AKKU_2 clr AKKU_3 clr AKKU_4 clr AKKU_5 clr AKKU_6 clr AKKU_7 clr AKKU_8 flt_mul_end: jmp flt_binop_return_x ;***************************************************************************************** ;Division ; ;AKKU = Y / AKKU ; ;***************************************************************************************** .CSEG flt_div: push yl push yh in yl ,spl in yh ,sph f_isnumber r16 ,flt_div_01 rjmp flt_binop_return_x ;Y/NAN = NAN flt_div_01: tst AKKU_E1 ;AKKU is Zero ? brne flt_div_02 ;no tst AKKU_E2 brne flt_div_02 ;no f_ldiexp r16 ,0x7FF ;Y/0 = NAN rjmp flt_binop_return_x flt_div_02: ldd r16 ,Y+FLT_Y_E2 ldd r17 ,Y+FLT_Y_E1 tst r17 ;FLT_Y is Zero ? brne flt_div_03 ;no tst r16 brne flt_div_03 ;no rjmp flt_binop_return_y ;0/X = 0 flt_div_03: cpi r17 ,high(FLT_E_NAN) ;FLT_Y is NAN ? brne flt_div_04 ;no cpi r16 ,low(FLT_E_NAN) brne flt_div_04 ;no rjmp flt_binop_return_y ;NAN/X = NAN flt_div_04: sub r16 ,AKKU_E2 ;exp(Y) - exp(AKKU) + BIAS sbc r17 ,AKKU_E1 subi r16 ,low(-FLT_E_BIAS) sbci r17 ,high(-FLT_E_BIAS) movw AKKU_E1:AKKU_E2 ,r17:r16 ldd r0 ,Y+FLT_Y_S ;sign eor AKKU_S ,r0 ldd AKKUB_2 ,Y+FLT_Y_2 ldd AKKUB_3 ,Y+FLT_Y_3 ldd AKKUB_4 ,Y+FLT_Y_4 ldd AKKUB_5 ,Y+FLT_Y_5 ldd AKKUB_6 ,Y+FLT_Y_6 ldd AKKUB_7 ,Y+FLT_Y_7 ldd AKKUB_8 ,Y+FLT_Y_8 ldi r16 ,7 ;7 registers to set ldi r17 ,0b00010000 ;bitmask for result clr r0 ;result flt_div_05_loop: sub AKKUB_8 ,AKKU_8 ;A = A - B sbc AKKUB_7 ,AKKU_7 sbc AKKUB_6 ,AKKU_6 sbc AKKUB_5 ,AKKU_5 sbc AKKUB_4 ,AKKU_4 sbc AKKUB_3 ,AKKU_3 sbc AKKUB_2 ,AKKU_2 brcs flt_div_06_zero ;no underflow ? or r0 ,r17 ;result bit = 1 rjmp flt_div_07 flt_div_06_zero: add AKKUB_8 ,AKKU_8 adc AKKUB_7 ,AKKU_7 adc AKKUB_6 ,AKKU_6 adc AKKUB_5 ,AKKU_5 adc AKKUB_4 ,AKKU_4 adc AKKUB_3 ,AKKU_3 adc AKKUB_2 ,AKKU_2 flt_div_07: lsl AKKUB_8 ;Y = Y * 2 rol AKKUB_7 rol AKKUB_6 rol AKKUB_5 rol AKKUB_4 rol AKKUB_3 rol AKKUB_2 lsr r17 ;shift mask for next bit in memory brne flt_div_05_loop push r0 ;save result clr r0 ;next 8 result bits ldi r17 ,0b10000000 ;set mask for next 8 bits dec r16 ;more registers brne flt_div_05_loop cp AKKUB_8 ,AKKU_8 ;one more step for correct rounding cpc AKKUB_7 ,AKKU_7 ;If AKKU > AKKUB (Carry set) cpc AKKUB_6 ,AKKU_6 ; next Bit is 0 cpc AKKUB_5 ,AKKU_5 ; no round up cpc AKKUB_4 ,AKKU_4 ;else cpc AKKUB_3 ,AKKU_3 ; next bit is 1 cpc AKKUB_2 ,AKKU_2 ; round up pop AKKU_8 pop AKKU_7 pop AKKU_6 pop AKKU_5 pop AKKU_4 pop AKKU_3 pop AKKU_2 brcs flt_div_08_noroundup ;Carry set (AKKU > AKKUB) sec ;Add 1 adc AKKU_8 ,r0 adc AKKU_7 ,r0 adc AKKU_6 ,r0 adc AKKU_5 ,r0 adc AKKU_4 ,r0 adc AKKU_3 ,r0 adc AKKU_2 ,r0 flt_div_08_noroundup: bst AKKU_2 ,4 ;leading 1 present ? brts flt_div_09_end ;yes lsl AKKU_8 ;shift left one bit rol AKKU_7 ;and adjust exponent rol AKKU_6 rol AKKU_5 rol AKKU_4 rol AKKU_3 rol AKKU_2 sec ;exponent -1 sbc AKKU_E2 ,r0 sbc AKKU_E1 ,r0 flt_div_09_end: or r0 ,AKKU_E1 brmi flt_div_end_zero or r0 ,AKKU_E2 breq flt_div_end_zero rjmp flt_binop_return_x ;return X flt_div_end_zero: clr AKKU_E1 clr AKKU_E2 clr AKKU_S clr AKKU_2 clr AKKU_3 clr AKKU_4 clr AKKU_5 clr AKKU_6 clr AKKU_7 clr AKKU_8 rjmp flt_binop_return_x ;return X