ack/util/int/do_logic.c

156 lines
2.7 KiB
C
Raw Permalink Normal View History

2019-03-17 14:42:00 +00:00
/** @file
* Sources of the "LOGICAL" group instructions
1988-06-22 16:57:09 +00:00
*/
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 "warn.h"
#include "mem.h"
#include "shadow.h"
#include "trap.h"
#include "text.h"
#include "fra.h"
#include "switch.h"
1988-06-22 16:57:09 +00:00
#ifdef LOGGING
extern int must_test;
#endif /* LOGGING */
1988-06-22 16:57:09 +00:00
#ifdef LOGGING
#define check_def(p,l) if (!st_sh(p) || !st_sh(p+l)) {warning(WUNLOG);}
#else
#define check_def(p,l)
#endif /* LOGGING */
1988-06-22 16:57:09 +00:00
2019-03-17 14:42:00 +00:00
/** AND w: Boolean and on two groups of w bytes. Size of objects to be compared
* (in bytes) on top of stack
*/
void DoAND(register size l)
1988-06-22 16:57:09 +00:00
{
register ptr p;
LOG(("@X6 DoAND(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
l = arg_w(l);
for (p = SP; p < (SP + l); p++) {
check_def(p, l);
stack_loc(p + l) &= stack_loc(p);
}
st_dec(l);
}
2019-03-17 14:42:00 +00:00
/** IOR w: Boolean inclusive or on two groups of w bytes */
void DoIOR(register size l)
1988-06-22 16:57:09 +00:00
{
register ptr p;
LOG(("@X6 DoIOR(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
l = arg_w(l);
for (p = SP; p < (SP + l); p++) {
check_def(p, l);
stack_loc(p + l) |= stack_loc(p);
}
st_dec(l);
}
2019-03-17 14:42:00 +00:00
/** XOR w: Boolean exclusive or on two groups of w bytes */
void DoXOR(register size l)
1988-06-22 16:57:09 +00:00
{
register ptr p;
LOG(("@X6 DoXOR(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
l = arg_w(l);
for (p = SP; p < (SP + l); p++) {
check_def(p, l);
stack_loc(p + l) ^= stack_loc(p);
}
st_dec(l);
}
2019-03-17 14:42:00 +00:00
/** COM w: Complement (one's complement of top w bytes) */
void DoCOM(register size l)
1988-06-22 16:57:09 +00:00
{
register ptr p;
LOG(("@X6 DoCOM(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
l = arg_w(l);
for (p = SP; p < (SP + l); p++) {
check_def(p, 0);
stack_loc(p) = ~stack_loc(p);
}
}
2019-03-17 14:42:00 +00:00
/** ROL w: Rotate left a group of w bytes */
void DoROL(register size l)
1988-06-22 16:57:09 +00:00
{
1989-11-22 13:38:37 +00:00
register long s, t = uwpop();
1988-06-22 16:57:09 +00:00
register long signbit;
LOG(("@X6 DoROL(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
signbit = (arg_wi(l) == 2) ? SIGNBIT2 : SIGNBIT4;
s = upop(l);
#ifdef LOGGING
if (must_test) {
/* check shift distance */
if (t < 0) {
warning(WSHNEG);
t = 0;
}
if (t >= l*8) {
warning(WSHLARGE);
t = l*8 - 1;
}
}
#endif /* LOGGING */
1988-06-22 16:57:09 +00:00
/* calculate result */
while (t--) {
s = (s & signbit) ? ((s<<1) | BIT(0)) : (s<<1);
}
npush(s, l);
}
2019-03-17 14:42:00 +00:00
/** ROR w: Rotate right a group of w bytes */
void DoROR(register size l)
1988-06-22 16:57:09 +00:00
{
1989-11-22 13:38:37 +00:00
register long s, t = uwpop();
1988-06-22 16:57:09 +00:00
register long signbit;
LOG(("@X6 DoROR(%ld)", l));
1988-06-22 16:57:09 +00:00
spoilFRA();
signbit = (arg_wi(l) == 2) ? SIGNBIT2 : SIGNBIT4;
s = upop(l);
#ifdef LOGGING
if (must_test) {
/* check shift distance */
if (t < 0) {
warning(WSHNEG);
t = 0;
}
if (t >= l*8) {
warning(WSHLARGE);
t = l*8 - 1;
}
}
#endif /* LOGGING */
1988-06-22 16:57:09 +00:00
/* calculate result */
while (t--) {
/* the >> in C does sign extension, the ROR does not */
if (s & BIT(0))
s = (s >> 1) | signbit;
else s = (s >> 1) & ~signbit;
}
npush(s, l);
}