xref: /aosp_15_r20/dalvik/docs/porting-proto.c.txt (revision 055d459012065f78d96b68be8421640240ddf631)
1*055d4590SKeyi Gui/*
2*055d4590SKeyi Gui * Copyright (C) 2009 The Android Open Source Project
3*055d4590SKeyi Gui *
4*055d4590SKeyi Gui * Licensed under the Apache License, Version 2.0 (the "License");
5*055d4590SKeyi Gui * you may not use this file except in compliance with the License.
6*055d4590SKeyi Gui * You may obtain a copy of the License at
7*055d4590SKeyi Gui *
8*055d4590SKeyi Gui *      http://www.apache.org/licenses/LICENSE-2.0
9*055d4590SKeyi Gui *
10*055d4590SKeyi Gui * Unless required by applicable law or agreed to in writing, software
11*055d4590SKeyi Gui * distributed under the License is distributed on an "AS IS" BASIS,
12*055d4590SKeyi Gui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*055d4590SKeyi Gui * See the License for the specific language governing permissions and
14*055d4590SKeyi Gui * limitations under the License.
15*055d4590SKeyi Gui */
16*055d4590SKeyi Gui
17*055d4590SKeyi Gui/*
18*055d4590SKeyi Gui * Dalvik instruction fragments, useful when porting mterp.
19*055d4590SKeyi Gui *
20*055d4590SKeyi Gui * Compile this and examine the output to see what your compiler generates.
21*055d4590SKeyi Gui * This can give you a head start on some of the more complicated operations.
22*055d4590SKeyi Gui *
23*055d4590SKeyi Gui * Example:
24*055d4590SKeyi Gui *   % gcc -c -O2 -save-temps -fverbose-asm porting-proto.c
25*055d4590SKeyi Gui *   % less porting-proto.s
26*055d4590SKeyi Gui */
27*055d4590SKeyi Gui#include <stdint.h>
28*055d4590SKeyi Gui
29*055d4590SKeyi Guitypedef int8_t s1;
30*055d4590SKeyi Guitypedef uint8_t u1;
31*055d4590SKeyi Guitypedef int16_t s2;
32*055d4590SKeyi Guitypedef uint16_t u2;
33*055d4590SKeyi Guitypedef int32_t s4;
34*055d4590SKeyi Guitypedef uint32_t u4;
35*055d4590SKeyi Guitypedef int64_t s8;
36*055d4590SKeyi Guitypedef uint64_t u8;
37*055d4590SKeyi Gui
38*055d4590SKeyi Guis4 iadd32(s4 x, s4 y) { return x + y; }
39*055d4590SKeyi Guis8 iadd64(s8 x, s8 y) { return x + y; }
40*055d4590SKeyi Guifloat fadd32(float x, float y) { return x + y; }
41*055d4590SKeyi Guidouble fadd64(double x, double y) { return x + y; }
42*055d4590SKeyi Gui
43*055d4590SKeyi Guis4 isub32(s4 x, s4 y) { return x - y; }
44*055d4590SKeyi Guis8 isub64(s8 x, s8 y) { return x - y; }
45*055d4590SKeyi Guifloat fsub32(float x, float y) { return x - y; }
46*055d4590SKeyi Guidouble fsub64(double x, double y) { return x - y; }
47*055d4590SKeyi Gui
48*055d4590SKeyi Guis4 irsub32lit8(s4 x) { return 25 - x; }
49*055d4590SKeyi Gui
50*055d4590SKeyi Guis4 imul32(s4 x, s4 y) { return x * y; }
51*055d4590SKeyi Guis8 imul64(s8 x, s8 y) { return x * y; }
52*055d4590SKeyi Guifloat fmul32(float x, float y) { return x * y; }
53*055d4590SKeyi Guidouble fmul64(double x, double y) { return x * y; }
54*055d4590SKeyi Gui
55*055d4590SKeyi Guis4 idiv32(s4 x, s4 y) { return x / y; }
56*055d4590SKeyi Guis8 idiv64(s8 x, s8 y) { return x / y; }
57*055d4590SKeyi Guifloat fdiv32(float x, float y) { return x / y; }
58*055d4590SKeyi Guidouble fdiv64(double x, double y) { return x / y; }
59*055d4590SKeyi Gui
60*055d4590SKeyi Guis4 irem32(s4 x, s4 y) { return x % y; }
61*055d4590SKeyi Guis8 irem64(s8 x, s8 y) { return x % y; }
62*055d4590SKeyi Gui
63*055d4590SKeyi Guis4 iand32(s4 x, s4 y) { return x & y; }
64*055d4590SKeyi Guis8 iand64(s8 x, s8 y) { return x & y; }
65*055d4590SKeyi Gui
66*055d4590SKeyi Guis4 ior32(s4 x, s4 y) { return x | y; }
67*055d4590SKeyi Guis8 ior64(s8 x, s8 y) { return x | y; }
68*055d4590SKeyi Gui
69*055d4590SKeyi Guis4 ixor32(s4 x, s4 y) { return x ^ y; }
70*055d4590SKeyi Guis8 ixor64(s8 x, s8 y) { return x ^ y; }
71*055d4590SKeyi Gui
72*055d4590SKeyi Guis4 iasl32(s4 x, s4 count) { return x << (count & 0x1f); }
73*055d4590SKeyi Guis8 iasl64(s8 x, s4 count) { return x << (count & 0x3f); }
74*055d4590SKeyi Gui
75*055d4590SKeyi Guis4 iasr32(s4 x, s4 count) { return x >> (count & 0x1f); }
76*055d4590SKeyi Guis8 iasr64(s8 x, s4 count) { return x >> (count & 0x3f); }
77*055d4590SKeyi Gui
78*055d4590SKeyi Guis4 ilsr32(s4 x, s4 count) { return ((u4)x) >> (count & 0x1f); } // unsigned
79*055d4590SKeyi Guis8 ilsr64(s8 x, s4 count) { return ((u8)x) >> (count & 0x3f); } // unsigned
80*055d4590SKeyi Gui
81*055d4590SKeyi Guis4 ineg32(s4 x) { return -x; }
82*055d4590SKeyi Guis8 ineg64(s8 x) { return -x; }
83*055d4590SKeyi Guifloat fneg32(float x) { return -x; }
84*055d4590SKeyi Guidouble fneg64(double x) { return -x; }
85*055d4590SKeyi Gui
86*055d4590SKeyi Guis4 inot32(s4 x) { return x ^ -1; }
87*055d4590SKeyi Guis8 inot64(s8 x) { return x ^ -1LL; }
88*055d4590SKeyi Gui
89*055d4590SKeyi Guis4 float2int(float x) { return (s4) x; }
90*055d4590SKeyi Guidouble float2double(float x) { return (double) x; }
91*055d4590SKeyi Guis4 double2int(double x) { return (s4) x; }
92*055d4590SKeyi Guifloat double2float(double x) { return (float) x; }
93*055d4590SKeyi Gui
94*055d4590SKeyi Gui/*
95*055d4590SKeyi Gui * ARM lib doesn't clamp large values or NaN the way we want on these two.
96*055d4590SKeyi Gui * If the simple version isn't correct, use the long version.  (You can use
97*055d4590SKeyi Gui * dalvik/tests/041-narrowing to verify.)
98*055d4590SKeyi Gui */
99*055d4590SKeyi Guis8 float2long(float x) { return (s8) x; }
100*055d4590SKeyi Guis8 float2long_clamp(float x)
101*055d4590SKeyi Gui{
102*055d4590SKeyi Gui    static const float kMaxLong = (float)0x7fffffffffffffffULL;
103*055d4590SKeyi Gui    static const float kMinLong = (float)0x8000000000000000ULL;
104*055d4590SKeyi Gui
105*055d4590SKeyi Gui    if (x >= kMaxLong) {
106*055d4590SKeyi Gui        return 0x7fffffffffffffffULL;
107*055d4590SKeyi Gui    } else if (x <= kMinLong) {
108*055d4590SKeyi Gui        return 0x8000000000000000ULL;
109*055d4590SKeyi Gui    } else if (x != x) {
110*055d4590SKeyi Gui        return 0;
111*055d4590SKeyi Gui    } else {
112*055d4590SKeyi Gui        return (s8) x;
113*055d4590SKeyi Gui    }
114*055d4590SKeyi Gui}
115*055d4590SKeyi Guis8 double2long(double x) { return (s8) x; }
116*055d4590SKeyi Guis8 double2long_clamp(double x)
117*055d4590SKeyi Gui{
118*055d4590SKeyi Gui    static const double kMaxLong = (double)0x7fffffffffffffffULL;
119*055d4590SKeyi Gui    static const double kMinLong = (double)0x8000000000000000ULL;
120*055d4590SKeyi Gui
121*055d4590SKeyi Gui    if (x >= kMaxLong) {
122*055d4590SKeyi Gui        return 0x7fffffffffffffffULL;
123*055d4590SKeyi Gui    } else if (x <= kMinLong) {
124*055d4590SKeyi Gui        return 0x8000000000000000ULL;
125*055d4590SKeyi Gui    } else if (x != x) {
126*055d4590SKeyi Gui        return 0;
127*055d4590SKeyi Gui    } else {
128*055d4590SKeyi Gui        return (s8) x;
129*055d4590SKeyi Gui    }
130*055d4590SKeyi Gui}
131*055d4590SKeyi Gui
132*055d4590SKeyi Guis1 int2byte(s4 x) { return (s1) x; }
133*055d4590SKeyi Guis2 int2short(s4 x) { return (s2) x; }
134*055d4590SKeyi Guiu2 int2char(s4 x) { return (u2) x; }
135*055d4590SKeyi Guis8 int2long(s4 x) { return (s8) x; }
136*055d4590SKeyi Guifloat int2float(s4 x) { return (float) x; }
137*055d4590SKeyi Guidouble int2double(s4 x) { return (double) x; }
138*055d4590SKeyi Gui
139*055d4590SKeyi Guis4 long2int(s8 x) { return (s4) x; }
140*055d4590SKeyi Guifloat long2float(s8 x) { return (float) x; }
141*055d4590SKeyi Guidouble long2double(s8 x) { return (double) x; }
142*055d4590SKeyi Gui
143*055d4590SKeyi Guiint cmpl_float(float x, float y)
144*055d4590SKeyi Gui{
145*055d4590SKeyi Gui    int result;
146*055d4590SKeyi Gui
147*055d4590SKeyi Gui    if (x == y)
148*055d4590SKeyi Gui        result = 0;
149*055d4590SKeyi Gui    else if (x > y)
150*055d4590SKeyi Gui        result = 1;
151*055d4590SKeyi Gui    else /* (x < y) or NaN */
152*055d4590SKeyi Gui        result = -1;
153*055d4590SKeyi Gui    return result;
154*055d4590SKeyi Gui}
155*055d4590SKeyi Gui
156*055d4590SKeyi Guiint cmpg_float(float x, float y)
157*055d4590SKeyi Gui{
158*055d4590SKeyi Gui    int result;
159*055d4590SKeyi Gui
160*055d4590SKeyi Gui    if (x == y)
161*055d4590SKeyi Gui        result = 0;
162*055d4590SKeyi Gui    else if (x < y)
163*055d4590SKeyi Gui        result = -1;
164*055d4590SKeyi Gui    else /* (x > y) or NaN */
165*055d4590SKeyi Gui        result = 1;
166*055d4590SKeyi Gui    return result;
167*055d4590SKeyi Gui}
168*055d4590SKeyi Gui
169*055d4590SKeyi Guiint cmpl_double(double x, double y)
170*055d4590SKeyi Gui{
171*055d4590SKeyi Gui    int result;
172*055d4590SKeyi Gui
173*055d4590SKeyi Gui    if (x == y)
174*055d4590SKeyi Gui        result = 0;
175*055d4590SKeyi Gui    else if (x > y)
176*055d4590SKeyi Gui        result = 1;
177*055d4590SKeyi Gui    else /* (x < y) or NaN */
178*055d4590SKeyi Gui        result = -1;
179*055d4590SKeyi Gui    return result;
180*055d4590SKeyi Gui}
181*055d4590SKeyi Gui
182*055d4590SKeyi Guiint cmpg_double(double x, double y)
183*055d4590SKeyi Gui{
184*055d4590SKeyi Gui    int result;
185*055d4590SKeyi Gui
186*055d4590SKeyi Gui    if (x == y)
187*055d4590SKeyi Gui        result = 0;
188*055d4590SKeyi Gui    else if (x < y)
189*055d4590SKeyi Gui        result = -1;
190*055d4590SKeyi Gui    else /* (x > y) or NaN */
191*055d4590SKeyi Gui        result = 1;
192*055d4590SKeyi Gui    return result;
193*055d4590SKeyi Gui}
194*055d4590SKeyi Gui
195*055d4590SKeyi Guiint cmp_long(s8 x, s8 y)
196*055d4590SKeyi Gui{
197*055d4590SKeyi Gui    int result;
198*055d4590SKeyi Gui
199*055d4590SKeyi Gui    if (x == y)
200*055d4590SKeyi Gui        result = 0;
201*055d4590SKeyi Gui    else if (x < y)
202*055d4590SKeyi Gui        result = -1;
203*055d4590SKeyi Gui    else /* (x > y) */
204*055d4590SKeyi Gui        result = 1;
205*055d4590SKeyi Gui    return result;
206*055d4590SKeyi Gui}
207*055d4590SKeyi Gui
208*055d4590SKeyi Gui/* instruction decoding fragments */
209*055d4590SKeyi Guiu1 unsignedAA(u2 x) { return x >> 8; }
210*055d4590SKeyi Guis1 signedAA(u2 x) { return (s4)(x << 16) >> 24; }
211*055d4590SKeyi Guis2 signedBB(u2 x) { return (s2) x; }
212*055d4590SKeyi Guiu1 unsignedA(u2 x) { return (x >> 8) & 0x0f; }
213*055d4590SKeyi Guiu1 unsignedB(u2 x) { return x >> 12; }
214*055d4590SKeyi Gui
215*055d4590SKeyi Gui/* some handy immediate constants when working with float/double */
216*055d4590SKeyi Guiu4 const_43e00000(u4 highword) { return 0x43e00000; }
217*055d4590SKeyi Guiu4 const_c3e00000(u4 highword) { return 0xc3e00000; }
218*055d4590SKeyi Guiu4 const_ffc00000(u4 highword) { return 0xffc00000; }
219*055d4590SKeyi Guiu4 const_41dfffff(u4 highword) { return 0x41dfffff; }
220*055d4590SKeyi Guiu4 const_c1e00000(u4 highword) { return 0xc1e00000; }
221*055d4590SKeyi Gui
222*055d4590SKeyi Gui/*
223*055d4590SKeyi Gui * Test for some gcc-defined symbols.  If you're frequently switching
224*055d4590SKeyi Gui * between different cross-compiler architectures or CPU feature sets,
225*055d4590SKeyi Gui * this can help you keep track of which one you're compiling for.
226*055d4590SKeyi Gui */
227*055d4590SKeyi Gui#ifdef __arm__
228*055d4590SKeyi Gui# warning "found __arm__"
229*055d4590SKeyi Gui#endif
230*055d4590SKeyi Gui#ifdef __ARM_EABI__
231*055d4590SKeyi Gui# warning "found __ARM_EABI__"
232*055d4590SKeyi Gui#endif
233*055d4590SKeyi Gui#ifdef __VFP_FP__
234*055d4590SKeyi Gui# warning "found __VFP_FP__"    /* VFP-format doubles used; may not have VFP */
235*055d4590SKeyi Gui#endif
236*055d4590SKeyi Gui#if defined(__VFP_FP__) && !defined(__SOFTFP__)
237*055d4590SKeyi Gui# warning "VFP in use"
238*055d4590SKeyi Gui#endif
239*055d4590SKeyi Gui#ifdef __ARM_ARCH_5TE__
240*055d4590SKeyi Gui# warning "found __ARM_ARCH_5TE__"
241*055d4590SKeyi Gui#endif
242*055d4590SKeyi Gui#ifdef __ARM_ARCH_7A__
243*055d4590SKeyi Gui# warning "found __ARM_ARCH_7A__"
244*055d4590SKeyi Gui#endif
245