Home | History | Annotate | Download | only in target-i386
      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., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 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)(CPUX86State *env)
     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)(CPUX86State *env)
     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)(CPUX86State *env)
     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)(CPUX86State *env)
     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)(CPUX86State *env)
    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)(CPUX86State *env)
    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)(CPUX86State *env)
    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)(CPUX86State *env)
    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)(CPUX86State *env)
    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)(CPUX86State *env)
    166 {
    167     return 0;
    168 }
    169 
    170 static int glue(compute_all_inc, SUFFIX)(CPUX86State *env)
    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)(CPUX86State *env)
    187 {
    188     return CC_SRC;
    189 }
    190 #endif
    191 
    192 static int glue(compute_all_dec, SUFFIX)(CPUX86State *env)
    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)(CPUX86State *env)
    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)(CPUX86State *env)
    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)(CPUX86State *env)
    227 {
    228     return CC_SRC & 1;
    229 }
    230 #endif
    231 
    232 static int glue(compute_all_sar, SUFFIX)(CPUX86State *env)
    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)(CPUX86State *env)
    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)(CPUX86State *env)
    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 #undef DATA_BITS
    269 #undef SHIFT_MASK
    270 #undef SHIFT1_MASK
    271 #undef SIGN_MASK
    272 #undef DATA_TYPE
    273 #undef DATA_STYPE
    274 #undef DATA_MASK
    275 #undef SUFFIX
    276