XenevaOS
Loading...
Searching...
No Matches
XenevaOS
BaseHdr
linux
math64.h
Go to the documentation of this file.
1
#ifndef __LINUX_MATH64_H__
2
#define __LINUX_MATH64_H__
3
4
/*
5
* DCL <linux/math64.h> -- 64-bit division and 32x32->64 multiplication.
6
*
7
* Every body below is the generic C answer (`/`, `%`, `(u64)a * b`) rather
8
* than an arch-specific routine, and that is the correct answer here rather
9
* than a simplification: this target is aarch64, which has a hardware 64-bit
10
* divider and a 32x32->64 multiplier (umulh), so each of these compiles to
11
* one instruction pair with no libgcc call -- the exact problem upstream's
12
* per-arch split (lib/div64.c and the per-arch lib directories) exists to
13
* avoid on 32-bit CPUs that trap or soft-divide. Matching mainline's
14
* *answers* is all that is owed, and for truncating integer division the
15
* hardware and the reference agree bit for bit, including the signed
16
* forms' round-toward-zero.
17
*
18
* include <linux/types.h> supplies u64/s64/u32/s32 (kernel.h's typedefs) so
19
* the prototypes read like mainline's. The include is safe in either
20
* direction: types.h's own kernel.h include is behind kernel.h's include
21
* guard, which any caller of this header has already set, and asm/div64.h
22
* has pulled types.h in before its bottom include of this file.
23
*
24
* Not every consumer names this header. drm_mm.c, drm_file.c, drm_rect.c,
25
* drm_format_helper.c and drm_fourcc.c reach it only through
26
* <asm/div64.h>, which includes it at the bottom -- see the bridge note
27
* there. That is why the helpers must be inline here and not in a DCL shim:
28
* a definition the caller cannot see is not a definition.
29
*
30
* upstream include/linux/math64.h (mainline v7.2)
31
*/
32
33
#include <
linux/types.h
>
34
35
/*
36
* div64_u64 / DIV64_U64_ROUND_UP -- the one pair this header carried for the
37
* tty/serial stage, kept because serial_core.c:451 still uses it:
38
*
39
* temp *= NSEC_PER_SEC;
40
* port->frame_time = (unsigned int)DIV64_U64_ROUND_UP(temp, baud);
41
*
42
* which turns a bit time into the nanoseconds a whole frame takes, rounded
43
* *up* because a frame time that rounds down would make uart_poll_timeout()
44
* wake before the last stop bit had left the wire -- the caller then polls
45
* once more and, on a slow line, can poll forever. Rounding up is the safe
46
* direction and it is what upstream's div64_u64() does behind this macro.
47
* Written as a macro rather than an inline for the same reachability reason
48
* as the rest, just at an earlier stage: serial_core.c happened to include
49
* the header, and a plain expression cannot disagree with itself.
50
*/
51
#define div64_u64(a, b) ((u64)(a) / (u64)(b))
52
#define DIV64_U64_ROUND_UP(n, d) (div64_u64((u64)(n) + (u64)(d) - 1, (d)))
53
54
/*
55
* div64_u64_rem -- 64/64 divide, remainder through the out parameter.
56
*
57
* The two callers, drm_mm.c:575 and :792, use only the remainder: each
58
* adjusts an alignment up to the next multiple of `alignment` when
59
* `alignment` is not a power of two (a power of two goes through the
60
* remainder_mask fast path beside the call). Getting this wrong does not
61
* fault -- it places a node at a misaligned start, and only the
62
* alignment-aware users of drm_mm (address-space VA allocation with a
63
* non-power-of-two guard) would ever see it.
64
*/
65
static
inline
u64
div64_u64_rem(
u64
dividend,
u64
divisor,
u64
*remainder)
66
{
67
*remainder = dividend % divisor;
68
return
dividend / divisor;
69
}
70
71
/*
72
* div64_s64 -- signed 64/64 divide.
73
*
74
* Reached from <drm/drm_fixed.h>, whose fixed-point arithmetic is compiled
75
* into vkms_composer.o and vkms_formats.o. drm_fixed.h:166 divides one
76
* fixed-point value by another and :215-227 computes a per-step tolerance
77
* for the blend matrices; both compare the result against zero or against a
78
* tolerance, so a divide that did not follow the operands' sign would flip a
79
* blend decision rather than merely lose a fraction.
80
*/
81
static
inline
s64
div64_s64(
s64
dividend,
s64
divisor)
82
{
83
return
dividend / divisor;
84
}
85
86
/*
87
* div_u64 -- unsigned 64/32 divide.
88
*
89
* drm_file.c:857 steps a byte count down by SZ_1K for fdinfo units
90
* (`sz = div_u64(sz, SZ_1K)`) and drm_vblank.c:659-660 turns
91
* pixels * 1000000 into a line/frame duration in nanoseconds
92
* (`div_u64((u64) mode->crtc_htotal * 1000000, dotclock)`). The 64-bit
93
* dividend is the reason the name exists: a plain division by a 32-bit
94
* value would still be a 64-bit operation, but the explicit u32 parameter
95
* is what tells a 32-bit compiler it may use the cheap path.
96
*/
97
static
inline
u64
div_u64(
u64
dividend,
u32
divisor)
98
{
99
return
dividend / divisor;
100
}
101
102
/*
103
* div_s64 -- signed 64/32 divide.
104
*
105
* One caller, drm_vblank.c:807: the elapsed-time delta between the queried
106
* scanout position and the start of the display scanline is computed as
107
* `1000000LL * (vpos * mode->crtc_htotal + hpos)`, which is negative when
108
* the query lands before the first line has been scanned. That negative has
109
* to stay negative -- it is added to a raw timestamp -- so the unsigned form
110
* would be a silent timestamp jump of almost 2^64 nanoseconds.
111
*/
112
static
inline
s64
div_s64(
s64
dividend,
s32
divisor)
113
{
114
return
dividend / divisor;
115
}
116
117
/*
118
* mul_u32_u32 -- unsigned 32x32 -> 64 multiply.
119
*
120
* Both callers multiply quantities that legitimately exceed 32 bits:
121
* drm_rect.c:65 scales a clipped source rectangle by the destination
122
* extent, and drm_modes.c:1307 computes a fixed-point refresh rate
123
* (`mul_u32_u32(num, 1000)` where num already sits in the fixed-point
124
* domain). Without the widening cast the product would wrap at 2^32 and the
125
* scaled rectangle/rate would be wrong by a multiple of 2^32 -- the
126
* truncation would be invisible until a large mode was used.
127
*/
128
static
inline
u64
mul_u32_u32(
u32
a
,
u32
b
)
129
{
130
return
(
u64
)
a
*
b
;
131
}
132
133
/*
134
* KHZ2PICOS -- a frequency in kHz as picoseconds, `(1000000000UL/(a))`.
135
*
136
* Upstream's home is <uapi/linux/fb.h>:241; DCL's <linux/fb.h> is a stub
137
* kept only so the include resolves -- drm_modes.c:35 includes it with the
138
* comment "for KHZ2PICOS()" and gets nothing from it. The macro is placed
139
* here instead because this header (through the asm/div64.h bridge) is
140
* reached by both comparers: drm_edid.c:4409-4410 and :4511-4512 match an
141
* EDID mode against CEA mode clocks, drm_modes.c:1495 compares two
142
* drm_display_modes. All of them compare `mode->clock` (kHz, an int) after
143
* scaling to picoseconds, which is how KHz becomes comparable with EDID's
144
* kHz-with-decimals without floating point. 1000000000UL fits unsigned long
145
* on this LLP64 target (32 bits) with room to spare, and `a` is a mode clock
146
* in kHz, so the only input that would fault is zero -- which no parsed
147
* display mode carries.
148
*/
149
#ifndef KHZ2PICOS
150
#define KHZ2PICOS(a) (1000000000UL / (a))
151
#endif
152
153
#endif
/* __LINUX_MATH64_H__ */
types.h
a
size_t a
Definition
main.cpp:156
b
size_t b
Definition
main.cpp:156
s64
int64_t s64
Definition
kernel.h:21
u64
uint64_t u64
Definition
kernel.h:17
s32
int32_t s32
Definition
kernel.h:20
u32
uint32_t u32
Definition
kernel.h:16
Generated by
1.9.8