Add MSBIT* and LSBIT* macro's to sim-bits.h
[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 /* Macro's to type cast 32bit constants to 64bits */
66 #define SIGNED64(val)   ((signed64)(signed32)(val))
67 #define UNSIGNED64(val) ((unsigned64)(unsigned32)(val))
68
69
70 /* Start a section of ALU code */
71
72 #define ALU16_BEGIN(VAL) \
73 { \
74   signed_word alu_carry_val; \
75   unsigned_word alu_overflow_val; \
76   ALU16_SET(VAL)
77
78 #define ALU32_BEGIN(VAL) \
79 { \
80   natural_word alu_val; \
81   unsigned64 alu_carry_val; \
82   signed64 alu_overflow_val; \
83   ALU32_SET(VAL)
84
85 #define ALU_BEGIN(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_BEGIN)(VAL)
86
87 /* More basic alu operations */
88
89
90
91 #define ALU16_SET(VAL) \
92 do { \
93   alu_carry_val = (unsigned16)(VAL); \
94   alu_overflow_val = (signed16)(VAL); \
95 } while (0)
96
97 #define ALU32_SET(VAL) \
98 do { \
99   alu_val = (unsigned32)(VAL); \
100   alu_carry_val = (unsigned32)(alu_val); \
101   alu_overflow_val = (signed32)(alu_val); \
102 } while (0)
103
104 #define ALU64_SET(VAL) \
105 do { \
106   alu_val = (VAL); \
107   alu_carry_val = ((unsigned64)alu_val) >> 32; \
108   alu_overflow_val = ((signed64)alu_val) >> 32; \
109 } while (0)
110
111 #define ALU_SET(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET)(VAL)
112
113
114
115
116 #define ALU16_ADD(VAL) \
117 do { \
118   alu_carry_val += (unsigned16)(VAL); \
119   alu_overflow_val += (signed16)(VAL); \
120 } while (0)
121
122 #define ALU32_ADD(VAL) \
123 do { \
124   alu_val += (VAL); \
125   alu_carry_val += (unsigned32)(VAL); \
126   alu_overflow_val += (signed32)(VAL); \
127 } while (0)
128
129 #define ALU64_ADD(VAL) \
130 do { \
131   unsigned64 alu_lo = (UNSIGNED64(alu_val) \
132                        + UNSIGNED64(VAL)); \
133   signed alu_carry = ((alu_lo & BIT(31)) != 0); \
134   alu_carry_val = (alu_carry_val \
135                    + UNSIGNED64(EXTRACTED(val, 0, 31)) \
136                    + alu_carry); \
137   alu_overflow_val = (alu_overflow_val \
138                       + SIGNED64(EXTRACTED(val, 0, 31)) \
139                       + alu_carry); \
140   alu_val = alu_val + val; \
141 } while (0)
142
143 #define ALU_ADD(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD)(VAL)
144
145
146
147
148 #define ALU16_ADD_CA \
149 do { \
150   signed carry = ALU_CARRY; \
151   ALU16_ADD(carry); \
152 } while (0)
153
154 #define ALU32_ADD_CA \
155 do { \
156   signed carry = ALU_CARRY; \
157   ALU32_ADD(carry); \
158 } while (0)
159
160 #define ALU64_ADD_CA \
161 do { \
162   signed carry = ALU_CARRY; \
163   ALU64_ADD(carry); \
164 } while (0)
165
166 #define ALU_ADD_CA XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD_CA)
167
168
169
170
171 #define ALU16_SUB(VAL) \
172 do { \
173   alu_carry_val -= (unsigned16)(VAL); \
174   alu_overflow_val -= (signed16)(VAL); \
175 } while (0)
176
177 #define ALU32_SUB(VAL) \
178 do { \
179   alu_val -= (VAL); \
180   alu_carry_val -= (unsigned32)(VAL); \
181   alu_overflow_val -= (signed32)(VAL); \
182 } while (0)
183
184 #define ALU64_SUB(VAL) \
185 do { \
186   error("ALU_SUB64"); \
187 } while (0)
188
189 #define ALU_SUB(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB)(VAL)
190
191
192
193
194 #define ALU16_SUB_CA \
195 do { \
196   signed carry = ALU_CARRY; \
197   ALU16_SUB(carry); \
198 } while (0)
199
200 #define ALU32_SUB_CA \
201 do { \
202   signed carry = ALU_CARRY; \
203   ALU32_SUB(carry); \
204 } while (0)
205
206 #define ALU64_SUB_CA \
207 do { \
208   signed carry = ALU_CARRY; \
209   ALU64_SUB(carry); \
210 } while (0)
211
212 #define ALU_SUB_CA XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB_CA)
213
214
215
216
217 #define ALU16_OR(VAL) \
218 do { \
219   error("ALU16_OR"); \
220 } while (0)
221
222 #define ALU32_OR(VAL) \
223 do { \
224   alu_val |= (VAL); \
225   alu_carry_val = (unsigned32)(alu_val); \
226   alu_overflow_val = (signed32)(alu_val); \
227 } while (0)
228
229 #define ALU64_OR(VAL) \
230 do { \
231   error("ALU_OR64"); \
232 } while (0)
233
234 #define ALU_OR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OR)(VAL)
235
236
237
238
239 #define ALU16_XOR(VAL) \
240 do { \
241   error("ALU16_XOR"); \
242 } while (0)
243
244 #define ALU32_XOR(VAL) \
245 do { \
246   alu_val ^= (VAL); \
247   alu_carry_val = (unsigned32)(alu_val); \
248   alu_overflow_val = (signed32)(alu_val); \
249 } while (0)
250
251 #define ALU64_XOR(VAL) \
252 do { \
253   error("ALU_XOR64"); \
254 } while (0)
255
256 #define ALU_XOR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_XOR)(VAL)
257
258
259
260
261 #define ALU16_NEGATE \
262 do { \
263   error("ALU_NEGATE16"); \
264 } while (0)
265
266 #define ALU32_NEGATE \
267 do { \
268   alu_val = -alu_val; \
269   alu_carry_val = -alu_carry_val; \
270   alu_overflow_val = -alu_overflow_val; \
271 } while(0)
272
273 #define ALU64_NEGATE \
274 do { \
275   error("ALU_NEGATE64"); \
276 } while (0)
277
278 #define ALU_NEGATE XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGATE)
279
280
281
282
283 #define ALU16_AND(VAL) \
284 do { \
285   error("ALU_AND16"); \
286 } while (0)
287
288 #define ALU32_AND(VAL) \
289 do { \
290   alu_val &= (VAL); \
291   alu_carry_val = (unsigned32)(alu_val); \
292   alu_overflow_val = (signed32)(alu_val); \
293 } while (0)
294
295 #define ALU64_AND(VAL) \
296 do { \
297   error("ALU_AND64"); \
298 } while (0)
299
300 #define ALU_AND(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_AND)(VAL)
301
302
303
304
305 #define ALU16_NOT(VAL) \
306 do { \
307   error("ALU_NOT16"); \
308 } while (0)
309
310 #define ALU32_NOT \
311 do { \
312   signed64 new_alu_val = ~alu_val; \
313   ALU_SET(new_alu_val); \
314 } while (0)
315
316 #define ALU64_NOT \
317 do { \
318   error("ALU_NOT64"); \
319 } while (0)
320
321 #define ALU_NOT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NOT)
322
323
324
325 /* Make available various results */
326
327
328 /* overflow occures if the sign bit differs from the carry bit */
329
330 #define ALU16_HAD_OVERFLOW \
331   (!(alu_overflow_val & MSBIT32 (0)) != !(alu_overflow_val & MSBIT32 (16)))
332   
333 #define ALU32_HAD_OVERFLOW \
334   ((((unsigned64)(alu_overflow_val & BIT64(0))) >> 32) \
335    != (alu_overflow_val & MSBIT64(32)))
336
337 #define ALU_HAD_OVERFLOW XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_OVERFLOW)
338
339 /* carry found in bit before sign */
340
341 #define ALU16_HAD_CARRY \
342     (alu_carry_val & MSBIT32(16))
343
344 #define ALU32_HAD_CARRY \
345     (alu_carry_val & MSBIT64(31))
346
347
348 #endif