X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=interpreters%2Fnitfol%2Fop_math.c;fp=interpreters%2Fnitfol%2Fop_math.c;h=923bcde0d887a8a092037cdb1a84c94bc9ed371a;hb=c98ccb87aa2581cbcd0458682727274b6e9a8cf7;hp=0000000000000000000000000000000000000000;hpb=a1689380dcfe59c99e70da8c311ace071d113ce5;p=rodin%2Fchimara.git diff --git a/interpreters/nitfol/op_math.c b/interpreters/nitfol/op_math.c new file mode 100644 index 0000000..923bcde --- /dev/null +++ b/interpreters/nitfol/op_math.c @@ -0,0 +1,253 @@ +/* Nitfol - z-machine interpreter using Glk for output. + Copyright (C) 1999 Evin Robertson + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + + The author can be reached at nitfol@deja.com +*/ +#include "nitfol.h" + + +void op_load(void) +{ + mop_store_result(get_var(operand[0])); +} + +void op_store(void) +{ + set_var(operand[0], operand[1]); +} + +void op_add(void) +{ + mop_store_result(ARITHMASK(operand[0] + operand[1])); +} + +void op_sub(void) +{ + mop_store_result(ARITHMASK(operand[0] + neg(operand[1]))); +} + + +void op_and(void) +{ + mop_store_result(operand[0] & operand[1]); +} + +void op_or(void) +{ + mop_store_result(operand[0] | operand[1]); +} + +void op_not(void) +{ + mop_store_result(ARITHMASK(~operand[0])); +} + + +void op_art_shift(void) +{ + if(is_neg(operand[1])) { + if(is_neg(operand[0])) { + zword i; + zword foo = operand[0]; + /* FIXME: is there a better way? */ + for(i = 0; i < neg(operand[1]); i++) { + foo >>= 1; + foo |= ZWORD_TOPBITMASK; + } + mop_store_result(foo); + } else { + mop_store_result(operand[0] >> neg(operand[1])); + } + } else { + mop_store_result(ARITHMASK(operand[0] << operand[1])); + } +} + +void op_log_shift(void) +{ + if(is_neg(operand[1])) + mop_store_result(operand[0] >> neg(operand[1]) ); + else + mop_store_result(ARITHMASK(operand[0] << operand[1])); +} + + +void op_dec(void) +{ + zword val = ARITHMASK(get_var(operand[0]) - 1); + set_var(operand[0], val); +} + +void op_dec_chk(void) +{ + zword val = ARITHMASK(get_var(operand[0]) - 1); + set_var(operand[0], val); + + if(is_lessthan(val, operand[1])) + mop_take_branch(); + else + mop_skip_branch(); +} + +void op_inc(void) +{ + zword val = ARITHMASK(get_var(operand[0]) + 1); + set_var(operand[0], val); +} + +void op_inc_chk(void) +{ + unsigned val = ARITHMASK(get_var(operand[0]) + 1); + set_var(operand[0], val); + + if(is_greaterthan(val, operand[1])) + mop_take_branch(); + else + mop_skip_branch(); +} + + +zword z_mult(zword a, zword b) +{ + int sign = 0; + + if(is_neg(a)) { + a = neg(a); + sign = 1; + } + if(is_neg(b)) { + b = neg(b); + sign ^= 1; + } + + if(sign) + return ARITHMASK(neg(a * b)); + else + return ARITHMASK(a * b); + +} + + +zword z_div(zword a, zword b) +{ + int sign = 0; + + if(b == 0) { + n_show_error(E_MATH, "division by zero", a); + return ZWORD_MAX; + } + + if(is_neg(a)) { + a = neg(a); + sign = 1; + } + if(is_neg(b)) { + b = neg(b); + sign ^= 1; + } + + if(sign) + return neg(a / b); + else + return a / b; +} + + +zword z_mod(zword a, zword b) +{ + int sign = 0; + + if(b == 0) { + n_show_error(E_MATH, "modulo by zero", a); + return 0; + } + + if(is_neg(a)) { + a = neg(a); + sign = 1; + } + if(is_neg(b)) { + b = neg(b); + } + + if(sign) + return neg(a % b); + else + return a % b; +} + + +void op_div(void) +{ + mop_store_result(z_div(operand[0], operand[1])); +} + + +void op_mod(void) +{ + mop_store_result(z_mod(operand[0], operand[1])); +} + + +void op_mul(void) +{ + mop_store_result(z_mult(operand[0], operand[1])); +} + + +/* FIXME: use our own rng */ +zword z_random(zword num) +{ + static BOOL rising = FALSE; + static unsigned r = 0; + zword result = 0; + + if(num == 0) { + if(faked_random_seed) + srand(faked_random_seed); + else + srand(time(NULL)); + rising = FALSE; + } else if(is_neg(num)) { + if(neg(num) < 1000) { + r = 0; + rising = TRUE; + } else { + srand(neg(num)); + rising = FALSE; + } + } else { + if(rising) { + r++; + if(r > num) + r = 1; + result = r; + } else { + result = (1 + (rand() % num)); + } + } + return result; +} + +void op_random(void) +{ + if(operand[0] == 0) + n_show_port(E_MATH, "some interpreters don't like @random 0", operand[0]); + + mop_store_result(z_random(operand[0])); +} +