Commit | Line | Data |
---|---|---|
b85e4829 AC |
1 | /* The common simulator framework for GDB, the GNU Debugger. |
2 | ||
ecd75fc8 | 3 | Copyright 2002-2014 Free Software Foundation, Inc. |
b85e4829 AC |
4 | |
5 | Contributed by Andrew Cagney and Red Hat. | |
6 | ||
7 | This file is part of GDB. | |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
4744ac1b | 11 | the Free Software Foundation; either version 3 of the License, or |
b85e4829 AC |
12 | (at your option) any later version. |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
4744ac1b | 20 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
c906108c SS |
21 | |
22 | ||
23 | #ifndef _SIM_ALU_H_ | |
24 | #define _SIM_ALU_H_ | |
25 | ||
26 | #include "symcat.h" | |
27 | ||
28 | ||
29 | /* INTEGER ALU MODULE: | |
30 | ||
31 | This module provides an implementation of 2's complement arithmetic | |
32 | including the recording of carry and overflow status bits. | |
33 | ||
34 | ||
35 | EXAMPLE: | |
36 | ||
37 | Code using this module includes it into sim-main.h and then, as a | |
38 | convention, defines macro's ALU*_END that records the result of any | |
6439295f | 39 | arithmetic performed. Ex: |
c906108c SS |
40 | |
41 | #include "sim-alu.h" | |
42 | #define ALU32_END(RES) \ | |
43 | (RES) = ALU32_OVERFLOW_RESULT; \ | |
44 | carry = ALU32_HAD_CARRY_BORROW; \ | |
45 | overflow = ALU32_HAD_OVERFLOW | |
46 | ||
47 | The macro's are then used vis: | |
48 | ||
49 | { | |
50 | ALU32_BEGIN (GPR[i]); | |
51 | ALU32_ADDC (GPR[j]); | |
52 | ALU32_END (GPR[k]); | |
53 | } | |
54 | ||
55 | ||
56 | NOTES: | |
57 | ||
58 | Macros exist for efficiently computing 8, 16, 32 and 64 bit | |
59 | arithmetic - ALU8_*, ALU16_*, .... In addition, according to | |
60 | TARGET_WORD_BITSIZE a set of short-hand macros are defined - ALU_* | |
61 | ||
62 | Initialization: | |
63 | ||
64 | ALU*_BEGIN(ACC): Declare initialize the ALU accumulator with ACC. | |
65 | ||
66 | Results: | |
67 | ||
68 | The calculation of the final result may be computed a number | |
69 | of different ways. Three different overflow macro's are | |
70 | defined, the most efficient one to use depends on which other | |
71 | outputs from the alu are being used. | |
72 | ||
73 | ALU*_RESULT: Generic ALU result output. | |
74 | ||
75 | ALU*_HAD_OVERFLOW: Returns a nonzero value if signed overflow | |
6439295f | 76 | occurred. |
c906108c SS |
77 | |
78 | ALU*_OVERFLOW_RESULT: If the macro ALU*_HAD_OVERFLOW is being | |
79 | used this is the most efficient result available. Ex: | |
80 | ||
81 | #define ALU16_END(RES) \ | |
82 | if (ALU16_HAD_OVERFLOW) \ | |
83 | sim_engine_halt (...); \ | |
84 | (RES) = ALU16_OVERFLOW_RESULT | |
028f6515 | 85 | |
c906108c | 86 | ALU*_HAD_CARRY_BORROW: Returns a nonzero value if unsigned |
6439295f CD |
87 | overflow or underflow (also referred to as carry and borrow) |
88 | occurred. | |
c906108c SS |
89 | |
90 | ALU*_CARRY_BORROW_RESULT: If the macro ALU*_HAD_CARRY_BORROW is being | |
91 | used this is the most efficient result available. Ex: | |
92 | ||
93 | #define ALU64_END(RES) \ | |
94 | State.carry = ALU64_HAD_CARRY_BORROW; \ | |
95 | (RES) = ALU64_CARRY_BORROW_RESULT | |
028f6515 MF |
96 | |
97 | ||
c906108c SS |
98 | Addition: |
99 | ||
100 | ALU*_ADD(VAL): Add VAL to the ALU accumulator. Record any | |
101 | overflow as well as the final result. | |
102 | ||
103 | ALU*_ADDC(VAL): Add VAL to the ALU accumulator. Record any | |
104 | carry-out or overflow as well as the final result. | |
105 | ||
106 | ALU*_ADDC_C(VAL,CI): Add VAL and CI (carry-in). Record any | |
107 | carry-out or overflow as well as the final result. | |
108 | ||
109 | Subtraction: | |
110 | ||
111 | ALU*_SUB(VAL): Subtract VAL from the ALU accumulator. Record | |
112 | any underflow as well as the final result. | |
113 | ||
114 | ALU*_SUBC(VAL): Subtract VAL from the ALU accumulator using | |
115 | negated addition. Record any underflow or carry-out as well | |
116 | as the final result. | |
117 | ||
118 | ALU*_SUBB(VAL): Subtract VAL from the ALU accumulator using | |
119 | direct subtraction (ACC+~VAL+1). Record any underflow or | |
120 | borrow-out as well as the final result. | |
121 | ||
122 | ALU*_SUBC_X(VAL,CI): Subtract VAL and CI (carry-in) from the | |
123 | ALU accumulator using extended negated addition (ACC+~VAL+CI). | |
124 | Record any underflow or carry-out as well as the final result. | |
125 | ||
126 | ALU*_SUBB_B(VAL,BI): Subtract VAL and BI (borrow-in) from the | |
127 | ALU accumulator using direct subtraction. Record any | |
128 | underflow or borrow-out as well as the final result. | |
129 | ||
130 | ||
131 | */ | |
132 | ||
133 | ||
134 | ||
6439295f | 135 | /* Twos complement arithmetic - addition/subtraction - carry/borrow |
c906108c SS |
136 | (or you thought you knew the answer to 0-0) |
137 | ||
028f6515 | 138 | |
c906108c SS |
139 | |
140 | Notation and Properties: | |
141 | ||
142 | ||
143 | Xn denotes the value X stored in N bits. | |
144 | ||
145 | MSBn (X): The most significant (sign) bit of X treated as an N bit | |
146 | value. | |
147 | ||
148 | SEXTn (X): The infinite sign extension of X treated as an N bit | |
149 | value. | |
150 | ||
151 | MAXn, MINn: The upper and lower bound of a signed, two's | |
152 | complement N bit value. | |
153 | ||
154 | UMAXn: The upper bound of an unsigned N bit value (the lower | |
155 | bound is always zero). | |
156 | ||
028f6515 | 157 | Un: UMAXn + 1. Unsigned arithmetic is computed `modulo (Un)'. |
c906108c | 158 | |
6439295f | 159 | X[p]: Is bit P of X. X[0] denotes the least significant bit. |
c906108c SS |
160 | |
161 | ~X[p]: Is the inversion of bit X[p]. Also equal to 1-X[p], | |
162 | (1+X[p])mod(2). | |
163 | ||
164 | ||
165 | ||
166 | Addition - Overflow - Introduction: | |
167 | ||
168 | ||
169 | Overflow/Overflow indicates an error in computation of signed | |
6439295f | 170 | arithmetic. i.e. given X,Y in [MINn..MAXn]; overflow |
c906108c SS |
171 | indicates that the result X+Y > MAXn or X+Y < MIN_INTx. |
172 | ||
173 | Hardware traditionally implements overflow by computing the XOR of | |
174 | carry-in/carry-out of the most significant bit of the ALU. Here | |
175 | other methods need to be found. | |
176 | ||
177 | ||
178 | ||
179 | Addition - Overflow - method 1: | |
180 | ||
181 | ||
6439295f | 182 | Overflow occurs when the sign (most significant bit) of the two N |
c906108c SS |
183 | bit operands is identical but different to the sign of the result: |
184 | ||
185 | Rn = (Xn + Yn) | |
186 | V = MSBn (~(Xn ^ Yn) & (Rn ^ Xn)) | |
187 | ||
188 | ||
189 | ||
190 | Addition - Overflow - method 2: | |
191 | ||
192 | ||
193 | The two N bit operands are sign extended to M>N bits and then | |
6439295f | 194 | added. Overflow occurs when SIGN_BIT<n> and SIGN_BIT<m> do not |
c906108c | 195 | match. |
028f6515 | 196 | |
c906108c SS |
197 | Rm = (SEXTn (Xn) + SEXTn (Yn)) |
198 | V = MSBn ((Rm >> (M - N)) ^ Rm) | |
199 | ||
200 | ||
201 | ||
202 | Addition - Overflow - method 3: | |
203 | ||
204 | ||
205 | The two N bit operands are sign extended to M>N bits and then | |
6439295f | 206 | added. Overflow occurs when the result is outside of the sign |
c906108c SS |
207 | extended range [MINn .. MAXn]. |
208 | ||
209 | ||
210 | ||
211 | Addition - Overflow - method 4: | |
212 | ||
213 | ||
214 | Given the Result and Carry-out bits, the oVerflow from the addition | |
215 | of X, Y and carry-In can be computed using the equation: | |
216 | ||
217 | Rn = (Xn + Yn) | |
218 | V = (MSBn ((Xn ^ Yn) ^ Rn)) ^ C) | |
219 | ||
220 | As shown in the table below: | |
221 | ||
222 | I X Y R C | V | X^Y ^R ^C | |
223 | ---------------+---+------------- | |
224 | 0 0 0 0 0 | 0 | 0 0 0 | |
225 | 0 0 1 1 0 | 0 | 1 0 0 | |
226 | 0 1 0 1 0 | 0 | 1 0 0 | |
227 | 0 1 1 0 1 | 1 | 0 0 1 | |
228 | 1 0 0 1 0 | 1 | 0 1 1 | |
229 | 1 0 1 0 1 | 0 | 1 1 0 | |
230 | 1 1 0 0 1 | 0 | 1 1 0 | |
231 | 1 1 1 1 1 | 0 | 0 1 0 | |
232 | ||
233 | ||
234 | ||
235 | Addition - Carry - Introduction: | |
236 | ||
237 | ||
6439295f | 238 | Carry (poorly named) indicates that an overflow occurred for |
c906108c SS |
239 | unsigned N bit addition. i.e. given X, Y in [0..UMAXn] then |
240 | carry indicates X+Y > UMAXn or X+Y >= Un. | |
241 | ||
242 | The following table lists the output for all given inputs into a | |
243 | full-adder. | |
028f6515 | 244 | |
c906108c SS |
245 | I X Y R | C |
246 | ------------+--- | |
247 | 0 0 0 0 | 0 | |
248 | 0 0 1 1 | 0 | |
249 | 0 1 0 1 | 0 | |
250 | 0 1 1 0 | 1 | |
251 | 1 0 0 1 | 0 | |
252 | 1 0 1 0 | 1 | |
253 | 1 1 0 0 | 1 | |
254 | 1 1 1 1 | 1 | |
255 | ||
256 | (carry-In, X, Y, Result, Carry-out): | |
257 | ||
258 | ||
259 | ||
260 | Addition - Carry - method 1: | |
261 | ||
262 | ||
263 | Looking at the terms X, Y and R we want an equation for C. | |
264 | ||
265 | XY\R 0 1 | |
266 | +------- | |
028f6515 | 267 | 00 | 0 0 |
c906108c SS |
268 | 01 | 1 0 |
269 | 11 | 1 1 | |
270 | 10 | 1 0 | |
271 | ||
272 | This giving us the sum-of-prod equation: | |
273 | ||
274 | MSBn ((Xn & Yn) | (Xn & ~Rn) | (Yn & ~Rn)) | |
275 | ||
276 | Verifying: | |
277 | ||
028f6515 | 278 | I X Y R | C | X&Y X&~R Y&~R |
c906108c SS |
279 | ------------+---+--------------- |
280 | 0 0 0 0 | 0 | 0 0 0 | |
281 | 0 0 1 1 | 0 | 0 0 0 | |
282 | 0 1 0 1 | 0 | 0 0 0 | |
283 | 0 1 1 0 | 1 | 1 1 1 | |
284 | 1 0 0 1 | 0 | 0 0 0 | |
285 | 1 0 1 0 | 1 | 0 0 1 | |
286 | 1 1 0 0 | 1 | 0 1 0 | |
287 | 1 1 1 1 | 1 | 1 0 0 | |
288 | ||
289 | ||
290 | ||
291 | Addition - Carry - method 2: | |
292 | ||
293 | ||
294 | Given two signed N bit numbers, a carry can be detected by treating | |
295 | the numbers as N bit unsigned and adding them using M>N unsigned | |
6439295f | 296 | arithmetic. Carry is indicated by bit (1 << N) being set (result |
c906108c SS |
297 | >= 2**N). |
298 | ||
299 | ||
300 | ||
301 | Addition - Carry - method 3: | |
302 | ||
303 | ||
304 | Given the oVerflow bit. The carry can be computed from: | |
305 | ||
306 | (~R&V) | (R&V) | |
307 | ||
308 | ||
309 | ||
310 | Addition - Carry - method 4: | |
311 | ||
312 | Given two signed numbers. Treating them as unsigned we have: | |
313 | ||
314 | 0 <= X < Un, 0 <= Y < Un | |
315 | ==> X + Y < 2 Un | |
316 | ||
6439295f | 317 | Consider Y when carry occurs: |
c906108c SS |
318 | |
319 | X + Y >= Un, Y < Un | |
6439295f | 320 | ==> (Un - X) <= Y < Un # rearrange |
c906108c SS |
321 | ==> Un <= X + Y < Un + X < 2 Un # add Xn |
322 | ==> 0 <= (X + Y) mod Un < X mod Un | |
323 | ||
6439295f | 324 | or when carry as occurred: |
c906108c SS |
325 | |
326 | (X + Y) mod Un < X mod Un | |
327 | ||
6439295f | 328 | Consider Y when carry does not occur: |
c906108c SS |
329 | |
330 | X + Y < Un | |
331 | have X < Un, Y >= 0 | |
332 | ==> X <= X + Y < Un | |
333 | ==> X mod Un <= (X + Y) mod Un | |
334 | ||
6439295f | 335 | or when carry has not occurred: |
c906108c SS |
336 | |
337 | ! ( (X + Y) mod Un < X mod Un) | |
338 | ||
6439295f | 339 | hence we get carry by computing in N bit unsigned arithmetic. |
c906108c SS |
340 | |
341 | carry <- (Xn + Yn) < Xn | |
342 | ||
343 | ||
344 | ||
345 | Subtraction - Introduction | |
346 | ||
347 | ||
348 | There are two different ways of computing the signed two's | |
349 | complement difference of two numbers. The first is based on | |
350 | negative addition, the second on direct subtraction. | |
351 | ||
352 | ||
353 | ||
354 | Subtraction - Carry - Introduction - Negated Addition | |
355 | ||
356 | ||
357 | The equation X - Y can be computed using: | |
358 | ||
359 | X + (-Y) | |
360 | ==> X + ~Y + 1 # -Y = ~Y + 1 | |
361 | ||
362 | In addition to the result, the equation produces Carry-out. For | |
6439295f | 363 | succeeding extended precision calculations, the more general |
c906108c SS |
364 | equation can be used: |
365 | ||
366 | C[p]:R[p] = X[p] + ~Y[p] + C[p-1] | |
367 | where C[0]:R[0] = X[0] + ~Y[0] + 1 | |
368 | ||
369 | ||
370 | ||
371 | Subtraction - Borrow - Introduction - Direct Subtraction | |
372 | ||
373 | ||
374 | The alternative to negative addition is direct subtraction where | |
375 | `X-Y is computed directly. In addition to the result of the | |
376 | calculation, a Borrow bit is produced. In general terms: | |
377 | ||
378 | B[p]:R[p] = X[p] - Y[p] - B[p-1] | |
379 | where B[0]:R[0] = X[0] - Y[0] | |
380 | ||
381 | The Borrow bit is the complement of the Carry bit produced by | |
382 | Negated Addition above. A dodgy proof follows: | |
383 | ||
384 | Case 0: | |
385 | C[0]:R[0] = X[0] + ~Y[0] + 1 | |
386 | ==> C[0]:R[0] = X[0] + 1 - Y[0] + 1 # ~Y[0] = (1 - Y[0])? | |
387 | ==> C[0]:R[0] = 2 + X[0] - Y[0] | |
388 | ==> C[0]:R[0] = 2 + B[0]:R[0] | |
389 | ==> C[0]:R[0] = (1 + B[0]):R[0] | |
390 | ==> C[0] = ~B[0] # (1 + B[0]) mod 2 = ~B[0]? | |
391 | ||
392 | Case P: | |
393 | C[p]:R[p] = X[p] + ~Y[p] + C[p-1] | |
394 | ==> C[p]:R[p] = X[p] + 1 - Y[0] + 1 - B[p-1] | |
395 | ==> C[p]:R[p] = 2 + X[p] - Y[0] - B[p-1] | |
396 | ==> C[p]:R[p] = 2 + B[p]:R[p] | |
397 | ==> C[p]:R[p] = (1 + B[p]):R[p] | |
398 | ==> C[p] = ~B[p] | |
399 | ||
400 | The table below lists all possible inputs/outputs for a | |
401 | full-subtractor: | |
402 | ||
403 | X Y I | R B | |
404 | 0 0 0 | 0 0 | |
405 | 0 0 1 | 1 1 | |
406 | 0 1 0 | 1 1 | |
407 | 0 1 1 | 0 1 | |
408 | 1 0 0 | 1 0 | |
409 | 1 0 1 | 0 0 | |
410 | 1 1 0 | 0 0 | |
411 | 1 1 1 | 1 1 | |
412 | ||
413 | ||
414 | ||
415 | Subtraction - Method 1 | |
416 | ||
417 | ||
418 | Treating Xn and Yn as unsigned values then a borrow (unsigned | |
6439295f | 419 | underflow) occurs when: |
c906108c SS |
420 | |
421 | B = Xn < Yn | |
422 | ==> C = Xn >= Yn | |
423 | ||
424 | */ | |
425 | ||
426 | ||
427 | ||
428 | /* 8 bit target expressions: | |
429 | ||
430 | Since the host's natural bitsize > 8 bits, carry method 2 and | |
431 | overflow method 2 are used. */ | |
432 | ||
433 | #define ALU8_BEGIN(VAL) \ | |
434 | unsigned alu8_cr = (unsigned8) (VAL); \ | |
435 | signed alu8_vr = (signed8) (alu8_cr) | |
436 | ||
437 | #define ALU8_SET(VAL) \ | |
438 | alu8_cr = (unsigned8) (VAL); \ | |
439 | alu8_vr = (signed8) (alu8_cr) | |
440 | ||
441 | #define ALU8_SET_CARRY_BORROW(CARRY) \ | |
442 | do { \ | |
443 | if (CARRY) \ | |
444 | alu8_cr |= ((signed)-1) << 8; \ | |
445 | else \ | |
446 | alu8_cr &= 0xff; \ | |
447 | } while (0) | |
448 | ||
449 | #define ALU8_HAD_CARRY_BORROW (alu8_cr & LSBIT32(8)) | |
450 | #define ALU8_HAD_OVERFLOW (((alu8_vr >> 8) ^ alu8_vr) & LSBIT32 (8-1)) | |
451 | ||
452 | #define ALU8_RESULT ((unsigned8) alu8_cr) | |
453 | #define ALU8_CARRY_BORROW_RESULT ((unsigned8) alu8_cr) | |
454 | #define ALU8_OVERFLOW_RESULT ((unsigned8) alu8_vr) | |
455 | ||
456 | /* #define ALU8_END ????? - target dependant */ | |
457 | ||
458 | ||
459 | ||
460 | /* 16 bit target expressions: | |
461 | ||
462 | Since the host's natural bitsize > 16 bits, carry method 2 and | |
463 | overflow method 2 are used. */ | |
464 | ||
465 | #define ALU16_BEGIN(VAL) \ | |
466 | signed alu16_cr = (unsigned16) (VAL); \ | |
467 | unsigned alu16_vr = (signed16) (alu16_cr) | |
468 | ||
469 | #define ALU16_SET(VAL) \ | |
470 | alu16_cr = (unsigned16) (VAL); \ | |
471 | alu16_vr = (signed16) (alu16_cr) | |
472 | ||
473 | #define ALU16_SET_CARRY_BORROW(CARRY) \ | |
474 | do { \ | |
475 | if (CARRY) \ | |
476 | alu16_cr |= ((signed)-1) << 16; \ | |
477 | else \ | |
478 | alu16_cr &= 0xffff; \ | |
479 | } while (0) | |
480 | ||
481 | #define ALU16_HAD_CARRY_BORROW (alu16_cr & LSBIT32(16)) | |
482 | #define ALU16_HAD_OVERFLOW (((alu16_vr >> 16) ^ alu16_vr) & LSBIT32 (16-1)) | |
483 | ||
484 | #define ALU16_RESULT ((unsigned16) alu16_cr) | |
485 | #define ALU16_CARRY_BORROW_RESULT ((unsigned16) alu16_cr) | |
486 | #define ALU16_OVERFLOW_RESULT ((unsigned16) alu16_vr) | |
487 | ||
488 | /* #define ALU16_END ????? - target dependant */ | |
489 | ||
490 | ||
491 | ||
492 | /* 32 bit target expressions: | |
493 | ||
6439295f | 494 | Since most hosts do not support 64 (> 32) bit arithmetic, carry |
c906108c SS |
495 | method 4 and overflow method 4 are used. */ |
496 | ||
497 | #define ALU32_BEGIN(VAL) \ | |
498 | unsigned32 alu32_r = (VAL); \ | |
499 | int alu32_c = 0; \ | |
500 | int alu32_v = 0 | |
501 | ||
502 | #define ALU32_SET(VAL) \ | |
503 | alu32_r = (VAL); \ | |
504 | alu32_c = 0; \ | |
505 | alu32_v = 0 | |
506 | ||
507 | #define ALU32_SET_CARRY_BORROW(CARRY) alu32_c = (CARRY) | |
508 | ||
509 | #define ALU32_HAD_CARRY_BORROW (alu32_c) | |
510 | #define ALU32_HAD_OVERFLOW (alu32_v) | |
511 | ||
512 | #define ALU32_RESULT (alu32_r) | |
513 | #define ALU32_CARRY_BORROW_RESULT (alu32_r) | |
514 | #define ALU32_OVERFLOW_RESULT (alu32_r) | |
515 | ||
516 | ||
517 | ||
518 | /* 64 bit target expressions: | |
519 | ||
520 | Even though the host typically doesn't support native 64 bit | |
6439295f | 521 | arithmetic, it is still used. */ |
c906108c SS |
522 | |
523 | #define ALU64_BEGIN(VAL) \ | |
524 | unsigned64 alu64_r = (VAL); \ | |
525 | int alu64_c = 0; \ | |
526 | int alu64_v = 0 | |
527 | ||
528 | #define ALU64_SET(VAL) \ | |
529 | alu64_r = (VAL); \ | |
530 | alu64_c = 0; \ | |
531 | alu64_v = 0 | |
532 | ||
533 | #define ALU64_SET_CARRY_BORROW(CARRY) alu64_c = (CARRY) | |
534 | ||
535 | #define ALU64_HAD_CARRY_BORROW (alu64_c) | |
536 | #define ALU64_HAD_OVERFLOW (alu64_v) | |
537 | ||
538 | #define ALU64_RESULT (alu64_r) | |
539 | #define ALU64_CARRY_BORROW_RESULT (alu64_r) | |
540 | #define ALU64_OVERFLOW_RESULT (alu64_r) | |
541 | ||
542 | ||
543 | ||
544 | /* Generic versions of above macros */ | |
545 | ||
546 | #define ALU_BEGIN XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_BEGIN) | |
547 | #define ALU_SET XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET) | |
548 | #define ALU_SET_CARRY XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SET_CARRY) | |
549 | ||
550 | #define ALU_HAD_OVERFLOW XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_OVERFLOW) | |
551 | #define ALU_HAD_CARRY XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_HAD_CARRY) | |
552 | ||
553 | #define ALU_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_RESULT) | |
554 | #define ALU_OVERFLOW_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OVERFLOW_RESULT) | |
555 | #define ALU_CARRY_RESULT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_CARRY_RESULT) | |
556 | ||
557 | ||
558 | ||
559 | /* Basic operation - add (overflowing) */ | |
560 | ||
561 | #define ALU8_ADD(VAL) \ | |
562 | do { \ | |
563 | unsigned8 alu8add_val = (VAL); \ | |
564 | ALU8_ADDC (alu8add_val); \ | |
565 | } while (0) | |
566 | ||
567 | #define ALU16_ADD(VAL) \ | |
568 | do { \ | |
569 | unsigned16 alu16add_val = (VAL); \ | |
570 | ALU16_ADDC (alu8add_val); \ | |
571 | } while (0) | |
572 | ||
573 | #define ALU32_ADD(VAL) \ | |
574 | do { \ | |
575 | unsigned32 alu32add_val = (VAL); \ | |
576 | ALU32_ADDC (alu32add_val); \ | |
577 | } while (0) | |
578 | ||
579 | #define ALU64_ADD(VAL) \ | |
580 | do { \ | |
581 | unsigned64 alu64add_val = (unsigned64) (VAL); \ | |
582 | ALU64_ADDC (alu64add_val); \ | |
583 | } while (0) | |
584 | ||
585 | #define ALU_ADD XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADD) | |
586 | ||
587 | ||
588 | ||
589 | /* Basic operation - add carrying (and overflowing) */ | |
590 | ||
591 | #define ALU8_ADDC(VAL) \ | |
592 | do { \ | |
593 | unsigned8 alu8addc_val = (VAL); \ | |
594 | alu8_cr += (unsigned8)(alu8addc_val); \ | |
595 | alu8_vr += (signed8)(alu8addc_val); \ | |
596 | } while (0) | |
597 | ||
598 | #define ALU16_ADDC(VAL) \ | |
599 | do { \ | |
600 | unsigned16 alu16addc_val = (VAL); \ | |
601 | alu16_cr += (unsigned16)(alu16addc_val); \ | |
602 | alu16_vr += (signed16)(alu16addc_val); \ | |
603 | } while (0) | |
604 | ||
605 | #define ALU32_ADDC(VAL) \ | |
606 | do { \ | |
607 | unsigned32 alu32addc_val = (VAL); \ | |
608 | unsigned32 alu32addc_sign = alu32addc_val ^ alu32_r; \ | |
609 | alu32_r += (alu32addc_val); \ | |
610 | alu32_c = (alu32_r < alu32addc_val); \ | |
611 | alu32_v = ((alu32addc_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \ | |
612 | } while (0) | |
613 | ||
614 | #define ALU64_ADDC(VAL) \ | |
615 | do { \ | |
616 | unsigned64 alu64addc_val = (unsigned64) (VAL); \ | |
617 | unsigned64 alu64addc_sign = alu64addc_val ^ alu64_r; \ | |
618 | alu64_r += (alu64addc_val); \ | |
619 | alu64_c = (alu64_r < alu64addc_val); \ | |
620 | alu64_v = ((alu64addc_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63; \ | |
621 | } while (0) | |
622 | ||
623 | #define ALU_ADDC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC) | |
624 | ||
625 | ||
626 | ||
627 | /* Compound operation - add carrying (and overflowing) with carry-in */ | |
628 | ||
629 | #define ALU8_ADDC_C(VAL,C) \ | |
630 | do { \ | |
631 | unsigned8 alu8addcc_val = (VAL); \ | |
632 | unsigned8 alu8addcc_c = (C); \ | |
633 | alu8_cr += (unsigned)(unsigned8)alu8addcc_val + alu8addcc_c; \ | |
634 | alu8_vr += (signed)(signed8)(alu8addcc_val) + alu8addcc_c; \ | |
635 | } while (0) | |
636 | ||
637 | #define ALU16_ADDC_C(VAL,C) \ | |
638 | do { \ | |
639 | unsigned16 alu16addcc_val = (VAL); \ | |
640 | unsigned16 alu16addcc_c = (C); \ | |
641 | alu16_cr += (unsigned)(unsigned16)alu16addcc_val + alu16addcc_c; \ | |
642 | alu16_vr += (signed)(signed16)(alu16addcc_val) + alu16addcc_c; \ | |
643 | } while (0) | |
644 | ||
645 | #define ALU32_ADDC_C(VAL,C) \ | |
646 | do { \ | |
647 | unsigned32 alu32addcc_val = (VAL); \ | |
648 | unsigned32 alu32addcc_c = (C); \ | |
649 | unsigned32 alu32addcc_sign = (alu32addcc_val ^ alu32_r); \ | |
650 | alu32_r += (alu32addcc_val + alu32addcc_c); \ | |
651 | alu32_c = ((alu32_r < alu32addcc_val) \ | |
652 | || (alu32addcc_c && alu32_r == alu32addcc_val)); \ | |
653 | alu32_v = ((alu32addcc_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31;\ | |
654 | } while (0) | |
655 | ||
656 | #define ALU64_ADDC_C(VAL,C) \ | |
657 | do { \ | |
658 | unsigned64 alu64addcc_val = (VAL); \ | |
659 | unsigned64 alu64addcc_c = (C); \ | |
660 | unsigned64 alu64addcc_sign = (alu64addcc_val ^ alu64_r); \ | |
661 | alu64_r += (alu64addcc_val + alu64addcc_c); \ | |
662 | alu64_c = ((alu64_r < alu64addcc_val) \ | |
663 | || (alu64addcc_c && alu64_r == alu64addcc_val)); \ | |
664 | alu64_v = ((alu64addcc_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 63;\ | |
665 | } while (0) | |
666 | ||
667 | #define ALU_ADDC_C XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_ADDC_C) | |
668 | ||
669 | ||
670 | ||
671 | /* Basic operation - subtract (overflowing) */ | |
672 | ||
673 | #define ALU8_SUB(VAL) \ | |
674 | do { \ | |
675 | unsigned8 alu8sub_val = (VAL); \ | |
676 | ALU8_ADDC_C (~alu8sub_val, 1); \ | |
677 | } while (0) | |
678 | ||
679 | #define ALU16_SUB(VAL) \ | |
680 | do { \ | |
681 | unsigned16 alu16sub_val = (VAL); \ | |
682 | ALU16_ADDC_C (~alu16sub_val, 1); \ | |
683 | } while (0) | |
684 | ||
685 | #define ALU32_SUB(VAL) \ | |
686 | do { \ | |
687 | unsigned32 alu32sub_val = (VAL); \ | |
688 | ALU32_ADDC_C (~alu32sub_val, 1); \ | |
689 | } while (0) | |
690 | ||
691 | #define ALU64_SUB(VAL) \ | |
692 | do { \ | |
693 | unsigned64 alu64sub_val = (VAL); \ | |
694 | ALU64_ADDC_C (~alu64sub_val, 1); \ | |
695 | } while (0) | |
696 | ||
697 | #define ALU_SUB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUB) | |
698 | ||
699 | ||
700 | ||
701 | /* Basic operation - subtract carrying (and overflowing) */ | |
702 | ||
703 | #define ALU8_SUBC(VAL) \ | |
704 | do { \ | |
705 | unsigned8 alu8subc_val = (VAL); \ | |
706 | ALU8_ADDC_C (~alu8subc_val, 1); \ | |
707 | } while (0) | |
708 | ||
709 | #define ALU16_SUBC(VAL) \ | |
710 | do { \ | |
711 | unsigned16 alu16subc_val = (VAL); \ | |
712 | ALU16_ADDC_C (~alu16subc_val, 1); \ | |
713 | } while (0) | |
714 | ||
715 | #define ALU32_SUBC(VAL) \ | |
716 | do { \ | |
717 | unsigned32 alu32subc_val = (VAL); \ | |
718 | ALU32_ADDC_C (~alu32subc_val, 1); \ | |
719 | } while (0) | |
720 | ||
721 | #define ALU64_SUBC(VAL) \ | |
722 | do { \ | |
723 | unsigned64 alu64subc_val = (VAL); \ | |
724 | ALU64_ADDC_C (~alu64subc_val, 1); \ | |
725 | } while (0) | |
726 | ||
727 | #define ALU_SUBC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBC) | |
728 | ||
729 | ||
730 | ||
731 | /* Compound operation - subtract carrying (and overflowing), extended */ | |
732 | ||
733 | #define ALU8_SUBC_X(VAL,C) \ | |
734 | do { \ | |
735 | unsigned8 alu8subcx_val = (VAL); \ | |
736 | unsigned8 alu8subcx_c = (C); \ | |
737 | ALU8_ADDC_C (~alu8subcx_val, alu8subcx_c); \ | |
738 | } while (0) | |
739 | ||
740 | #define ALU16_SUBC_X(VAL,C) \ | |
741 | do { \ | |
742 | unsigned16 alu16subcx_val = (VAL); \ | |
743 | unsigned16 alu16subcx_c = (C); \ | |
744 | ALU16_ADDC_C (~alu16subcx_val, alu16subcx_c); \ | |
745 | } while (0) | |
746 | ||
747 | #define ALU32_SUBC_X(VAL,C) \ | |
748 | do { \ | |
749 | unsigned32 alu32subcx_val = (VAL); \ | |
750 | unsigned32 alu32subcx_c = (C); \ | |
751 | ALU32_ADDC_C (~alu32subcx_val, alu32subcx_c); \ | |
752 | } while (0) | |
753 | ||
754 | #define ALU64_SUBC_X(VAL,C) \ | |
755 | do { \ | |
756 | unsigned64 alu64subcx_val = (VAL); \ | |
757 | unsigned64 alu64subcx_c = (C); \ | |
758 | ALU64_ADDC_C (~alu64subcx_val, alu64subcx_c); \ | |
759 | } while (0) | |
760 | ||
761 | #define ALU_SUBC_X XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBC_X) | |
762 | ||
763 | ||
764 | ||
765 | /* Basic operation - subtract borrowing (and overflowing) */ | |
766 | ||
767 | #define ALU8_SUBB(VAL) \ | |
768 | do { \ | |
769 | unsigned8 alu8subb_val = (VAL); \ | |
770 | alu8_cr -= (unsigned)(unsigned8)alu8subb_val; \ | |
771 | alu8_vr -= (signed)(signed8)alu8subb_val; \ | |
772 | } while (0) | |
773 | ||
774 | #define ALU16_SUBB(VAL) \ | |
775 | do { \ | |
776 | unsigned16 alu16subb_val = (VAL); \ | |
777 | alu16_cr -= (unsigned)(unsigned16)alu16subb_val; \ | |
778 | alu16_vr -= (signed)(signed16)alu16subb_val; \ | |
779 | } while (0) | |
780 | ||
781 | #define ALU32_SUBB(VAL) \ | |
782 | do { \ | |
783 | unsigned32 alu32subb_val = (VAL); \ | |
784 | unsigned32 alu32subb_sign = alu32subb_val ^ alu32_r; \ | |
785 | alu32_c = (alu32_r < alu32subb_val); \ | |
786 | alu32_r -= (alu32subb_val); \ | |
787 | alu32_v = ((alu32subb_sign ^ - (unsigned32)alu32_c) ^ alu32_r) >> 31; \ | |
788 | } while (0) | |
789 | ||
790 | #define ALU64_SUBB(VAL) \ | |
791 | do { \ | |
792 | unsigned64 alu64subb_val = (VAL); \ | |
793 | unsigned64 alu64subb_sign = alu64subb_val ^ alu64_r; \ | |
794 | alu64_c = (alu64_r < alu64subb_val); \ | |
795 | alu64_r -= (alu64subb_val); \ | |
796 | alu64_v = ((alu64subb_sign ^ - (unsigned64)alu64_c) ^ alu64_r) >> 31; \ | |
797 | } while (0) | |
798 | ||
799 | #define ALU_SUBB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBB) | |
800 | ||
801 | ||
802 | ||
803 | /* Compound operation - subtract borrowing (and overflowing) with borrow-in */ | |
804 | ||
805 | #define ALU8_SUBB_B(VAL,B) \ | |
806 | do { \ | |
807 | unsigned8 alu8subbb_val = (VAL); \ | |
808 | unsigned8 alu8subbb_b = (B); \ | |
809 | alu8_cr -= (unsigned)(unsigned8)alu8subbb_val; \ | |
810 | alu8_cr -= (unsigned)(unsigned8)alu8subbb_b; \ | |
811 | alu8_vr -= (signed)(signed8)alu8subbb_val + alu8subbb_b; \ | |
812 | } while (0) | |
813 | ||
814 | #define ALU16_SUBB_B(VAL,B) \ | |
815 | do { \ | |
816 | unsigned16 alu16subbb_val = (VAL); \ | |
817 | unsigned16 alu16subbb_b = (B); \ | |
818 | alu16_cr -= (unsigned)(unsigned16)alu16subbb_val; \ | |
819 | alu16_cr -= (unsigned)(unsigned16)alu16subbb_b; \ | |
820 | alu16_vr -= (signed)(signed16)alu16subbb_val + alu16subbb_b; \ | |
821 | } while (0) | |
822 | ||
823 | #define ALU32_SUBB_B(VAL,B) \ | |
824 | do { \ | |
825 | unsigned32 alu32subbb_val = (VAL); \ | |
826 | unsigned32 alu32subbb_b = (B); \ | |
827 | ALU32_ADDC_C (~alu32subbb_val, !alu32subbb_b); \ | |
828 | alu32_c = !alu32_c; \ | |
829 | } while (0) | |
830 | ||
831 | #define ALU64_SUBB_B(VAL,B) \ | |
832 | do { \ | |
833 | unsigned64 alu64subbb_val = (VAL); \ | |
834 | unsigned64 alu64subbb_b = (B); \ | |
835 | ALU64_ADDC_C (~alu64subbb_val, !alu64subbb_b); \ | |
836 | alu64_c = !alu64_c; \ | |
837 | } while (0) | |
838 | ||
839 | #define ALU_SUBB_B XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_SUBB_B) | |
840 | ||
841 | ||
842 | ||
843 | /* Basic operation - negate (overflowing) */ | |
844 | ||
845 | #define ALU8_NEG() \ | |
846 | do { \ | |
847 | signed alu8neg_val = (ALU8_RESULT); \ | |
848 | ALU8_SET (1); \ | |
849 | ALU8_ADDC (~alu8neg_val); \ | |
850 | } while (0) | |
851 | ||
852 | #define ALU16_NEG() \ | |
853 | do { \ | |
854 | signed alu16neg_val = (ALU16_RESULT); \ | |
855 | ALU16_SET (1); \ | |
856 | ALU16_ADDC (~alu16neg_val); \ | |
857 | } while (0) | |
858 | ||
859 | #define ALU32_NEG() \ | |
860 | do { \ | |
861 | unsigned32 alu32neg_val = (ALU32_RESULT); \ | |
862 | ALU32_SET (1); \ | |
863 | ALU32_ADDC (~alu32neg_val); \ | |
864 | } while(0) | |
865 | ||
866 | #define ALU64_NEG() \ | |
867 | do { \ | |
868 | unsigned64 alu64neg_val = (ALU64_RESULT); \ | |
869 | ALU64_SET (1); \ | |
870 | ALU64_ADDC (~alu64neg_val); \ | |
871 | } while (0) | |
872 | ||
873 | #define ALU_NEG XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEG) | |
874 | ||
875 | ||
876 | ||
877 | ||
878 | /* Basic operation - negate carrying (and overflowing) */ | |
879 | ||
880 | #define ALU8_NEGC() \ | |
881 | do { \ | |
882 | signed alu8negc_val = (ALU8_RESULT); \ | |
883 | ALU8_SET (1); \ | |
884 | ALU8_ADDC (~alu8negc_val); \ | |
885 | } while (0) | |
886 | ||
887 | #define ALU16_NEGC() \ | |
888 | do { \ | |
889 | signed alu16negc_val = (ALU16_RESULT); \ | |
890 | ALU16_SET (1); \ | |
891 | ALU16_ADDC (~alu16negc_val); \ | |
892 | } while (0) | |
893 | ||
894 | #define ALU32_NEGC() \ | |
895 | do { \ | |
896 | unsigned32 alu32negc_val = (ALU32_RESULT); \ | |
897 | ALU32_SET (1); \ | |
898 | ALU32_ADDC (~alu32negc_val); \ | |
899 | } while(0) | |
900 | ||
901 | #define ALU64_NEGC() \ | |
902 | do { \ | |
903 | unsigned64 alu64negc_val = (ALU64_RESULT); \ | |
904 | ALU64_SET (1); \ | |
905 | ALU64_ADDC (~alu64negc_val); \ | |
906 | } while (0) | |
907 | ||
908 | #define ALU_NEGC XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGC) | |
909 | ||
910 | ||
911 | ||
912 | ||
913 | /* Basic operation - negate borrowing (and overflowing) */ | |
914 | ||
915 | #define ALU8_NEGB() \ | |
916 | do { \ | |
917 | signed alu8negb_val = (ALU8_RESULT); \ | |
918 | ALU8_SET (0); \ | |
919 | ALU8_SUBB (alu8negb_val); \ | |
920 | } while (0) | |
921 | ||
922 | #define ALU16_NEGB() \ | |
923 | do { \ | |
924 | signed alu16negb_val = (ALU16_RESULT); \ | |
925 | ALU16_SET (0); \ | |
926 | ALU16_SUBB (alu16negb_val); \ | |
927 | } while (0) | |
928 | ||
929 | #define ALU32_NEGB() \ | |
930 | do { \ | |
931 | unsigned32 alu32negb_val = (ALU32_RESULT); \ | |
932 | ALU32_SET (0); \ | |
933 | ALU32_SUBB (alu32negb_val); \ | |
934 | } while(0) | |
935 | ||
936 | #define ALU64_NEGB() \ | |
937 | do { \ | |
938 | unsigned64 alu64negb_val = (ALU64_RESULT); \ | |
939 | ALU64_SET (0); \ | |
940 | ALU64_SUBB (alu64negb_val); \ | |
941 | } while (0) | |
942 | ||
943 | #define ALU_NEGB XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NEGB) | |
944 | ||
945 | ||
946 | ||
947 | ||
948 | /* Other */ | |
949 | ||
950 | #define ALU8_OR(VAL) \ | |
951 | do { \ | |
952 | error("ALU16_OR"); \ | |
953 | } while (0) | |
954 | ||
955 | #define ALU16_OR(VAL) \ | |
956 | do { \ | |
957 | error("ALU16_OR"); \ | |
958 | } while (0) | |
959 | ||
960 | #define ALU32_OR(VAL) \ | |
961 | do { \ | |
962 | alu32_r |= (VAL); \ | |
963 | alu32_c = 0; \ | |
964 | alu32_v = 0; \ | |
965 | } while (0) | |
966 | ||
967 | #define ALU64_OR(VAL) \ | |
968 | do { \ | |
969 | alu64_r |= (VAL); \ | |
970 | alu64_c = 0; \ | |
971 | alu64_v = 0; \ | |
972 | } while (0) | |
973 | ||
974 | #define ALU_OR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_OR)(VAL) | |
975 | ||
976 | ||
977 | ||
978 | #define ALU16_XOR(VAL) \ | |
979 | do { \ | |
980 | error("ALU16_XOR"); \ | |
981 | } while (0) | |
982 | ||
983 | #define ALU32_XOR(VAL) \ | |
984 | do { \ | |
985 | alu32_r ^= (VAL); \ | |
986 | alu32_c = 0; \ | |
987 | alu32_v = 0; \ | |
988 | } while (0) | |
989 | ||
990 | #define ALU64_XOR(VAL) \ | |
991 | do { \ | |
992 | alu64_r ^= (VAL); \ | |
993 | alu64_c = 0; \ | |
994 | alu64_v = 0; \ | |
995 | } while (0) | |
996 | ||
997 | #define ALU_XOR(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_XOR)(VAL) | |
998 | ||
999 | ||
1000 | ||
1001 | ||
1002 | #define ALU16_AND(VAL) \ | |
1003 | do { \ | |
1004 | error("ALU_AND16"); \ | |
1005 | } while (0) | |
1006 | ||
1007 | #define ALU32_AND(VAL) \ | |
1008 | do { \ | |
1009 | alu32_r &= (VAL); \ | |
59c0b43d | 1010 | alu32_c = 0; \ |
c906108c SS |
1011 | alu32_v = 0; \ |
1012 | } while (0) | |
1013 | ||
1014 | #define ALU64_AND(VAL) \ | |
1015 | do { \ | |
1016 | alu64_r &= (VAL); \ | |
59c0b43d | 1017 | alu64_c = 0; \ |
c906108c SS |
1018 | alu64_v = 0; \ |
1019 | } while (0) | |
1020 | ||
1021 | #define ALU_AND(VAL) XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_AND)(VAL) | |
1022 | ||
1023 | ||
1024 | ||
1025 | ||
1026 | #define ALU16_NOT(VAL) \ | |
1027 | do { \ | |
1028 | error("ALU_NOT16"); \ | |
1029 | } while (0) | |
1030 | ||
1031 | #define ALU32_NOT \ | |
1032 | do { \ | |
1033 | alu32_r = ~alu32_r; \ | |
1034 | alu32_c = 0; \ | |
1035 | alu32_v = 0; \ | |
1036 | } while (0) | |
1037 | ||
1038 | #define ALU64_NOT \ | |
1039 | do { \ | |
1040 | alu64_r = ~alu64_r; \ | |
1041 | alu64_c = 0; \ | |
1042 | alu64_v = 0; \ | |
1043 | } while (0) | |
1044 | ||
1045 | #define ALU_NOT XCONCAT3(ALU,WITH_TARGET_WORD_BITSIZE,_NOT) | |
1046 | ||
1047 | #endif |