idecode_expression.h revision 1.1.1.4 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 christos 64bit arrithemetic 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 christos Unfortunatly 128bit arrithemetic 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