qemu/target/i386/cc_helper_template.h
<<
>>
Prefs
   1/*
   2 *  x86 condition code 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, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#define DATA_BITS (1 << (3 + SHIFT))
  21
  22#if DATA_BITS == 8
  23#define SUFFIX b
  24#define DATA_TYPE uint8_t
  25#elif DATA_BITS == 16
  26#define SUFFIX w
  27#define DATA_TYPE uint16_t
  28#elif DATA_BITS == 32
  29#define SUFFIX l
  30#define DATA_TYPE uint32_t
  31#elif DATA_BITS == 64
  32#define SUFFIX q
  33#define DATA_TYPE uint64_t
  34#else
  35#error unhandled operand size
  36#endif
  37
  38#define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1))
  39
  40/* dynamic flags computation */
  41
  42static int glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
  43{
  44    int cf, pf, af, zf, sf, of;
  45    DATA_TYPE src2 = dst - src1;
  46
  47    cf = dst < src1;
  48    pf = parity_table[(uint8_t)dst];
  49    af = (dst ^ src1 ^ src2) & CC_A;
  50    zf = (dst == 0) * CC_Z;
  51    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
  52    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
  53    return cf | pf | af | zf | sf | of;
  54}
  55
  56static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
  57{
  58    return dst < src1;
  59}
  60
  61static int glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
  62                                         DATA_TYPE src3)
  63{
  64    int cf, pf, af, zf, sf, of;
  65    DATA_TYPE src2 = dst - src1 - src3;
  66
  67    cf = (src3 ? dst <= src1 : dst < src1);
  68    pf = parity_table[(uint8_t)dst];
  69    af = (dst ^ src1 ^ src2) & 0x10;
  70    zf = (dst == 0) << 6;
  71    sf = lshift(dst, 8 - DATA_BITS) & 0x80;
  72    of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
  73    return cf | pf | af | zf | sf | of;
  74}
  75
  76static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1,
  77                                       DATA_TYPE src3)
  78{
  79    return src3 ? dst <= src1 : dst < src1;
  80}
  81
  82static int glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
  83{
  84    int cf, pf, af, zf, sf, of;
  85    DATA_TYPE src1 = dst + src2;
  86
  87    cf = src1 < src2;
  88    pf = parity_table[(uint8_t)dst];
  89    af = (dst ^ src1 ^ src2) & CC_A;
  90    zf = (dst == 0) * CC_Z;
  91    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
  92    of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
  93    return cf | pf | af | zf | sf | of;
  94}
  95
  96static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2)
  97{
  98    DATA_TYPE src1 = dst + src2;
  99
 100    return src1 < src2;
 101}
 102
 103static int glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
 104                                         DATA_TYPE src3)
 105{
 106    int cf, pf, af, zf, sf, of;
 107    DATA_TYPE src1 = dst + src2 + src3;
 108
 109    cf = (src3 ? src1 <= src2 : src1 < src2);
 110    pf = parity_table[(uint8_t)dst];
 111    af = (dst ^ src1 ^ src2) & 0x10;
 112    zf = (dst == 0) << 6;
 113    sf = lshift(dst, 8 - DATA_BITS) & 0x80;
 114    of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
 115    return cf | pf | af | zf | sf | of;
 116}
 117
 118static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2,
 119                                       DATA_TYPE src3)
 120{
 121    DATA_TYPE src1 = dst + src2 + src3;
 122
 123    return (src3 ? src1 <= src2 : src1 < src2);
 124}
 125
 126static int glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
 127{
 128    int cf, pf, af, zf, sf, of;
 129
 130    cf = 0;
 131    pf = parity_table[(uint8_t)dst];
 132    af = 0;
 133    zf = (dst == 0) * CC_Z;
 134    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
 135    of = 0;
 136    return cf | pf | af | zf | sf | of;
 137}
 138
 139static int glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
 140{
 141    int cf, pf, af, zf, sf, of;
 142    DATA_TYPE src2;
 143
 144    cf = src1;
 145    src1 = dst - 1;
 146    src2 = 1;
 147    pf = parity_table[(uint8_t)dst];
 148    af = (dst ^ src1 ^ src2) & CC_A;
 149    zf = (dst == 0) * CC_Z;
 150    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
 151    of = (dst == SIGN_MASK) * CC_O;
 152    return cf | pf | af | zf | sf | of;
 153}
 154
 155static int glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
 156{
 157    int cf, pf, af, zf, sf, of;
 158    DATA_TYPE src2;
 159
 160    cf = src1;
 161    src1 = dst + 1;
 162    src2 = 1;
 163    pf = parity_table[(uint8_t)dst];
 164    af = (dst ^ src1 ^ src2) & CC_A;
 165    zf = (dst == 0) * CC_Z;
 166    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
 167    of = (dst == SIGN_MASK - 1) * CC_O;
 168    return cf | pf | af | zf | sf | of;
 169}
 170
 171static int glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
 172{
 173    int cf, pf, af, zf, sf, of;
 174
 175    cf = (src1 >> (DATA_BITS - 1)) & CC_C;
 176    pf = parity_table[(uint8_t)dst];
 177    af = 0; /* undefined */
 178    zf = (dst == 0) * CC_Z;
 179    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
 180    /* of is defined iff shift count == 1 */
 181    of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
 182    return cf | pf | af | zf | sf | of;
 183}
 184
 185static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
 186{
 187    return (src1 >> (DATA_BITS - 1)) & CC_C;
 188}
 189
 190static int glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
 191{
 192    int cf, pf, af, zf, sf, of;
 193
 194    cf = src1 & 1;
 195    pf = parity_table[(uint8_t)dst];
 196    af = 0; /* undefined */
 197    zf = (dst == 0) * CC_Z;
 198    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
 199    /* of is defined iff shift count == 1 */
 200    of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
 201    return cf | pf | af | zf | sf | of;
 202}
 203
 204/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
 205   CF are modified and it is slower to do that.  Note as well that we
 206   don't truncate SRC1 for computing carry to DATA_TYPE.  */
 207static int glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1)
 208{
 209    int cf, pf, af, zf, sf, of;
 210
 211    cf = (src1 != 0);
 212    pf = parity_table[(uint8_t)dst];
 213    af = 0; /* undefined */
 214    zf = (dst == 0) * CC_Z;
 215    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
 216    of = cf * CC_O;
 217    return cf | pf | af | zf | sf | of;
 218}
 219
 220static int glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
 221{
 222    int cf, pf, af, zf, sf, of;
 223
 224    cf = (src1 == 0);
 225    pf = 0; /* undefined */
 226    af = 0; /* undefined */
 227    zf = (dst == 0) * CC_Z;
 228    sf = lshift(dst, 8 - DATA_BITS) & CC_S;
 229    of = 0;
 230    return cf | pf | af | zf | sf | of;
 231}
 232
 233static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1)
 234{
 235    return src1 == 0;
 236}
 237
 238#undef DATA_BITS
 239#undef SIGN_MASK
 240#undef DATA_TYPE
 241#undef DATA_MASK
 242#undef SUFFIX
 243