347 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			347 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Sources of the "LOGICAL" group instructions
 | 
						|
 */
 | 
						|
 | 
						|
/* $Header$ */
 | 
						|
 | 
						|
#include	<em_abs.h>
 | 
						|
#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"
 | 
						|
 | 
						|
#ifdef	LOGGING
 | 
						|
extern int must_test;
 | 
						|
#endif	LOGGING
 | 
						|
 | 
						|
#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
 | 
						|
 | 
						|
DoANDl2(arg)
 | 
						|
	size arg;
 | 
						|
{
 | 
						|
	/* AND w: Boolean and on two groups of w bytes */
 | 
						|
	register size l = (L_arg_2() * arg);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoANDl2(%ld)", l));
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
DoANDm(arg)
 | 
						|
	size arg;
 | 
						|
{
 | 
						|
	/* AND w: Boolean and on two groups of w bytes */
 | 
						|
	register size l = arg_w(arg);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoANDm(%ld)", l));
 | 
						|
	spoilFRA();
 | 
						|
	for (p = SP; p < (SP + l); p ++) {
 | 
						|
		check_def(p, l);
 | 
						|
		stack_loc(p + l) &= stack_loc(p);
 | 
						|
	}
 | 
						|
	st_dec(l);
 | 
						|
}
 | 
						|
 | 
						|
DoANDz()
 | 
						|
{
 | 
						|
	/* AND w: Boolean and on two groups of w bytes */
 | 
						|
	/* size of objects to be compared (in bytes) on top of stack */
 | 
						|
	register size l = upop(wsize);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoANDz(%ld)", l));
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
DoIORl2(arg)
 | 
						|
	size arg;
 | 
						|
{
 | 
						|
	/* IOR w: Boolean inclusive or on two groups of w bytes */
 | 
						|
	register size l = (L_arg_2() * arg);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoIORl2(%ld)", l));
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
DoIORm(arg)
 | 
						|
	size arg;
 | 
						|
{
 | 
						|
	/* IOR w: Boolean inclusive or on two groups of w bytes */
 | 
						|
	register size l = arg_w(arg);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoIORm(%ld)", l));
 | 
						|
	spoilFRA();
 | 
						|
	for (p = SP; p < (SP + l); p++) {
 | 
						|
		check_def(p, l);
 | 
						|
		stack_loc(p + l) |= stack_loc(p);
 | 
						|
	}
 | 
						|
	st_dec(l);
 | 
						|
}
 | 
						|
 | 
						|
DoIORs(hob, wfac)
 | 
						|
	long hob;
 | 
						|
	size wfac;
 | 
						|
{
 | 
						|
	/* IOR w: Boolean inclusive or on two groups of w bytes */
 | 
						|
	register size l = (S_arg(hob) * wfac);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoIORs(%ld)", l));
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
DoIORz()
 | 
						|
{
 | 
						|
	/* IOR w: Boolean inclusive or on two groups of w bytes */
 | 
						|
	register size l = upop(wsize);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoIORz(%ld)", l));
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
DoXORl2(arg)
 | 
						|
	size arg;
 | 
						|
{
 | 
						|
	/* XOR w: Boolean exclusive or on two groups of w bytes */
 | 
						|
	register size l = (L_arg_2() * arg);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoXORl2(%ld)", l));
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
DoXORz()
 | 
						|
{
 | 
						|
	/* XOR w: Boolean exclusive or on two groups of w bytes */
 | 
						|
	register size l = upop(wsize);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoXORz(%ld)", l));
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
DoCOMl2(arg)
 | 
						|
	size arg;
 | 
						|
{
 | 
						|
	/* COM w: Complement (one's complement of top w bytes) */
 | 
						|
	register size l = (L_arg_2() * arg);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoCOMl2(%ld)", l));
 | 
						|
	spoilFRA();
 | 
						|
	l = arg_w(l);
 | 
						|
	for (p = SP; p < (SP + l); p++) {
 | 
						|
		check_def(p, 0);
 | 
						|
		stack_loc(p) = ~stack_loc(p);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
DoCOMz()
 | 
						|
{
 | 
						|
	/* COM w: Complement (one's complement of top w bytes) */
 | 
						|
	register size l = upop(wsize);
 | 
						|
	register ptr p;
 | 
						|
 | 
						|
	LOG(("@X6 DoCOMz(%ld)", l));
 | 
						|
	spoilFRA();
 | 
						|
	l = arg_w(l);
 | 
						|
	for (p = SP; p < (SP + l); p++) {
 | 
						|
		check_def(p, l);
 | 
						|
		stack_loc(p) = ~stack_loc(p);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
DoROLl2(arg)
 | 
						|
	size arg;
 | 
						|
{
 | 
						|
	/* ROL w: Rotate left a group of w bytes */
 | 
						|
	register size l = (L_arg_2() * arg);
 | 
						|
	register long s, t = upop(wsize);
 | 
						|
	register long signbit;
 | 
						|
 | 
						|
	LOG(("@X6 DoROLl2(%ld)", l));
 | 
						|
	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
 | 
						|
	
 | 
						|
	/* calculate result */
 | 
						|
	while (t--) {
 | 
						|
		s = (s & signbit) ? ((s<<1) | BIT(0)) : (s<<1);
 | 
						|
	}
 | 
						|
	npush(s, l);
 | 
						|
}
 | 
						|
 | 
						|
DoROLz()
 | 
						|
{
 | 
						|
	/* ROL w: Rotate left a group of w bytes */
 | 
						|
	register size l = upop(wsize);
 | 
						|
	register long s, t = upop(wsize);
 | 
						|
	register long signbit;
 | 
						|
 | 
						|
	LOG(("@X6 DoROLz(%ld)", l));
 | 
						|
	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
 | 
						|
	
 | 
						|
	/* calculate result */
 | 
						|
	while (t--) {
 | 
						|
		s = (s & signbit) ? ((s<<1) | BIT(0)) : (s<<1);
 | 
						|
	}
 | 
						|
	npush(s, l);
 | 
						|
}
 | 
						|
 | 
						|
DoRORl2(arg)
 | 
						|
	size arg;
 | 
						|
{
 | 
						|
	/* ROR w: Rotate right a group of w bytes */
 | 
						|
	register size l = (L_arg_2() * arg);
 | 
						|
	register long s, t = upop(wsize);
 | 
						|
	register long signbit;
 | 
						|
 | 
						|
	LOG(("@X6 DoRORl2(%ld)", l));
 | 
						|
	spoilFRA();
 | 
						|
	signbit = (l == 2) ? SIGNBIT2 : SIGNBIT4;
 | 
						|
	s = upop(arg_wi(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
 | 
						|
	
 | 
						|
	/* 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);
 | 
						|
}
 | 
						|
 | 
						|
DoRORz()
 | 
						|
{
 | 
						|
	/* ROR w: Rotate right a group of w bytes */
 | 
						|
	register size l = upop(wsize);
 | 
						|
	register long s, t = upop(wsize);
 | 
						|
	register long signbit;
 | 
						|
 | 
						|
	LOG(("@X6 DoRORz(%ld)", l));
 | 
						|
	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
 | 
						|
	
 | 
						|
	/* 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);
 | 
						|
}
 |