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