|
|
1.1 ! root 1: /* $Id: sparc-rc-cc.c,v 1.2 2009/08/28 01:41:45 fredette Exp $ */ ! 2: ! 3: /* ic/sparc/sparc-rc-cc.c - SPARC recode condition code support: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2008 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #if TME_SPARC_RECODE_SIZE(ic) == TME_RECODE_SIZE_32 ! 37: ! 38: _TME_RCSID("$Id: sparc-rc-cc.c,v 1.2 2009/08/28 01:41:45 fredette Exp $"); ! 39: ! 40: /* macros: */ ! 41: ! 42: /* this converts sparc64 icc flags into the current architecture's icc ! 43: flags: */ ! 44: #define TME_SPARC_ICC(ccr_icc) \ ! 45: ((ccr_icc) \ ! 46: * (((TME_SPARC_VERSION(ic) < 9) \ ! 47: * (TME_SPARC32_PSR_ICC \ ! 48: / TME_SPARC64_CCR_ICC)) \ ! 49: + (TME_SPARC_VERSION(ic) >= 9))) ! 50: ! 51: #define TME_SPARC_RECODE_CCR_NEED(insn_class, insn_size, size) \ ! 52: ((((insn_class == TME_RECODE_INSN_CLASS_ADDITIVE) \ ! 53: * ((TME_SPARC64_CCR_ICC_C \ ! 54: * (TME_RECODE_FLAG_NEED(insn_class, insn_size, \ ! 55: TME_RECODE_COND_C, size) \ ! 56: != 0)) \ ! 57: + (TME_SPARC64_CCR_ICC_V \ ! 58: * (TME_RECODE_FLAG_NEED(insn_class, insn_size, \ ! 59: TME_RECODE_COND_V, size) \ ! 60: != 0)))) \ ! 61: + (TME_SPARC64_CCR_ICC_Z \ ! 62: * (TME_RECODE_FLAG_NEED(insn_class, insn_size, \ ! 63: TME_RECODE_COND_Z, size) \ ! 64: != 0)) \ ! 65: + (TME_SPARC64_CCR_ICC_N \ ! 66: * (TME_RECODE_FLAG_NEED(insn_class, insn_size, \ ! 67: TME_RECODE_COND_N, size) \ ! 68: != 0))) \ ! 69: * ((TME_SPARC64_CCR_XCC \ ! 70: / TME_SPARC64_CCR_ICC) \ ! 71: * (size > TME_RECODE_SIZE_32))) ! 72: ! 73: /* this macro gives the %icc and %xcc N and Z flags: */ ! 74: #define TME_SPARC_RECODE_CCR_N_Z(dst, ccr_need) \ ! 75: (0 \ ! 76: + ((((tme_uint32_t) (dst)) == 0) \ ! 77: * ((ccr_need) & TME_SPARC64_CCR_ICC_Z)) \ ! 78: + ((((tme_int32_t) (dst)) < 0) \ ! 79: * ((ccr_need) & TME_SPARC64_CCR_ICC_N)) \ ! 80: + ((((tme_sparc_ireg_t) (dst)) == 0) \ ! 81: * ((ccr_need) & TME_SPARC64_CCR_XCC_Z)) \ ! 82: + ((((dst) & TME_SPARC_IREG_MSBIT) != 0) \ ! 83: * ((ccr_need) & TME_SPARC64_CCR_XCC_N))) ! 84: ! 85: /* this macro updates %icc and %xcc: */ ! 86: #define TME_SPARC_RECODE_CCR_UPDATE(ic, ccr, ccr_need) \ ! 87: do { \ ! 88: if (TME_SPARC_VERSION((struct tme_sparc *) (ic)) >= 9) { \ ! 89: ((struct tme_sparc *) (ic))->tme_sparc64_ireg_ccr \ ! 90: = ((((struct tme_sparc *) (ic))->tme_sparc64_ireg_ccr \ ! 91: & ~ccr_need) \ ! 92: | ccr); \ ! 93: } \ ! 94: else { \ ! 95: ((struct tme_sparc *) (ic))->tme_sparc32_ireg_psr \ ! 96: = ((((struct tme_sparc *) (ic))->tme_sparc32_ireg_psr \ ! 97: & ~TME_SPARC_ICC(ccr_need)) \ ! 98: | TME_SPARC_ICC(ccr_need)); \ ! 99: } \ ! 100: } while (/* CONSTCOND */ 0) ! 101: ! 102: /* rename various things by the architecture size: */ ! 103: #define _tme_sparc_flags_additive _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_additive) ! 104: #define _tme_sparc_flags_logical _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_logical) ! 105: #define _tme_sparc_flags_func_logical _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_func_logical) ! 106: #define _tme_sparc_flags_func_add _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_func_add) ! 107: #define _tme_sparc_flags_func_sub _TME_SPARC_RECODE_SIZE(_tme_sparc,_flags_func_sub) ! 108: #define _tme_sparc_recode_conds_func_icc _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_conds_func_icc) ! 109: #define _tme_sparc_recode_cc_init _TME_SPARC_RECODE_SIZE(_tme_sparc,_recode_cc_init) ! 110: ! 111: /* the sparc64 recode xcc conditions function: */ ! 112: static int ! 113: _tme_sparc64_recode_conds_func_xcc(tme_recode_uguest_t flags, tme_uint32_t cond) ! 114: { ! 115: return (_tme_sparc_conds_icc ! 116: [TME_FIELD_MASK_EXTRACTU(flags, TME_SPARC64_CCR_XCC)] ! 117: & (1 << cond)); ! 118: } ! 119: ! 120: #endif /* TME_SPARC_RECODE_SIZE(ic) == TME_RECODE_SIZE_32 */ ! 121: ! 122: /* the additive instruction flags: */ ! 123: static const struct tme_recode_flag _tme_sparc_flags_additive[] = { ! 124: #if TME_SPARC_VERSION(ic) >= 9 ! 125: { ! 126: TME_RECODE_COND_N, ! 127: TME_RECODE_SIZE_64, ! 128: TME_SPARC64_CCR_XCC_N ! 129: }, ! 130: { ! 131: TME_RECODE_COND_Z, ! 132: TME_RECODE_SIZE_64, ! 133: TME_SPARC64_CCR_XCC_Z ! 134: }, ! 135: { ! 136: TME_RECODE_COND_V, ! 137: TME_RECODE_SIZE_64, ! 138: TME_SPARC64_CCR_XCC_V ! 139: }, ! 140: { ! 141: TME_RECODE_COND_C, ! 142: TME_RECODE_SIZE_64, ! 143: TME_SPARC64_CCR_XCC_C ! 144: }, ! 145: #endif /* TME_SPARC_VERSION(ic) >= 9 */ ! 146: { ! 147: TME_RECODE_COND_N, ! 148: TME_RECODE_SIZE_32, ! 149: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_N) ! 150: }, ! 151: { ! 152: TME_RECODE_COND_Z, ! 153: TME_RECODE_SIZE_32, ! 154: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_Z) ! 155: }, ! 156: { ! 157: TME_RECODE_COND_V, ! 158: TME_RECODE_SIZE_32, ! 159: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_V) ! 160: }, ! 161: { ! 162: TME_RECODE_COND_C, ! 163: TME_RECODE_SIZE_32, ! 164: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_C) ! 165: }, ! 166: { ! 167: 0, ! 168: 0, ! 169: 0 ! 170: } ! 171: }; ! 172: ! 173: /* the logical instruction flags: */ ! 174: static const struct tme_recode_flag _tme_sparc_flags_logical[] = { ! 175: #if TME_SPARC_VERSION(ic) >= 9 ! 176: { ! 177: TME_RECODE_COND_N, ! 178: TME_RECODE_SIZE_64, ! 179: TME_SPARC64_CCR_XCC_N ! 180: }, ! 181: { ! 182: TME_RECODE_COND_Z, ! 183: TME_RECODE_SIZE_64, ! 184: TME_SPARC64_CCR_XCC_Z ! 185: }, ! 186: { ! 187: TME_RECODE_COND_FALSE, ! 188: 0, ! 189: TME_SPARC64_CCR_XCC_V ! 190: }, ! 191: { ! 192: TME_RECODE_COND_FALSE, ! 193: 0, ! 194: TME_SPARC64_CCR_XCC_C ! 195: }, ! 196: #endif /* TME_SPARC_VERSION(ic) >= 9 */ ! 197: { ! 198: TME_RECODE_COND_N, ! 199: TME_RECODE_SIZE_32, ! 200: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_N) ! 201: }, ! 202: { ! 203: TME_RECODE_COND_Z, ! 204: TME_RECODE_SIZE_32, ! 205: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_Z) ! 206: }, ! 207: { ! 208: TME_RECODE_COND_FALSE, ! 209: 0, ! 210: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_V) ! 211: }, ! 212: { ! 213: TME_RECODE_COND_FALSE, ! 214: 0, ! 215: TME_SPARC_ICC(TME_SPARC64_CCR_ICC_C) ! 216: }, ! 217: { ! 218: 0, ! 219: 0, ! 220: 0 ! 221: } ! 222: }; ! 223: ! 224: /* the logical instruction flags function: */ ! 225: static void ! 226: _tme_sparc_flags_func_logical(struct tme_ic *ic, ! 227: tme_recode_uguest_t src1, ! 228: tme_recode_uguest_t src2, ! 229: tme_recode_uguest_t dst) ! 230: { ! 231: unsigned int ccr_need; ! 232: ! 233: ccr_need ! 234: = (TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_LOGICAL, ! 235: TME_SPARC_RECODE_SIZE(ic), ! 236: TME_RECODE_SIZE_32) ! 237: | TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_LOGICAL, ! 238: TME_SPARC_RECODE_SIZE(ic), ! 239: TME_SPARC_RECODE_SIZE(ic))); ! 240: ! 241: TME_SPARC_RECODE_CCR_UPDATE(ic, ! 242: TME_SPARC_RECODE_CCR_N_Z(dst, ccr_need), ! 243: ccr_need); ! 244: } ! 245: ! 246: /* the add instruction flags function: */ ! 247: static void ! 248: _tme_sparc_flags_func_add(struct tme_ic *ic, ! 249: tme_recode_uguest_t src1, ! 250: tme_recode_uguest_t src2, ! 251: tme_recode_uguest_t dst) ! 252: { ! 253: unsigned int ccr_need; ! 254: unsigned int ccr; ! 255: ! 256: ccr_need ! 257: = (TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_ADDITIVE, ! 258: TME_SPARC_RECODE_SIZE(ic), ! 259: TME_RECODE_SIZE_32) ! 260: | TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_ADDITIVE, ! 261: TME_SPARC_RECODE_SIZE(ic), ! 262: TME_SPARC_RECODE_SIZE(ic))); ! 263: ! 264: /* make the %icc and %xcc N and Z flags: */ ! 265: ccr = TME_SPARC_RECODE_CCR_N_Z(dst, ccr_need); ! 266: ! 267: /* if src1 and src2 both have bit 31 set, or if dst does not have ! 268: bit 31 set and either src1 or src2 does, set %icc.C: */ ! 269: if (((tme_int32_t) ((src1 & src2) | (~dst & (src1 | src2)))) < 0) { ! 270: ccr += (ccr_need & TME_SPARC64_CCR_ICC_C); ! 271: } ! 272: ! 273: /* if src1 and src2 have the same bit 31, and dst has a different ! 274: bit 31, set %icc.V: */ ! 275: if (((tme_int32_t) ((src2 ^ dst) & (src1 ^ ~src2))) < 0) { ! 276: ccr += (ccr_need & TME_SPARC64_CCR_ICC_V); ! 277: } ! 278: ! 279: /* if src1 and src2 both have the most-significant bit set, or if ! 280: dst does not have the most-significant bit set either src1 or ! 281: src2 does, set %xcc.C: */ ! 282: if (((src1 & src2) | (~dst & (src1 | src2))) & TME_SPARC_IREG_MSBIT) { ! 283: ccr += (ccr_need & TME_SPARC64_CCR_XCC_C); ! 284: } ! 285: ! 286: /* if src1 and src2 have the same most-significant bit, and dst has ! 287: a different most-significant bit, set %xcc.V: */ ! 288: if (((src2 ^ dst) & (src1 ^ ~src2)) & TME_SPARC_IREG_MSBIT) { ! 289: ccr += (ccr_need & TME_SPARC64_CCR_XCC_V); ! 290: } ! 291: ! 292: TME_SPARC_RECODE_CCR_UPDATE(ic, ccr, ccr_need); ! 293: } ! 294: ! 295: /* the sub instruction flags function: */ ! 296: static void ! 297: _tme_sparc_flags_func_sub(struct tme_ic *ic, ! 298: tme_recode_uguest_t src1, ! 299: tme_recode_uguest_t src2, ! 300: tme_recode_uguest_t dst) ! 301: { ! 302: unsigned int ccr_need; ! 303: unsigned int ccr; ! 304: ! 305: ccr_need ! 306: = (TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_ADDITIVE, ! 307: TME_SPARC_RECODE_SIZE(ic), ! 308: TME_RECODE_SIZE_32) ! 309: | TME_SPARC_RECODE_CCR_NEED(TME_RECODE_INSN_CLASS_ADDITIVE, ! 310: TME_SPARC_RECODE_SIZE(ic), ! 311: TME_SPARC_RECODE_SIZE(ic))); ! 312: ! 313: /* make the %icc and %xcc N and Z flags: */ ! 314: ccr = TME_SPARC_RECODE_CCR_N_Z(dst, ccr_need); ! 315: ! 316: /* if src2 is greater than src1 in 32 bits, set %icc.C: */ ! 317: if (((tme_uint32_t) src2) > ((tme_uint32_t) src1)) { ! 318: ccr += (ccr_need & TME_SPARC64_CCR_ICC_C); ! 319: } ! 320: ! 321: /* if src1 and src2 have different bit 31s, and dst has a different ! 322: bit 31 than src1, set %icc.V: */ ! 323: if (((tme_int32_t) ((src1 ^ src2) & (src1 ^ dst))) < 0) { ! 324: ccr += (ccr_need & TME_SPARC64_CCR_ICC_V); ! 325: } ! 326: ! 327: /* if src2 is greater than src1, set %xcc.C: */ ! 328: if (((tme_sparc_ireg_t) src2) > ((tme_sparc_ireg_t) src1)) { ! 329: ccr += (ccr_need & TME_SPARC64_CCR_XCC_C); ! 330: } ! 331: ! 332: /* if src1 and src2 have different most-significant bits, and dst ! 333: has a different most-significant bit than src1, set %xcc.V: */ ! 334: if (((src1 ^ src2) & (src1 ^ dst)) & TME_SPARC_IREG_MSBIT) { ! 335: ccr += (ccr_need & TME_SPARC64_CCR_XCC_V); ! 336: } ! 337: ! 338: TME_SPARC_RECODE_CCR_UPDATE(ic, ccr, ccr_need); ! 339: } ! 340: ! 341: /* the sparc icc conditions function: */ ! 342: static int ! 343: _tme_sparc_recode_conds_func_icc(tme_recode_uguest_t flags, tme_uint32_t cond) ! 344: { ! 345: return (_tme_sparc_conds_icc ! 346: [TME_FIELD_MASK_EXTRACTU(flags, TME_SPARC_ICC(TME_SPARC64_CCR_ICC))] ! 347: & (1 << cond)); ! 348: } ! 349: ! 350: /* this initializes for condition codes: */ ! 351: static void ! 352: _tme_sparc_recode_cc_init(struct tme_sparc *ic) ! 353: { ! 354: struct tme_recode_ic *recode_ic; ! 355: struct tme_recode_flags_group flags_group; ! 356: struct tme_recode_conds_group conds_group; ! 357: ! 358: /* recover the recode ic: */ ! 359: recode_ic = ic->tme_sparc_recode_ic; ! 360: ! 361: /* make the common parts of a flags group: */ ! 362: memset((char *) &flags_group, 0, sizeof(flags_group)); ! 363: flags_group.tme_recode_flags_group_insn_size = TME_SPARC_RECODE_SIZE(ic); ! 364: if (TME_SPARC_VERSION(ic) <= 8) { ! 365: flags_group.tme_recode_flags_group_flags_reg_size = TME_RECODE_SIZE_32; ! 366: flags_group.tme_recode_flags_group_flags_reg = TME_SPARC32_IREG_PSR; ! 367: } ! 368: else { ! 369: flags_group.tme_recode_flags_group_flags_reg_size = TME_RECODE_SIZE_8; ! 370: flags_group.tme_recode_flags_group_flags_reg = TME_SPARC64_IREG_CCR << 3; ! 371: } ! 372: ! 373: /* make the flags thunk for addcc and addxcc: */ ! 374: flags_group.tme_recode_flags_group_insn_class = TME_RECODE_INSN_CLASS_ADDITIVE; ! 375: flags_group.tme_recode_flags_group_flags = _tme_sparc_flags_additive; ! 376: flags_group.tme_recode_flags_group_guest_func = _tme_sparc_flags_func_add; ! 377: ic->tme_sparc_recode_flags_thunk_add ! 378: = tme_recode_flags_thunk(recode_ic, ! 379: &flags_group); ! 380: ! 381: /* make the flags thunk for subcc and subxcc: */ ! 382: flags_group.tme_recode_flags_group_insn_class = TME_RECODE_INSN_CLASS_ADDITIVE; ! 383: flags_group.tme_recode_flags_group_flags = _tme_sparc_flags_additive; ! 384: flags_group.tme_recode_flags_group_guest_func = _tme_sparc_flags_func_sub; ! 385: ic->tme_sparc_recode_flags_thunk_sub ! 386: = tme_recode_flags_thunk(recode_ic, ! 387: &flags_group); ! 388: ! 389: /* make the flags thunk for the logical instructions: */ ! 390: flags_group.tme_recode_flags_group_insn_class = TME_RECODE_INSN_CLASS_LOGICAL; ! 391: flags_group.tme_recode_flags_group_flags = _tme_sparc_flags_logical; ! 392: flags_group.tme_recode_flags_group_guest_func = _tme_sparc_flags_func_logical; ! 393: ic->tme_sparc_recode_flags_thunk_logical ! 394: = tme_recode_flags_thunk(recode_ic, ! 395: &flags_group); ! 396: ! 397: /* make the common parts of a conditions group: */ ! 398: memset((char *) &conds_group, 0, sizeof(conds_group)); ! 399: conds_group.tme_recode_conds_group_flags_reg_size = flags_group.tme_recode_flags_group_flags_reg_size; ! 400: conds_group.tme_recode_conds_group_flags_reg = flags_group.tme_recode_flags_group_flags_reg; ! 401: conds_group.tme_recode_conds_group_cond_count = TME_SPARC_COND_NOT; ! 402: ! 403: /* make the conditions thunk for %icc: */ ! 404: conds_group.tme_recode_conds_group_flags = TME_SPARC_ICC(TME_SPARC64_CCR_ICC); ! 405: conds_group.tme_recode_conds_group_guest_func = _tme_sparc_recode_conds_func_icc; ! 406: ic->tme_sparc_recode_conds_thunk_icc ! 407: = tme_recode_conds_thunk(recode_ic, ! 408: &conds_group); ! 409: ! 410: /* if this is a sparc64: */ ! 411: if (TME_SPARC_VERSION(ic) >= 9) { ! 412: ! 413: /* make the flags thunk for the sparc64 internal "rcc" flags. ! 414: this is identical to the flags thunk for the logical ! 415: instructions, except it uses the internal "rcc" register: */ ! 416: flags_group.tme_recode_flags_group_flags_reg = TME_SPARC64_IREG_RCC << 3; ! 417: ic->tme_sparc_recode_flags_thunk_rcc ! 418: = tme_recode_flags_thunk(recode_ic, ! 419: &flags_group); ! 420: ! 421: /* make the conditions thunk for %xcc: */ ! 422: conds_group.tme_recode_conds_group_flags = TME_SPARC64_CCR_XCC; ! 423: conds_group.tme_recode_conds_group_guest_func = _tme_sparc64_recode_conds_func_xcc; ! 424: ic->tme_sparc_recode_conds_thunk_xcc ! 425: = tme_recode_conds_thunk(recode_ic, ! 426: &conds_group); ! 427: ! 428: /* make the conditions thunk for the internal "rcc" flags. this ! 429: is identical to the conditions thunk for %xcc, except it uses ! 430: the internal "rcc" register: */ ! 431: conds_group.tme_recode_conds_group_flags_reg = flags_group.tme_recode_flags_group_flags_reg; ! 432: ic->tme_sparc_recode_conds_thunk_rcc ! 433: = tme_recode_conds_thunk(recode_ic, ! 434: &conds_group); ! 435: } ! 436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.