symbian-qemu-0.9.1-12/qemu-symbian-svp/target-i386/helper_template.h
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  *  i386 helpers
       
     3  *
       
     4  *  Copyright (c) 2008 Fabrice Bellard
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Lesser General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * Lesser General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Lesser General Public
       
    17  * License along with this library; if not, write to the Free Software
       
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    19  */
       
    20 #define DATA_BITS (1 << (3 + SHIFT))
       
    21 #define SHIFT_MASK (DATA_BITS - 1)
       
    22 #define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1))
       
    23 #if DATA_BITS <= 32
       
    24 #define SHIFT1_MASK 0x1f
       
    25 #else
       
    26 #define SHIFT1_MASK 0x3f
       
    27 #endif
       
    28 
       
    29 #if DATA_BITS == 8
       
    30 #define SUFFIX b
       
    31 #define DATA_TYPE uint8_t
       
    32 #define DATA_STYPE int8_t
       
    33 #define DATA_MASK 0xff
       
    34 #elif DATA_BITS == 16
       
    35 #define SUFFIX w
       
    36 #define DATA_TYPE uint16_t
       
    37 #define DATA_STYPE int16_t
       
    38 #define DATA_MASK 0xffff
       
    39 #elif DATA_BITS == 32
       
    40 #define SUFFIX l
       
    41 #define DATA_TYPE uint32_t
       
    42 #define DATA_STYPE int32_t
       
    43 #define DATA_MASK 0xffffffff
       
    44 #elif DATA_BITS == 64
       
    45 #define SUFFIX q
       
    46 #define DATA_TYPE uint64_t
       
    47 #define DATA_STYPE int64_t
       
    48 #define DATA_MASK 0xffffffffffffffffULL
       
    49 #else
       
    50 #error unhandled operand size
       
    51 #endif
       
    52 
       
    53 /* dynamic flags computation */
       
    54 
       
    55 static int glue(compute_all_add, SUFFIX)(void)
       
    56 {
       
    57     int cf, pf, af, zf, sf, of;
       
    58     target_long src1, src2;
       
    59     src1 = CC_SRC;
       
    60     src2 = CC_DST - CC_SRC;
       
    61     cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
       
    62     pf = parity_table[(uint8_t)CC_DST];
       
    63     af = (CC_DST ^ src1 ^ src2) & 0x10;
       
    64     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
    65     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
    66     of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
       
    67     return cf | pf | af | zf | sf | of;
       
    68 }
       
    69 
       
    70 static int glue(compute_c_add, SUFFIX)(void)
       
    71 {
       
    72     int cf;
       
    73     target_long src1;
       
    74     src1 = CC_SRC;
       
    75     cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
       
    76     return cf;
       
    77 }
       
    78 
       
    79 static int glue(compute_all_adc, SUFFIX)(void)
       
    80 {
       
    81     int cf, pf, af, zf, sf, of;
       
    82     target_long src1, src2;
       
    83     src1 = CC_SRC;
       
    84     src2 = CC_DST - CC_SRC - 1;
       
    85     cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
       
    86     pf = parity_table[(uint8_t)CC_DST];
       
    87     af = (CC_DST ^ src1 ^ src2) & 0x10;
       
    88     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
    89     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
    90     of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
       
    91     return cf | pf | af | zf | sf | of;
       
    92 }
       
    93 
       
    94 static int glue(compute_c_adc, SUFFIX)(void)
       
    95 {
       
    96     int cf;
       
    97     target_long src1;
       
    98     src1 = CC_SRC;
       
    99     cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
       
   100     return cf;
       
   101 }
       
   102 
       
   103 static int glue(compute_all_sub, SUFFIX)(void)
       
   104 {
       
   105     int cf, pf, af, zf, sf, of;
       
   106     target_long src1, src2;
       
   107     src1 = CC_DST + CC_SRC;
       
   108     src2 = CC_SRC;
       
   109     cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
       
   110     pf = parity_table[(uint8_t)CC_DST];
       
   111     af = (CC_DST ^ src1 ^ src2) & 0x10;
       
   112     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
   113     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
   114     of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
       
   115     return cf | pf | af | zf | sf | of;
       
   116 }
       
   117 
       
   118 static int glue(compute_c_sub, SUFFIX)(void)
       
   119 {
       
   120     int cf;
       
   121     target_long src1, src2;
       
   122     src1 = CC_DST + CC_SRC;
       
   123     src2 = CC_SRC;
       
   124     cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
       
   125     return cf;
       
   126 }
       
   127 
       
   128 static int glue(compute_all_sbb, SUFFIX)(void)
       
   129 {
       
   130     int cf, pf, af, zf, sf, of;
       
   131     target_long src1, src2;
       
   132     src1 = CC_DST + CC_SRC + 1;
       
   133     src2 = CC_SRC;
       
   134     cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
       
   135     pf = parity_table[(uint8_t)CC_DST];
       
   136     af = (CC_DST ^ src1 ^ src2) & 0x10;
       
   137     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
   138     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
   139     of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
       
   140     return cf | pf | af | zf | sf | of;
       
   141 }
       
   142 
       
   143 static int glue(compute_c_sbb, SUFFIX)(void)
       
   144 {
       
   145     int cf;
       
   146     target_long src1, src2;
       
   147     src1 = CC_DST + CC_SRC + 1;
       
   148     src2 = CC_SRC;
       
   149     cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
       
   150     return cf;
       
   151 }
       
   152 
       
   153 static int glue(compute_all_logic, SUFFIX)(void)
       
   154 {
       
   155     int cf, pf, af, zf, sf, of;
       
   156     cf = 0;
       
   157     pf = parity_table[(uint8_t)CC_DST];
       
   158     af = 0;
       
   159     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
   160     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
   161     of = 0;
       
   162     return cf | pf | af | zf | sf | of;
       
   163 }
       
   164 
       
   165 static int glue(compute_c_logic, SUFFIX)(void)
       
   166 {
       
   167     return 0;
       
   168 }
       
   169 
       
   170 static int glue(compute_all_inc, SUFFIX)(void)
       
   171 {
       
   172     int cf, pf, af, zf, sf, of;
       
   173     target_long src1, src2;
       
   174     src1 = CC_DST - 1;
       
   175     src2 = 1;
       
   176     cf = CC_SRC;
       
   177     pf = parity_table[(uint8_t)CC_DST];
       
   178     af = (CC_DST ^ src1 ^ src2) & 0x10;
       
   179     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
   180     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
   181     of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
       
   182     return cf | pf | af | zf | sf | of;
       
   183 }
       
   184 
       
   185 #if DATA_BITS == 32
       
   186 static int glue(compute_c_inc, SUFFIX)(void)
       
   187 {
       
   188     return CC_SRC;
       
   189 }
       
   190 #endif
       
   191 
       
   192 static int glue(compute_all_dec, SUFFIX)(void)
       
   193 {
       
   194     int cf, pf, af, zf, sf, of;
       
   195     target_long src1, src2;
       
   196     src1 = CC_DST + 1;
       
   197     src2 = 1;
       
   198     cf = CC_SRC;
       
   199     pf = parity_table[(uint8_t)CC_DST];
       
   200     af = (CC_DST ^ src1 ^ src2) & 0x10;
       
   201     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
   202     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
   203     of = ((CC_DST & DATA_MASK) == ((target_ulong)SIGN_MASK - 1)) << 11;
       
   204     return cf | pf | af | zf | sf | of;
       
   205 }
       
   206 
       
   207 static int glue(compute_all_shl, SUFFIX)(void)
       
   208 {
       
   209     int cf, pf, af, zf, sf, of;
       
   210     cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
       
   211     pf = parity_table[(uint8_t)CC_DST];
       
   212     af = 0; /* undefined */
       
   213     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
   214     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
   215     /* of is defined if shift count == 1 */
       
   216     of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
       
   217     return cf | pf | af | zf | sf | of;
       
   218 }
       
   219 
       
   220 static int glue(compute_c_shl, SUFFIX)(void)
       
   221 {
       
   222     return (CC_SRC >> (DATA_BITS - 1)) & CC_C;
       
   223 }
       
   224 
       
   225 #if DATA_BITS == 32
       
   226 static int glue(compute_c_sar, SUFFIX)(void)
       
   227 {
       
   228     return CC_SRC & 1;
       
   229 }
       
   230 #endif
       
   231 
       
   232 static int glue(compute_all_sar, SUFFIX)(void)
       
   233 {
       
   234     int cf, pf, af, zf, sf, of;
       
   235     cf = CC_SRC & 1;
       
   236     pf = parity_table[(uint8_t)CC_DST];
       
   237     af = 0; /* undefined */
       
   238     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
   239     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
   240     /* of is defined if shift count == 1 */
       
   241     of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
       
   242     return cf | pf | af | zf | sf | of;
       
   243 }
       
   244 
       
   245 #if DATA_BITS == 32
       
   246 static int glue(compute_c_mul, SUFFIX)(void)
       
   247 {
       
   248     int cf;
       
   249     cf = (CC_SRC != 0);
       
   250     return cf;
       
   251 }
       
   252 #endif
       
   253 
       
   254 /* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
       
   255    CF are modified and it is slower to do that. */
       
   256 static int glue(compute_all_mul, SUFFIX)(void)
       
   257 {
       
   258     int cf, pf, af, zf, sf, of;
       
   259     cf = (CC_SRC != 0);
       
   260     pf = parity_table[(uint8_t)CC_DST];
       
   261     af = 0; /* undefined */
       
   262     zf = ((DATA_TYPE)CC_DST == 0) << 6;
       
   263     sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
       
   264     of = cf << 11;
       
   265     return cf | pf | af | zf | sf | of;
       
   266 }
       
   267 
       
   268 /* shifts */
       
   269 
       
   270 target_ulong glue(helper_rcl, SUFFIX)(target_ulong t0, target_ulong t1)
       
   271 {
       
   272     int count, eflags;
       
   273     target_ulong src;
       
   274     target_long res;
       
   275 
       
   276     count = t1 & SHIFT1_MASK;
       
   277 #if DATA_BITS == 16
       
   278     count = rclw_table[count];
       
   279 #elif DATA_BITS == 8
       
   280     count = rclb_table[count];
       
   281 #endif
       
   282     if (count) {
       
   283         eflags = helper_cc_compute_all(CC_OP);
       
   284         t0 &= DATA_MASK;
       
   285         src = t0;
       
   286         res = (t0 << count) | ((target_ulong)(eflags & CC_C) << (count - 1));
       
   287         if (count > 1)
       
   288             res |= t0 >> (DATA_BITS + 1 - count);
       
   289         t0 = res;
       
   290         env->cc_tmp = (eflags & ~(CC_C | CC_O)) |
       
   291             (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
       
   292             ((src >> (DATA_BITS - count)) & CC_C);
       
   293     } else {
       
   294         env->cc_tmp = -1;
       
   295     }
       
   296     return t0;
       
   297 }
       
   298 
       
   299 target_ulong glue(helper_rcr, SUFFIX)(target_ulong t0, target_ulong t1)
       
   300 {
       
   301     int count, eflags;
       
   302     target_ulong src;
       
   303     target_long res;
       
   304 
       
   305     count = t1 & SHIFT1_MASK;
       
   306 #if DATA_BITS == 16
       
   307     count = rclw_table[count];
       
   308 #elif DATA_BITS == 8
       
   309     count = rclb_table[count];
       
   310 #endif
       
   311     if (count) {
       
   312         eflags = helper_cc_compute_all(CC_OP);
       
   313         t0 &= DATA_MASK;
       
   314         src = t0;
       
   315         res = (t0 >> count) | ((target_ulong)(eflags & CC_C) << (DATA_BITS - count));
       
   316         if (count > 1)
       
   317             res |= t0 << (DATA_BITS + 1 - count);
       
   318         t0 = res;
       
   319         env->cc_tmp = (eflags & ~(CC_C | CC_O)) |
       
   320             (lshift(src ^ t0, 11 - (DATA_BITS - 1)) & CC_O) |
       
   321             ((src >> (count - 1)) & CC_C);
       
   322     } else {
       
   323         env->cc_tmp = -1;
       
   324     }
       
   325     return t0;
       
   326 }
       
   327 
       
   328 #undef DATA_BITS
       
   329 #undef SHIFT_MASK
       
   330 #undef SHIFT1_MASK
       
   331 #undef SIGN_MASK
       
   332 #undef DATA_TYPE
       
   333 #undef DATA_STYPE
       
   334 #undef DATA_MASK
       
   335 #undef SUFFIX