1 /*
2  * operand.c
3  *
4  * Operand manipulation routines
5  *
6  */
7 
8 #include "ztypes.h"
9 
10 /*
11  * load_operand
12  *
13  * Load an operand, either: a variable, popped from the stack or a literal.
14  *
15  */
16 
17 #ifdef __STDC__
load_operand(int type)18 zword_t load_operand (int type)
19 #else
20 zword_t load_operand (type)
21 int type;
22 #endif
23 {
24     zword_t operand;
25 
26     if (type) {
27 
28         /* Type 1: byte literal, or type 2: operand specifier */
29 
30         operand = (zword_t) read_code_byte ();
31         if (type == 2) {
32 
33             /* If operand specifier non-zero then it's a variable, otherwise
34                it's the top of the stack */
35 
36             if (operand)
37                 operand = load_variable (operand);
38             else
39                 operand = stack[sp++];
40         }
41     } else
42 
43         /* Type 0: word literal */
44 
45         operand = read_code_word ();
46 
47     return (operand);
48 
49 }/* load_operand */
50 
51 /*
52  * store_operand
53  *
54  * Store an operand, either as a variable pushed on the stack.
55  *
56  */
57 
58 #ifdef __STDC__
store_operand(zword_t operand)59 void store_operand (zword_t operand)
60 #else
61 void store_operand (operand)
62 zword_t operand;
63 #endif
64 {
65     zbyte_t specifier;
66 
67     /* Read operand specifier byte */
68 
69     specifier = read_code_byte ();
70 
71     /* If operand specifier non-zero then it's a variable, otherwise it's the
72        pushed on the stack */
73 
74     if (specifier)
75         store_variable (specifier, operand);
76     else
77         stack[--sp] = operand;
78 
79 }/* store_operand */
80 
81 /*
82  * load_variable
83  *
84  * Load a variable, either: a stack local variable, a global variable or the top
85  * of the stack.
86  *
87  */
88 
89 #ifdef __STDC__
load_variable(int number)90 zword_t load_variable (int number)
91 #else
92 zword_t load_variable (number)
93 int number;
94 #endif
95 {
96     zword_t variable;
97 
98     if (number) {
99         if (number < 16)
100 
101             /* number in range 1 - 15, it's a stack local variable */
102 
103             variable = stack[fp - (number - 1)];
104         else
105 
106             /* number > 15, it's a global variable */
107 
108             variable = get_word (h_globals_offset + ((number - 16) * 2));
109     } else
110 
111         /* number = 0, get from top of stack */
112 
113         variable = stack[sp];
114 
115     return (variable);
116 
117 }/* load_variable */
118 
119 /*
120  * store_variable
121  *
122  * Store a variable, either: a stack local variable, a global variable or the top
123  * of the stack.
124  *
125  */
126 
127 #ifdef __STDC__
store_variable(int number,zword_t variable)128 void store_variable (int number, zword_t variable)
129 #else
130 void store_variable (number, variable)
131 int number;
132 zword_t variable;
133 #endif
134 {
135 
136     if (number) {
137         if (number < 16)
138 
139             /* number in range 1 - 15, it's a stack local variable */
140 
141             stack[fp - (number - 1)] = variable;
142         else
143 
144             /* number > 15, it's a global variable */
145 
146             set_word (h_globals_offset + ((number - 16) * 2), variable);
147     } else
148 
149         /* number = 0, get from top of stack */
150 
151         stack[sp] = variable;
152 
153 }/* store_variable */
154 
155 /*
156  * conditional_jump
157  *
158  * Take a jump after an instruction based on the flag, either true or false. The
159  * jump can be modified by the change logic flag. Normally jumps are taken
160  * when the flag is true. When the change logic flag is set then the jump is
161  * taken when flag is false. A PC relative jump can also be taken. This jump can
162  * either be a positive or negative byte or word range jump. An additional
163  * feature is the return option. If the jump offset is zero or one then that
164  * literal value is passed to the return instruction, instead of a jump being
165  * taken. Complicated or what!
166  *
167  */
168 
169 #ifdef __STDC__
conditional_jump(int flag)170 void conditional_jump (int flag)
171 #else
172 void conditional_jump (flag)
173 int flag;
174 #endif
175 {
176     zbyte_t specifier;
177     zword_t offset;
178 
179     /* Read the specifier byte */
180 
181     specifier = read_code_byte ();
182 
183     /* If the reverse logic flag is set then reverse the flag */
184 
185     if (specifier & 0x80)
186         flag = (flag) ? 0 : 1;
187 
188     /* Jump offset is in bottom 6 bits */
189 
190     offset = (zword_t) specifier & 0x3f;
191 
192     /* If the byte range jump flag is not set then load another offset byte */
193 
194     if ((specifier & 0x40) == 0) {
195 
196         /* Add extra offset byte to existing shifted offset */
197 
198         offset = (offset << 8) + read_code_byte ();
199 
200         /* If top bit of offset is set then propogate the sign bit */
201 
202         if (offset & 0x2000)
203             offset |= 0xc000;
204     }
205 
206     /* If the flag is false then do the jump */
207 
208     if (flag == 0)
209 
210         /* If offset equals 0 or 1 return that value instead */
211 
212         if (offset == 0 || offset == 1)
213             ret (offset);
214         else
215 
216             /* Add offset to PC */
217 
218             pc = (unsigned long) (pc + (short) offset - 2);
219 
220 }/* conditional_jump */
221