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