17

All mainstream microprocessors from the 4004 on, have implemented signed integer arithmetic with twos complement and silent wraparound on overflow (by which I mean that the CPU itself will not trap, though might set a flag that code could check). The C language standard allows signed integer arithmetic to trap on overflow, and GCC will do this if you specify -ftrapv.

Which historical CPUs (not necessarily microcomputer) have implemented trap on signed integer overflow (i.e. the CPU itself generates the trap)? I believe Mill does so, but that is still an R&D project, not a shipping CPU.

15
  • 7
    Does the x86 INTO (i.e. “int o”) count? It triggers an interrupt if the overflow flag is set, so can be used as a single-byte suffix anywhere you want to trap on overflow. And, yes, that’s signed overflow, not carry. Commented Feb 4, 2024 at 14:58
  • 3
    @Tommy - I'd say not, since it's not intrinsically different from the 'jump on overflow set' instruction that practically every processor with an overflow flag implements, from the MIX on up. Commented Feb 4, 2024 at 16:32
  • 11
    MIPS has add and addi which triggers an exception on signed integer overflow (addu and addiu if you don't want overflow checking signed or unsigned). RISC V has done away with the trapping adds. MC68000 has trapv instruction which triggers an exception if the overflow flag is set (e.g. a preceding add set the overflow flag). Commented Feb 4, 2024 at 16:53
  • 1
    @tommy - it surely falls into 'setting a flag that code can check' as mentioned by the OP. Commented Feb 4, 2024 at 17:21
  • 2
    @dave: A compact way to check the overflow flag is sort of half way between having overflow-trapping add like MIPS vs. only having conditional branches that don't record a return address. With the latter, you'd need a unique branch target for every possibly-overflowing operation to figure out which one overflowed. That's why x86 and m68k have into and trapv as well as jo or however m68k spells the branch condition. A user-space callo would be equally useful, or more useful in some programs without needing the OS's help. Commented Feb 5, 2024 at 5:24

9 Answers 9

22

The VAX optionally enables integer-overflow traps. The Processor Status Word (the half of the Processor Status Longword accessible to unprivileged modes) has trap enables for integer overflow, decimal overflow, and floating-point underflow.

The integer and decimal overflow enable bits in the PSW are set from the entry mask of a subroutine entered by a CALLS/CALLG instruction, and therefore each routine specifies its requirements for trapping.

DEC standard 32, VAX Architecture - see pages 1-25 to 1-27 for processor status, 3-71 on for procedure calls.

19

MIPS has always had trapping on overflow -- the add and sub instructions trap on signed overflow. It also has addu and subu instructions (unsigned, wrapping) that do not trap, so some compilers use them for all addition/subtraction, since with two's complement wrapping signed is the same as wrapping unsigned.

4
  • As a consequence, do DLX and RISC V have it too? Commented Feb 5, 2024 at 17:26
  • 4
    RISC-V does not (and is pretty much totally unlike MIPS, having no real connection to it). DLX I don't really know, but mostly seems to be toy, not having traps at all. Commented Feb 5, 2024 at 23:51
  • 1
    Real-world MIPS compilers just don't use the "signed" instructions at all, AFAICT. Commented Feb 6, 2024 at 15:47
  • 1
    that's why add and addi are very rarely used. Compiler generated almost always use addu/addiu Commented Feb 6, 2024 at 17:19
12

SPARC had TADDccTV and TSUBccTV : "Tagged Add (modify icc) Trap on Overflow"

These very rarely used instructions were created for dynamic typing, object oriented languages such as Lisp and Smalltalk.

With these instructions, the two lower bits of 32bits operands are "tags" to indicate if the value is an integer, or instead a pointer to an object structure. Adding an integer with an object would trigger a trap.

Integer overflows would also trigger traps, to allow variable precision integers, short integers are directly encoded in 32bits values, large integers are objects in memory ("fixnum" and "bignum" in Lisp).

11

The AT&T Bellmac 32 microprocessor, first released in 1980, could automatically trap on integer overflow. Bit 22 of its processor status word enables the overflow trap.

9

I think indisputably the most important/influential machine to do this was the IBM S/360 and its compatible successors (370, 390, "z"). Two's-complement overflow stores the truncated result, sets condition code 3, and interrupts IF a bit in the PSW register enables that. In OS/360 if you (or something you use like a language runtime) haven't ESTAEd, this caused an ABEND with IIRC code 0C-something (probably still does, but I haven't used anything after VS2).

S/360 also has packed-decimal arithmetic (aka BCD; standard not an option or extension like some contemporaneous machines), and overflow there similarly interrupts if enabled by a different PSW bit. (Floating-point overflow interrupts unconditionally, as do both integer and decimal zerodivide.)

Another machine I used, the Tandem-then-Compaq-then-HPE NonStop, also had interrupt on several arithmetic conditions (integer-2sC or floating-point overflow or zerodivide) enabled by a (single) bit in the ENV register, see page 85 here. I believe the HP3000 on which NonStop was loosely based was similar. (NonStop only fakes decimal; it has 64-bit-signed-binary arithmetic which can handle magnitudes over 10^18, plus special instructions to scale by powers of 10 and convert from and to decimal character strings.)

4

BESM-6, which did not have a separate integer ALU, would trap on overflow by default.

Integer calculations were done by disabling normalization and using either zero exponent (mostly in assembly programming), or an exponent signifying the actual value of the number (typically in Fortran, to facilitate mixing reals and integers in expressions).

Neither representation caused an integer overflow trap, instead the result started to deviate from the chosen representation of an integer, which could cause arbitrary errors later).

However, if the maximum possible exponent were used to represent integers, "integer" operations (*1) would cause an overflow trap when appropriate. I'm not aware of a programming system which used that convention, though.

*1) Integer multiplications and divisions had to be done with short routines performing pre- or post-adjustment of the exponents regardless of the representation, so it could be arranged that in those routines, either the mul/div instruction, or a following exponent adjustment instruction would trap if the result could not be represented as a integer.

