* sim-alu.h (ALU64_HAD_OVERFLOW): Define.
[external/binutils.git] / sim / common / sim-alu.h
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4     Copyright (C) 1997, Free Software Foundation, Inc.
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15  
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  
20     */
21
22
23 #ifndef _SIM_ALU_H_
24 #define _SIM_ALU_H_
25
26 #include "sim-xcat.h"
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
48
49 /* 16bit target expressions:
50
51    These are a simplified version of the 32bit target expressions */
52
53
54
55 /* 64bit target expressions:
56
57    Unfortunatly 128bit arrithemetic isn't that common.  Consequently
58    the 32/64 bit trick can not be used.  Instead all calculations are
59    required to retain carry/overflow information in separate
60    variables.  Even with this restriction it is still possible for the
61    trick of letting the compiler discard the calculation of unneeded
62    values */
63
64
65 /* Start a section of ALU code */
66
67 #define ALU16_BEGIN(VAL) \
68 { \
69   signed_word alu_carry_val; \
70   unsigned_word alu_overflow_val; \
71   ALU16_SET(VAL)
72
73 #define ALU32_BEGIN(VAL) \
74 { \
75   natural_word alu_val; \
76   unsigned64 alu_carry_val; \
77   signed64 alu_overflow_val; \
78   ALU32_SET(VAL)
79
80 #define ALU64_BEGIN(VAL) \
81 { \
82   natural64 alu_val; \
83   unsigned64 alu_carry_val; \
84   signed64 alu_overflow_val; \
85   ALU64_SET(VAL)
86
87
88 #define ALU_BEGIN(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_BEGIN)(VAL)
89
90 /* More basic alu operations */
91
92
93
94 #define ALU16_SET(VAL) \
95 do { \
96   alu_carry_val = (unsigned16)(VAL); \
97   alu_overflow_val = (signed16)(VAL); \
98 } while (0)
99
100 #define ALU32_SET(VAL) \
101 do { \
102   alu_val = (unsigned32)(VAL); \
103   alu_carry_val = (unsigned32)(alu_val); \
104   alu_overflow_val = (signed32)(alu_val); \
105 } while (0)
106
107 #define ALU64_SET(VAL) \
108 do { \
109   alu_val = (VAL); \
110   alu_carry_val = ((unsigned64)alu_val) >> 32; \
111   alu_overflow_val = ((signed64)alu_val) >> 32; \
112 } while (0)
113
114 #define ALU_SET(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET)(VAL)
115
116
117
118
119 #define ALU16_ADD(VAL) \
120 do { \
121   alu_carry_val += (unsigned16)(VAL); \
122   alu_overflow_val += (signed16)(VAL); \
123 } while (0)
124
125 #define ALU32_ADD(VAL) \
126 do { \
127   alu_val += (VAL); \
128   alu_carry_val += (unsigned32)(VAL); \
129   alu_overflow_val += (signed32)(VAL); \
130 } while (0)
131
132 #define ALU64_ADD(VAL) \
133 do { \
134   unsigned64 val = (VAL); \
135   unsigned64 alu_lo = alu_val + val; \
136   signed alu_carry = ((alu_lo & LSBIT64 (31)) != 0); \
137   alu_carry_val = (alu_carry_val \
138                    + MSEXTRACTED64 (val, 0, 31) \
139                    + alu_carry); \
140   alu_overflow_val = (alu_overflow_val \
141                       + MSEXTRACTED64 (val, 0, 31) \
142                       + alu_carry); \
143   alu_val = alu_val + val; \
144 } while (0)
145
146 #define ALU_ADD(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD)(VAL)
147
148
149
150
151 #define ALU16_ADD_CA \
152 do { \
153   signed carry = ALU_CARRY; \
154   ALU16_ADD(carry); \
155 } while (0)
156
157 #define ALU32_ADD_CA \
158 do { \
159   signed carry = ALU_CARRY; \
160   ALU32_ADD(carry); \
161 } while (0)
162
163 #define ALU64_ADD_CA \
164 do { \
165   signed carry = ALU_CARRY; \
166   ALU64_ADD(carry); \
167 } while (0)
168
169 #define ALU_ADD_CA XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD_CA)
170
171
172
173
174 #define ALU16_SUB(VAL) \
175 do { \
176   alu_carry_val -= (unsigned16)(VAL); \
177   alu_overflow_val -= (signed16)(VAL); \
178 } while (0)
179
180 #define ALU32_SUB(VAL) \
181 do { \
182   alu_val -= (VAL); \
183   alu_carry_val -= (unsigned32)(VAL); \
184   alu_overflow_val -= (signed32)(VAL); \
185 } while (0)
186
187 #define ALU64_SUB(VAL) \
188 do { \
189   signed64 subval = -(VAL); /* -MININT? */ \
190   ALU64_ADD (subval); \
191 } while (0)
192
193 #define ALU_SUB(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB)(VAL)
194
195
196
197
198 #define ALU16_SUB_CA \
199 do { \
200   signed carry = ALU_CARRY; \
201   ALU16_SUB(carry); \
202 } while (0)
203
204 #define ALU32_SUB_CA \
205 do { \
206   signed carry = ALU_CARRY; \
207   ALU32_SUB(carry); \
208 } while (0)
209
210 #define ALU64_SUB_CA \
211 do { \
212   signed carry = ALU_CARRY; \
213   ALU64_SUB(carry); \
214 } while (0)
215
216 #define ALU_SUB_CA XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB_CA)
217
218
219
220
221 #define ALU16_OR(VAL) \
222 do { \
223   error("ALU16_OR"); \
224 } while (0)
225
226 #define ALU32_OR(VAL) \
227 do { \
228   alu_val |= (VAL); \
229   alu_carry_val = (unsigned32)(alu_val); \
230   alu_overflow_val = (signed32)(alu_val); \
231 } while (0)
232
233 #define ALU64_OR(VAL) \
234 do { \
235   error("ALU_OR64"); \
236 } while (0)
237
238 #define ALU_OR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OR)(VAL)
239
240
241
242
243 #define ALU16_XOR(VAL) \
244 do { \
245   error("ALU16_XOR"); \
246 } while (0)
247
248 #define ALU32_XOR(VAL) \
249 do { \
250   alu_val ^= (VAL); \
251   alu_carry_val = (unsigned32)(alu_val); \
252   alu_overflow_val = (signed32)(alu_val); \
253 } while (0)
254
255 #define ALU64_XOR(VAL) \
256 do { \
257   error("ALU_XOR64"); \
258 } while (0)
259
260 #define ALU_XOR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_XOR)(VAL)
261
262
263
264
265 #define ALU16_NEGATE \
266 do { \
267   error("ALU_NEGATE16"); \
268 } while (0)
269
270 #define ALU32_NEGATE \
271 do { \
272   alu_val = -alu_val; \
273   alu_carry_val = -alu_carry_val; \
274   alu_overflow_val = -alu_overflow_val; \
275 } while(0)
276
277 #define ALU64_NEGATE \
278 do { \
279   error("ALU_NEGATE64"); \
280 } while (0)
281
282 #define ALU_NEGATE XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGATE)
283
284
285
286
287 #define ALU16_AND(VAL) \
288 do { \
289   error("ALU_AND16"); \
290 } while (0)
291
292 #define ALU32_AND(VAL) \
293 do { \
294   alu_val &= (VAL); \
295   alu_carry_val = (unsigned32)(alu_val); \
296   alu_overflow_val = (signed32)(alu_val); \
297 } while (0)
298
299 #define ALU64_AND(VAL) \
300 do { \
301   error("ALU_AND64"); \
302 } while (0)
303
304 #define ALU_AND(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_AND)(VAL)
305
306
307
308
309 #define ALU16_NOT(VAL) \
310 do { \
311   error("ALU_NOT16"); \
312 } while (0)
313
314 #define ALU32_NOT \
315 do { \
316   signed64 new_alu_val = ~alu_val; \
317   ALU_SET(new_alu_val); \
318 } while (0)
319
320 #define ALU64_NOT \
321 do { \
322   error("ALU_NOT64"); \
323 } while (0)
324
325 #define ALU_NOT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NOT)
326
327
328
329 /* Make available various results */
330
331
332 /* overflow occures if the sign bit differs from the carry bit */
333
334 #define ALU16_HAD_OVERFLOW \
335   (!(alu_overflow_val & MSBIT32 (0)) != !(alu_overflow_val & MSBIT32 (16)))
336   
337 #define ALU32_HAD_OVERFLOW \
338   ((((unsigned64)(alu_overflow_val & MSBIT64(0))) >> 32) \
339    != (unsigned64)(alu_overflow_val & MSBIT64(32)))
340
341 #define ALU64_HAD_OVERFLOW \
342   ((alu_val & MSBIT64 (0)) != (alu_overflow_val & MSBIT64 (0)))
343
344 #define ALU_HAD_OVERFLOW XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_OVERFLOW)
345
346
347 /* carry found in bit before sign */
348
349 #define ALU16_HAD_CARRY \
350     (alu_carry_val & MSBIT32(16))
351
352 #define ALU32_HAD_CARRY \
353     (alu_carry_val & MSBIT64(31))
354
355
356 #endif