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