File tree 1 file changed +35
-0
lines changed
compiler-builtins/src/int
1 file changed +35
-0
lines changed Original file line number Diff line number Diff line change @@ -43,6 +43,41 @@ intrinsics! {
43
43
44
44
( ( rem as u64 ) << 32 ) | ( div as u64 )
45
45
}
46
+
47
+ #[ naked]
48
+ pub unsafe extern "C" fn __udivmodqi4( ) {
49
+ // compute unsigned 8-bit `n / d` and `n % d`.
50
+ //
51
+ // Note: GCC implements a [non-standard calling convention](https://gcc.gnu.org/wiki/avr-gcc#Exceptions_to_the_Calling_Convention) for this function.
52
+ // Inputs:
53
+ // R24: dividend
54
+ // R22: divisor
55
+ // Outputs:
56
+ // R24: quotient (dividend / divisor)
57
+ // R25: remainder (dividend % divisor)
58
+ // Clobbers:
59
+ // R23: loop counter
60
+ core:: arch:: naked_asm!(
61
+ // This assembly routine implements the [long division](https://en.wikipedia.org/wiki/Division_algorithm#Long_division) algorithm.
62
+ // Bits shift out of the dividend and into the quotient, so R24 is used for both.
63
+ "clr R25" , // remainder = 0
64
+
65
+ "ldi R23, 8" , // for each bit
66
+ "1:" ,
67
+ "lsl R24" , // shift the dividend MSb
68
+ "rol R25" , // into the remainder LSb
69
+
70
+ "cp R25, R22" , // if remainder >= divisor
71
+ "brlo 2f" ,
72
+ "sub R25, R22" , // remainder -= divisor
73
+ "sbr R24, 1" , // quotient |= 1
74
+ "2:" ,
75
+
76
+ "dec R23" , // end loop
77
+ "brne 1b" ,
78
+ "ret" ,
79
+ ) ;
80
+ }
46
81
}
47
82
48
83
intrinsics ! {
You can’t perform that action at this time.
0 commit comments