Home | History | Annotate | Line # | Download | only in ppc
      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  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  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.6  christos #include "ansidecl.h"
     21  1.6  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.6  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.8  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.8  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.7  christos #define ALU_SIGNED64(val)   ((int64_t)(int32_t)(val))
     61  1.7  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.6  christos   signed_word alu_val; \
     69  1.6  christos   uint64_t alu_carry_val; \
     70  1.6  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.6  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.6  christos   alu_carry_val = ((uint64_t)alu_val) >> 32; \
    122  1.6  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.6  christos   alu_carry_val = (uint32_t)(alu_val); \
    130  1.6  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.7  christos   uint64_t alu_lo = (ALU_UNSIGNED64(alu_val) \
    138  1.7  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.7  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.7  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.6  christos   alu_carry_val += (uint32_t)(val); \
    154  1.6  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.6  christos   alu_carry_val -= (uint32_t)(val); \
    183  1.6  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.6  christos   alu_carry_val = (uint32_t)(alu_val); \
    195  1.6  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.6  christos   alu_carry_val = (uint32_t)(alu_val); \
    207  1.6  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.6  christos   alu_carry_val = (uint32_t)(alu_val); \
    233  1.6  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.6  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.6  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