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