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