This is machine.c in view mode; [Download] [Up]
/* * Copyright (C) 1985-1992 New York University * * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for * warranty (none) and distribution info and also the GNU General Public * License for more details. */ /* machine.c - procedures which optionally may be recoded in assembly language * * This file contains procedures which perform the integer arithmetic * operations (addition, subtraction and multiplication) which require * overflow detection of the result. C does not provide an efficient * mechanism for catching overflows, so this is accomplished by doing * some checking of the signs of the operands and result. * * A more appropriate mechanism, would be to have this computation and * overflow check written in assembly language, where more control of * the overflow bit can be realized. * * Each of the arithmetic procedures accept three parameters. The first * two are the operands and the third is a pointer to an int representating * a flag indicating whether there was an overflow in the operation or not. * * All of the arithmetic procedures can be compiled as is, however * if there is a desire for an more efficient implementation assembly * routine can be supplied which will supercede the C versions. If * this is done you must define the appropriate symbolic name immediately * below to avoid compiling the c prototype code. For example, once * word_add is done in assembly, insert a define for WORD_ADD under * an "ifdef" for the appropriate machine (sun, vax, etc) as is shown * for the IBM_PC case below. * * MOVE_MEM is included here only because some run-time libraries might * contain a routine which does the equivalent job and therefore could * be substituted for the C code given here for it. */ #include "config.h" #include "machineprots.h" /* * macros used to check for overflow condition on integer addition and * subtraction. We assume twos complement arithmetic with wraparound on * overflow */ #define sign(x) (x < 0 ? 1 : 0) #define addoverflow(op1,op2,res) (sign(op1)==sign(op2) && sign(res)!=sign(op1)) #define suboverflow(op1,op2,res) (sign(op1)!=sign(op2) && sign(res)!=sign(op1)) #ifndef WORD_ADD int word_add(int a, int b, int *overflow) /*;word_add*/ { /* add with overflow check */ register int r; r = a + b; *overflow = addoverflow(a, b, r); return r; } #endif #ifndef WORD_SUB int word_sub(int a, int b, int *overflow) /*;word_sub*/ { /* subtract with overflow check */ register int r; r = a - b; *overflow = suboverflow(a, b, r); return r; } #endif #ifndef WORD_MUL int word_mul(int a, int b, int *overflow) /*;word_mul*/ { /* multiply with overflow check */ register int r; if(a) { r = a * b; *overflow = (b != r/a) || (a == -1 && b < 0 && r < 0); } else { *overflow = r = 0; } return r; } #endif #ifndef LONG_ADD long long_add(long a, long b, int *overflow) /*;long_add*/ { /* add with overflow check */ register long r; r = a + b; *overflow = addoverflow(a, b, r); return r; } #endif #ifndef LONG_SUB long long_sub(long a, long b, int *overflow) /*;long_sub*/ { /* subtract with overflow check */ register long r; r = a - b; *overflow = suboverflow(a, b, r); return r; } #endif #ifndef LONG_MUL long long_mul(long a, long b, int *overflow) /*;long_mul*/ { /* multiply with overflow check */ register long r; if(a) { r = a * b; *overflow = (b != r/a) || (a == -1 && b < 0 && r < 0); } else { r = 0; *overflow = (int)r; } return r; } #endif #ifndef MOVE_MEM void move_mem(int *src, int *dst, int n) /*;move_mem*/ { /* move n words from src to dst * We must watch for possible overlap. */ unsigned long usrc, udst; unsigned int i; /* View pointers as unsigned to see if possible overlap */ if (n==0) return; usrc = (unsigned) src; udst = (unsigned) dst; if (usrc >= udst) { /* if no possibility of overlap */ for (i=0;i<n;i++) *dst++ = *src++; } else { /* Here if possible overlap (usrc<udst) , set base to smaller * of pointer values and determine corresponding indices */ if ((usrc + sizeof(int)*(n-1)) < udst ) { /* can use upwards loops */ for (i=0; i<n; i++) *dst++ = *src++; } else { /* overlap, must move backwards */ ; n--; dst += n; src += n; for (i=0; i<=n; i++) { *dst-- = *src--; } } } } #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.