ifengine/math.c
2018-09-08 19:51:49 -05:00

305 lines
4.6 KiB
C

/* $Id: math.c,v 1.3 2000/07/05 15:20:34 jholder Exp $
* --------------------------------------------------------------------
* see doc/License.txt for License Information
* --------------------------------------------------------------------
*
* File name: $Id: math.c,v 1.3 2000/07/05 15:20:34 jholder Exp $
*
* Description:
*
* Modification history:
* $Log: math.c,v $
* Revision 1.3 2000/07/05 15:20:34 jholder
* Updated code to remove warnings.
*
* Revision 1.2 2000/05/25 22:28:56 jholder
* changes routine names to reflect zmachine opcode names per spec 1.0
*
* Revision 1.1.1.1 2000/05/10 14:21:34 jholder
*
* imported
*
*
* --------------------------------------------------------------------
*/
/*
* math.c
*
* Arithmetic, compare and logical instructions
*
*/
#include "ztypes.h"
/*
* z_add
*
* Add two operands
*
*/
void z_add( zword_t a, zword_t b )
{
store_operand( (zword_t)(a + b) );
}
/*
* z_sub
*
* Subtract two operands
*
*/
void z_sub( zword_t a, zword_t b )
{
store_operand( (zword_t)(a - b) );
}
/*
* mul
*
* Multiply two operands
*
*/
void z_mul( zword_t a, zword_t b )
{
store_operand( (zword_t)(( ZINT16 ) a * ( ZINT16 ) b) );
}
/*
* z_div
*
* Divide two operands
*
*/
void z_div( zword_t a, zword_t b )
{
/* The magic rule is: round towards zero. */
ZINT16 sa = ( ZINT16 ) a;
ZINT16 sb = ( ZINT16 ) b;
ZINT16 res;
if ( sb < 0 )
{
sa = -sa;
sb = -sb;
}
if ( sb == 0 )
{
#ifdef STRICTZ
report_strictz_error( STRZERR_DIV_ZERO,
"@div attempted with a divisor of zero. Result set to 32767 (0x7fff)." );
#endif
res = 32767;
}
else if ( sa >= 0 )
{
res = sa / sb;
}
else
{
res = -( ( -sa ) / ( sb ) );
}
store_operand( res );
}
/*
* z_mod
*
* Modulus divide two operands
*
*/
void z_mod( zword_t a, zword_t b )
{
/* The magic rule is: be consistent with divide, because
* (a/b)*a + (a%b) == a. So (a%b) has the same sign as a. */
ZINT16 sa = ( ZINT16 ) a;
ZINT16 sb = ( ZINT16 ) b;
ZINT16 res;
if ( sb < 0 )
{
sb = -sb;
}
if ( sb == 0 )
{
#ifdef STRICTZ
report_strictz_error( STRZERR_DIV_ZERO,
"@mod attempted with a divisor of zero. Result set to 0." );
#endif
res = 0;
}
if ( sa >= 0 )
{
res = sa % sb;
}
else
{
res = -( ( -sa ) % ( sb ) );
}
store_operand( res );
}
/*
* z_log_shift
*
* Shift +/- n bits
*
*/
void z_log_shift( zword_t a, zword_t b )
{
if ( ( ZINT16 ) b > 0 )
store_operand( (zword_t)( a << ( ZINT16 ) b ) );
else
store_operand( (zword_t)( a >> -( ( ZINT16 ) b ) ) );
}
/*
* z_art_shift
*
* Aritmetic shift +/- n bits
*
*/
void z_art_shift( zword_t a, zword_t b )
{
if ( ( ZINT16 ) b > 0 )
store_operand( ( zword_t ) ( ( ZINT16 ) a << ( ZINT16 ) b ) );
else
store_operand( ( zword_t ) ( ( ZINT16 ) a >> -( ( ZINT16 ) b ) ) );
}
/*
* z_or
*
* Logical OR
*
*/
void z_or( zword_t a, zword_t b )
{
store_operand( (zword_t)(a | b) );
}
/*
* z_not
*
* Logical NOT
*
*/
void z_not( zword_t a )
{
store_operand( (zword_t)(~a) );
}
/*
* z_and
*
* Logical AND
*
*/
void z_and( zword_t a, zword_t b )
{
store_operand( (zword_t)(a & b) );
}
/*
* z_random
*
* Return random number between 1 and operand
*
*/
void z_random( zword_t a )
{
if ( a == 0 )
store_operand( 0 );
else if ( a & 0x8000 )
{ /* (a < 0) - used to set seed with #RANDOM */
SRANDOM_FUNC( ( unsigned int ) abs( a ) );
store_operand( 0 );
}
else /* (a > 0) */
store_operand( (zword_t)(( RANDOM_FUNC( ) % a ) + 1) );
}
/*
* z_test
*
* Jump if operand 2 bit mask not set in operand 1
*
*/
void z_test( zword_t a, zword_t b )
{
conditional_jump( ( ( ~a ) & b ) == 0 );
}
/*
* z_jz
*
* Compare operand against zero
*
*/
void z_jz( zword_t a )
{
conditional_jump( a == 0 );
}
/*
* z_je
*
* Jump if operand 1 is equal to any other operand
*
*/
void z_je( int count, zword_t * operand )
{
int i;
for ( i = 1; i < count; i++ )
if ( operand[0] == operand[i] )
{
conditional_jump( TRUE );
return;
}
conditional_jump( FALSE );
}
/*
* z_jl
*
* Jump if operand 1 is less than operand 2
*
*/
void z_jl( zword_t a, zword_t b )
{
conditional_jump( ( ZINT16 ) a < ( ZINT16 ) b );
}
/*
* z_jg
*
* Jump if operand 1 is greater than operand 2
*
*/
void z_jg( zword_t a, zword_t b )
{
conditional_jump( ( ZINT16 ) a > ( ZINT16 ) b );
}