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