mirror of
https://github.com/Interlisp/maiko.git
synced 2026-01-15 07:54:13 +00:00
* Use gcc / clang overflow builtins. This avoids expensive checks for overflow that employ undefined behavior. This is a step along the way towards replacing the old hand-written assembler that did the same thing in terms of using the CPU's overflow detection. * Remove unimplemented SPARC asm for multiplication, divide, and remainder. This wasn't implemented before, and for multiplication, it is now implemented for gcc and friends using overflow detection. * Remove USE_INLINE_ARITH. Now that we have the compiler built-ins for detecting overflow, we don't need custom assembly for it for each platform. For now, we keep, but still don't use, the code that do a hot path through the dispatch loop for some math. This code isn't actually running or in use, but it is separate from how the other inline arithmetic was being performed. These are the `fast_op_*` functions that are implemented in assembler.
167 lines
3.5 KiB
C
167 lines
3.5 KiB
C
/* $Id: arith4.c,v 1.3 1999/05/31 23:35:21 sybalsky Exp $ (C) Copyright Venue, All Rights Reserved
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* (C) Copyright 1989-95 Venue. All Rights Reserved. */
|
|
/* Manufactured in the United States of America. */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#include "version.h"
|
|
|
|
/***********************************************************************/
|
|
/*
|
|
File Name : arith4.c
|
|
|
|
Including : OP_times2 326Q(OP_itimes2 332Q)
|
|
|
|
OP_quot 327Q(OP_iquot 333Q)
|
|
OP_reminder 334Q
|
|
|
|
*/
|
|
/**********************************************************************/
|
|
|
|
#include "lispemul.h"
|
|
#include "lispmap.h"
|
|
#include "lspglob.h"
|
|
#include "lsptypes.h"
|
|
#include "address.h"
|
|
#include "adr68k.h"
|
|
#include "cell.h"
|
|
#include "medleyfp.h"
|
|
#include "arith.h"
|
|
|
|
#include "arith4defs.h"
|
|
#include "fpdefs.h"
|
|
#include "mkcelldefs.h"
|
|
|
|
/**********************************************************************/
|
|
/*
|
|
|
|
Func name : N_OP_times2(itimes2)
|
|
|
|
*/
|
|
/**********************************************************************/
|
|
int N_OP_times2(int tosm1, int tos) {
|
|
int arg1, arg2;
|
|
int result;
|
|
|
|
N_GETNUMBER(tosm1, arg1, doufn);
|
|
N_GETNUMBER(tos, arg2, doufn);
|
|
|
|
#ifdef USE_OVERFLOW_BUILTINS
|
|
|
|
if (__builtin_smul_overflow(arg1, arg2, &result)) {
|
|
goto doufn2;
|
|
}
|
|
N_ARITH_SWITCH(result);
|
|
|
|
#else
|
|
|
|
result = arg1 * arg2;
|
|
if ((arg2 != 0) && ((result / arg2) != arg1)) goto doufn2;
|
|
N_ARITH_SWITCH(result);
|
|
|
|
#endif
|
|
|
|
doufn2:
|
|
ERROR_EXIT(tos);
|
|
doufn:
|
|
return (N_OP_ftimes2(tosm1, tos));
|
|
|
|
} /* end N_OP_times2 */
|
|
|
|
int N_OP_itimes2(int tosm1, int tos) {
|
|
int arg1, arg2;
|
|
int result;
|
|
|
|
N_IGETNUMBER(tosm1, arg1, doufn);
|
|
N_IGETNUMBER(tos, arg2, doufn);
|
|
|
|
#ifdef USE_OVERFLOW_BUILTINS
|
|
|
|
if (__builtin_smul_overflow(arg1, arg2, &result)) {
|
|
goto doufn;
|
|
}
|
|
N_ARITH_SWITCH(result);
|
|
|
|
#else
|
|
|
|
/* UB: signed integer overflow: 1073741824 * 32768 cannot be represented in type 'int' */
|
|
result = arg1 * arg2;
|
|
if ((arg2 != 0) && ((result / arg2) != arg1)) { goto doufn; }
|
|
N_ARITH_SWITCH(result);
|
|
|
|
#endif
|
|
|
|
doufn:
|
|
ERROR_EXIT(tos);
|
|
|
|
} /* end N_OP_itimes2 */
|
|
|
|
/**********************************************************************/
|
|
/*
|
|
|
|
Func name : N_OP_quot(iquot)
|
|
|
|
*/
|
|
/**********************************************************************/
|
|
int N_OP_quot(int tosm1, int tos) {
|
|
int arg1, arg2;
|
|
int result;
|
|
|
|
N_GETNUMBER(tosm1, arg1, doufn);
|
|
N_GETNUMBER(tos, arg2, doufn);
|
|
if (arg2 == 0) goto doufn2;
|
|
|
|
result = arg1 / arg2; /* lmm: note: no error case!! */
|
|
N_ARITH_SWITCH(result);
|
|
|
|
doufn2:
|
|
ERROR_EXIT(tos);
|
|
doufn:
|
|
return (N_OP_fquotient(tosm1, tos));
|
|
|
|
} /* end N_OP_quot */
|
|
|
|
int N_OP_iquot(int tosm1, int tos) {
|
|
register int arg1, arg2;
|
|
register int result;
|
|
|
|
N_IGETNUMBER(tosm1, arg1, doufn);
|
|
N_IGETNUMBER(tos, arg2, doufn);
|
|
if (arg2 == 0) goto doufn;
|
|
|
|
result = arg1 / arg2;
|
|
N_ARITH_SWITCH(result);
|
|
|
|
doufn:
|
|
ERROR_EXIT(tos);
|
|
|
|
} /* end N_OP_quot */
|
|
|
|
/**********************************************************************/
|
|
/*
|
|
|
|
Func name : N_OP_iremainder
|
|
|
|
*/
|
|
/**********************************************************************/
|
|
|
|
int N_OP_iremainder(int tosm1, int tos) {
|
|
register int arg1, arg2;
|
|
register int result;
|
|
|
|
N_IGETNUMBER(tosm1, arg1, doufn);
|
|
N_IGETNUMBER(tos, arg2, doufn);
|
|
if (arg2 == 0) goto doufn;
|
|
|
|
result = arg1 % arg2;
|
|
N_ARITH_SWITCH(result);
|
|
|
|
doufn:
|
|
ERROR_EXIT(tos);
|
|
|
|
} /* end N_OP_iremainder */
|