1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2005 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef ANDROID_GGL_FIXED_H
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ANDROID_GGL_FIXED_H
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <math.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pixelflinger/pixelflinger.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define CONST           __attribute__((const))
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ALWAYS_INLINE   __attribute__((always_inline))
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst GGLfixed FIXED_BITS = 16;
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst GGLfixed FIXED_EPSILON  = 1;
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst GGLfixed FIXED_ONE  = 1L<<FIXED_BITS;
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst GGLfixed FIXED_HALF = 1L<<(FIXED_BITS-1);
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst GGLfixed FIXED_MIN  = 0x80000000L;
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst GGLfixed FIXED_MAX  = 0x7FFFFFFFL;
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglIntToFixed(GGLfixed i)       ALWAYS_INLINE ;
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglFixedToIntRound(GGLfixed f)  ALWAYS_INLINE ;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglFixedToIntFloor(GGLfixed f)  ALWAYS_INLINE ;
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglFixedToIntCeil(GGLfixed f)   ALWAYS_INLINE ;
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglFracx(GGLfixed v)            ALWAYS_INLINE ;
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglFloorx(GGLfixed v)           ALWAYS_INLINE ;
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglCeilx(GGLfixed v)            ALWAYS_INLINE ;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglCenterx(GGLfixed v)          ALWAYS_INLINE ;
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglRoundx(GGLfixed v)           ALWAYS_INLINE ;
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglIntToFixed(GGLfixed i) {
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return i<<FIXED_BITS;
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglFixedToIntRound(GGLfixed f) {
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return (f + FIXED_HALF)>>FIXED_BITS;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglFixedToIntFloor(GGLfixed f) {
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return f>>FIXED_BITS;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglFixedToIntCeil(GGLfixed f) {
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return (f + ((1<<FIXED_BITS) - 1))>>FIXED_BITS;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglFracx(GGLfixed v) {
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return v & ((1<<FIXED_BITS)-1);
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglFloorx(GGLfixed v) {
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglFixedToIntFloor(v)<<FIXED_BITS;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglCeilx(GGLfixed v) {
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglFixedToIntCeil(v)<<FIXED_BITS;
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglCenterx(GGLfixed v) {
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglFloorx(v + FIXED_HALF) | FIXED_HALF;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglRoundx(GGLfixed v) {
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglFixedToIntRound(v)<<FIXED_BITS;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// conversion from (unsigned) int, short, byte to fixed...
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define GGL_B_TO_X(_x)      GGLfixed( ((int32_t(_x)+1)>>1)<<10 )
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define GGL_S_TO_X(_x)      GGLfixed( ((int32_t(_x)+1)>>1)<<2 )
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define GGL_I_TO_X(_x)      GGLfixed( ((int32_t(_x)>>1)+1)>>14 )
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define GGL_UB_TO_X(_x)     GGLfixed(   uint32_t(_x) +      \
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                        (uint32_t(_x)<<8) + \
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                        (uint32_t(_x)>>7) )
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define GGL_US_TO_X(_x)     GGLfixed( (_x) + ((_x)>>15) )
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define GGL_UI_TO_X(_x)     GGLfixed( (((_x)>>1)+1)>>15 )
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglPowx(GGLfixed x, GGLfixed y) CONST;
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglSqrtx(GGLfixed a) CONST;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglSqrtRecipx(GGLfixed x) CONST;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectGGLfixed gglFastDivx(GGLfixed n, GGLfixed d) CONST;
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t gglMulDivi(int32_t a, int32_t b, int32_t c);
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t gglRecipQNormalized(int32_t x, int* exponent);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t gglRecipQ(GGLfixed x, int q) CONST;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglRecip(GGLfixed x) CONST;
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglRecip(GGLfixed x) {
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglRecipQ(x, 16);
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglRecip28(GGLfixed x) CONST;
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t gglRecip28(GGLfixed x) {
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglRecipQ(x, 28);
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if defined(__arm__) && !defined(__thumb__)
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// inline ARM implementations
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) CONST;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) {
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLfixed result, t;
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (__builtin_constant_p(shift)) {
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "movs   %[lo], %[lo], lsr %[rshift]         \n"
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "adc    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : [lo]"=r"(result), [hi]"=r"(t), [x]"=r"(x)
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "%[x]"(x), [y]"r"(y), [lshift] "I"(32-shift), [rshift] "I"(shift)
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "cc"
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "movs   %[lo], %[lo], lsr %[rshift]         \n"
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "adc    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "%[x]"(x), [y]"r"(y), [lshift] "r"(32-shift), [rshift] "r"(shift)
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "cc"
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) {
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLfixed result, t;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (__builtin_constant_p(shift)) {
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "add    %[lo], %[a],  %[lo], lsr %[rshift]  \n"
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "add    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "I"(32-shift), [rshift] "I"(shift)
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "add    %[lo], %[a],  %[lo], lsr %[rshift]  \n"
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "add    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "r"(32-shift), [rshift] "r"(shift)
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) {
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLfixed result, t;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (__builtin_constant_p(shift)) {
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "rsb    %[lo], %[a],  %[lo], lsr %[rshift]  \n"
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "add    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "I"(32-shift), [rshift] "I"(shift)
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asm("smull  %[lo], %[hi], %[x], %[y]            \n"
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "rsb    %[lo], %[a],  %[lo], lsr %[rshift]  \n"
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        "add    %[lo], %[lo], %[hi], lsl %[lshift]  \n"
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : [lo]"=&r"(result), [hi]"=&r"(t), [x]"=&r"(x)
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "%[x]"(x), [y]"r"(y), [a]"r"(a), [lshift] "r"(32-shift), [rshift] "r"(shift)
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int64_t gglMulii(int32_t x, int32_t y) CONST;
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int64_t gglMulii(int32_t x, int32_t y)
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // 64-bits result: r0=low, r1=high
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    union {
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct {
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int32_t lo;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int32_t hi;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } s;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int64_t res;
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    };
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asm("smull %0, %1, %2, %3   \n"
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "=r"(s.lo), "=&r"(s.hi)
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        : "%r"(x), "r"(y)
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        :
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        );
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return res;
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
193734f50c2fe5b8778370b687c29401effcb254862Duane Sand#elif defined(__mips__) && __mips_isa_rev < 6
194096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
195096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand/*inline MIPS implementations*/
196096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandinline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
197096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandinline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
198096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    GGLfixed result,tmp,tmp1,tmp2;
199096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
200096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    if (__builtin_constant_p(shift)) {
201096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        if (shift == 0) {
202096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            asm ("mult %[a], %[b] \t\n"
203096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand              "mflo  %[res]   \t\n"
204096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [res]"=&r"(result),[tmp]"=&r"(tmp)
205096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [a]"r"(a),[b]"r"(b)
206096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : "%hi","%lo"
207096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
208096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        } else if (shift == 32)
209096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        {
210096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            asm ("mult %[a], %[b] \t\n"
211096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "li  %[tmp],1\t\n"
212096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sll  %[tmp],%[tmp],0x1f\t\n"
213096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "mflo %[res]   \t\n"
214096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu %[tmp1],%[tmp],%[res] \t\n"
215096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sltu %[tmp1],%[tmp1],%[tmp]\t\n"   /*obit*/
216096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sra %[tmp],%[tmp],0x1f \t\n"
217096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "mfhi  %[res]   \t\n"
218096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu %[res],%[res],%[tmp]\t\n"
219096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu %[res],%[res],%[tmp1]\t\n"
220096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1)
221096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [a]"r"(a),[b]"r"(b),[shift]"I"(shift)
222096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : "%hi","%lo"
223096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
224096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        } else if ((shift >0) && (shift < 32))
225096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        {
226096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            asm ("mult %[a], %[b] \t\n"
227096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "li  %[tmp],1 \t\n"
228096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
229096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "mflo  %[res]   \t\n"
230096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu %[tmp1],%[tmp],%[res] \t\n"
231096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
232096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu  %[res],%[res],%[tmp] \t\n"
233096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "mfhi  %[tmp]   \t\n"
234096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu  %[tmp],%[tmp],%[tmp1] \t\n"
235096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sll   %[tmp],%[tmp],%[lshift] \t\n"
236096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "srl   %[res],%[res],%[rshift]    \t\n"
237096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "or    %[res],%[res],%[tmp] \t\n"
238096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
239096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [a]"r"(a),[b]"r"(b),[lshift]"I"(32-shift),[rshift]"I"(shift),[shiftm1]"I"(shift-1)
240096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : "%hi","%lo"
241096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
242096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        } else {
243096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            asm ("mult %[a], %[b] \t\n"
244096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "li  %[tmp],1 \t\n"
245096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
246096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "mflo  %[res]   \t\n"
247096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu %[tmp1],%[tmp],%[res] \t\n"
248096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
249096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sra  %[tmp2],%[tmp],0x1f \t\n"
250096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu  %[res],%[res],%[tmp] \t\n"
251096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "mfhi  %[tmp]   \t\n"
252096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu  %[tmp],%[tmp],%[tmp2] \t\n"
253096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "addu  %[tmp],%[tmp],%[tmp1] \t\n"            /*tmp=hi*/
254096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "srl   %[tmp2],%[res],%[rshift]    \t\n"
255096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "srav  %[res], %[tmp],%[rshift]\t\n"
256096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sll   %[tmp],%[tmp],1 \t\n"
257096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "sll   %[tmp],%[tmp],%[norbits] \t\n"
258096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "or    %[tmp],%[tmp],%[tmp2] \t\n"
259096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "movz  %[res],%[tmp],%[bit5] \t\n"
260096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
261096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [a]"r"(a),[b]"r"(b),[norbits]"I"(~(shift)),[rshift]"I"(shift),[shiftm1] "I"(shift-1),[bit5]"I"(shift & 0x20)
262096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : "%hi","%lo"
263096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
264096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        }
265096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } else {
266096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        asm ("mult %[a], %[b] \t\n"
267096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "li  %[tmp],1 \t\n"
268096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
269096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "mflo  %[res]   \t\n"
270096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "addu %[tmp1],%[tmp],%[res] \t\n"
271096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
272096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "sra  %[tmp2],%[tmp],0x1f \t\n"
273096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "addu  %[res],%[res],%[tmp] \t\n"
274096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "mfhi  %[tmp]   \t\n"
275096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "addu  %[tmp],%[tmp],%[tmp2] \t\n"
276096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "addu  %[tmp],%[tmp],%[tmp1] \t\n"            /*tmp=hi*/
277096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "srl   %[tmp2],%[res],%[rshift]    \t\n"
278096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "srav  %[res], %[tmp],%[rshift]\t\n"
279096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "sll   %[tmp],%[tmp],1 \t\n"
280096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "sll   %[tmp],%[tmp],%[norbits] \t\n"
281096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "or    %[tmp],%[tmp],%[tmp2] \t\n"
282096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "movz  %[res],%[tmp],%[bit5] \t\n"
283096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand         : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
284096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand         : [a]"r"(a),[b]"r"(b),[norbits]"r"(~(shift)),[rshift] "r"(shift),[shiftm1]"r"(shift-1),[bit5] "r"(shift & 0x20)
285096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand         : "%hi","%lo"
286096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand         );
287096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        }
288096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
289096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        return result;
290096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
291096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
292096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandinline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
293096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandinline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
294096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    GGLfixed result,t,tmp1,tmp2;
295096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
296096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    if (__builtin_constant_p(shift)) {
297096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        if (shift == 0) {
298096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 asm ("mult %[a], %[b] \t\n"
299096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 "mflo  %[lo]   \t\n"
300096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 "addu  %[lo],%[lo],%[c]    \t\n"
301096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 : [lo]"=&r"(result)
302096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
303096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 : "%hi","%lo"
304096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 );
305096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                } else if (shift == 32) {
306096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    asm ("mult %[a], %[b] \t\n"
307096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "mfhi  %[lo]   \t\n"
308096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "addu  %[lo],%[lo],%[c]    \t\n"
309096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [lo]"=&r"(result)
310096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [a]"r"(a),[b]"r"(b),[c]"r"(c)
311096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : "%hi","%lo"
312096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    );
313096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                } else if ((shift>0) && (shift<32)) {
314096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    asm ("mult %[a], %[b] \t\n"
315096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "mflo  %[res]   \t\n"
316096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "mfhi  %[t]   \t\n"
317096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "srl   %[res],%[res],%[rshift]    \t\n"
318096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "sll   %[t],%[t],%[lshift]     \t\n"
319096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "or  %[res],%[res],%[t]    \t\n"
320096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "addu  %[res],%[res],%[c]    \t\n"
321096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [res]"=&r"(result),[t]"=&r"(t)
322096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
323096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : "%hi","%lo"
324096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    );
325096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                } else {
326096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    asm ("mult %[a], %[b] \t\n"
327096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "nor %[tmp1],$zero,%[shift]\t\n"
328096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "mflo  %[res]   \t\n"
329096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "mfhi  %[t]   \t\n"
330096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "srl   %[res],%[res],%[shift]    \t\n"
331096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "sll   %[tmp2],%[t],1     \t\n"
332096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
333096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "or  %[tmp1],%[tmp2],%[res]    \t\n"
334096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "srav  %[res],%[t],%[shift]     \t\n"
335096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "andi %[tmp2],%[shift],0x20\t\n"
336096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "movz %[res],%[tmp1],%[tmp2]\t\n"
337096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "addu  %[res],%[res],%[c]    \t\n"
338096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
339096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
340096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : "%hi","%lo"
341096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    );
342096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                }
343096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            } else {
344096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                asm ("mult %[a], %[b] \t\n"
345096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "nor %[tmp1],$zero,%[shift]\t\n"
346096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "mflo  %[res]   \t\n"
347096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "mfhi  %[t]   \t\n"
348096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "srl   %[res],%[res],%[shift]    \t\n"
349096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "sll   %[tmp2],%[t],1     \t\n"
350096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
351096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "or  %[tmp1],%[tmp2],%[res]    \t\n"
352096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "srav  %[res],%[t],%[shift]     \t\n"
353096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "andi %[tmp2],%[shift],0x20\t\n"
354096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "movz %[res],%[tmp1],%[tmp2]\t\n"
355096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "addu  %[res],%[res],%[c]    \t\n"
356096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
357096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
358096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                : "%hi","%lo"
359096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                );
360096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            }
361096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            return result;
362096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
363096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
364096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandinline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
365096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandinline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
366096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    GGLfixed result,t,tmp1,tmp2;
367096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
368096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    if (__builtin_constant_p(shift)) {
369096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        if (shift == 0) {
370096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 asm ("mult %[a], %[b] \t\n"
371096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 "mflo  %[lo]   \t\n"
372096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 "subu  %[lo],%[lo],%[c]    \t\n"
373096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 : [lo]"=&r"(result)
374096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
375096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 : "%hi","%lo"
376096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                 );
377096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                } else if (shift == 32) {
378096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    asm ("mult %[a], %[b] \t\n"
379096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "mfhi  %[lo]   \t\n"
380096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "subu  %[lo],%[lo],%[c]    \t\n"
381096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [lo]"=&r"(result)
382096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [a]"r"(a),[b]"r"(b),[c]"r"(c)
383096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : "%hi","%lo"
384096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    );
385096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                } else if ((shift>0) && (shift<32)) {
386096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    asm ("mult %[a], %[b] \t\n"
387096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "mflo  %[res]   \t\n"
388096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "mfhi  %[t]   \t\n"
389096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "srl   %[res],%[res],%[rshift]    \t\n"
390096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "sll   %[t],%[t],%[lshift]     \t\n"
391096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "or  %[res],%[res],%[t]    \t\n"
392096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "subu  %[res],%[res],%[c]    \t\n"
393096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [res]"=&r"(result),[t]"=&r"(t)
394096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
395096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    : "%hi","%lo"
396096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    );
397096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                } else {
398096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    asm ("mult %[a], %[b] \t\n"
399096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    "nor %[tmp1],$zero,%[shift]\t\n"
400096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "mflo  %[res]   \t\n"
401096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "mfhi  %[t]   \t\n"
402096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "srl   %[res],%[res],%[shift]    \t\n"
403096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "sll   %[tmp2],%[t],1     \t\n"
404096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
405096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "or  %[tmp1],%[tmp2],%[res]    \t\n"
406096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "srav  %[res],%[t],%[shift]     \t\n"
407096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "andi %[tmp2],%[shift],0x20\t\n"
408096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "movz %[res],%[tmp1],%[tmp2]\t\n"
409096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     "subu  %[res],%[res],%[c]    \t\n"
410096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
411096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
412096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     : "%hi","%lo"
413096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                     );
414096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                    }
415096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                } else {
416096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                asm ("mult %[a], %[b] \t\n"
417096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "nor %[tmp1],$zero,%[shift]\t\n"
418096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "mflo  %[res]   \t\n"
419096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "mfhi  %[t]   \t\n"
420096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "srl   %[res],%[res],%[shift]    \t\n"
421096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "sll   %[tmp2],%[t],1     \t\n"
422096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
423096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "or  %[tmp1],%[tmp2],%[res]    \t\n"
424096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "srav  %[res],%[t],%[shift]     \t\n"
425096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "andi %[tmp2],%[shift],0x20\t\n"
426096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "movz %[res],%[tmp1],%[tmp2]\t\n"
427096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                "subu  %[res],%[res],%[c]    \t\n"
428096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
429096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
430096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                : "%hi","%lo"
431096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                );
432096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            }
433096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return result;
434096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
435096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
436096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandinline int64_t gglMulii(int32_t x, int32_t y) CONST;
437096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandinline int64_t gglMulii(int32_t x, int32_t y) {
438096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    union {
439096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        struct {
440096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#if defined(__MIPSEL__)
441096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            int32_t lo;
442096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            int32_t hi;
443096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#elif defined(__MIPSEB__)
444096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            int32_t hi;
445096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            int32_t lo;
446096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#endif
447096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        } s;
448096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        int64_t res;
449096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    }u;
450096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    asm("mult %2, %3 \t\n"
451096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "mfhi %1   \t\n"
452096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "mflo %0   \t\n"
453096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : "=r"(u.s.lo), "=&r"(u.s.hi)
454096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : "%r"(x), "r"(y)
455096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand	: "%hi","%lo"
456096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        );
457096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return u.res;
458096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
460658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat#elif defined(__aarch64__)
461658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat
462658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat// inline AArch64 implementations
463658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat
464658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhatinline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift) CONST;
465658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhatinline GGLfixed gglMulx(GGLfixed x, GGLfixed y, int shift)
466658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat{
467658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    GGLfixed result;
468658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    GGLfixed round;
469658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat
470658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    asm("mov    %x[round], #1                        \n"
471658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        "lsl    %x[round], %x[round], %x[shift]      \n"
472658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        "lsr    %x[round], %x[round], #1             \n"
473658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        "smaddl %x[result], %w[x], %w[y],%x[round]   \n"
474658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        "lsr    %x[result], %x[result], %x[shift]    \n"
475658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        : [round]"=&r"(round), [result]"=&r"(result) \
476658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        : [x]"r"(x), [y]"r"(y), [shift] "r"(shift)   \
477658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        :
478658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat       );
479658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    return result;
480658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat}
481658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhatinline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
482658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhatinline GGLfixed gglMulAddx(GGLfixed x, GGLfixed y, GGLfixed a, int shift)
483658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat{
484658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    GGLfixed result;
485658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    asm("smull  %x[result], %w[x], %w[y]                     \n"
486658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        "lsr    %x[result], %x[result], %x[shift]            \n"
487658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        "add    %w[result], %w[result], %w[a]                \n"
488658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        : [result]"=&r"(result)                               \
489658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        : [x]"r"(x), [y]"r"(y), [a]"r"(a), [shift] "r"(shift) \
490658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        :
491658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        );
492658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    return result;
493658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat}
494658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat
495658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhatinline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift) CONST;
496658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhatinline GGLfixed gglMulSubx(GGLfixed x, GGLfixed y, GGLfixed a, int shift)
497658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat{
498658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat
499658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    GGLfixed result;
500658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    int rshift;
501658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat
502658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    asm("smull  %x[result], %w[x], %w[y]                     \n"
503658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        "lsr    %x[result], %x[result], %x[shift]            \n"
504658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        "sub    %w[result], %w[result], %w[a]                \n"
505658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        : [result]"=&r"(result)                               \
506658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        : [x]"r"(x), [y]"r"(y), [a]"r"(a), [shift] "r"(shift) \
507658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        :
508658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        );
509658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    return result;
510658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat}
511658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhatinline int64_t gglMulii(int32_t x, int32_t y) CONST;
512658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhatinline int64_t gglMulii(int32_t x, int32_t y)
513658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat{
514658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    int64_t res;
515658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    asm("smull  %x0, %w1, %w2 \n"
516658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        : "=r"(res)
517658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        : "%r"(x), "r"(y)
518658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        :
519658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat        );
520658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    return res;
521658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat}
522658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat
523606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes#elif defined(__mips__) && __mips_isa_rev == 6
524606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes
525606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes/*inline MIPS implementations*/
526606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughesinline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
527606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughesinline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
528606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    GGLfixed result,tmp,tmp1,tmp2;
529606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes
530606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    if (__builtin_constant_p(shift)) {
531606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        if (shift == 0) {
532606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            asm ("mul %[res], %[a], %[b] \t\n"
533606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            : [res]"=&r"(result)
534606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            : [a]"r"(a),[b]"r"(b)
535606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            );
536606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        } else if (shift == 32)
537606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        {
538606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            asm ("mul %[res], %[a], %[b] \t\n"
539606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "li  %[tmp],1\t\n"
540606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sll  %[tmp],%[tmp],0x1f\t\n"
541606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu %[tmp1],%[tmp],%[res] \t\n"
542606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "muh %[res], %[a], %[b] \t\n"
543606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sltu %[tmp1],%[tmp1],%[tmp]\t\n"   /*obit*/
544606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sra %[tmp],%[tmp],0x1f \t\n"
545606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu %[res],%[res],%[tmp]\t\n"
546606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu %[res],%[res],%[tmp1]\t\n"
547606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1)
548606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            : [a]"r"(a),[b]"r"(b),[shift]"I"(shift)
549606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            );
550606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        } else if ((shift >0) && (shift < 32))
551606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        {
552606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            asm ("mul %[res], %[a], %[b] \t\n"
553606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "li  %[tmp],1 \t\n"
554606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
555606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu %[tmp1],%[tmp],%[res] \t\n"
556606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
557606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu  %[res],%[res],%[tmp] \t\n"
558606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "muh %[tmp], %[a], %[b] \t\n"
559606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu  %[tmp],%[tmp],%[tmp1] \t\n"
560606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sll   %[tmp],%[tmp],%[lshift] \t\n"
561606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "srl   %[res],%[res],%[rshift]    \t\n"
562606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "or    %[res],%[res],%[tmp] \t\n"
563606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
564606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            : [a]"r"(a),[b]"r"(b),[lshift]"I"(32-shift),[rshift]"I"(shift),[shiftm1]"I"(shift-1)
565606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            );
566606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        } else {
567606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            asm ("mul %[res], %[a], %[b] \t\n"
568606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "li  %[tmp],1 \t\n"
569606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
570606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu %[tmp1],%[tmp],%[res] \t\n"
571606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
572606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sra  %[tmp2],%[tmp],0x1f \t\n"
573606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu  %[res],%[res],%[tmp] \t\n"
574606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "muh  %[tmp], %[a], %[b]   \t\n"
575606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu  %[tmp],%[tmp],%[tmp2] \t\n"
576606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "addu  %[tmp],%[tmp],%[tmp1] \t\n"            /*tmp=hi*/
577606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "srl   %[tmp2],%[res],%[rshift]    \t\n"
578606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "srav  %[res], %[tmp],%[rshift]\t\n"
579606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sll   %[tmp],%[tmp],1 \t\n"
580606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "sll   %[tmp],%[tmp],%[norbits] \t\n"
581606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "or    %[tmp],%[tmp],%[tmp2] \t\n"
582606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "seleqz  %[tmp],%[tmp],%[bit5] \t\n"
583606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "selnez  %[res],%[res],%[bit5] \t\n"
584606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            "or    %[res],%[res],%[tmp] \t\n"
585606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
586606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            : [a]"r"(a),[b]"r"(b),[norbits]"I"(~(shift)),[rshift]"I"(shift),[shiftm1] "I"(shift-1),[bit5]"I"(shift & 0x20)
587606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            );
588606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        }
589606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    } else {
590606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        asm ("mul %[res], %[a], %[b] \t\n"
591606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "li  %[tmp],1 \t\n"
592606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "sll  %[tmp],%[tmp],%[shiftm1] \t\n"
593606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "addu %[tmp1],%[tmp],%[res] \t\n"
594606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "sltu %[tmp1],%[tmp1],%[tmp] \t\n"  /*obit?*/
595606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "sra  %[tmp2],%[tmp],0x1f \t\n"
596606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "addu  %[res],%[res],%[tmp] \t\n"
597606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "muh  %[tmp], %[a], %[b] \t\n"
598606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "addu  %[tmp],%[tmp],%[tmp2] \t\n"
599606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "addu  %[tmp],%[tmp],%[tmp1] \t\n"            /*tmp=hi*/
600606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "srl   %[tmp2],%[res],%[rshift]    \t\n"
601606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "srav  %[res], %[tmp],%[rshift]\t\n"
602606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "sll   %[tmp],%[tmp],1 \t\n"
603606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "sll   %[tmp],%[tmp],%[norbits] \t\n"
604606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "or    %[tmp],%[tmp],%[tmp2] \t\n"
605606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "seleqz  %[tmp],%[tmp],%[bit5] \t\n"
606606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "selnez  %[res],%[res],%[bit5] \t\n"
607606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "or    %[res],%[res],%[tmp] \t\n"
608606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes         : [res]"=&r"(result),[tmp]"=&r"(tmp),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
609606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes         : [a]"r"(a),[b]"r"(b),[norbits]"r"(~(shift)),[rshift] "r"(shift),[shiftm1]"r"(shift-1),[bit5] "r"(shift & 0x20)
610606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes         );
611606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        }
612606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        return result;
613606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes}
614606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes
615606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughesinline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
616606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughesinline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
617606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    GGLfixed result,t,tmp1,tmp2;
618606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes
619606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    if (__builtin_constant_p(shift)) {
620606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        if (shift == 0) {
621606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 asm ("mul %[lo], %[a], %[b] \t\n"
622606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 "addu  %[lo],%[lo],%[c]    \t\n"
623606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 : [lo]"=&r"(result)
624606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
625606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 );
626606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                } else if (shift == 32) {
627606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    asm ("muh %[lo], %[a], %[b] \t\n"
628606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "addu  %[lo],%[lo],%[c]    \t\n"
629606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [lo]"=&r"(result)
630606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [a]"r"(a),[b]"r"(b),[c]"r"(c)
631606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    );
632606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                } else if ((shift>0) && (shift<32)) {
633606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    asm ("mul %[res], %[a], %[b] \t\n"
634606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "muh  %[t], %[a], %[b] \t\n"
635606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "srl   %[res],%[res],%[rshift]    \t\n"
636606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "sll   %[t],%[t],%[lshift]     \t\n"
637606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "or  %[res],%[res],%[t]    \t\n"
638606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "addu  %[res],%[res],%[c]    \t\n"
639606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [res]"=&r"(result),[t]"=&r"(t)
640606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
641606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    );
642606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                } else {
643606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    asm ("mul %[res], %[a], %[b] \t\n"
644606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "muh %[t], %[a], %[b] \t\n"
645606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "nor %[tmp1],$zero,%[shift]\t\n"
646606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "srl   %[res],%[res],%[shift]    \t\n"
647606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "sll   %[tmp2],%[t],1     \t\n"
648606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
649606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "or  %[tmp1],%[tmp2],%[res]    \t\n"
650606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "srav  %[res],%[t],%[shift]     \t\n"
651606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "andi %[tmp2],%[shift],0x20\t\n"
652606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
653606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "selnez %[res],%[res],%[tmp2]\t\n"
654606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "or %[res],%[res],%[tmp1]\t\n"
655606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "addu  %[res],%[res],%[c]    \t\n"
656606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
657606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
658606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    );
659606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                }
660606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            } else {
661606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                asm ("mul %[res], %[a], %[b] \t\n"
662606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "muh %[t], %[a], %[b] \t\n"
663606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "nor %[tmp1],$zero,%[shift]\t\n"
664606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "srl   %[res],%[res],%[shift]    \t\n"
665606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "sll   %[tmp2],%[t],1     \t\n"
666606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
667606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "or  %[tmp1],%[tmp2],%[res]    \t\n"
668606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "srav  %[res],%[t],%[shift]     \t\n"
669606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "andi %[tmp2],%[shift],0x20\t\n"
670606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
671606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "selnez %[res],%[res],%[tmp2]\t\n"
672606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "or %[res],%[res],%[tmp1]\t\n"
673606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "addu  %[res],%[res],%[c]    \t\n"
674606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
675606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
676606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                );
677606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            }
678606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            return result;
679606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes}
680606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes
681606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughesinline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
682606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughesinline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
683606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    GGLfixed result,t,tmp1,tmp2;
684606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes
685606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    if (__builtin_constant_p(shift)) {
686606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        if (shift == 0) {
687606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 asm ("mul %[lo], %[a], %[b] \t\n"
688606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 "subu  %[lo],%[lo],%[c]    \t\n"
689606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 : [lo]"=&r"(result)
690606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 : [a]"r"(a),[b]"r"(b),[c]"r"(c)
691606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                 );
692606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                } else if (shift == 32) {
693606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    asm ("muh %[lo], %[a], %[b] \t\n"
694606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "subu  %[lo],%[lo],%[c]    \t\n"
695606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [lo]"=&r"(result)
696606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [a]"r"(a),[b]"r"(b),[c]"r"(c)
697606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    );
698606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                } else if ((shift>0) && (shift<32)) {
699606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    asm ("mul %[res], %[a], %[b] \t\n"
700606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "muh %[t], %[a], %[b] \t\n"
701606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "srl   %[res],%[res],%[rshift]    \t\n"
702606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "sll   %[t],%[t],%[lshift]     \t\n"
703606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "or  %[res],%[res],%[t]    \t\n"
704606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "subu  %[res],%[res],%[c]    \t\n"
705606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [res]"=&r"(result),[t]"=&r"(t)
706606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[lshift]"I"(32-shift),[rshift]"I"(shift)
707606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    );
708606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                } else {
709606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    asm ("mul %[res], %[a], %[b] \t\n"
710606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "muh %[t], %[a], %[b] \t\n"
711606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "nor %[tmp1],$zero,%[shift]\t\n"
712606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "srl   %[res],%[res],%[shift]    \t\n"
713606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "sll   %[tmp2],%[t],1     \t\n"
714606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
715606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "or  %[tmp1],%[tmp2],%[res]    \t\n"
716606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "srav  %[res],%[t],%[shift]     \t\n"
717606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "andi %[tmp2],%[shift],0x20\t\n"
718606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
719606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "selnez %[res],%[res],%[tmp2]\t\n"
720606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "or %[res],%[res],%[tmp1]\t\n"
721606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    "subu  %[res],%[res],%[c]    \t\n"
722606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
723606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"I"(shift)
724606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                     );
725606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                    }
726606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                } else {
727606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                asm ("mul %[res], %[a], %[b] \t\n"
728606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "muh %[t], %[a], %[b] \t\n"
729606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "nor %[tmp1],$zero,%[shift]\t\n"
730606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "srl   %[res],%[res],%[shift]    \t\n"
731606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "sll   %[tmp2],%[t],1     \t\n"
732606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "sllv  %[tmp2],%[tmp2],%[tmp1]     \t\n"
733606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "or  %[tmp1],%[tmp2],%[res]    \t\n"
734606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "srav  %[res],%[t],%[shift]     \t\n"
735606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "andi %[tmp2],%[shift],0x20\t\n"
736606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "seleqz %[tmp1],%[tmp1],%[tmp2]\t\n"
737606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "selnez %[res],%[res],%[tmp2]\t\n"
738606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "or %[res],%[res],%[tmp1]\t\n"
739606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                "subu  %[res],%[res],%[c]    \t\n"
740606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                : [res]"=&r"(result),[t]"=&r"(t),[tmp1]"=&r"(tmp1),[tmp2]"=&r"(tmp2)
741606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                : [a]"r"(a),[b]"r"(b),[c]"r"(c),[shift]"r"(shift)
742606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes                );
743606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            }
744606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    return result;
745606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes}
746606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes
747606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughesinline int64_t gglMulii(int32_t x, int32_t y) CONST;
748606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughesinline int64_t gglMulii(int32_t x, int32_t y) {
749606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    union {
750606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        struct {
751606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes#if defined(__MIPSEL__)
752606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            int32_t lo;
753606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            int32_t hi;
754606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes#elif defined(__MIPSEB__)
755606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            int32_t hi;
756606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes            int32_t lo;
757606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes#endif
758606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        } s;
759606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        int64_t res;
760606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    }u;
761606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    asm("mul %0, %2, %3 \t\n"
762606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        "muh %1, %2, %3 \t\n"
763606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        : "=r"(u.s.lo), "=&r"(u.s.hi)
764606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        : "%r"(x), "r"(y)
765606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes        );
766606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes    return u.res;
767606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes}
768606d4aecfb6a1e911dac207caeba617d1379c1f7Elliott Hughes
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else // ----------------------------------------------------------------------
770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) CONST;
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulx(GGLfixed a, GGLfixed b, int shift) {
773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return GGLfixed((int64_t(a)*b + (1<<(shift-1)))>>shift);
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return GGLfixed((int64_t(a)*b)>>shift) + c;
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) CONST;
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c, int shift) {
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return GGLfixed((int64_t(a)*b)>>shift) - c;
782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int64_t gglMulii(int32_t a, int32_t b) CONST;
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int64_t gglMulii(int32_t a, int32_t b) {
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return int64_t(a)*b;
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ------------------------------------------------------------------------
791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulx(GGLfixed a, GGLfixed b) CONST;
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulx(GGLfixed a, GGLfixed b) {
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglMulx(a, b, 16);
795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c) CONST;
797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulAddx(GGLfixed a, GGLfixed b, GGLfixed c) {
798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglMulAddx(a, b, c, 16);
799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c) CONST;
801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglMulSubx(GGLfixed a, GGLfixed b, GGLfixed c) {
802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglMulSubx(a, b, c, 16);
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ------------------------------------------------------------------------
806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int32_t gglClz(int32_t x) CONST;
808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int32_t gglClz(int32_t x)
809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
810658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat#if (defined(__arm__) && !defined(__thumb__)) || defined(__mips__) || defined(__aarch64__)
811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return __builtin_clz(x);
812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!x) return 32;
814dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t exp = 31;
815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (x & 0xFFFF0000) { exp -=16; x >>= 16; }
816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (x & 0x0000ff00) { exp -= 8; x >>= 8; }
817dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (x & 0x000000f0) { exp -= 4; x >>= 4; }
818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (x & 0x0000000c) { exp -= 2; x >>= 2; }
819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (x & 0x00000002) { exp -= 1; }
820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return exp;
821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
823dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
824dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ------------------------------------------------------------------------
825dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
826dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint32_t gglDivQ(GGLfixed n, GGLfixed d, int32_t i) CONST;
827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int32_t gglDivQ16(GGLfixed n, GGLfixed d) CONST;
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int32_t gglDivQ16(GGLfixed n, GGLfixed d) {
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglDivQ(n, d, 16);
831dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int32_t gglDivx(GGLfixed n, GGLfixed d) CONST;
834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int32_t gglDivx(GGLfixed n, GGLfixed d) {
835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return gglDivQ(n, d, 16);
836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ------------------------------------------------------------------------
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
840dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglRecipFast(GGLfixed x) CONST;
841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglRecipFast(GGLfixed x)
842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // This is a really bad approximation of 1/x, but it's also
844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // very fast. x must be strictly positive.
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // if x between [0.5, 1[ , then 1/x = 3-2*x
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // (we use 2.30 fixed-point)
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t lz = gglClz(x);
848dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return (0xC0000000 - (x << (lz - 1))) >> (30-lz);
849dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ------------------------------------------------------------------------
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglClampx(GGLfixed c) CONST;
854dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline GGLfixed gglClampx(GGLfixed c)
855dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
856dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if defined(__thumb__)
857dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // clamp without branches
858dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c &= ~(c>>31);  c = FIXED_ONE - c;
859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c &= ~(c>>31);  c = FIXED_ONE - c;
860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
861dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if defined(__arm__)
862dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // I don't know why gcc thinks its smarter than me! The code below
863dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // clamps to zero in one instruction, but gcc won't generate it and
864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // replace it by a cmp + movlt (it's quite amazing actually).
865dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asm("bic %0, %1, %1, asr #31\n" : "=r"(c) : "r"(c));
866658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat#elif defined(__aarch64__)
867658f89dc5c418dbbc0c5d78f5861855b90ca8c9fAshok Bhat    asm("bic %w0, %w1, %w1, asr #31\n" : "=r"(c) : "r"(c));
868dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
869dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c &= ~(c>>31);
870dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
871dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (c>FIXED_ONE)
872dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c = FIXED_ONE;
873dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
874dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return c;
875dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
876dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
877dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ------------------------------------------------------------------------
878dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
879dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif // ANDROID_GGL_FIXED_H
880