1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - GX -
3 File: fx_cp.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/fx/fx_cp.h>
19 #include <nitro/cp/divider.h>
20 #include <nitro/cp/sqrt.h>
21
22 #define FX_DIV_SHIFT (32 - FX32_SHIFT) // 20
23 #define FX_DIV_1_2 (1 << (FX_DIV_SHIFT - 1))
24
25 #define FX_SQRT_SHIFT ((32 + FX32_SHIFT) / 2 - FX32_SHIFT) // 10
26 #define FX_SQRT_1_2 (1 << (FX_SQRT_SHIFT - 1))
27
28 #define FX_INVSQRT_SHIFT \
29 (FX64C_SHIFT + ((32 + FX32_SHIFT) / 2 - FX32_SHIFT)) // 42
30 #define FX_INVSQRT_1_2 (1LL << (FX_INVSQRT_SHIFT - 1))
31
32
33 /*---------------------------------------------------------------------------*
34 Name: FX_Div
35
36 Description: Divides 'numer' by 'denom', and returns the result in fx32
37 format. This uses the divider.
38
39 Arguments: numer a value in fx32 format
40 denom a value in fx32 format
41
42 Returns: result in fx32 format
43 *---------------------------------------------------------------------------*/
FX_Div(fx32 numer,fx32 denom)44 fx32 FX_Div(fx32 numer, fx32 denom)
45 {
46 FX_DivAsync(numer, denom);
47 return FX_GetDivResult();
48 }
49
50
51 /*---------------------------------------------------------------------------*
52 Name: FX_DivFx64c
53
54 Description: Divides 'numer' by 'denom', and returns the result in fx64c
55 format. This uses the divider.
56
57 Arguments: numer a value in fx32 format
58 denom a value in fx32 format
59
60 Returns: result in fx64c format
61 *---------------------------------------------------------------------------*/
FX_DivFx64c(fx32 numer,fx32 denom)62 fx64c FX_DivFx64c(fx32 numer, fx32 denom)
63 {
64 FX_DivAsync(numer, denom);
65 return (fx64c)CP_GetDivResult64();
66 }
67
68 /*---------------------------------------------------------------------------*
69 Name: FX_Inv
70
71 Description: Returns an inverse number of 'denom'. This uses the divider.
72
73 Arguments: denom a value in fx32 format
74
75 Returns: result in fx32 format
76 *---------------------------------------------------------------------------*/
FX_Inv(fx32 denom)77 fx32 FX_Inv(fx32 denom)
78 {
79 FX_InvAsync(denom);
80 return FX_GetDivResult();
81 }
82
83
84 /*---------------------------------------------------------------------------*
85 Name: FX_InvFx64c
86
87 Description: Returns an inverse number of 'denom'. This uses the divider.
88
89 Arguments: denom a value in fx32 format
90
91 Returns: result in fx64c format
92 *---------------------------------------------------------------------------*/
FX_InvFx64c(fx32 denom)93 fx64c FX_InvFx64c(fx32 denom)
94 {
95 FX_InvAsync(denom);
96 return (fx64c)CP_GetDivResult64();
97 }
98
99
100 /*---------------------------------------------------------------------------*
101 Name: FX_Sqrt
102
103 Description: Returns a square root of 'x'. This uses the sqrt unit.
104
105 Arguments: x a value in fx32 format
106
107 Returns: result in fx32 format
108 *---------------------------------------------------------------------------*/
FX_Sqrt(fx32 x)109 fx32 FX_Sqrt(fx32 x)
110 {
111 SDK_ASSERT(!CP_IsSqrtBusy());
112 if (x > 0)
113 {
114 CP_SetSqrt64((u64)x << 32);
115 return FX_GetSqrtResult();
116 }
117 else
118 {
119 return 0;
120 }
121 }
122
123
124 /*---------------------------------------------------------------------------*
125 Name: FX_InvSqrt
126
127 Description: Returns an inverse of a square root of 'x'. This uses
128 the divider and the sqrt unit.
129
130 Arguments: x a value in fx32 format
131
132 Returns: result in fx32 format
133 *---------------------------------------------------------------------------*/
FX_InvSqrt(fx32 x)134 fx32 FX_InvSqrt(fx32 x)
135 {
136 if (x > 0)
137 {
138 fx64c inv_x;
139 s64 sqrt_x;
140 s64 tmp;
141
142 FX_InvAsync(x);
143 FX_SqrtAsync(x);
144
145 inv_x = FX_GetInvResultFx64c();
146 sqrt_x = CP_GetSqrtResult32();
147 tmp = inv_x * sqrt_x;
148 return (fx32)((tmp + FX_INVSQRT_1_2) >> FX_INVSQRT_SHIFT);
149 }
150 else
151 {
152 return 0;
153 }
154 }
155
156
157 /*---------------------------------------------------------------------------*
158 Name: FX_GetDivResultFx64c
159
160 Description: Get the result of division in fx64c format.
161 This function must be called after FX_DivAsync/FX_DivAsyncImm is executed.
162
163 Arguments: none
164
165 Returns: the result of division in fx64c format
166 *---------------------------------------------------------------------------*/
FX_GetDivResultFx64c(void)167 fx64c FX_GetDivResultFx64c(void)
168 {
169 return (fx64c)CP_GetDivResult64();
170 }
171
172
173 /*---------------------------------------------------------------------------*
174 Name: FX_GetDivResult
175
176 Description: Get the result of division in fx32 format.
177 This function must be called after FX_DivAsync/FX_DivAsyncImm is executed.
178
179 Arguments: none
180
181 Returns: the result of division in fx32 format
182 *---------------------------------------------------------------------------*/
FX_GetDivResult(void)183 fx32 FX_GetDivResult(void)
184 {
185 return (fx32)((CP_GetDivResult64() + FX_DIV_1_2) >> FX_DIV_SHIFT);
186 }
187
188 /*---------------------------------------------------------------------------*
189 Name: FX_InvAsync
190
191 Description: Just the same as FX_DivAsync(FX32_ONE, denom).
192 This function sets numer and denom onto the divider.
193 It also sets up the divider DIVMODE 01(64/32)
194
195 Arguments: denom in fx32 format
196
197 Returns: none
198 *---------------------------------------------------------------------------*/
FX_InvAsync(fx32 denom)199 void FX_InvAsync(fx32 denom)
200 {
201 SDK_ASSERT(!CP_IsDivBusy());
202 FX_DIVISION_BY_ZERO(FX32_ONE, denom);
203
204 CP_SetDiv64_32((u64)FX32_ONE << 32, (u32)denom);
205 }
206
207
208 // Sqrt
209 /*---------------------------------------------------------------------------*
210 Name: FX_SqrtAsync
211
212 Description: Use a sqrt calculator asynchronously.
213 This function sets numer onto the calculator.
214 It also sets up the calculator SQRTMODE 01(64).
215
216 Arguments: numer in fx32 format
217
218 Returns: none
219 *---------------------------------------------------------------------------*/
FX_SqrtAsync(fx32 x)220 void FX_SqrtAsync(fx32 x)
221 {
222 SDK_ASSERT(!CP_IsSqrtBusy());
223 if (x > 0)
224 {
225 CP_SetSqrt64((u64)x << 32);
226 }
227 else
228 {
229 CP_SetSqrt64(0);
230 }
231 }
232
233
234 /*---------------------------------------------------------------------------*
235 Name: FX_SqrtAsyncImm
236
237 Description: Use a sqrt calculator asynchronously.
238 This function sets numer onto the calculator.
239 It assumes that the calculator is in SQRTMODE 01(64).
240
241 Arguments: numer in fx32 format
242
243 Returns: none
244 *---------------------------------------------------------------------------*/
FX_SqrtAsyncImm(fx32 x)245 void FX_SqrtAsyncImm(fx32 x)
246 {
247 SDK_ASSERT(!CP_IsSqrtBusy());
248 if (x > 0)
249 {
250 CP_SetSqrtImm64((u64)x << 32);
251 }
252 else
253 {
254 CP_SetSqrtImm64(0);
255 }
256 }
257
258
259 /*---------------------------------------------------------------------------*
260 Name: FX_GetSqrtResult
261
262 Description: Get the result of sqrt in fx32 format.
263 This function must be called after FX_SqrtAsync/FX_SqrtAsyncImm is executed.
264
265 Arguments: none
266
267 Returns: the result of sqrt in fx32 format
268 *---------------------------------------------------------------------------*/
FX_GetSqrtResult(void)269 fx32 FX_GetSqrtResult(void)
270 {
271 return (fx32)((CP_GetSqrtResult32() + FX_SQRT_1_2) >> FX_SQRT_SHIFT);
272 }
273
274
275 // Div
276 /*---------------------------------------------------------------------------*
277 Name: FX_DivAsync
278
279 Description: Use a divider asynchronously.
280 This function sets numer and denom onto the divider.
281 It also sets up the divider DIVMODE 01(64/32)
282
283 Arguments: numer in fx32 format
284 denom in fx32 format
285
286 Returns: none
287 *---------------------------------------------------------------------------*/
FX_DivAsync(fx32 numer,fx32 denom)288 void FX_DivAsync(fx32 numer, fx32 denom)
289 {
290 SDK_ASSERT(!CP_IsDivBusy());
291 FX_DIVISION_BY_ZERO(numer, denom);
292
293 CP_SetDiv64_32((u64)numer << 32, (u32)denom);
294 }
295
296
297
298
299 /*---------------------------------------------------------------------------*
300 Name: FX_DivS32
301
302 Description: Divides an integer by an integer, and returns the result
303 in integer. This uses the divider. Faster than software emulation.
304
305 Arguments: numer a value in s32 format
306 denom a value in s32 format
307
308 Returns: result in s32 format
309 *---------------------------------------------------------------------------*/
FX_DivS32(s32 a,s32 b)310 s32 FX_DivS32(s32 a, s32 b)
311 {
312 SDK_ASSERT(!CP_IsDivBusy());
313 FX_DIVISION_BY_ZERO(a, b);
314 CP_SetDiv32_32((u32)a, (u32)b);
315 return CP_GetDivResult32();
316 }
317
318
319 /*---------------------------------------------------------------------------*
320 Name: FX_ModS32
321
322 Description: Divides an integer by an integer, and returns the remainder
323 in integer. This uses the divider. Faster than software emulation.
324
325 Arguments: numer a value in s32 format
326 denom a value in s32 format
327
328 Returns: result in s32 format
329 *---------------------------------------------------------------------------*/
FX_ModS32(s32 a,s32 b)330 s32 FX_ModS32(s32 a, s32 b)
331 {
332 SDK_ASSERT(!CP_IsDivBusy());
333 FX_DIVISION_BY_ZERO(a, b);
334 CP_SetDiv32_32((u32)a, (u32)b);
335 return CP_GetDivRemainder32();
336 }
337