1 1.1 christos /* This file is part of the program psim. 2 1.1 christos 3 1.1 christos Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney 4 1.1 christos 5 1.1 christos This program is free software; you can redistribute it and/or modify 6 1.1 christos it under the terms of the GNU General Public License as published by 7 1.1.1.2 christos the Free Software Foundation; either version 3 of the License, or 8 1.1 christos (at your option) any later version. 9 1.1 christos 10 1.1 christos This program is distributed in the hope that it will be useful, 11 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 12 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 1.1 christos GNU General Public License for more details. 14 1.1 christos 15 1.1 christos You should have received a copy of the GNU General Public License 16 1.1.1.2 christos along with this program; if not, see <http://www.gnu.org/licenses/>. 17 1.1 christos 18 1.1 christos */ 19 1.1 christos 20 1.1.1.3 christos #include "ansidecl.h" 21 1.1.1.3 christos 22 1.1 christos /* Additional, and optional expressions. */ 23 1.1 christos #ifdef WITH_ALTIVEC 24 1.1 christos #include "altivec_expression.h" 25 1.1 christos #endif 26 1.1 christos #ifdef WITH_E500 27 1.1 christos #include "e500_expression.h" 28 1.1 christos #endif 29 1.1 christos 30 1.1 christos /* 32bit target expressions: 31 1.1 christos 32 1.1 christos Each calculation is performed three times using each of the 33 1.1.1.3 christos int64_t, uint64_t and long integer types. The macro ALU_END 34 1.1 christos (in _ALU_RESULT_VAL) then selects which of the three alternative 35 1.1 christos results will be used in the final assignment of the target 36 1.1 christos register. As this selection is determined at compile time by 37 1.1 christos fields in the instruction (OE, EA, Rc) the compiler has sufficient 38 1.1 christos information to firstly simplify the selection code into a single 39 1.1 christos case and then back anotate the equations and hence eliminate any 40 1.1 christos resulting dead code. That dead code being the calculations that, 41 1.1 christos as it turned out were not in the end needed. 42 1.1 christos 43 1.1.1.5 christos 64bit arithmetic is used firstly because it allows the use of 44 1.1 christos gcc's efficient long long operators (typically efficiently output 45 1.1 christos inline) and secondly because the resultant answer will contain in 46 1.1 christos the low 32bits the answer while in the high 32bits is either carry 47 1.1 christos or status information. */ 48 1.1 christos 49 1.1 christos /* 64bit target expressions: 50 1.1 christos 51 1.1.1.5 christos Unfortunately 128bit arithmetic isn't that common. Consequently 52 1.1 christos the 32/64 bit trick can not be used. Instead all calculations are 53 1.1 christos required to retain carry/overflow information in separate 54 1.1 christos variables. Even with this restriction it is still possible for the 55 1.1 christos trick of letting the compiler discard the calculation of unneeded 56 1.1 christos values */ 57 1.1 christos 58 1.1 christos 59 1.1 christos /* Macro's to type cast 32bit constants to 64bits */ 60 1.1.1.4 christos #define ALU_SIGNED64(val) ((int64_t)(int32_t)(val)) 61 1.1.1.4 christos #define ALU_UNSIGNED64(val) ((uint64_t)(uint32_t)(val)) 62 1.1 christos 63 1.1 christos 64 1.1 christos /* Start a section of ALU code */ 65 1.1 christos 66 1.1 christos #define ALU_BEGIN(val) \ 67 1.1 christos { \ 68 1.1.1.3 christos signed_word alu_val; \ 69 1.1.1.3 christos uint64_t alu_carry_val; \ 70 1.1.1.3 christos int64_t alu_overflow_val; \ 71 1.1 christos ALU_SET(val) 72 1.1 christos 73 1.1 christos 74 1.1 christos /* assign the result to the target register */ 75 1.1 christos 76 1.1 christos #define ALU_END(TARG,CA,OE,Rc) \ 77 1.1 christos { /* select the result to use */ \ 78 1.1 christos signed_word const alu_result = _ALU_RESULT_VAL(CA,OE,Rc); \ 79 1.1 christos /* determine the overflow bit if needed */ \ 80 1.1 christos if (OE) { \ 81 1.1.1.3 christos if ((((uint64_t)(alu_overflow_val & BIT64(0))) \ 82 1.1 christos >> 32) \ 83 1.1 christos == (alu_overflow_val & BIT64(32))) \ 84 1.1 christos XER &= (~xer_overflow); \ 85 1.1 christos else \ 86 1.1 christos XER |= (xer_summary_overflow | xer_overflow); \ 87 1.1 christos } \ 88 1.1 christos /* Update the carry bit if needed */ \ 89 1.1 christos if (CA) { \ 90 1.1 christos XER = ((XER & ~xer_carry) \ 91 1.1 christos | SHUFFLED32((alu_carry_val >> 32), 31, xer_carry_bit)); \ 92 1.1 christos /* if (alu_carry_val & BIT64(31)) \ 93 1.1 christos XER |= (xer_carry); \ 94 1.1 christos else \ 95 1.1 christos XER &= (~xer_carry); */ \ 96 1.1 christos } \ 97 1.1 christos TRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n", \ 98 1.1 christos (long)alu_result, (long)alu_result, (long)XER)); \ 99 1.1 christos /* Update the Result Conditions if needed */ \ 100 1.1 christos CR0_COMPARE(alu_result, 0, Rc); \ 101 1.1 christos /* assign targ same */ \ 102 1.1 christos TARG = alu_result; \ 103 1.1 christos }} 104 1.1 christos 105 1.1 christos /* select the result from the different options */ 106 1.1 christos 107 1.1 christos #define _ALU_RESULT_VAL(CA,OE,Rc) (WITH_TARGET_WORD_BITSIZE == 64 \ 108 1.1 christos ? alu_val \ 109 1.1 christos : (OE \ 110 1.1 christos ? alu_overflow_val \ 111 1.1 christos : (CA \ 112 1.1 christos ? alu_carry_val \ 113 1.1 christos : alu_val))) 114 1.1 christos 115 1.1 christos 116 1.1 christos /* More basic alu operations */ 117 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 118 1.1 christos #define ALU_SET(val) \ 119 1.1 christos do { \ 120 1.1 christos alu_val = val; \ 121 1.1.1.3 christos alu_carry_val = ((uint64_t)alu_val) >> 32; \ 122 1.1.1.3 christos alu_overflow_val = ((int64_t)alu_val) >> 32; \ 123 1.1 christos } while (0) 124 1.1 christos #endif 125 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 126 1.1 christos #define ALU_SET(val) \ 127 1.1 christos do { \ 128 1.1 christos alu_val = val; \ 129 1.1.1.3 christos alu_carry_val = (uint32_t)(alu_val); \ 130 1.1.1.3 christos alu_overflow_val = (int32_t)(alu_val); \ 131 1.1 christos } while (0) 132 1.1 christos #endif 133 1.1 christos 134 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 135 1.1 christos #define ALU_ADD(val) \ 136 1.1 christos do { \ 137 1.1.1.4 christos uint64_t alu_lo = (ALU_UNSIGNED64(alu_val) \ 138 1.1.1.4 christos + ALU_UNSIGNED64(val)); \ 139 1.1 christos signed alu_carry = ((alu_lo & BIT(31)) != 0); \ 140 1.1 christos alu_carry_val = (alu_carry_val \ 141 1.1.1.4 christos + ALU_UNSIGNED64(EXTRACTED(val, 0, 31)) \ 142 1.1 christos + alu_carry); \ 143 1.1 christos alu_overflow_val = (alu_overflow_val \ 144 1.1.1.4 christos + ALU_SIGNED64(EXTRACTED(val, 0, 31)) \ 145 1.1 christos + alu_carry); \ 146 1.1 christos alu_val = alu_val + val; \ 147 1.1 christos } while (0) 148 1.1 christos #endif 149 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 150 1.1 christos #define ALU_ADD(val) \ 151 1.1 christos do { \ 152 1.1 christos alu_val += val; \ 153 1.1.1.3 christos alu_carry_val += (uint32_t)(val); \ 154 1.1.1.3 christos alu_overflow_val += (int32_t)(val); \ 155 1.1 christos } while (0) 156 1.1 christos #endif 157 1.1 christos 158 1.1 christos 159 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 160 1.1 christos #define ALU_ADD_CA \ 161 1.1 christos do { \ 162 1.1 christos signed carry = MASKED32(XER, xer_carry_bit, xer_carry_bit) != 0; \ 163 1.1 christos ALU_ADD(carry); \ 164 1.1 christos } while (0) 165 1.1 christos #endif 166 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 167 1.1 christos #define ALU_ADD_CA \ 168 1.1 christos do { \ 169 1.1 christos signed carry = MASKED32(XER, xer_carry_bit, xer_carry_bit) != 0; \ 170 1.1 christos ALU_ADD(carry); \ 171 1.1 christos } while (0) 172 1.1 christos #endif 173 1.1 christos 174 1.1 christos 175 1.1 christos #if 0 176 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 177 1.1 christos #endif 178 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 179 1.1 christos #define ALU_SUB(val) \ 180 1.1 christos do { \ 181 1.1 christos alu_val -= val; \ 182 1.1.1.3 christos alu_carry_val -= (uint32_t)(val); \ 183 1.1.1.3 christos alu_overflow_val -= (int32_t)(val); \ 184 1.1 christos } while (0) 185 1.1 christos #endif 186 1.1 christos #endif 187 1.1 christos 188 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 189 1.1 christos #endif 190 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 191 1.1 christos #define ALU_OR(val) \ 192 1.1 christos do { \ 193 1.1 christos alu_val |= val; \ 194 1.1.1.3 christos alu_carry_val = (uint32_t)(alu_val); \ 195 1.1.1.3 christos alu_overflow_val = (int32_t)(alu_val); \ 196 1.1 christos } while (0) 197 1.1 christos #endif 198 1.1 christos 199 1.1 christos 200 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 201 1.1 christos #endif 202 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 203 1.1 christos #define ALU_XOR(val) \ 204 1.1 christos do { \ 205 1.1 christos alu_val ^= val; \ 206 1.1.1.3 christos alu_carry_val = (uint32_t)(alu_val); \ 207 1.1.1.3 christos alu_overflow_val = (int32_t)(alu_val); \ 208 1.1 christos } while (0) 209 1.1 christos #endif 210 1.1 christos 211 1.1 christos 212 1.1 christos #if 0 213 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 214 1.1 christos #endif 215 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 216 1.1 christos #define ALU_NEGATE \ 217 1.1 christos do { \ 218 1.1 christos alu_val = -alu_val; \ 219 1.1 christos alu_carry_val = -alu_carry_val; \ 220 1.1 christos alu_overflow_val = -alu_overflow_val; \ 221 1.1 christos } while(0) 222 1.1 christos #endif 223 1.1 christos #endif 224 1.1 christos 225 1.1 christos 226 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 227 1.1 christos #endif 228 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 229 1.1 christos #define ALU_AND(val) \ 230 1.1 christos do { \ 231 1.1 christos alu_val &= val; \ 232 1.1.1.3 christos alu_carry_val = (uint32_t)(alu_val); \ 233 1.1.1.3 christos alu_overflow_val = (int32_t)(alu_val); \ 234 1.1 christos } while (0) 235 1.1 christos #endif 236 1.1 christos 237 1.1 christos 238 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 64) 239 1.1 christos #define ALU_NOT \ 240 1.1 christos do { \ 241 1.1.1.3 christos int64_t new_alu_val = ~alu_val; \ 242 1.1 christos ALU_SET(new_alu_val); \ 243 1.1 christos } while (0) 244 1.1 christos #endif 245 1.1 christos #if (WITH_TARGET_WORD_BITSIZE == 32) 246 1.1 christos #define ALU_NOT \ 247 1.1 christos do { \ 248 1.1 christos signed new_alu_val = ~alu_val; \ 249 1.1 christos ALU_SET(new_alu_val); \ 250 1.1 christos } while(0) 251 1.1 christos #endif 252 1.1 christos 253 1.1 christos 254 1.1 christos /* Macros for updating the condition register */ 255 1.1 christos 256 1.1 christos #define CR1_UPDATE(Rc) \ 257 1.1 christos do { \ 258 1.1 christos if (Rc) { \ 259 1.1 christos CR_SET(1, EXTRACTED32(FPSCR, fpscr_fx_bit, fpscr_ox_bit)); \ 260 1.1 christos } \ 261 1.1 christos } while (0) 262 1.1 christos 263 1.1 christos 264 1.1 christos #define _DO_CR_COMPARE(LHS, RHS) \ 265 1.1 christos (((LHS) < (RHS)) \ 266 1.1 christos ? cr_i_negative \ 267 1.1 christos : (((LHS) > (RHS)) \ 268 1.1 christos ? cr_i_positive \ 269 1.1 christos : cr_i_zero)) 270 1.1 christos 271 1.1 christos #define CR_SET(REG, VAL) MBLIT32(CR, REG*4, REG*4+3, VAL) 272 1.1 christos #define CR_FIELD(REG) EXTRACTED32(CR, REG*4, REG*4+3) 273 1.1 christos #define CR_SET_XER_SO(REG, VAL) \ 274 1.1 christos do { \ 275 1.1 christos creg new_bits = ((XER & xer_summary_overflow) \ 276 1.1 christos ? (cr_i_summary_overflow | VAL) \ 277 1.1 christos : VAL); \ 278 1.1 christos CR_SET(REG, new_bits); \ 279 1.1 christos } while(0) 280 1.1 christos 281 1.1 christos #define CR_COMPARE(REG, LHS, RHS) \ 282 1.1 christos do { \ 283 1.1 christos creg new_bits = ((XER & xer_summary_overflow) \ 284 1.1 christos ? (cr_i_summary_overflow | _DO_CR_COMPARE(LHS,RHS)) \ 285 1.1 christos : _DO_CR_COMPARE(LHS,RHS)); \ 286 1.1 christos CR_SET(REG, new_bits); \ 287 1.1 christos } while (0) 288 1.1 christos 289 1.1 christos #define CR0_COMPARE(LHS, RHS, Rc) \ 290 1.1 christos do { \ 291 1.1 christos if (Rc) { \ 292 1.1 christos CR_COMPARE(0, LHS, RHS); \ 293 1.1 christos TRACE(trace_alu, \ 294 1.1 christos ("CR=0x%08lx, LHS=%ld, RHS=%ld\n", \ 295 1.1 christos (unsigned long)CR, (long)LHS, (long)RHS)); \ 296 1.1 christos } \ 297 1.1 christos } while (0) 298 1.1 christos 299 1.1 christos 300 1.1 christos 301 1.1 christos /* Bring data in from the cold */ 302 1.1 christos 303 1.1 christos #define MEM(SIGN, EA, NR_BYTES) \ 304 1.1 christos ((SIGN##_##NR_BYTES) vm_data_map_read_##NR_BYTES(cpu_data_map(processor), EA, \ 305 1.1 christos processor, cia)) \ 306 1.1 christos 307 1.1 christos #define STORE(EA, NR_BYTES, VAL) \ 308 1.1 christos do { \ 309 1.1 christos vm_data_map_write_##NR_BYTES(cpu_data_map(processor), EA, VAL, \ 310 1.1 christos processor, cia); \ 311 1.1 christos } while (0) 312 1.1 christos 313 1.1 christos 314 1.1 christos 315 1.1 christos /* some FPSCR update macros. */ 316 1.1 christos 317 1.1 christos #define FPSCR_BEGIN \ 318 1.1 christos { \ 319 1.1.1.3 christos fpscreg old_fpscr ATTRIBUTE_UNUSED = FPSCR 320 1.1 christos 321 1.1 christos #define FPSCR_END(Rc) { \ 322 1.1 christos /* always update VX */ \ 323 1.1 christos if ((FPSCR & fpscr_vx_bits)) \ 324 1.1 christos FPSCR |= fpscr_vx; \ 325 1.1 christos else \ 326 1.1 christos FPSCR &= ~fpscr_vx; \ 327 1.1 christos /* always update FEX */ \ 328 1.1 christos if (((FPSCR & fpscr_vx) && (FPSCR & fpscr_ve)) \ 329 1.1 christos || ((FPSCR & fpscr_ox) && (FPSCR & fpscr_oe)) \ 330 1.1 christos || ((FPSCR & fpscr_ux) && (FPSCR & fpscr_ue)) \ 331 1.1 christos || ((FPSCR & fpscr_zx) && (FPSCR & fpscr_ze)) \ 332 1.1 christos || ((FPSCR & fpscr_xx) && (FPSCR & fpscr_xe))) \ 333 1.1 christos FPSCR |= fpscr_fex; \ 334 1.1 christos else \ 335 1.1 christos FPSCR &= ~fpscr_fex; \ 336 1.1 christos CR1_UPDATE(Rc); \ 337 1.1 christos /* interrupt enabled? */ \ 338 1.1 christos if ((MSR & (msr_floating_point_exception_mode_0 \ 339 1.1 christos | msr_floating_point_exception_mode_1)) \ 340 1.1 christos && (FPSCR & fpscr_fex)) \ 341 1.1 christos program_interrupt(processor, cia, \ 342 1.1 christos floating_point_enabled_program_interrupt); \ 343 1.1 christos }} 344 1.1 christos 345 1.1 christos #define FPSCR_SET(REG, VAL) MBLIT32(FPSCR, REG*4, REG*4+3, VAL) 346 1.1 christos #define FPSCR_FIELD(REG) EXTRACTED32(FPSCR, REG*4, REG*4+3) 347 1.1 christos 348 1.1 christos #define FPSCR_SET_FPCC(VAL) MBLIT32(FPSCR, fpscr_fpcc_bit, fpscr_fpcc_bit+3, VAL) 349 1.1 christos 350 1.1 christos /* Handle various exceptions */ 351 1.1 christos 352 1.1 christos #define FPSCR_OR_VX(VAL) \ 353 1.1 christos do { \ 354 1.1 christos /* NOTE: VAL != 0 */ \ 355 1.1 christos FPSCR |= (VAL); \ 356 1.1 christos FPSCR |= fpscr_fx; \ 357 1.1 christos } while (0) 358 1.1 christos 359 1.1 christos #define FPSCR_SET_OX(COND) \ 360 1.1 christos do { \ 361 1.1 christos if (COND) { \ 362 1.1 christos FPSCR |= fpscr_ox; \ 363 1.1 christos FPSCR |= fpscr_fx; \ 364 1.1 christos } \ 365 1.1 christos else \ 366 1.1 christos FPSCR &= ~fpscr_ox; \ 367 1.1 christos } while (0) 368 1.1 christos 369 1.1 christos #define FPSCR_SET_UX(COND) \ 370 1.1 christos do { \ 371 1.1 christos if (COND) { \ 372 1.1 christos FPSCR |= fpscr_ux; \ 373 1.1 christos FPSCR |= fpscr_fx; \ 374 1.1 christos } \ 375 1.1 christos else \ 376 1.1 christos FPSCR &= ~fpscr_ux; \ 377 1.1 christos } while (0) 378 1.1 christos 379 1.1 christos #define FPSCR_SET_ZX(COND) \ 380 1.1 christos do { \ 381 1.1 christos if (COND) { \ 382 1.1 christos FPSCR |= fpscr_zx; \ 383 1.1 christos FPSCR |= fpscr_fx; \ 384 1.1 christos } \ 385 1.1 christos else \ 386 1.1 christos FPSCR &= ~fpscr_zx; \ 387 1.1 christos } while (0) 388 1.1 christos 389 1.1 christos #define FPSCR_SET_XX(COND) \ 390 1.1 christos do { \ 391 1.1 christos if (COND) { \ 392 1.1 christos FPSCR |= fpscr_xx; \ 393 1.1 christos FPSCR |= fpscr_fx; \ 394 1.1 christos } \ 395 1.1 christos } while (0) 396 1.1 christos 397 1.1 christos /* Note: code using SET_FI must also explicitly call SET_XX */ 398 1.1 christos 399 1.1 christos #define FPSCR_SET_FR(COND) do { \ 400 1.1 christos if (COND) \ 401 1.1 christos FPSCR |= fpscr_fr; \ 402 1.1 christos else \ 403 1.1 christos FPSCR &= ~fpscr_fr; \ 404 1.1 christos } while (0) 405 1.1 christos 406 1.1 christos #define FPSCR_SET_FI(COND) \ 407 1.1 christos do { \ 408 1.1 christos if (COND) { \ 409 1.1 christos FPSCR |= fpscr_fi; \ 410 1.1 christos } \ 411 1.1 christos else \ 412 1.1 christos FPSCR &= ~fpscr_fi; \ 413 1.1 christos } while (0) 414 1.1 christos 415 1.1 christos #define FPSCR_SET_FPRF(VAL) \ 416 1.1 christos do { \ 417 1.1 christos FPSCR = (FPSCR & ~fpscr_fprf) | (VAL); \ 418 1.1 christos } while (0) 419