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