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