where : ibrtses embedded

# AVR math

## ASM

### signed16 multiplied with unsigned8 - limited

```assumed the CPU supports the required commands
all in CSEG :
; multiply S16:=S16*U8 with overflow protection both ways
;
; result:= Z^, S16:=Y^, U8:=u1	 16 bit as little endian
;
; there is no overflow bigger than 0x7FFF or smaller 0x8000
MulS16U8:
push	temp
push	u2
push	u3
push	u4
push	u5

clr	u2	; low result
clr	u3	; high result
ld	u4,Y	; low S16
ldd	u5,Y+1	; high S16
ldd	temp,Y+1	; get sign of S16
andi	temp,0x80
brne	ms16u8_1
; positive
ms16u8_0:
lsr	u1
brcc	ms16u8_3	; skip
mov	temp,u3
andi	temp,0x80
brne	ms16u8_2	; positive overflow
ms16u8_3:
tst	u1
breq	ms16u8_end	; end
lsl	u4		; shift left
rol	u5
brmi	ms16u8_6	; goes negative
rjmp	ms16u8_0	;again
ms16u8_2:			;positive overflow
ldi	u2,0xFF		; set max number 0x7FFF
ldi	u3,0x7F
rjmp	ms16u8_end	; end
ms16u8_6:			; shift goes negative
tst	u1		;  set overflow if more to add
brne	ms16u8_2
rjmp	ms16u8_end	;  or terminate if end
; negative
ms16u8_1:
lsr	u1
brcc	ms16u8_4	;skip
mov	temp,u3
andi	temp,0x80
breq	ms16u8_5	;negative overflow
ms16u8_4:
tst	u1
breq	ms16u8_end	;end;
lsl	u4
rol	u5
brpl	ms16u8_7	; goes positive
rjmp	ms16u8_1	;again
ms16u8_5:			;negative overflow
ldi	u2,0x00		; set min number=0x8000
ldi	u3,0x80
rjmp	ms16u8_end	; end
ms16u8_7:			;shift goes positive
tst	u1		; set overflow if more to add
brne	ms16u8_5
ms16u8_end:
st	Z,u2
std	Z+1,u3

pop	u5
pop	u4
pop	u3
pop	u2
pop	temp
ret
```

### add 2 signed 16 bit - limited

``` assume U1..U3 as R16..R31
;addition of 2 signed 16 bit with overflow protection
; add into 24 bit then test
;
; result:= Z^, S16:=Y^, Z^:=Z^+Y^  16 bit as little endian
;
; there is no overflow bigger than 0x7FFF or smaller 0x8000

push	temp
push	u1
push	u2
push	u3
push	u4
push	u5

ld	u2,Z	; low result
ldd	u3,Z+1	; high result
ld	u4,Y	; low S16
ldd	u5,Y+1	; high S16
tst	u3
brpl	as16_1
; neg Z
tst	u5
brpl	as16_2
; neg + neg
brmi	as16_end
; neg + neg overflow
ldi	u2,0x00
ldi	u3,0x80
; ok
rjmp	as16_end
; neg + pos
as16_2:
rjmp	as16_end
; pos + neg
as16_3:
rjmp	as16_end
; pos Z
as16_1:
tst	u5
brmi	as16_3
; pos + pos
ldi	temp,0
ldi	u1,0
brpl	as16_end
; pos + pos overflow
ldi	u2,0xFF
ldi	u3,0x7F
as16_end:
st	Z,u2
std	Z+1,u3

pop	u5
pop	u4
pop	u3
pop	u2
pop	u1
pop	temp
ret
```

Questions ?
Suggestions?
Feedback ?

#### disclaimer

AVR index
embedded software pages
home

last updated: 18.sept.00