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