3

The 68000 also has a trap-on-overflow instruction.

6
  • 3
    If you're talking about trapv, that's like x86 into: take an exception according to flags. This was discussed in comments. It is more useful for overflow-checking than just a conditional branch, though, because you can figure out which operation overflowed without having a separate branch target for every add/sub + jump-if-overflow. Commented Feb 5, 2024 at 5:21
  • 2
    @PeterCordes: Attempting to accurately report which operation overflowed makes optimization difficult; further, in many cases what's needed isn't knowledge of where overflow occurred, but rather that overflow did not cause erroneous results. If code needs to add 256 int32_t values, it may care about whether overflow caused the computation to yield an incorrect total, but be perfectly happy with an implementation that e.g. adds all of the values to produce an int64_t and only traps if the final total is outside the range of int32_t. Such an implementation may be much faster... Commented Feb 5, 2024 at 17:16
  • 1
    ...than one which had to trap if any intermediate subtotal exceeded the range of int32_t, especially if an integer overflow trap that occurred while processing the leading portion of an array would be required to prevent a memory-fault trap in cases where the latter portion was inaccessible. Commented Feb 5, 2024 at 17:24
  • 2
    @PeterCordes: If a program reports that an overflow occurred with certain inputs, then feeding those inputs to a build that traps every individual operation against overflow will identify someplace where the program performed an invalid computation. If an optimized build with an "overall" overflow check could run twice as fast as one which checked every operation, and most attempts to run a program don't result in any overflow, the cost of having to occasionally run a program a second time would be less than the savings from using looser overflow semantics. Commented Feb 5, 2024 at 17:58
  • 3
    @PeterCordes: The notion that safety checks should be omitted from production build is fundamentally misguided and dangerous, especially when applied to code which receives input from untrustworthy sources. Testing by its nature will often be blind to failure modes that weren't anticipated by the programmer, but may be exploited by someone seeking to create maliciously malformed data. Commented Feb 5, 2024 at 18:01
3

The UNIVAC I (1953) traps to 0 on arithmetic overflow.

Programming Manual -- Chapter 7, page 93 in the PDF, deals with overflow.

Specifically, the trap is effected by executing the pair of instructions in address 0; these instructions may or may not transfer control to a more extensive handler.

The trap cannot be disabled, though of course the two-instruction trap vector can be coded to do nothing.

Curiously to modern eyes, there is overflow trapping on division but not on multiplication. This is a consequence of regarding the decimal point as being "on the left", i.e. the magnitude of operands was always less than 1.

1

S/360, and many others, have a divide with a double length dividend. I believe the name for the interrupt bit is zerodivide, but it happens when the quotient is too big for the result register. In the usual case, the dividend is sign extended, and so only an actual zero divisor generates zerodivide.

As previously noted, S/360 and successors have the 4 bit program mask, which allows user programs to enable/disable four exceptions.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.