qemu/target/sparc/cc_helper.c
<<
>>
Prefs
   1/*
   2 * Helpers for lazy condition code handling
   3 *
   4 *  Copyright (c) 2003-2005 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#include "qemu/osdep.h"
  21#include "cpu.h"
  22#include "exec/helper-proto.h"
  23
  24static uint32_t compute_all_flags(CPUSPARCState *env)
  25{
  26    return env->psr & PSR_ICC;
  27}
  28
  29static uint32_t compute_C_flags(CPUSPARCState *env)
  30{
  31    return env->psr & PSR_CARRY;
  32}
  33
  34static inline uint32_t get_NZ_icc(int32_t dst)
  35{
  36    uint32_t ret = 0;
  37
  38    if (dst == 0) {
  39        ret = PSR_ZERO;
  40    } else if (dst < 0) {
  41        ret = PSR_NEG;
  42    }
  43    return ret;
  44}
  45
  46#ifdef TARGET_SPARC64
  47static uint32_t compute_all_flags_xcc(CPUSPARCState *env)
  48{
  49    return env->xcc & PSR_ICC;
  50}
  51
  52static uint32_t compute_C_flags_xcc(CPUSPARCState *env)
  53{
  54    return env->xcc & PSR_CARRY;
  55}
  56
  57static inline uint32_t get_NZ_xcc(target_long dst)
  58{
  59    uint32_t ret = 0;
  60
  61    if (!dst) {
  62        ret = PSR_ZERO;
  63    } else if (dst < 0) {
  64        ret = PSR_NEG;
  65    }
  66    return ret;
  67}
  68#endif
  69
  70static inline uint32_t get_V_div_icc(target_ulong src2)
  71{
  72    uint32_t ret = 0;
  73
  74    if (src2 != 0) {
  75        ret = PSR_OVF;
  76    }
  77    return ret;
  78}
  79
  80static uint32_t compute_all_div(CPUSPARCState *env)
  81{
  82    uint32_t ret;
  83
  84    ret = get_NZ_icc(CC_DST);
  85    ret |= get_V_div_icc(CC_SRC2);
  86    return ret;
  87}
  88
  89static uint32_t compute_C_div(CPUSPARCState *env)
  90{
  91    return 0;
  92}
  93
  94static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
  95{
  96    uint32_t ret = 0;
  97
  98    if (dst < src1) {
  99        ret = PSR_CARRY;
 100    }
 101    return ret;
 102}
 103
 104static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
 105                                      uint32_t src2)
 106{
 107    uint32_t ret = 0;
 108
 109    if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
 110        ret = PSR_CARRY;
 111    }
 112    return ret;
 113}
 114
 115static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
 116                                     uint32_t src2)
 117{
 118    uint32_t ret = 0;
 119
 120    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
 121        ret = PSR_OVF;
 122    }
 123    return ret;
 124}
 125
 126#ifdef TARGET_SPARC64
 127static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
 128{
 129    uint32_t ret = 0;
 130
 131    if (dst < src1) {
 132        ret = PSR_CARRY;
 133    }
 134    return ret;
 135}
 136
 137static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
 138                                      target_ulong src2)
 139{
 140    uint32_t ret = 0;
 141
 142    if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
 143        ret = PSR_CARRY;
 144    }
 145    return ret;
 146}
 147
 148static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
 149                                     target_ulong src2)
 150{
 151    uint32_t ret = 0;
 152
 153    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
 154        ret = PSR_OVF;
 155    }
 156    return ret;
 157}
 158
 159static uint32_t compute_all_add_xcc(CPUSPARCState *env)
 160{
 161    uint32_t ret;
 162
 163    ret = get_NZ_xcc(CC_DST);
 164    ret |= get_C_add_xcc(CC_DST, CC_SRC);
 165    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
 166    return ret;
 167}
 168
 169static uint32_t compute_C_add_xcc(CPUSPARCState *env)
 170{
 171    return get_C_add_xcc(CC_DST, CC_SRC);
 172}
 173#endif
 174
 175static uint32_t compute_all_add(CPUSPARCState *env)
 176{
 177    uint32_t ret;
 178
 179    ret = get_NZ_icc(CC_DST);
 180    ret |= get_C_add_icc(CC_DST, CC_SRC);
 181    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
 182    return ret;
 183}
 184
 185static uint32_t compute_C_add(CPUSPARCState *env)
 186{
 187    return get_C_add_icc(CC_DST, CC_SRC);
 188}
 189
 190#ifdef TARGET_SPARC64
 191static uint32_t compute_all_addx_xcc(CPUSPARCState *env)
 192{
 193    uint32_t ret;
 194
 195    ret = get_NZ_xcc(CC_DST);
 196    ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
 197    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
 198    return ret;
 199}
 200
 201static uint32_t compute_C_addx_xcc(CPUSPARCState *env)
 202{
 203    return get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
 204}
 205#endif
 206
 207static uint32_t compute_all_addx(CPUSPARCState *env)
 208{
 209    uint32_t ret;
 210
 211    ret = get_NZ_icc(CC_DST);
 212    ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
 213    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
 214    return ret;
 215}
 216
 217static uint32_t compute_C_addx(CPUSPARCState *env)
 218{
 219    return get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
 220}
 221
 222static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
 223{
 224    uint32_t ret = 0;
 225
 226    if ((src1 | src2) & 0x3) {
 227        ret = PSR_OVF;
 228    }
 229    return ret;
 230}
 231
 232static uint32_t compute_all_tadd(CPUSPARCState *env)
 233{
 234    uint32_t ret;
 235
 236    ret = get_NZ_icc(CC_DST);
 237    ret |= get_C_add_icc(CC_DST, CC_SRC);
 238    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
 239    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
 240    return ret;
 241}
 242
 243static uint32_t compute_all_taddtv(CPUSPARCState *env)
 244{
 245    uint32_t ret;
 246
 247    ret = get_NZ_icc(CC_DST);
 248    ret |= get_C_add_icc(CC_DST, CC_SRC);
 249    return ret;
 250}
 251
 252static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
 253{
 254    uint32_t ret = 0;
 255
 256    if (src1 < src2) {
 257        ret = PSR_CARRY;
 258    }
 259    return ret;
 260}
 261
 262static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
 263                                      uint32_t src2)
 264{
 265    uint32_t ret = 0;
 266
 267    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
 268        ret = PSR_CARRY;
 269    }
 270    return ret;
 271}
 272
 273static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
 274                                     uint32_t src2)
 275{
 276    uint32_t ret = 0;
 277
 278    if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
 279        ret = PSR_OVF;
 280    }
 281    return ret;
 282}
 283
 284
 285#ifdef TARGET_SPARC64
 286static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
 287{
 288    uint32_t ret = 0;
 289
 290    if (src1 < src2) {
 291        ret = PSR_CARRY;
 292    }
 293    return ret;
 294}
 295
 296static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
 297                                      target_ulong src2)
 298{
 299    uint32_t ret = 0;
 300
 301    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
 302        ret = PSR_CARRY;
 303    }
 304    return ret;
 305}
 306
 307static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
 308                                     target_ulong src2)
 309{
 310    uint32_t ret = 0;
 311
 312    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
 313        ret = PSR_OVF;
 314    }
 315    return ret;
 316}
 317
 318static uint32_t compute_all_sub_xcc(CPUSPARCState *env)
 319{
 320    uint32_t ret;
 321
 322    ret = get_NZ_xcc(CC_DST);
 323    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
 324    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
 325    return ret;
 326}
 327
 328static uint32_t compute_C_sub_xcc(CPUSPARCState *env)
 329{
 330    return get_C_sub_xcc(CC_SRC, CC_SRC2);
 331}
 332#endif
 333
 334static uint32_t compute_all_sub(CPUSPARCState *env)
 335{
 336    uint32_t ret;
 337
 338    ret = get_NZ_icc(CC_DST);
 339    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
 340    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 341    return ret;
 342}
 343
 344static uint32_t compute_C_sub(CPUSPARCState *env)
 345{
 346    return get_C_sub_icc(CC_SRC, CC_SRC2);
 347}
 348
 349#ifdef TARGET_SPARC64
 350static uint32_t compute_all_subx_xcc(CPUSPARCState *env)
 351{
 352    uint32_t ret;
 353
 354    ret = get_NZ_xcc(CC_DST);
 355    ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
 356    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
 357    return ret;
 358}
 359
 360static uint32_t compute_C_subx_xcc(CPUSPARCState *env)
 361{
 362    return get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
 363}
 364#endif
 365
 366static uint32_t compute_all_subx(CPUSPARCState *env)
 367{
 368    uint32_t ret;
 369
 370    ret = get_NZ_icc(CC_DST);
 371    ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
 372    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 373    return ret;
 374}
 375
 376static uint32_t compute_C_subx(CPUSPARCState *env)
 377{
 378    return get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
 379}
 380
 381static uint32_t compute_all_tsub(CPUSPARCState *env)
 382{
 383    uint32_t ret;
 384
 385    ret = get_NZ_icc(CC_DST);
 386    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
 387    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 388    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
 389    return ret;
 390}
 391
 392static uint32_t compute_all_tsubtv(CPUSPARCState *env)
 393{
 394    uint32_t ret;
 395
 396    ret = get_NZ_icc(CC_DST);
 397    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
 398    return ret;
 399}
 400
 401static uint32_t compute_all_logic(CPUSPARCState *env)
 402{
 403    return get_NZ_icc(CC_DST);
 404}
 405
 406static uint32_t compute_C_logic(CPUSPARCState *env)
 407{
 408    return 0;
 409}
 410
 411#ifdef TARGET_SPARC64
 412static uint32_t compute_all_logic_xcc(CPUSPARCState *env)
 413{
 414    return get_NZ_xcc(CC_DST);
 415}
 416#endif
 417
 418typedef struct CCTable {
 419    uint32_t (*compute_all)(CPUSPARCState *env); /* return all the flags */
 420    uint32_t (*compute_c)(CPUSPARCState *env);  /* return the C flag */
 421} CCTable;
 422
 423static const CCTable icc_table[CC_OP_NB] = {
 424    /* CC_OP_DYNAMIC should never happen */
 425    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
 426    [CC_OP_DIV] = { compute_all_div, compute_C_div },
 427    [CC_OP_ADD] = { compute_all_add, compute_C_add },
 428    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
 429    [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
 430    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
 431    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
 432    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
 433    [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
 434    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
 435    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
 436};
 437
 438#ifdef TARGET_SPARC64
 439static const CCTable xcc_table[CC_OP_NB] = {
 440    /* CC_OP_DYNAMIC should never happen */
 441    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
 442    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
 443    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
 444    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
 445    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
 446    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
 447    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
 448    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
 449    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
 450    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
 451    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
 452};
 453#endif
 454
 455void helper_compute_psr(CPUSPARCState *env)
 456{
 457    uint32_t new_psr;
 458
 459    new_psr = icc_table[CC_OP].compute_all(env);
 460    env->psr = new_psr;
 461#ifdef TARGET_SPARC64
 462    new_psr = xcc_table[CC_OP].compute_all(env);
 463    env->xcc = new_psr;
 464#endif
 465    CC_OP = CC_OP_FLAGS;
 466}
 467
 468uint32_t helper_compute_C_icc(CPUSPARCState *env)
 469{
 470    return icc_table[CC_OP].compute_c(env) >> PSR_CARRY_SHIFT;
 471}
 472