home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
compress
/
filearchivers
/
zip
/
zip-1.00.lha
/
operand.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-09
|
5KB
|
223 lines
/*
* operand.c
*
* Operand manipulation routines
*
* Mark Howell 28-Jul-1992 V1.0
*
*/
#include "ztypes.h"
/*
* load_operand
*
* Load an operand, either: a variable, popped from the stack or a literal.
*
*/
#ifdef __STDC__
zword_t load_operand (int type)
#else
zword_t load_operand (type)
int type;
#endif
{
zword_t operand;
if (type) {
/* Type 1: byte literal, or type 2: operand specifier */
operand = (zword_t) read_code_byte ();
if (type == 2) {
/* If operand specifier non-zero then it's a variable, otherwise
it's the top of the stack */
if (operand)
operand = load_variable (operand);
else
operand = stack[sp++];
}
} else
/* Type 0: word literal */
operand = read_code_word ();
return (operand);
}/* load_operand */
/*
* store_operand
*
* Store an operand, either as a variable pushed on the stack.
*
*/
#ifdef __STDC__
void store_operand (zword_t operand)
#else
void store_operand (operand)
zword_t operand;
#endif
{
zbyte_t specifier;
/* Read operand specifier byte */
specifier = read_code_byte ();
/* If operand specifier non-zero then it's a variable, otherwise it's the
pushed on the stack */
if (specifier)
store_variable (specifier, operand);
else
stack[--sp] = operand;
}/* store_operand */
/*
* load_variable
*
* Load a variable, either: a stack local variable, a global variable or the top
* of the stack.
*
*/
#ifdef __STDC__
zword_t load_variable (int number)
#else
zword_t load_variable (number)
int number;
#endif
{
zword_t variable;
if (number) {
if (number < 16)
/* number in range 1 - 15, it's a stack local variable */
variable = stack[fp - (number - 1)];
else
/* number > 15, it's a global variable */
variable = get_word (h_globals_offset + ((number - 16) * 2));
} else
/* number = 0, get from top of stack */
variable = stack[sp];
return (variable);
}/* load_variable */
/*
* store_variable
*
* Store a variable, either: a stack local variable, a global variable or the top
* of the stack.
*
*/
#ifdef __STDC__
void store_variable (int number, zword_t variable)
#else
void store_variable (number, variable)
int number;
zword_t variable;
#endif
{
if (number) {
if (number < 16)
/* number in range 1 - 15, it's a stack local variable */
stack[fp - (number - 1)] = variable;
else
/* number > 15, it's a global variable */
set_word (h_globals_offset + ((number - 16) * 2), variable);
} else
/* number = 0, get from top of stack */
stack[sp] = variable;
}/* store_variable */
/*
* conditional_jump
*
* Take a jump after an instruction based on the flag, either true or false. The
* jump can be modified by the change logic flag. Normally jumps are taken
* when the flag is true. When the change logic flag is set then the jump is
* taken when flag is false. A PC relative jump can also be taken. This jump can
* either be a positive or negative byte or word range jump. An additional
* feature is the return option. If the jump offset is zero or one then that
* literal value is passed to the return instruction, instead of a jump being
* taken. Complicated or what!
*
*/
#ifdef __STDC__
void conditional_jump (int flag)
#else
void conditional_jump (flag)
int flag;
#endif
{
zbyte_t specifier;
zword_t offset;
/* Read the specifier byte */
specifier = read_code_byte ();
/* If the reverse logic flag is set then reverse the flag */
if (specifier & 0x80)
flag = (flag) ? 0 : 1;
/* Jump offset is in bottom 6 bits */
offset = (zword_t) specifier & 0x3f;
/* If the byte range jump flag is not set then load another offset byte */
if ((specifier & 0x40) == 0) {
/* Add extra offset byte to existing shifted offset */
offset = (offset << 8) + read_code_byte ();
/* If top bit of offset is set then propogate the sign bit */
if (offset & 0x2000)
offset |= 0xc000;
}
/* If the flag is false then do the jump */
if (flag == 0)
/* If offset equals 0 or 1 return that value instead */
if (offset == 0 || offset == 1)
ret (offset);
else
/* Add offset to PC */
pc = (unsigned long) (pc + (short) offset - 2);
}/* conditional_jump */