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    uint32_t ret;
 204
 205    ret = get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
 206    return ret;
 207}
 208#endif
 209
 210static uint32_t compute_all_addx(CPUSPARCState *env)
 211{
 212    uint32_t ret;
 213
 214    ret = get_NZ_icc(CC_DST);
 215    ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
 216    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
 217    return ret;
 218}
 219
 220static uint32_t compute_C_addx(CPUSPARCState *env)
 221{
 222    uint32_t ret;
 223
 224    ret = get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
 225    return ret;
 226}
 227
 228static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
 229{
 230    uint32_t ret = 0;
 231
 232    if ((src1 | src2) & 0x3) {
 233        ret = PSR_OVF;
 234    }
 235    return ret;
 236}
 237
 238static uint32_t compute_all_tadd(CPUSPARCState *env)
 239{
 240    uint32_t ret;
 241
 242    ret = get_NZ_icc(CC_DST);
 243    ret |= get_C_add_icc(CC_DST, CC_SRC);
 244    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
 245    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
 246    return ret;
 247}
 248
 249static uint32_t compute_all_taddtv(CPUSPARCState *env)
 250{
 251    uint32_t ret;
 252
 253    ret = get_NZ_icc(CC_DST);
 254    ret |= get_C_add_icc(CC_DST, CC_SRC);
 255    return ret;
 256}
 257
 258static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
 259{
 260    uint32_t ret = 0;
 261
 262    if (src1 < src2) {
 263        ret = PSR_CARRY;
 264    }
 265    return ret;
 266}
 267
 268static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
 269                                      uint32_t src2)
 270{
 271    uint32_t ret = 0;
 272
 273    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
 274        ret = PSR_CARRY;
 275    }
 276    return ret;
 277}
 278
 279static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
 280                                     uint32_t src2)
 281{
 282    uint32_t ret = 0;
 283
 284    if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
 285        ret = PSR_OVF;
 286    }
 287    return ret;
 288}
 289
 290
 291#ifdef TARGET_SPARC64
 292static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
 293{
 294    uint32_t ret = 0;
 295
 296    if (src1 < src2) {
 297        ret = PSR_CARRY;
 298    }
 299    return ret;
 300}
 301
 302static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
 303                                      target_ulong src2)
 304{
 305    uint32_t ret = 0;
 306
 307    if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
 308        ret = PSR_CARRY;
 309    }
 310    return ret;
 311}
 312
 313static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
 314                                     target_ulong src2)
 315{
 316    uint32_t ret = 0;
 317
 318    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
 319        ret = PSR_OVF;
 320    }
 321    return ret;
 322}
 323
 324static uint32_t compute_all_sub_xcc(CPUSPARCState *env)
 325{
 326    uint32_t ret;
 327
 328    ret = get_NZ_xcc(CC_DST);
 329    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
 330    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
 331    return ret;
 332}
 333
 334static uint32_t compute_C_sub_xcc(CPUSPARCState *env)
 335{
 336    return get_C_sub_xcc(CC_SRC, CC_SRC2);
 337}
 338#endif
 339
 340static uint32_t compute_all_sub(CPUSPARCState *env)
 341{
 342    uint32_t ret;
 343
 344    ret = get_NZ_icc(CC_DST);
 345    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
 346    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 347    return ret;
 348}
 349
 350static uint32_t compute_C_sub(CPUSPARCState *env)
 351{
 352    return get_C_sub_icc(CC_SRC, CC_SRC2);
 353}
 354
 355#ifdef TARGET_SPARC64
 356static uint32_t compute_all_subx_xcc(CPUSPARCState *env)
 357{
 358    uint32_t ret;
 359
 360    ret = get_NZ_xcc(CC_DST);
 361    ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
 362    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
 363    return ret;
 364}
 365
 366static uint32_t compute_C_subx_xcc(CPUSPARCState *env)
 367{
 368    uint32_t ret;
 369
 370    ret = get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
 371    return ret;
 372}
 373#endif
 374
 375static uint32_t compute_all_subx(CPUSPARCState *env)
 376{
 377    uint32_t ret;
 378
 379    ret = get_NZ_icc(CC_DST);
 380    ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
 381    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 382    return ret;
 383}
 384
 385static uint32_t compute_C_subx(CPUSPARCState *env)
 386{
 387    uint32_t ret;
 388
 389    ret = get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
 390    return ret;
 391}
 392
 393static uint32_t compute_all_tsub(CPUSPARCState *env)
 394{
 395    uint32_t ret;
 396
 397    ret = get_NZ_icc(CC_DST);
 398    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
 399    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 400    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
 401    return ret;
 402}
 403
 404static uint32_t compute_all_tsubtv(CPUSPARCState *env)
 405{
 406    uint32_t ret;
 407
 408    ret = get_NZ_icc(CC_DST);
 409    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
 410    return ret;
 411}
 412
 413static uint32_t compute_all_logic(CPUSPARCState *env)
 414{
 415    return get_NZ_icc(CC_DST);
 416}
 417
 418static uint32_t compute_C_logic(CPUSPARCState *env)
 419{
 420    return 0;
 421}
 422
 423#ifdef TARGET_SPARC64
 424static uint32_t compute_all_logic_xcc(CPUSPARCState *env)
 425{
 426    return get_NZ_xcc(CC_DST);
 427}
 428#endif
 429
 430typedef struct CCTable {
 431    uint32_t (*compute_all)(CPUSPARCState *env); /* return all the flags */
 432    uint32_t (*compute_c)(CPUSPARCState *env);  /* return the C flag */
 433} CCTable;
 434
 435static const CCTable icc_table[CC_OP_NB] = {
 436    /* CC_OP_DYNAMIC should never happen */
 437    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
 438    [CC_OP_DIV] = { compute_all_div, compute_C_div },
 439    [CC_OP_ADD] = { compute_all_add, compute_C_add },
 440    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
 441    [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
 442    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
 443    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
 444    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
 445    [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
 446    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
 447    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
 448};
 449
 450#ifdef TARGET_SPARC64
 451static const CCTable xcc_table[CC_OP_NB] = {
 452    /* CC_OP_DYNAMIC should never happen */
 453    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
 454    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
 455    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
 456    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
 457    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
 458    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
 459    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
 460    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
 461    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
 462    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
 463    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
 464};
 465#endif
 466
 467void helper_compute_psr(CPUSPARCState *env)
 468{
 469    uint32_t new_psr;
 470
 471    new_psr = icc_table[CC_OP].compute_all(env);
 472    env->psr = new_psr;
 473#ifdef TARGET_SPARC64
 474    new_psr = xcc_table[CC_OP].compute_all(env);
 475    env->xcc = new_psr;
 476#endif
 477    CC_OP = CC_OP_FLAGS;
 478}
 479
 480uint32_t helper_compute_C_icc(CPUSPARCState *env)
 481{
 482    uint32_t ret;
 483
 484    ret = icc_table[CC_OP].compute_c(env) >> PSR_CARRY_SHIFT;
 485    return ret;
 486}
 487