|
;**** A P P L I C A T I O N N O T E A V R ? ? ? ************************
;*
;* Title: 32-bit Arithmetic Routines with Macrolibrary
;* Project: Math32
;* Version: 2.3
;* Last updated: 2003.09.15
;* Create Date: 1999.10.25
;* Target MCU: AT90S8515 (as well as others AVR uC)
;* (C) ATMEL Corporation (mailto:avr@atmel.com)
;* Originator: (C) 1999-2003 Andre Birua (mailto:birua@hotmail.com)
;* This Application Note absolutely free in use anybody
;* INTERPRETATION
;* This package of assembler subprograms is developed for integer arithmetic
;* with tracing of sign bit in 32 bits calculations and data reloads.
;* It is based on microcontroller register file to the maximum.
;* In real users projects available abundant digit capacity allows to avoid
;* overflow and reduces inaccuracy of rounding errors in chain calculations.
;* Included macro definitions will increase readability of assembler source
;* at bit by bit and multibyte data operations inside AVR software model
;*
;* DESCRIPTION
;* This Application Note lists:
;* i) Math32 subroutines for the following:
;* Add/Subtract/Multiply/Divide/Complement 32 bits operands,
;* Binary 16 & 24 bits operand to/back BCD conversion,
;* Binary 32 bits operand to BCD conversion,
;* Initialization of data memory on a pattern,
;* Load/Store group of registers from/to data space;
;* ii) macro definitions call mathematical and data transfer subroutines;
;* iii) useful general macroinstructions for the AVR 8-Bit RISC family
;*
;* "ADD32" Add without Carry Rd32 = Rd32 + Rr32
;* "SUB32" Subtract without Carry Rd32 = Rd32 - Rr32
;* "MUL32" Multiply Unsigned Rd64 = Rd32 * Rr32
;* "DIV32" Divide Unsigned Rd32 = Rd32 / Rr32 (Rd64)
;* "COM32" One's Complement Rd32 = 0xffffffff - Rd32
;* "NEG32" Two's Complement Rd32 = 0x00000000 - Rd32
;* "BCD2bin" BCD to Binary 16 Rd16 = Rd24|Rr24
;* "BCD3bin" BCD to Binary 24 Rd24 = Rd32|Rr32
;* "Bin2BCD" Binary 16 to BCD Rd24 = Rd16|Rr16
;* "Bin3BCD" Binary 24 to BCD Rd32 = Rd24|Rr24
;* "Bin4BCD" Binary 32 to BCD Rd40 = Rd32|Rr32 || hwrd(Rr32)&Rd16
;* "MathMem" Init Data Memory (MA) = 0x00|0xff
;* "MathLoad" Load Registers Rd32|Rr32 = (MA)
;* "MathSave" Store Registers (MA) = Rd32|Rd64
;*
;* Rd64: destination registers (8) in the register file
;* Rd32: destination (and source) registers (4) in the register file
;* Rr32: source registers (4) in the register file
;* (MA): address for access to variable in the internal memory (SRAM)
;* Note: Math32 use high registers, r0 and lower 512 bytes of data space,
;* so Rd64=r20:r27, Rd32=r20:r23, Rd24=r20:r22, Rd16=r20:r21,
;* Rd40=r20:r24, Rr32=r16:r19, Rr24=r16:r18, Rr16=r16:r17, MA=0:511
;*
;* Number of words & cycles (Min|Max) c o m m e n t s
;* "ADD32" 6 4|5 Size of Add32sign
;* "SUB32" 16 6|15 Size of Sub32sign
;* "MUL32" 24 460|556 Size of Mul32b, based on AVR200 16x16 unsigned
;* "DIV32" 28 528|688 Size of Div32b, based on AVR200 16/16 unsigned
;* "COM32" 5 4|4 Part of Sub32
;* "NEG32" 9 8|8 Part of Sub32
;* "BCD2bin" 26 86|89 Equivalent of AVR204, but smaller & quicker
;* "BCD3bin" 43 38|402 Different from BCD2bin translation algorithm
;* "Bin2BCD" 22 19|177 Equivalent of AVR204, but smaller & much faster
;* "Bin3BCD" 21 36|366 In the form of preamble for Bin2BCD
;* "Bin3BCD" 40 36|333 All-sufficient expansion of Bin2BCD
;* "Bin4BCD" 37 515|671 Based on AVR204 16-bit Bin to BCD conversion
;* "Bin4BCD" 48 874|878 All-sufficient transform instead of pre-Bin4BCD
;* "MathMem" 10 7|645 Size of MathMemLimit, max cycle for 128 bytes
;* "MathLoad" 15 41|46 Size and max cycle for Rr32 load
;* "MathSave" 14 13|78 Size and max cycle for Rd64 save
;* In total: 350 words Usually +7 cycles: rcall & ret
;*
;* All routines are Code Size` optimized implementations and debugged with
;* macrocode for AVR macro assembler version 1.30 (Jan 27 1999 01:30:00) &
;* AVR32 macro assembler version 1.30 (Sep 8 1999 01:30:00).
;* However, AVR32 macro assembler version 1.54 (Nov 14 2001 14:05:48) &
;* AVR32 macro assembler version 1.56 (May 6 2002 14:54:01)
;* generate dummy warnings: Register already defined by the .DEF directive
;* (command option for disable this kind of warning as yet is absent...)
;* CheckIt with AVR Studio !
;* NOTE
;* ` Bin4BCD transformations has partial loop optimization for speed-up
;* While using Math32, it is important to consider the allocation of the
;* microcontroller resources available for the program. It is required:
;* - to use r0,r16..r31 with Math32;
;* - to allocate variables used in calculation in the bottom of the memory;
;* - to use T flag as a sign bit (input, output and temporary),
;* if you need to operate negative numbers or up-down overflow error
;*
;* VERSION
;* 1.0 Original version (in use starting with 1999.12.22)
;* 1.1 Fixed precedence bugs if macroparameter is an assembler expression
;* 1.2 Modify CBF & SBF & IBF macrocalls
;* 1.3 Full modification mathematical and data transfer macronotation
;* 1.4 Optimaze for speed and code size Mul32 & Div32 & BCD2bin & Bin2BCD
;* 2.0 Version for publication (added description, note and demo sections)
;* 2.1 Updated Bin2BCD, added Bin4BCD conversion & XCH macrocall
;* 2.2 Added functionally closed modifications of Bin3&4BCD translation
;* 2.3 Added BCD3bin conversion, normalize the comment of Bin3&4BCD
;*
;* DEMO
;* section below is a sample of macrocalls and not an ordinary Math32 usage
;*
;***************************************************************************
.include "8515def.inc"
.listmac ;split Toggle_mode at AVR Studio
.cseg ;press Step_Over etceteras of
rjmp Demo ;trace Registers and Memory
;Words *** general macrocode for the AVR 8-Bit RISC microcontroller ***
;2 "CLF" CLear bit Flag in register via T flag
;2 "SEF" SEt bit Flag in register via T flag
;2 "CBF" Clear Bit(s) Flag(s) in register via temporary register
;2 "SBF" Set Bit(s) Flag(s) in register via temporary register
;2 "IBF" Invert Bit(s) Flag(s) in register via temporary register
;2 "OUTI" OUT port Immediate via temporary register
;4 "OUTIW" OUT port Immediate Word via temporary register
;2 "OUTW" OUT port Word from register pair
;2 "INW" IN port Word to register pair
;3 "XCH" data eXCHange between a two registers as exclusive OR only
;2 "MVW" MoVe register pair as Word
;2 "MVI" MoVe temporary register loaded Immediate
;4 "MOVS" MOVe direct in data Space via temporary register
;8 "MOVSW" MOVe direct in data Space Word via temporary register
;3 "STSI" STore direct to data Space Immediate via temporary register
;4 "STSIW" STore direct to data Space Immediate Word via temporary register
;4 "LDSW" LoaD direct from data Space Word to register pair
;4 "STSW" STore direct to data Space Word from register pair
;2 "LDIW" LoaD Immediate Word to register pair
;2 "LDDW" LoaD indirect with Displacement from data space Word to register pair
;2 "STDW" STore indirect with Displacement to data space Word from register pair
;2 "PUSHW" PUSH register pair (Word) on stack
;2 "POPW" POP register pair (Word) from stack
.macro CLF ; Register,Bit#
clt
bld @0,@1
.endmacro
.macro SEF ; Register,Bit#
set
bld @0,@1
.endmacro
.macro CBF ; Register,RegisterH,Bit#[,Bit#][,Bit#][,Bit#][,Bit#][,Bit#][,Bit#][,Bit#]
ldi @1,~(exp2(@2)|(-@3-1<0)*exp2(@3-0)|(-@4-1<0)*exp2(@4-0)|(-@5-1<0)*exp2(@5-0)|(-@6-1<0)*exp2(@6-0)|(-@7-1<0)*exp2(@7-0)|(-@8-1<0)*exp2(@8-0)|(-@9-1<0)*exp2(@9-0))
and @0,@1
.endmacro
.macro SBF ; Register,RegisterH,Bit#[,Bit#][,Bit#][,Bit#][,Bit#][,Bit#][,Bit#][,Bit#]
ldi @1,exp2(@2)|(-@3-1<0)*exp2(@3-0)|(-@4-1<0)*exp2(@4-0)|(-@5-1<0)*exp2(@5-0)|(-@6-1<0)*exp2(@6-0)|(-@7-1<0)*exp2(@7-0)|(-@8-1<0)*exp2(@8-0)|(-@9-1<0)*exp2(@9-0)
or @0,@1
.endmacro
.macro IBF ; Register,RegisterH,Bit#[,Bit#][,Bit#][,Bit#][,Bit#][,Bit#][,Bit#][,Bit#]
ldi @1,exp2(@2)|(-@3-1<0)*exp2(@3-0)|(-@4-1<0)*exp2(@4-0)|(-@5-1<0)*exp2(@5-0)|(-@6-1<0)*exp2(@6-0)|(-@7-1<0)*exp2(@7-0)|(-@8-1<0)*exp2(@8-0)|(-@9-1<0)*exp2(@9-0)
eor @0,@1
.endmacro
.macro OUTI ; Port,RegisterH,ConstantB
ldi @1,@2
out @0,@1
.endmacro
.macro OUTIW ; PortHL,RegisterH,ConstantW
ldi @1,high(@2)
out @0h,@1
ldi @1,low(@2)
out @0l,@1
.endmacro
.macro OUTW ; PortHL,RegisterHL
out @0h,@1h
out @0l,@1l
.endmacro
.macro INW ; RegisterHL,PortHL
in @0l,@1l
in @0h,@1h
.endmacro
.macro XCH ; Register,Register
eor @0,@1
eor @1,@0
eor @0,@1
.endmacro
.macro MVW ; RegisterHL,RegisterHL
mov @0h,@1h
mov @0l,@1l
.endmacro
.macro MVI ; RegisterL,RegisterH,ConstantB
ldi @1,@2
mov @0,@1
.endmacro
.macro MOVS ; Address,Register,Address
lds @1,@2
sts @0,@1
.endmacro
.macro MOVSW ; Address,Register,Address
lds @1,@2
sts @0,@1
lds @1,(@2)+1
sts (@0)+1,@1
.endmacro
.macro STSI ; Address,RegisterH,ConstantB
ldi @1,@2
sts @0,@1
.endmacro
.macro STSIW ; Address,RegisterH,ConstantW
ldi @1,low(@2)
sts @0,@1
ldi @1,high(@2)
sts (@0)+1,@1
.endmacro
.macro LDSW ; RegisterHL,Address
lds @0l,@1
lds @0h,(@1)+1
.endmacro
.macro STSW ; Address,RegisterHL
sts (@0)+1,@1h
sts @0,@1l
.endmacro
.macro LDIW ; RegisterHL,ConstantW
ldi @0l,low(@1)
ldi @0h,high(@1)
.endmacro
.macro LDDW ; RegisterHL,RegisterPair+Displacement
ldd @0l,@1
ldd @0h,@1+1
.endmacro
.macro STDW ; RegisterPair+Displacement,RegisterHL
std @0+1,@1h
std @0,@1l
.endmacro
.macro PUSHW ; RegisterHL
push @0l
push @0h
.endmacro
.macro POPW ; RegisterHL
pop @0h
pop @0l
.endmacro
;Words ***** mathematical and data transfer macrocalls *****
;3 "INITMEM" INITialize math data space (MEMory variable) in 0|0xff
;3 "MATHR16" load from MATH data space to Registers r16,r17,r18,r19
;3 "MATHR20" load from MATH data space to Registers r20,r21,r22,r23
;3 "OPERAND" load registers as mathematical OPERAND from math data space
;3 "RESULT2" store registers as mathematical RESULT to math data space (call)
;3 "RESULT3" store registers as mathematical RESULT to math data space (jump)
;1 "CNST16B" load immediate CoNSTant to r16 as Byte
;2 "CNST16W" load immediate CoNSTant to r16,r17 as Word
;3 "CNST16T" load immediate CoNSTant to r16,r17,r18 as Three bytes
;4 "CONST16" load immediate CONSTant to r16,r17,r18,r19 as double word
;4 "CONST20" load immediate CONSTant to r20,r21,r22,r23 as double word
.macro INITMEM ; Address[,Counter(1-128)[,0|1|limit]]
ldi ZL,@0
ldi ZH,@1-1<<1|high(@0)&1
rcall MathMem@2
.endmacro
.macro MATHR16 ; Address[,Bitmap]
ldi ZL,@0
ldi ZH,((-@1-1>0)*ObXXXX|@1-0)<<1|high(@0)&1
rcall R16MathLoad
.endmacro
.macro MATHR20 ; Address[,Bitmap]
ldi ZL,@0
ldi ZH,((-@1-1>0)*ObXXXX|@1-0)<<1|high(@0)&1
rcall R20MathLoad
.endmacro
.macro OPERAND ; Address[,[Bitmap][,r16|r20]]
ldi ZL,@0
ldi ZH,((-@1-1>0)*ObXXXX|@1-0)<<1|high(@0)&1
rcall @2MathLoad
.endmacro
.macro RESULT2 ; Address[,Bitmap]
ldi ZL,@0
ldi ZH,((-@1-1>0)*ObXXXX|@1-0)<<1|high(@0)&1
rcall MathSave-2*(((-@1-1>0)*ObXXXX|@1-0)>0x7f)
.endmacro
.macro RESULT3 ; Address[,Bitmap]
ldi ZL,@0
ldi ZH,((-@1-1>0)*ObXXXX|@1-0)<<1|high(@0)&1
rjmp MathSave-2*(((-@1-1>0)*ObXXXX|@1-0)>0x7f)
.endmacro
.macro CNST16B ; ConstantB (8 bits)
ldi r16,byte1(@0)
.endmacro
.macro CNST16W ; ConstantW (16 bits)
ldi r16,byte1(@0)
ldi r17,byte2(@0)
.endmacro
.macro CNST16T ; ConstantT (24 bits)
ldi r16,byte1(@0)
ldi r17,byte2(@0)
ldi r18,byte3(@0)
.endmacro
.macro CONST16 ; ConstantD (32 bits)
ldi r16,byte1(@0)
ldi r17,byte2(@0)
ldi r18,byte3(@0)
ldi r19,byte4(@0)
.endmacro
.macro CONST20 ; ConstantD (32 bits)
ldi r20,byte1(@0)
ldi r21,byte2(@0)
ldi r22,byte3(@0)
ldi r23,byte4(@0)
.endmacro
;***************************************************************************
;# # # # # # # # # Assign Math32 Symbol and Notation # # # # # # # # #
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;*
;* Add32[sign], Sub32[sign], Mul32[b|w|t], Div32[b|w|t] :
;* operand1 operand2 result
;* r20r21r22r23 +|-|*|/ r16r17r18r19 = r20r21r22r23[r24r25r26r27]
;*
;* Com32, Neg32 : Bin2BCD20, BCD2bin20 :
;* operand result operand result
;* r20r21r22r23 >>> r20r21r22r23 r20r21[r22] >>> r20r21[r22]
;*
;* BCD3bin, Bin3BCD, Bin4BCD : Bin2BCD16, BCD2bin16 :
;* operand result operand result
;* r16...r23 >>> r20r21r22[r23[r24]] r16r17[r18] >>> r20r21[r22]
;*
;***************************************************************************
.set ObXXXX=0b1111 ;default load & store memory variable bitmap upon
;little-endian format of numbers, i.e. abs.address(LSB) < abs.address(MSB)
;***************************************************************************
;*
;* Initialize Memory in Math Data Space
;*
;* First 512+127 bytes of data space can be initialize in 0 or 0xff
;* Limit: if Flag T==1 then EachMemoryByte=0 else EachMemoryByte=0xff
;*
;***************************************************************************
.def MathPattern=r28 ;YL
.def MathCounter=r29 ;YH
MathMemLimit: brts MathMem0x0 ;
MathMem0x1: ser MathPattern ;
cpse ZH,ZH ;skip next instruction
MathMem0x0: clr MathPattern ;
mov MathCounter,ZH ;copy counter
cbr ZH,0xfe ;Z points to math data space
NextMemByte: st Z+,MathPattern ;
subi MathCounter,2 ;
brcc NextMemByte ;while MathCounter>=0
ret ;
.equ MathMem=MathMem0x0 ;default initialize memory call
;***************************************************************************
;*
;* Registers Load from Math Data Space
;*
;* Load: r16r17r18r19r20r21r22r23 from first 512+3 bytes of data space
;* operand2 operand1 (max starting address: 0x1ff)
;*
;***************************************************************************
.def MathBmp=r26 ;only XL,XH from high registers
.def MathTmp=r27 ;do not keep useful data or not used below
R16MathLoad: ldi YL,16 ;Y points to operand2 LSB
cpse ZH,ZH ;skip next instruction
R20MathLoad: ldi YL,20 ;Y points to operand1 LSB
clr YH ;
mov MathBmp,ZH ;copy bitmap
cbr ZH,0xfe ;Z points to math data space
sbr MathBmp,0xe0 ;it is possible in each macrocall
MathLoadNext: lsr MathBmp ;
clr MathTmp ;load 0 to temp register
sbrc MathBmp,0 ;if bit 0 bitmap not clear
ld MathTmp,Z+ ; load operand from memory to temp
st Y+,MathTmp ;store temp to math register
sbrc MathBmp,4 ;
rjmp MathLoadNext ;while bit 4 of bitmap not clear
ret ;
.equ MathLoad=R20MathLoad ;default registers load call
;***************************************************************************
;*
;* Registers Save to Math Data Space
;*
;* Save: r20r21r22r23r24r25r26r27 to first 512+7 bytes of data space
;* result (remainder) (max starting address: 0x1ff)
;*
;***************************************************************************
.def MathBmp=r0 ;all high registers keep useful data or used below
sec ;
cpse ZH,ZH ;skip next instruction
R20MathSave: clc ;
mov MathBmp,ZH ;copy bitmap
cbr ZH,0xfe ;Z points to math data space
ror MathBmp ;now bitmap have all 8 bits
ldi YL,20 ;Y points to result LSB
MathSaveNext: clr YH ;
ld YH,Y+ ;in order to not use other registers
sbrc MathBmp,0 ;if bit 0 bitmap not clear
st Z+,YH ; store result byte to memory
lsr MathBmp ;
brne MathSaveNext ;while not empty bitmap
ret ;
.equ MathSave=R20MathSave ;default registers save call
;***************************************************************************
;*
;* Add32 == 32+32 Bit Unsigned Addition
;*
;* add1L::add1H + add2L::add2H = add1L::add1H
;* item item sum
;* r20r21r22r23 + r16r17r18r19 = r20r21r22r23
;*
;***************************************************************************
.def add20 = r16 ; item 2 byte 0 (LSB)
.def add21 = r17 ; item 2 byte 1
.def add22 = r18 ; item 2 byte 2
.def add23 = r19 ; item 2 byte 3 (MSB)
.def add10 = r20 ; item 1 byte 0 (LSB)
.def add11 = r21 ; item 1 byte 1
.def add12 = r22 ; item 1 byte 2
.def add13 = r23 ; item 1 byte 3 (MSB)
Add32sign: brts Sub32sign ;
Add32: add add10,add20 ;Add low bytes
adc add11,add21 ;Add higher bytes with carry
adc add12,add22 ;
adc add13,add23 ;
ret ;
;***************************************************************************
;*
;* Sub32 == 32-32 Bit Unsigned Subtraction
;*
;* sub1L::sub1H - sub2L::sub2H = sub1L::sub1H
;* minuend subtrahend difference
;* r20r21r22r23 - r16r17r18r19 = r20r21r22r23
;*
;***************************************************************************
.def sub20 = r16 ; subtrahend byte 0 (LSB)
.def sub21 = r17 ; subtrahend byte 1
.def sub22 = r18 ; subtrahend byte 2
.def sub23 = r19 ; subtrahend byte 3 (MSB)
.def sub10 = r20 ; minuend byte 0 (LSB)
.def sub11 = r21 ; minuend byte 1
.def sub12 = r22 ; minuend byte 2
.def sub13 = r23 ; minuend byte 3 (MSB)
Sub32sign: clt ;sign +
Sub32: sub sub10,sub20 ;Subtract low bytes
sbc sub11,sub21 ;Subtract higher bytes with carry
sbc sub12,sub22 ;
sbc sub13,sub23 ;
brcc Return32u ;return clear carry if result>=0
set ;sign -
Neg32: subi sub10,1 ;if result<0
sbci sub11,0 ; neg result
sbci sub12,0 ;
sbci sub13,0 ; (dec result)
Com32: com sub10 ; &
com sub11 ; (com result)
com sub12 ;
com sub13 ; return set carry after com
Return32u: ret ;
;***************************************************************************
;*
;* Mul32 == 32x32 Bit Unsigned Multiplication
;*
;* mp32uL::mp32uH x mc32uL::mc32uH = m32uL::m32uH
;* multiplier multiplicand result
;* r20r21r22r23 x r16r17r18r19 = r20r21r22r23r24r25r26r27
;*
;***************************************************************************
.def mc32u0 =r16 ; multiplicand byte 0 (LSB)
.def mc32u1 =r17 ; multiplicand byte 1
.def mc32u2 =r18 ; multiplicand byte 2
.def mc32u3 =r19 ; multiplicand byte 3 (MSB)
.def mp32u0 =r20 ; multiplier byte 0 (LSB)
.def mp32u1 =r21 ; multiplier byte 1
.def mp32u2 =r22 ; multiplier byte 2
.def mp32u3 =r23 ; multiplier byte 3 (MSB)
.def m32u0 =r20 ; result byte 0 (LSB)
.def m32u1 =r21 ; result byte 1
.def m32u2 =r22 ; result byte 2
.def m32u3 =r23 ; result byte 3
.def m32u4 =r24 ; result byte 4
.def m32u5 =r25 ; result byte 5
.def m32u6 =r26 ; result byte 6
.def m32u7 =r27 ; result byte 7 (MSB)
.def mcnt32u =r28 ; loop counter
Mul32b: clr mc32u1 ;multiplicand is one byte
Mul32w: clr mc32u2 ; two bytes
Mul32t: clr mc32u3 ; three bytes
Mul32: clr m32u7 ;clear 4 highest bytes of result
clr m32u6 ;
clr m32u5 ;
sub m32u4,m32u4 ;and carry
ldi mcnt32u,33 ;init loop counter
m32u_loop: ror m32u3 ;rotate result and multiplier
ror m32u2 ;
ror m32u1 ;
ror m32u0 ;
dec mcnt32u ;decrement loop counter
breq Return32u ;if counter zero return
brcc m32u_skip ;if bit 0 of multiplier set
add m32u4,mc32u0 ; add multiplicand to result
adc m32u5,mc32u1 ;
adc m32u6,mc32u2 ;
adc m32u7,mc32u3 ;
m32u_skip: ror m32u7 ;shift right result byte 7
ror m32u6 ;rotate right result
ror m32u5 ;
ror m32u4 ;
rjmp m32u_loop ;
;***************************************************************************
;*
;* Div32 == 32/32 Bit Unsigned Division
;*
;* dd32uL::dd32uH / dv32uL::dv32uH = dres32uL::dres32uH (drem32uL::drem32uH)
;* dividend divisor result remainder
;* r20r21r22r23 / r16r17r18r19 = r20r21r22r23 r24r25r26r27
;*
;***************************************************************************
.def dv32u0 =r16 ; divisor byte 0 (LSB)
.def dv32u1 =r17 ; divisor byte 1
.def dv32u2 =r18 ; divisor byte 2
.def dv32u3 =r19 ; divisor byte 3 (MSB)
.def dres32u0 =r20 ; result byte 0 (LSB)
.def dres32u1 =r21 ; result byte 1
.def dres32u2 =r22 ; result byte 2
.def dres32u3 =r23 ; result byte 3 (MSB)
.def dd32u0 =r20 ; dividend byte 0 (LSB)
.def dd32u1 =r21 ; dividend byte 1
.def dd32u2 =r22 ; dividend byte 2
.def dd32u3 =r23 ; dividend byte 3 (MSB)
.def drem32u0 =r24 ; remainder byte 0 (LSB)
.def drem32u1 =r25 ; remainder byte 1
.def drem32u2 =r26 ; remainder byte 2
.def drem32u3 =r27 ; remainder byte 3 (MSB)
.def dcnt32u =r28 ; loop counter
Div32b: clr dv32u1 ;divisor is one byte
Div32w: clr dv32u2 ; two bytes
Div32t: clr dv32u3 ; three bytes
Div32: clr drem32u0 ;clear 4 lower remainde byte
clr drem32u1 ;
clr drem32u2 ;
sub drem32u3,drem32u3;and carry
ldi dcnt32u,33 ;init loop counter
d32u_loop: rol dd32u0 ;shift left dividend
rol dd32u1 ;
rol dd32u2 ;
rol dd32u3 ;
dec dcnt32u ;decrement loop counter
breq Com32 ;if counter zero invert result
rol drem32u0 ;shift dividend into remainder
rol drem32u1 ;
rol drem32u2 ;
rol drem32u3 ;
sub drem32u0,dv32u0 ;remainder = remainder - divisor
sbc drem32u1,dv32u1 ;
sbc drem32u2,dv32u2 ;
sbc drem32u3,dv32u3 ;
brcc d32u_loop ;clear carry to be shifted into res
add drem32u0,dv32u0 ;if result negative
adc drem32u1,dv32u1 ; restore remainder
adc drem32u2,dv32u2 ;
adc drem32u3,dv32u3 ;
rjmp d32u_loop ; set carry to be shifted into res
;***************************************************************************
;*
;* BCD2bin == BCD to 16-Bit Binary Conversion
;*
;* fBCD0:fBCD1:fBCD2 >>> tbinL:tbinH
;* dec hex
;* r16r17r18 >>> r20r21
;*
;***************************************************************************
.def fBCD0 =r16 ; BCD value digits 0 and 1
.def fBCD1 =r17 ; BCD value digits 2 and 3
.def fBCD2 =r18 ; BCD value digit 4 (MSD is lowermost nibble)
.def mp10L =r20 : Low byte of number to be multiplied by 10
.def mp10H =r21 ; High byte of number to be multiplied by 10
.def tbinL =r20 ; Low byte of binary result (same as mp10L)
.def tbinH =r21 ; High byte of binary result (same as mp10H)
.def copyL =r22 ; temporary register
.def copyH =r23 ; temporary register
BCD2bin20: mov r16,r20 ;for compatibility with Math32
mov r17,r21 ;
mov r18,r22 ;
BCD2bin16: cbr fBCD2,0xf0 ;mask away upper nibble of fBCD2
mov mp10L,fBCD2 ;mp10L:mp10H = MSD
clr mp10H ;
clr fBCD2 ;for adci mp10H,0 below
rcall mul10bcd ;fBCDX = fBCD1
mov fBCD1,fBCD0 ;fBCDX = fBCD0
mul10bcd: ;mp10L:mp10H=10(10*mp10L:mp10H+highnibble(fBCDX))+lownibble(fBCDX)
rcall mul10add ;10*mp10L:mp10H+highnibble(fBCDX)
mul10add: ;mp10L:mp10H = 10*mp10L:mp10H+lownibble(fBCDX)
lsl mp10L ;multiply original by 2
rol mp10H ;
mov copyL,mp10L ;make copy (x2)
mov copyH,mp10H ;
lsl copyL ;multiply copy by 2 (x4)
rol copyH ;
lsl copyL ;multiply copy by 2 (x8)
rol copyH ;
add mp10L,copyL ;add copy to original (x10)
adc mp10H,copyH ;
swap fBCD1 ;fBCDX upper<=>lower nibble
mov copyL,fBCD1 ;
andi copyL,0x0f ;mask away upper nibble
add mp10L,copyL ;add lower nibble
adc mp10H,fBCD2 ;high byte of result + carry
ret ;
.equ BCD2bin=BCD2bin20 ;default registers BCD to BIN call
;***************************************************************************
;*
;* BCD3bin == BCD to 24-Bit Binary Conversion
;*
;* fBCD0:fBCD1:fBCD2:fBCD3 >>> tbin0:tbin1:tbin2
;* dec hex
;* r16r17r18r19 >>> r20r21r22
;*
;***************************************************************************
.def fBCD0 =r16 ; BCD value digits 0 and 1
.def fBCD1 =r17 ; BCD value digits 2 and 3
.def fBCD2 =r18 ; BCD value digits 4 and 5
.def fBCD3 =r19 ; BCD value digits 6 and 7 (MSD is 0|1)
.def tbin0 =r20 ; binary value byte 0 (LSB)
.def tbin1 =r21 ; binary value byte 1
.def tbin2 =r22 ; binary value byte 2 (MSB)
BCD3bin20: mov r16,r20 ;for compatibility with Math32
mov r17,r21 ;
mov r18,r22 ;
mov r19,r23 ;
BCD3bin16: ldi tbin0,0xca ;digit-to-digit presetting
ldi tbin1,0x1b ;-1111110=0xef0bba
ldi tbin2,0xff ;0xff1bca=0xef0bba-0xefeff0
sbrc fBCD3,4 ; delete decimal correction
subi fBCD3,6 ; if NUMBER<10000000 always
bcdbin_106: subi tbin0,byte1(-1000*1000) ;addit tbin,10^6
sbci tbin1,byte2(-1000*1000) ;
sbci tbin2,byte3(-1000*1000) ;
subi fBCD3,0x01 ;
brcc bcdbin_106 ;
bcdbin_105: subi tbin0,byte1(-100*1000) ;addit tbin,10^5
sbci tbin1,byte2(-100*1000) ;
sbci tbin2,byte3(-100*1000) ;
subi fBCD2,0x10 ;
brcc bcdbin_105 ;
bcdbin_104: subi tbin0,byte1(-10*1000) ;addit tbin,10^4
sbci tbin1,byte2(-10*1000) ;
sbci tbin2,byte3(-10*1000) ;
subi fBCD2,0x01 ;
brhc bcdbin_104 ;
bcdbin_103: subi tbin0,byte1(-1000) ;addit tbin,10^3
sbci tbin1,byte2(-1000) ;
sbci tbin2,byte3(-1000) ;
subi fBCD1,0x10 ;
brcc bcdbin_103 ;
bcdbin_102: subi tbin0,byte1(-100) ;addit tbin,10^2
sbci tbin1,byte2(-100) ;
sbci tbin2,byte3(-100) ;
subi fBCD1,0x01 ;
brhc bcdbin_102 ;
bcdbin_101: subi tbin0,byte1(-10) ;addit tbin,10^1
sbci tbin1,byte2(-10) ;
sbci tbin2,byte3(-10) ;
subi fBCD0,0x10 ;
brcc bcdbin_101 ;addit tbin,0xefeff0+LSD
add tbin0,fBCD0 ; addend of tbin1 & tbin2 is
adc tbin1,fBCD1 ; arbitrarily chosen const
adc tbin2,fBCD2 ; (pre take off from tbin)
ret
.equ BCD3bin=BCD3bin20 ;default registers BCD to BIN call
;***************************************************************************
;*
;* Bin2BCD == 16-bit Binary to BCD conversion
;*
;* fbinL:fbinH >>> tBCD0:tBCD1:tBCD2
;* hex dec
;* r16r17 >>> r20r21r22
;*
;***************************************************************************
.def fbinL =r16 ; binary value Low byte
.def fbinH =r17 ; binary value High byte
.def tBCD0 =r20 ; BCD value digits 0 and 1
.def tBCD1 =r21 ; BCD value digits 2 and 3
.def tBCD2 =r22 ; BCD value digit 4 (MSD is lowermost nibble)
Bin2BCD20: mov r16,r20 ;for compatibility with Math32
mov r17,r21 ;
Bin2BCD16: ldi tBCD2,0xff ;initialize digit 4
binbcd_4: inc tBCD2 ;
subi fbinL,low(10000);subiw fbin,10000
sbci fbinH,high(10000)
brcc binbcd_4 ;
ldi tBCD1,0x9f ;initialize digits 3 and 2
binbcd_3: subi tBCD1,0x10 ;
subi fbinL,low(-1000);addiw fbin,1000
sbci fbinH,high(-1000)
brcs binbcd_3 ;
binbcd_2: inc tBCD1 ;
subi fbinL,low(100) ;subiw fbin,100
sbci fbinH,high(100) ;
brcc binbcd_2 ;
ldi tBCD0,0xa0 ;initialize digits 1 and 0
binbcd_1: subi tBCD0,0x10 ;
subi fbinL,-10 ;addi fbin,10
brcs binbcd_1 ;
add tBCD0,fbinL ;LSD
binbcd_ret: ret ;
.equ Bin2BCD=Bin2BCD20 ;default registers BIN to BCD call
;***************************************************************************
;*
;* Bin4BCD == 32-bit Binary to BCD conversion [ together with Bin2BCD ]
;*
;* fbin0:fbin1:fbin2:fbin3 >>> tBCD0:tBCD1:tBCD2:tBCD3:tBCD4
;* hex dec
;* r18r19r20r21 >>> r20r21r22r23r24
;*
;***************************************************************************
.def fbin0 =r18 ; binary value byte 0 (LSB)
.def fbin1 =r19 ; binary value byte 1
.def fbin2 =r20 ; binary value byte 2
.def fbin3 =r21 ; binary value byte 3 (MSB)
.def tBCD0 =r20 ; BCD value digits 0 and 1 (same as fbin2)
.def tBCD1 =r21 ; BCD value digits 2 and 3 (same as fbin3)
.def tBCD2 =r22 ; BCD value digits 4 and 5
.def tBCD3 =r23 ; BCD value digits 6 and 7
.def tBCD4 =r24 ; BCD value digits 8 and 9 (MSD)
Bin4BCD: rcall Bin2BCD20 ;
clr tBCD3 ;initial highest bytes of result
ldi tBCD4,0xfe ;
binbcd_loop: subi tBCD0,-0x33 ;add 0x33 to digits 1 and 0
sbrs tBCD0,3 ;if bit 3 clear
subi tBCD0,0x03 ; sub 3
sbrs tBCD0,7 ;if bit 7 clear
subi tBCD0,0x30 ; sub $30
subi tBCD1,-0x33 ;add 0x33 to digits 3 and 2
sbrs tBCD1,3 ;if bit 3 clear
subi tBCD1,0x03 ; sub 3
sbrs tBCD1,7 ;if bit 7 clear
subi tBCD1,0x30 ; sub $30
subi tBCD2,-0x33 ;add 0x33 to digits 5 and 4
sbrs tBCD2,3 ;if bit 3 clear
subi tBCD2,0x03 ; sub 3
sbrs tBCD2,7 ;if bit 7 clear
subi tBCD2,0x30 ; sub $30
lsl fbin0 ;
rol fbin1 ;shift lower word
rol tBCD0 ;through all bytes
rol tBCD1 ;
rol tBCD2 ;
rol tBCD3 ;
rol tBCD4 ;
brmi binbcd_loop ;7 shifts w/o correction of MSD
rol fbinH ;since Bin2BCD fbinH = 0xff
brcc binbcd_ret ; so as to do 16_lsl in total
subi tBCD3,-0x33 ;add 0x33 to digits 7 and 6
sbrs tBCD3,3 ;if bit 3 clear
subi tBCD3,0x03 ; sub 3
sbrs tBCD3,7 ;if bit 7 clear
subi tBCD3,0x30 ; sub $30
subi tBCD4,-0x03 ;add 0x03 to digit 8 only
sbrs tBCD4,3 ;if bit 3 clear
subi tBCD4,0x03 ; sub 3
rjmp binbcd_loop ;
;***************************************************************************
;*
;* Bin4BCD == 32-bit Binary to BCD conversion
;*
;* fbin0:fbin1:fbin2:fbin3 >>> tBCD0:tBCD1:tBCD2:tBCD3:tBCD4
;* hex dec
;* r16r17r18r19 >>> r20r21r22r23r24
;*
;***************************************************************************
.def fbin0 =r16 ; binary value byte 0 (LSB)
.def fbin1 =r17 ; binary value byte 1
.def fbin2 =r18 ; binary value byte 2
.def fbin3 =r19 ; binary value byte 3 (MSB)
.def tBCD0 =r20 ; BCD value digits 0 and 1
.def tBCD1 =r21 ; BCD value digits 2 and 3
.def tBCD2 =r22 ; BCD value digits 4 and 5
.def tBCD3 =r23 ; BCD value digits 6 and 7
.def tBCD4 =r24 ; BCD value digits 8 and 9 (MSD)
Bin4BCD20: mov r16,r20 ;for compatibility with Math32
mov r17,r21 ;
mov r18,r22 ;
mov r19,r23 ;
Bin4BCD16: clr tBCD0 ;initial result (5 bytes)
clr tBCD1 ; & shift
clr tBCD2 ; loop
ldi tBCD3,0xfe ; counter
ldi tBCD4,0xff ; too
rjmp binbcd_jump ;for speed-up and skip of MSD corr
binbcd_876: subi tBCD4,-0x03 ;add 0x03 to digit 8 only
sbrs tBCD4,3 ;if bit 3 clear
subi tBCD4,0x03 ; sub 3
subi tBCD3,-0x33 ;add 0x33 to digits 7 and 6
sbrs tBCD3,3 ;if bit 3 clear
subi tBCD3,0x03 ; sub 3
sbrs tBCD3,7 ;if bit 7 clear
subi tBCD3,0x30 ; sub $30
binbcd_54: subi tBCD2,-0x33 ;add 0x33 to digits 5 and 4
sbrs tBCD2,3 ;if bit 3 clear
subi tBCD2,0x03 ; sub 3
sbrs tBCD2,7 ;if bit 7 clear
subi tBCD2,0x30 ; sub $30
binbcd_3210: subi tBCD1,-0x33 ;add 0x33 to digits 3 and 2
sbrs tBCD1,3 ;if bit 3 clear
subi tBCD1,0x03 ; sub 3
sbrs tBCD1,7 ;if bit 7 clear
subi tBCD1,0x30 ; sub $30
subi tBCD0,-0x33 ;add 0x33 to digits 1 and 0
sbrs tBCD0,3 ;if bit 3 clear
subi tBCD0,0x03 ; sub 3
sbrs tBCD0,7 ;if bit 7 clear
subi tBCD0,0x30 ; sub $30
binbcd_jump: lsl fbin0 ;
rol fbin1 ;
rol fbin2 ;
rol fbin3 ;shift input value
rol tBCD0 ;through all bytes
rol tBCD1 ;
rol tBCD2 ;
rol tBCD3 ;
rol tBCD4 ;
brcs binbcd_3210 ;16_lsl w/o correction of dig_87654
inc fbin0 ;
brpl binbcd_54 ;+7_lsl w/o correction of dig_876
sbrs fbin2,0 ;
rjmp binbcd_876 ;32_lsl in total (fbin = 0x1ffff)
ret ;
;***************************************************************************
;*
;* Bin3BCD == 24-bit Binary to BCD conversion [ together with Bin2BCD ]
;*
;* fbin0:fbin1:fbin2 >>> tBCD0:tBCD1:tBCD2:tBCD3
;* hex dec
;* r16r17r18 >>> r20r21r22r23
;*
;***************************************************************************
.def fbin0 =r16 ; binary value byte 0 (LSB)
.def fbin1 =r17 ; binary value byte 1
.def fbin2 =r18 ; binary value byte 2 (MSB)
.def tBCD0 =r20 ; BCD value digits 0 and 1
.def tBCD1 =r21 ; BCD value digits 2 and 3
.def tBCD2 =r22 ; BCD value digits 4 and 5
.def tBCD3 =r23 ; BCD value digits 6 and 7 (MSD)
Bin3BCD: ldi tBCD3,0xff ;initialize digits 7 and 6
binbcd_7: inc tBCD3 ;
subi fbin0,byte1(10000*100) ;subit fbin,1000000
sbci fbin1,byte2(10000*100) ;
sbci fbin2,byte3(10000*100) ;
brcc binbcd_7 ;
subi tBCD3,-6 ; delete decimal correction
sbrs tBCD3,4 ; if NUMBER<10000000 always
subi tBCD3,6 ;
ldi tBCD2,0x9f ;initialize digits 5 and 4
binbcd_6: subi tBCD2,0x10 ;
subi fbin0,byte1(-10000*10) ;addit fbin,100000
sbci fbin1,byte2(-10000*10) ;
sbci fbin2,byte3(-10000*10) ;
brcs binbcd_6 ;
binbcd_5: inc tBCD2 ;
subi fbin0,byte1(10000) ;subit fbin,10000
sbci fbin1,byte2(10000) ;
sbci fbin2,byte3(10000) ;
brcc binbcd_5 ;
rjmp binbcd_3-1 ;initialize digits 3 and 2
;***************************************************************************
;*
;* Bin3BCD == 24-bit Binary to BCD conversion
;*
;* fbin0:fbin1:fbin2 >>> tBCD0:tBCD1:tBCD2:tBCD3
;* hex dec
;* r16r17r18 >>> r20r21r22r23
;*
;***************************************************************************
.def fbin0 =r16 ; binary value byte 0 (LSB)
.def fbin1 =r17 ; binary value byte 1
.def fbin2 =r18 ; binary value byte 2 (MSB)
.def tBCD0 =r20 ; BCD value digits 0 and 1
.def tBCD1 =r21 ; BCD value digits 2 and 3
.def tBCD2 =r22 ; BCD value digits 4 and 5
.def tBCD3 =r23 ; BCD value digits 6 and 7 (MSD)
Bin3BCD20: mov r16,r20 ;for compatibility with Math32
mov r17,r21 ;
mov r18,r22 ;
Bin3BCD16: ldi tBCD3,0xfa ;initialize digits 7 and 6
binbcd_107: subi tBCD3,-0x10 ;
subi fbin0,byte1(10000*1000) ;subit fbin,10^7
sbci fbin1,byte2(10000*1000) ;
sbci fbin2,byte3(10000*1000) ;
brcc binbcd_107 ;
binbcd_106: dec tBCD3 ;
subi fbin0,byte1(-10000*100) ;addit fbin,10^6
sbci fbin1,byte2(-10000*100) ;
sbci fbin2,byte3(-10000*100) ;
brcs binbcd_106 ;
ldi tBCD2,0xfa ;initialize digits 5 and 4
binbcd_105: subi tBCD2,-0x10 ;
subi fbin0,byte1(10000*10) ;subit fbin,10^5
sbci fbin1,byte2(10000*10) ;
sbci fbin2,byte3(10000*10) ;
brcc binbcd_105 ;
binbcd_104: dec tBCD2 ;
subi fbin0,byte1(-10000) ;addit fbin,10^4
sbci fbin1,byte2(-10000) ;
sbci fbin2,byte3(-10000) ;
brcs binbcd_104 ;
ldi tBCD1,0xfa ;initialize digits 3 and 2
binbcd_103: subi tBCD1,-0x10 ;
subi fbin0,byte1(1000) ;subiw fbin,10^3
sbci fbin1,byte2(1000) ;
brcc binbcd_103 ;
binbcd_102: dec tBCD1 ;
subi fbin0,byte1(-100) ;addiw fbin,10^2
sbci fbin1,byte2(-100) ;
brcs binbcd_102 ;
ldi tBCD0,0xfa ;initialize digits 1 and 0
binbcd_101: subi tBCD0,-0x10 ;
subi fbin0,10 ;subi fbin,10^1
brcc binbcd_101 ;
add tBCD0,fbin0 ;LSD
ret ;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Demo: ;-)(-:-)(-;-)(-:-)(-;-)(-:-)(-;-)(-:-)(-;-)(-:-)(-;-)(-:-)(-;-)(-:-)
;***************************************************************************
;$ $ $ $ $ $ $ $ $ Illustrations with comments field $ $ $ $ $ $ $ $ $
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.dseg
Variable: .byte 4
VarWord1: .byte 2
VarWord2: .byte 2
Result: .byte 8
.equ Address1 =VarWord1
.equ Address2 =VarWord2
.equ Address =Variable
.set Constant =0x4321
.cseg
.def Temp =r16
.def TempL =r16
.def TempH =r17
.def Flags =r15
.equ _Flag1 =1
.equ _Flag2 =2
.equ _Flag3 =3
.equ _signResult=0
;*** OUTI, OUTIW, OUTW, INW
outiw SP,Temp,RAMEND ;initialize 16-bit Stack Pointer
outi TCNT0,Temp,0 ;clear Timer/Counter0 (8-bit)
inw Temp,TCNT1 ;read Timer/Counter1 (16-bit)
outw TCNT1,Temp ;write Timer/Counter1 (16-bit)
;*** CLF, SEF, CBF, SBF, IBF
clf Flags,_Flag1 ;clear (0) bit _Flag1
bld Flags,_Flag2 ; and bit _Flag2
cbf Flags,Temp,_Flag1,_Flag2 ;clear both at once
sef Flags,_Flag1 ;set (1) bit _Flag1
bld Flags,_Flag2 ; and bit _Flag2
sbf Flags,Temp,_Flag1,_Flag2 ;set both at once
ibf Flags,Temp,_Flag1,_Flag2,_Flag3 ;invert of 3 flags
ibf TempL,TempH,0,2,4,6 ;invert only even bits
;*** XCH, MVW, MVI, MOVS, MOVSW
xch TempL,TempH ;swap in Temp register pair
xch Temp,r0 ;swap bytes r0 & Temp
mvw X,Y ;copy of Y register pair into X pair
mvw Z,Temp ;copy of TempL&TempH into Z register pair
mvi Flags,Temp,exp2(_Flag1)|1<<_Flag2 ;initialize flags
mvi r0,Temp,Constant ;load to low register (0-15)
movs Address1,Temp,Address2 ;copy of one memory byte
movsw Address1,Temp,Address2 ;copy of two memory bytes
;*** STSI, STSIW, LDSW, STSW
stsi Address,Temp,Constant ;initialize of one memory byte
stsiw Address,Temp,Constant ;initialize of two memory bytes
ldsw Temp,Address1 ;copy of two memory bytes
stsw Address2,Temp ; via Temp register pair
;*** LDIW, LDDW, STDW
ldiw Temp,Constant ;initialize of register pair
ldiw Z,Address ;initialize of address pointer
lddw Temp,Z+(Address1-Address) ;copy of two memory bytes
stdw Z+(Address2-Address),Temp ; via Temp register pair
;*** PUSHW, POPW
pushw Y ;copy of Y register pair
popw X ; into X register pair
ldiw Temp,Maths
pushw Temp
ret ;equ jmp Maths
Maths:
;***** INITMEM
InitMem Address ;clear 128 bytes (latest Address+127)
InitMem Address,0 ;equ InitMem Address
InitMem Address,0,0 ;equ InitMem Address
InitMem Address,,1 ;for 128 bytes each:=0xff
InitMem Address,1 ;clear one byte at Address
InitMem Address1,Address2-Address1+2,Limit
;limitation: if bit_T=0 then 4_bytes:=0xff else 4_bytes:=0
ldi MathPattern,0xab
InitMem Address,,+1 ;128_bytes:=0xab doubly, but possibly
;***** MATHR16, MATHR20, OPERAND
Operand Address ;equ MathR20 Address,obXXXX
MathR20 Address ;equ Operand Address
.set ObXXXX=0b11
MathR16 Address ;equ Operand Address,0b0011,r16
.set ObXXXX=0b1111 ;default
Operand Address,,r16 ;equ MathR16 Address,obXXXX
Operand Address,,r20 ;equ MathR20 Address,obXXXX
Operand Address,0b11 ;equ MathR20 Address,0b0011
Operand Address,0b11,r16;equ MathR16 Address,0b0011
;load data with displacement (equ *256, *65536, *16777216)
MathR20 Address,0b0110 ;(data word)<<8
MathR16 Address,0b1000 ;(data byte)<<24
;***** CONST20, CONST16, CNST16T
; WARNING: AVRASM ver. 1.30 don't understand 32 bits constants, but all it
; expressions are internally 32 bits (the higher versions of assembler
; directly operate on value up to 0xffffffff)
Const20 0x76543210 ;error v1.30 (0x00003210)
Const20 1985229328 ;error v1.30 (12816)
Const16 0x7654<<16|0x3210 ;ok (0x76543210)
Cnst16t 0x7654*1024*1024+0x1234 ;ok (0x401234)
;***** CNST16B, CNST16W
Cnst16b Constant ;equ Const16 byte1(Constant)
rcall Div32b ; rcall Div32 ;but briefly
Cnst16w Constant<<1 ;non-equ Const16 Constant<<1
rcall Mul32w ; rcall Mul32 ;word overflow
;***** RESULT2, RESULT3
Result2 Address ;equ Result2 Address,obXXXX
;store data with displacement (equ /256, /65536, /16777216 and more)
Result2 Address,1<<7 ;(byte result)>>56
Result2 Address,0b111100 ;(double word result)>>16
Result2 Address,obXXXX<<4 ;(double word result)>>32
rjmp JointTail+3
JointTail: Result3 Address,0xff ;equ Result2 Address,0b11111111
rcall JointTail ;concluding RET inside Result call
;******* register pairs
.def AL=r16
.def AH=r17
.def BL=r18
.def BH=r19
.def CL=r20
.def CH=r21
.def DL=r22
.def DH=r23
.def WL=r24
.def WH=r25
ldiw C,0 ;equ
ldiw D,0x7654 ; Const20 0x7654<<16
ldiw A,0x3210 ;equ Cnst16w 0x3210
ldi AL,0x10 ;equ Cnst16b 0x10
mvw A,C ;copy of Const20
mvw B,D ; into Const16
adiw WL,1 ;as well as "adiw" for X,Y,Z register pairs
sbiw WL,1 ;as well as "sbiw" for X,Y,Z register pairs
;******* testing calculations
InitMem Variable,4,1 ; 0xffffffff to memory
Operand Variable
Const16 0xffff<<16|0xffff
rcall Mul32 ; 0xffffffff * 0xffffffff
Result2 Result,0b11111111 ; 0xfffffffe00000001
Operand Variable
Const16 0x1010<<16|0x1010
rcall Div32 ; 0xffffffff / 0x10101010
Result2 Result,0b11111111 ; 0xf (0x0f0f0f0f)
Operand Variable,0b111
Cnst16t 0x00ff<<16|0xffff
rcall Div32t ; 0xffffff / 0xffffff
Result2 Result ; 0x1 (0x0 no rollout)
Operand Variable,0b1100
Cnst16w 0xffff
rcall Div32w ; 0xffff0000 / 0xffff
Result2 Result ; 0x10000 (0x0 no rollout)
;******* data translations 16-bit (overall maximum 65535=0xffff)
;result Rd16|24
Const20 0x2748
rcall BCD2bin ;02748 = 0x0abc
Cnst16t 6<<16|0x5535
rcall BCD2bin16 ;65535 = 0xffff
Result2 Address,0b11
rcall Bin2BCD ;0xffff = 65535
Cnst16w 0xabba
rcall Bin2BCD16 ;0xabba = 43962
;******* data translations 32-bit (overall maximum 655359999=0x270fffff)
;BCD2Bin
stsiw Variable,Temp,0x5432 ;
stsiw Variable+2,Temp,0x9876 ;BCD 98765432 >>>
Operand Variable,0b11
rcall BCD2bin
pushw C ;temporary result always is 2 bytes
Operand Variable+2,0b11 ;or 0b111 if BCD have all 5 digits
rcall BCD2bin
ldiw D,0
Cnst16w 10000
rcall Mul32w
popw A ;B pair by this time =0
rcall Add32
Result2 Result,0b1111 ;>>> HEX 0x05e30a78
;Bin2BCD
stsiw Variable,Temp,0xffff ;
stsiw Variable+2,Temp,0x270f ;HEX 0x270fffff >>>
Operand Variable,0b1111
Cnst16w 10000 ;remainder always is 2 bytes
rcall Div32w ; as temporary result
rcall Bin2BCD
Result2 Result+2,0b111
mvw A,W ;W pair do not changed beyond
rcall Bin2BCD16
Result2 Result,0b11 ;>>> BCD 655359999
;******* 32-bit Bin4BCD conversion (overall maximum 4294967295=0xffffffff)
;result Rd40
ldi YL,18 ;one more dishonest trick
Operand Variable,0b1111,1+
rcall Bin4BCD ;0x270fffff >>> 655359999
Const20 0x1234<<16|0x5678
Result2 18
rcall Bin4BCD ;0x12345678 >>> 305419896
Const16 0xab98<<16|0xfedc
mvw C,A
rcall Bin4BCD ;0xfedcab98 >>> 4275874712
InitMem Variable,3,1 ; 0xffffff to memory
MathR20 Variable,0b111
MathR16 Variable,0b111
rcall Mul32t ;(0xffffff)^2 = 0xfffffe000001
Result2 18,0b111100 ; /65536 = 0xfffffe00
rcall Bin4BCD ;0xfffffe00 >>> 4294966784
;******* data translations 32-bit (overall maximum 4294967295=0xffffffff)
;Bin4BCD20
Operand Variable,0b1111
rcall Bin4BCD20 ;0x27ffffff >>> 671088639
Const20 0x1234<<16|0x5678
rcall Bin4BCD20 ;0x12345678 >>> 305419896
ldiw D,0
ldiw C,0xab
rcall Bin4BCD20 ; 0xab >>> 171
;Bin4BCD16
rcall Bin4BCD16 ; 0x1ffff >>> 131071
Const16 0xfedc<<16|0xab98
rcall Bin4BCD16 ;0xfedcab98 >>> 4275874712
InitMem Variable,4,1
MathR16 Variable,0b1111
rcall Bin4BCD16 ;0xffffffff >>> 4294967295
;******* data translations 24-bit (overall maximum 16777215=0xffffff)
;BCD3bin
Const20 $1670<<16|$2650
rcall BCD3bin ;16702650 >>> 0xfedcba
ldiw B,0
ldiw A,9
rcall BCD3bin16 ;00000009 >>> 0x000009 (fastest)
ldiw D,0x1599
ldiw C,0x9990
rcall BCD3bin20 ;15999990 >>> 0xf423f6 (slowest)
;Bin3BCD
Const16 0x98<<16|0x967f
rcall Bin3BCD ;0x98967f >>> 09999999
rcall Bin3BCD ;0xffff09 >>> 16776969
Cnst16t $0d00*256+$df22
rcall Bin3BCD ;0x0ddf22 >>> 00909090 (fastest)
Cnst16t $f500*256+$871d
rcall Bin3BCD ;0xf5871d >>> 16090909 (slowest)
;Bin3BCD20
MathR20 Variable,0b111
rcall Bin3BCD20 ;0xffffff >>> 16777215
rcall Bin3BCD20 ;0x777215 >>> 07827989
Const20 $a600*256+$75a2
rcall Bin3BCD20 ;0xa675a2 >>> 10909090 (slowest)
;Bin3BCD16
Cnst16t $8a00*256+$b75d
rcall Bin3BCD16 ;0x8ab75d >>> 09090909 (fastest)
ldi AH,0xff
rcall Bin3BCD16 ; 0xffff >>> 65535
ldi AL,0
rcall Bin3BCD16 ;0x000000 >>> 00000000
;******* formula recalculation: Result=(VarWord1-0xfff)/7+VarWord2/0x100
;VarWordX>=0
InitMem Variable,16 ;clear VarWordX & Result
rcall Formula ; -0x249.0000 as result
ldiw Temp,0xabcd ;these 2 lines are not equ
stsw VarWord1,Temp ;stsiw VarWord1,Temp,0xabcd
stsw VarWord2,Temp
rcall Formula ; 0x16ed.cd00 as result
stsiw VarWord1,Temp,0x00ff
stsiw VarWord2,Temp,0xff00
rcall Formula ; -0x125.9249 as result
stsiw VarWord1,Temp,0x0f0f
stsiw VarWord2,Temp,0xf0f0
rcall Formula ; 0x00ce.a6dc as result
InitMem VarWord1,4,1 ; 0x2349.2392 at the end
ldiw Temp,Demo
pushw Temp ;getting into demo loop
Formula:
MathR20 VarWord1,0b1100
Const16 0xfff<<16
rcall Sub32sign
Cnst16b 7
rcall Div32b
Result2 16 ;faster than call MathR16 20
MathR16 20 ;included for comparison only
MathR20 VarWord2,0b110
rcall Add32sign
bld Flags,_signResult
Result3 Result
.exit
;***************************************************************************
;*
;* REMARK
;* Sometimes expression as macroparameter must be enclosed in parentheses,
;* because they not are always present in above macrocalls
;* (remember about the priority of AVR assembler operators).
;* Accommodate oneself to ATmega: MOVW instruction e.g., etc.
;*
;***************************************************************************
;Feedback: please, include abbr."Math32" in Your e-mail subject line (!spam)
;from time to time it is possible mailbox overflow &| shut-down - I am sorry
;to make mention of http://www.i.com.ua/~birua when occasion offers - Thanks
;All the best & good luck!
|
|