Define SIGNED64 and UNSIGNED64 macros - handle MSC/GCC LL issue.
[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   error("ALU_SUB64"); \
190 } while (0)
191
192 #define ALU_SUB(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB)(VAL)
193
194
195
196
197 #define ALU16_SUB_CA \
198 do { \
199   signed carry = ALU_CARRY; \
200   ALU16_SUB(carry); \
201 } while (0)
202
203 #define ALU32_SUB_CA \
204 do { \
205   signed carry = ALU_CARRY; \
206   ALU32_SUB(carry); \
207 } while (0)
208
209 #define ALU64_SUB_CA \
210 do { \
211   signed carry = ALU_CARRY; \
212   ALU64_SUB(carry); \
213 } while (0)
214
215 #define ALU_SUB_CA XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB_CA)
216
217
218
219
220 #define ALU16_OR(VAL) \
221 do { \
222   error("ALU16_OR"); \
223 } while (0)
224
225 #define ALU32_OR(VAL) \
226 do { \
227   alu_val |= (VAL); \
228   alu_carry_val = (unsigned32)(alu_val); \
229   alu_overflow_val = (signed32)(alu_val); \
230 } while (0)
231
232 #define ALU64_OR(VAL) \
233 do { \
234   error("ALU_OR64"); \
235 } while (0)
236
237 #define ALU_OR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OR)(VAL)
238
239
240
241
242 #define ALU16_XOR(VAL) \
243 do { \
244   error("ALU16_XOR"); \
245 } while (0)
246
247 #define ALU32_XOR(VAL) \
248 do { \
249   alu_val ^= (VAL); \
250   alu_carry_val = (unsigned32)(alu_val); \
251   alu_overflow_val = (signed32)(alu_val); \
252 } while (0)
253
254 #define ALU64_XOR(VAL) \
255 do { \
256   error("ALU_XOR64"); \
257 } while (0)
258
259 #define ALU_XOR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_XOR)(VAL)
260
261
262
263
264 #define ALU16_NEGATE \
265 do { \
266   error("ALU_NEGATE16"); \
267 } while (0)
268
269 #define ALU32_NEGATE \
270 do { \
271   alu_val = -alu_val; \
272   alu_carry_val = -alu_carry_val; \
273   alu_overflow_val = -alu_overflow_val; \
274 } while(0)
275
276 #define ALU64_NEGATE \
277 do { \
278   error("ALU_NEGATE64"); \
279 } while (0)
280
281 #define ALU_NEGATE XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGATE)
282
283
284
285
286 #define ALU16_AND(VAL) \
287 do { \
288   error("ALU_AND16"); \
289 } while (0)
290
291 #define ALU32_AND(VAL) \
292 do { \
293   alu_val &= (VAL); \
294   alu_carry_val = (unsigned32)(alu_val); \
295   alu_overflow_val = (signed32)(alu_val); \
296 } while (0)
297
298 #define ALU64_AND(VAL) \
299 do { \
300   error("ALU_AND64"); \
301 } while (0)
302
303 #define ALU_AND(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_AND)(VAL)
304
305
306
307
308 #define ALU16_NOT(VAL) \
309 do { \
310   error("ALU_NOT16"); \
311 } while (0)
312
313 #define ALU32_NOT \
314 do { \
315   signed64 new_alu_val = ~alu_val; \
316   ALU_SET(new_alu_val); \
317 } while (0)
318
319 #define ALU64_NOT \
320 do { \
321   error("ALU_NOT64"); \
322 } while (0)
323
324 #define ALU_NOT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NOT)
325
326
327
328 /* Make available various results */
329
330
331 /* overflow occures if the sign bit differs from the carry bit */
332
333 #define ALU16_HAD_OVERFLOW \
334   (!(alu_overflow_val & MSBIT32 (0)) != !(alu_overflow_val & MSBIT32 (16)))
335   
336 #define ALU32_HAD_OVERFLOW \
337   ((((unsigned64)(alu_overflow_val & BIT64(0))) >> 32) \
338    != (alu_overflow_val & MSBIT64(32)))
339
340 #define ALU_HAD_OVERFLOW XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_OVERFLOW)
341
342 /* carry found in bit before sign */
343
344 #define ALU16_HAD_CARRY \
345     (alu_carry_val & MSBIT32(16))
346
347 #define ALU32_HAD_CARRY \
348     (alu_carry_val & MSBIT64(31))
349
350
351 #endif