ack/util/int/do_unsar.c

176 lines
3.2 KiB
C
Raw Normal View History

2019-03-17 14:42:00 +00:00
/** @file
1988-06-22 16:57:09 +00:00
* Sources of the "UNSIGNED ARITHMETIC" group instructions
*/
1994-06-24 11:31:16 +00:00
/* $Id$ */
1988-06-22 16:57:09 +00:00
2019-03-17 14:42:00 +00:00
#include "em_abs.h"
1988-06-22 16:57:09 +00:00
#include "logging.h"
#include "global.h"
#include "log.h"
#include "mem.h"
#include "trap.h"
#include "warn.h"
#include "text.h"
#include "fra.h"
/************************************************************************
* No checking is performed, except for division by zero. *
* The operands popped from the stack are put in unsigned *
* longs. Now the required operation can be performed *
* immediately. Whether the wordsize is two or four bytes *
* doesn't matter. Alas, arithmetic is performed modulo *
* the highest unsigned number for the given size plus 1. *
************************************************************************/
#ifdef LOGGING
extern int must_test;
#endif /* LOGGING */
1988-06-22 16:57:09 +00:00
#define adu(w1,w2) (unsigned long)(w1 + w2)
#define sbu(w1,w2) (unsigned long)(w1 - w2)
#define mlu(w1,w2) (unsigned long)(w1 * w2)
PRIVATE unsigned long dvu(), rmu(), slu(), sru();
2019-03-17 14:42:00 +00:00
/** ADU w: Addition */
void DoADU(register size l)
1988-06-22 16:57:09 +00:00
{
register unsigned long t = upop(arg_wi(l));
LOG(("@U6 DoADU(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
npush((long) adu(upop(l), t), l);
}
2019-03-17 14:42:00 +00:00
/** SBU w: Subtraction */
void DoSBU(register size l)
1988-06-22 16:57:09 +00:00
{
register unsigned long t = upop(arg_wi(l));
LOG(("@U6 DoSBU(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
npush((long) sbu(upop(l), t), l);
}
2019-03-17 14:42:00 +00:00
/** MLU w: Multiplication */
void DoMLU(register size l)
1988-06-22 16:57:09 +00:00
{
register unsigned long t = upop(arg_wi(l));
LOG(("@U6 DoMLU(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
npush((long) mlu(upop(l), t), l);
}
2019-03-17 14:42:00 +00:00
/** DVU w: Division */
void DoDVU(register size l)
1988-06-22 16:57:09 +00:00
{
register unsigned long t = upop(arg_wi(l));
LOG(("@U6 DoDVU(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
npush((long) dvu(upop(l), t), l);
}
2019-03-17 14:42:00 +00:00
/** RMU w: Remainder */
void DoRMU(register size l)
1988-06-22 16:57:09 +00:00
{
register unsigned long t = upop(arg_wi(l));
LOG(("@U6 DoRMU(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
npush((long) rmu(upop(l), t), l);
}
2019-03-17 14:42:00 +00:00
/** SLU w: Shift left */
void DoSLU(register size l)
1988-06-22 16:57:09 +00:00
{
1989-11-22 13:38:37 +00:00
register unsigned long t = uwpop();
1988-06-22 16:57:09 +00:00
LOG(("@U6 DoSLU(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
l = arg_wi(l);
npush((long) slu(upop(l), t, l), l);
}
2019-03-17 14:42:00 +00:00
/** SRU w: Shift right */
void DoSRU(register size l)
1988-06-22 16:57:09 +00:00
{
1989-11-22 13:38:37 +00:00
register unsigned long t = uwpop();
1988-06-22 16:57:09 +00:00
LOG(("@U6 DoSRU(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
l = arg_wi(l);
npush((long) sru(upop(l), t, l), l);
}
2019-03-17 14:42:00 +00:00
PRIVATE unsigned long dvu(
unsigned long w1,
unsigned long w2)
1988-06-22 16:57:09 +00:00
{
if (w2 == 0) {
if (!(IgnMask&BIT(EIDIVZ))) {
trap(EIDIVZ);
}
else return (0L);
}
return (w1 / w2);
}
2019-03-17 14:42:00 +00:00
PRIVATE unsigned long rmu(
unsigned long w1,
unsigned long w2)
1988-06-22 16:57:09 +00:00
{
if (w2 == 0) {
if (!(IgnMask&BIT(EIDIVZ))) {
trap(EIDIVZ);
}
else return (0L);
}
return (w1 % w2);
}
/*ARGSUSED*/
2019-03-17 14:42:00 +00:00
PRIVATE unsigned long slu(
unsigned long w1,
unsigned long w2,
size nbytes)
1988-06-22 16:57:09 +00:00
{
2019-03-17 14:42:00 +00:00
/* w1 << w2 */
1988-06-22 16:57:09 +00:00
#ifdef LOGGING
if (must_test) {
/* check shift distance */
if (w2 >= nbytes*8) {
warning(WSHLARGE);
w2 = nbytes*8 - 1;
}
}
#endif /* LOGGING */
1988-06-22 16:57:09 +00:00
/* calculate result */
return (w1 << w2);
}
/*ARGSUSED*/
2019-03-17 14:42:00 +00:00
PRIVATE unsigned long sru(
unsigned long w1,
unsigned long w2,
size nbytes)
1988-06-22 16:57:09 +00:00
{
2019-03-17 14:42:00 +00:00
/* w1 >> w2 */
1988-06-22 16:57:09 +00:00
#ifdef LOGGING
if (must_test) {
/* check shift distance */
if (w2 >= nbytes*8) {
warning(WSHLARGE);
w2 = nbytes*8 - 1;
}
}
#endif /* LOGGING */
1988-06-22 16:57:09 +00:00
/* calculate result */
return (w1 >> w2);
}