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