3-phase PV router
Loading...
Searching...
No Matches
FastDivision.cpp
Go to the documentation of this file.
1#include "FastDivision.h"
2
3uint16_t divu10(uint16_t n)
4{
5 uint16_t working;
6 asm volatile(
7 "ldi %A1, %3 \n\t"
8 "ldi %C1, 0x00 \n\t"
9 "ldi %D1, 0x00 \n\t"
10
11 "lsr %B0 \n\t" // we have divided by 2, now divide by 5.
12 "ror %A0 \n\t"
13
14 "subi %A0, 0xFF \n\t" //n++
15 "sbci %B0, 0xFF \n\t"
16
17 "mul %A0, %A1 \n\t" //A * X
18 "mov %B1, r1 \n\t"
19
20 "add %B1, r0 \n\t" //A* X'
21 "adc %C1, r1 \n\t"
22
23 "mul %B0, %A1 \n\t"
24 "add %B1, r0 \n\t" //A* X'
25 "adc %C1, r1 \n\t"
26 "adc %D1, %D1 \n\t" //D1 is known 0, we need to grab the carry
27
28 "add %C1, r0 \n\t" //A* X'
29 "adc %D1, r1 \n\t"
30
31 "movw %A0, %C1 \n\t" // >> 16
32
33 "eor r1, r1 \n\t"
34
35 : "=r"(n), "=r"(working)
36 : "0"(n), "M"(0x33)
37 : "r1", "r0");
38 return n;
39}
40
41void divmod10(uint32_t in, uint32_t &div, uint8_t &mod)
42{
43 //assumes that div/mod pointers arrive in r18:r19 and r20:r21 pairs (doesn't matter which way around)
44 //and that in arrives in r22:r25 quad
45 asm volatile(
46 "movw r30, %2 \n\t" //uint32_t* divPtr = ÷
47 "movw r26, %1 \n\t" //uint32_t* modPtr = &mod;
48
49 "mov r0, %A0 \n\t" //byte temp = in
50 "movw r18, %A0 \n\t" //uint32_t q = in;
51 "movw r20, %C0 \n\t"
52 "ori r18, 0x01 \n\t" //q |= 1;
53
54 "lsr r25 \n\t" //x = in >> 2 //note: x reuses registers of 'in', as 'in' was backed up in r0
55 "ror r24 \n\t"
56 "ror r23 \n\t"
57 "ror r22 \n\t"
58 "lsr r25 \n\t"
59 "ror r24 \n\t"
60 "ror r23 \n\t"
61 "ror r22 \n\t"
62
63 "sub r18, r22 \n\t" //q = q - x;
64 "sbc r19, r23 \n\t"
65 "sbc r20, r24 \n\t"
66 "sbc r21, r25 \n\t"
67
68 "movw r22, r18 \n\t" //x = q;
69 "movw r24, r20 \n\t"
70 "lsr r25 \n\t" //x = x >> 4;
71 "ror r24 \n\t"
72 "ror r23 \n\t"
73 "ror r22 \n\t"
74 "lsr r25 \n\t"
75 "ror r24 \n\t"
76 "ror r23 \n\t"
77 "ror r22 \n\t"
78 "lsr r25 \n\t"
79 "ror r24 \n\t"
80 "ror r23 \n\t"
81 "ror r22 \n\t"
82 "lsr r25 \n\t"
83 "ror r24 \n\t"
84 "ror r23 \n\t"
85 "ror r22 \n\t"
86
87 "add r22, r18 \n\t" //x = x + q
88 "adc r23, r19 \n\t"
89 "adc r24, r20 \n\t"
90 "adc r25, r21 \n\t"
91
92 "movw r18, r22 \n\t" //q = x
93 "movw r20, r24 \n\t"
94 "add r18, r23 \n\t" //q = q + (x >> 8)
95 "adc r19, r24 \n\t"
96 "adc r20, r25 \n\t"
97 "adc r21, r1 \n\t"
98
99 "movw r18, r20 \n\t" //q = q >> 16
100 "eor r20, r20 \n\t"
101 "eor r21, r21 \n\t"
102 "add r18, r23 \n\t" //q = q + (x>>8)
103 "adc r19, r24 \n\t"
104 "adc r20, r25 \n\t"
105 "adc r21, r1 \n\t"
106 "add r18, r22 \n\t" //q = q + x
107 "adc r19, r23 \n\t"
108 "adc r20, r24 \n\t"
109 "adc r21, r25 \n\t"
110
111 "mov r18, r19 \n\t" //q = q >> 8
112 "mov r19, r20 \n\t"
113 "mov r20, r21 \n\t"
114 "eor r21, r21 \n\t"
115 "add r18, r22 \n\t" //q = q + x
116 "adc r19, r23 \n\t"
117 "adc r20, r24 \n\t"
118 "adc r21, r25 \n\t"
119
120 "andi r18, 0xF8 \n\t" //q = q & ~0x7
121
122 "sub r0, r18 \n\t" //in = in - q
123
124 "lsr r21 \n\t" //q = q >> 2
125 "ror r20 \n\t"
126 "ror r19 \n\t"
127 "ror r18 \n\t"
128 "lsr r21 \n\t"
129 "ror r20 \n\t"
130 "ror r19 \n\t"
131 "ror r18 \n\t"
132
133 "sub r0, r18 \n\t" //in = in - q
134 "st X, r0 \n\t" //mod = in;
135
136 "lsr r21 \n\t" //q = q >> 1
137 "ror r20 \n\t"
138 "ror r19 \n\t"
139 "ror r18 \n\t"
140
141 "st Z, r18 \n\t" //div = q
142 "std Z+1, r19 \n\t"
143 "std Z+2, r20 \n\t"
144 "std Z+3, r21 \n\t"
145
146 :
147 : "r"(in), "r"(&mod), "r"(&div)
148 : "r0", "r26", "r27", "r31", "r31");
149}
void divmod10(uint32_t in, uint32_t &div, uint8_t &mod)
uint16_t divu10(uint16_t n)