1 /*
2 * interpre.c
3 *
4 * Main interpreter loop
5 *
6 */
7
8 #include "ztypes.h"
9
10 static int halt = FALSE;
11
12 /*
13 * interpret
14 *
15 * Interpret Z code
16 *
17 */
18
19 #ifdef __STDC__
interpret()20 int interpret ()
21 #else
22 int interpret ()
23 #endif
24 {
25 zbyte_t opcode;
26 zword_t specifier, operand[8];
27 int maxoperands, count, extended, i;
28
29 interpreter_status = 1;
30
31 /* Loop until HALT instruction executed */
32
33 for (interpreter_state = RUN; interpreter_state == RUN && halt == FALSE; ) {
34
35 /* Load opcode and set operand count */
36
37 opcode = read_code_byte ();
38 if (h_type > V4 && opcode == 0xbe) {
39 opcode = read_code_byte ();
40 extended = TRUE;
41 } else
42 extended = FALSE;
43 count = 0;
44
45 /* Multiple operand instructions */
46
47 if ((opcode < 0x80 || opcode > 0xc0) || extended == TRUE) {
48
49 /* Two operand class, load both operands */
50
51 if (opcode < 0x80 && extended == FALSE) {
52 operand[count++] = load_operand ((opcode & 0x40) ? 2 : 1);
53 operand[count++] = load_operand ((opcode & 0x20) ? 2 : 1);
54 opcode &= 0x1f;
55 } else {
56
57 /* Variable operand class, load operand specifier */
58
59 opcode &= 0x3f;
60 if (opcode == 0x2c || opcode == 0x3a) { /* Extended CALL instruction */
61 specifier = read_code_word ();
62 maxoperands = 8;
63 } else {
64 specifier = read_code_byte ();
65 maxoperands = 4;
66 }
67
68 /* Load operands */
69
70 for (i = (maxoperands - 1) * 2; i >= 0; i -= 2)
71 if (((specifier >> i) & 0x03) != 3)
72 operand[count++] = load_operand ((specifier >> i) & 0x03);
73 else
74 i = 0;
75 }
76
77 if (extended == TRUE)
78 switch ((char) opcode) {
79
80 /* Extended operand instructions */
81
82 case 0x00: save (count, operand); break;
83 case 0x01: restore (count, operand); break;
84 case 0x02: shift (operand[0], operand[1]); break;
85 case 0x03: arith_shift (operand[0], operand[1]); break;
86 case 0x04: set_font_attribute (operand[0]); break;
87
88 case 0x09: undo_save (); break;
89 case 0x0a: undo_restore (); break;
90
91 default: fatal ("Illegal operation");
92 }
93 else
94 switch ((char) opcode) {
95
96 /* Two or multiple operand instructions */
97
98 case 0x01: compare_je (count, operand); break;
99 case 0x02: compare_jl (operand[0], operand[1]); break;
100 case 0x03: compare_jg (operand[0], operand[1]); break;
101 case 0x04: decrement_check (operand[0], operand[1]); break;
102 case 0x05: increment_check (operand[0], operand[1]); break;
103 case 0x06: compare_parent_object (operand[0], operand[1]); break;
104 case 0x07: test (operand[0], operand[1]); break;
105 case 0x08: or (operand[0], operand[1]); break;
106 case 0x09: and (operand[0], operand[1]); break;
107 case 0x0a: test_attr (operand[0], operand[1]); break;
108 case 0x0b: set_attr (operand[0], operand[1]); break;
109 case 0x0c: clear_attr (operand[0], operand[1]); break;
110 case 0x0d: store_variable (operand[0], operand[1]); break;
111 case 0x0e: insert_object (operand[0], operand[1]); break;
112 case 0x0f: load_word (operand[0], operand[1]); break;
113 case 0x10: load_byte (operand[0], operand[1]); break;
114 case 0x11: load_property (operand[0], operand[1]); break;
115 case 0x12: load_property_address (operand[0], operand[1]); break;
116 case 0x13: load_next_property (operand[0], operand[1]); break;
117 case 0x14: add (operand[0], operand[1]); break;
118 case 0x15: subtract (operand[0], operand[1]); break;
119 case 0x16: multiply (operand[0], operand[1]); break;
120 case 0x17: divide (operand[0], operand[1]); break;
121 case 0x18: remainder (operand[0], operand[1]); break;
122 case 0x19: call (count, operand, FUNCTION); break;
123 case 0x1a: call (count, operand, PROCEDURE); break;
124 case 0x1b: set_colour_attribute (operand[0], operand[1]); break;
125 case 0x1c: unwind (operand[0], operand[1]); break;
126
127 /* Multiple operand instructions */
128
129 case 0x20: call (count, operand, FUNCTION); break;
130 case 0x21: store_word (operand[0], operand[1], operand[2]); break;
131 case 0x22: store_byte (operand[0], operand[1], operand[2]); break;
132 case 0x23: store_property (operand[0], operand[1], operand[2]); break;
133 case 0x24: read_line (count, operand); break;
134 case 0x25: print_character (operand[0]); break;
135 case 0x26: print_number (operand[0]); break;
136 case 0x27: ziprandom (operand[0]); break;
137 case 0x28: push_var (operand[0]); break;
138 case 0x29: pop_var (operand[0]); break;
139 case 0x2a: set_status_size (operand[0]); break;
140 case 0x2b: select_window (operand[0]); break;
141 case 0x2c: call (count, operand, FUNCTION); break;
142 case 0x2d: erase_window (operand[0]); break;
143 case 0x2e: erase_line (operand[0]); break;
144 case 0x2f: set_cursor_position (operand[0], operand[1]); break;
145
146 case 0x31: set_video_attribute (operand[0]); break;
147 case 0x32: set_format_mode (operand[0]); break;
148 case 0x33: set_print_modes (operand[0], operand[1]); break;
149 case 0x34: open_playback (operand[0]); break;
150 case 0x35: sound (count, operand); break;
151 case 0x36: read_character (count, operand); break;
152 case 0x37: scan_data (count, operand); break;
153 case 0x38: not (operand[0]); break;
154 case 0x39: call (count, operand, PROCEDURE); break;
155 case 0x3a: call (count, operand, PROCEDURE); break;
156 case 0x3b: tokenise (count, operand); break;
157 case 0x3c: encode (operand[0], operand[1], operand[2], operand[3]); break;
158 case 0x3d: move_data (operand[0], operand[1], operand[2]); break;
159 case 0x3e: print_window (count, operand); break;
160 case 0x3f: check_argument (operand[0]); break;
161
162 default: fatal ("Illegal operation");
163 }
164 } else {
165
166 /* Single operand class, load operand and execute instruction */
167
168 if (opcode < 0xb0) {
169 operand[0] = load_operand ((opcode >> 4) & 0x03);
170 switch ((char) opcode & 0x0f) {
171 case 0x00: compare_zero (operand[0]); break;
172 case 0x01: load_next_object (operand[0]); break;
173 case 0x02: load_child_object (operand[0]); break;
174 case 0x03: load_parent_object (operand[0]); break;
175 case 0x04: load_property_length (operand[0]); break;
176 case 0x05: increment (operand[0]); break;
177 case 0x06: decrement (operand[0]); break;
178 case 0x07: print_offset (operand[0]); break;
179 case 0x08: call (1, operand, FUNCTION); break;
180 case 0x09: remove_object (operand[0]); break;
181 case 0x0a: print_object (operand[0]); break;
182 case 0x0b: ret (operand[0]); break;
183 case 0x0c: jump (operand[0]); break;
184 case 0x0d: print_address (operand[0]); break;
185 case 0x0e: load (operand[0]); break;
186 case 0x0f:
187 if (h_type > V4)
188 call (1, operand, PROCEDURE);
189 else
190 not (operand[0]);
191 break;
192 }
193 } else {
194
195 /* Zero operand class, execute instruction */
196
197 switch ((char) opcode & 0x0f) {
198 case 0x00: ret (TRUE); break;
199 case 0x01: ret (FALSE); break;
200 case 0x02: print_literal (); break;
201 case 0x03: println_return (); break;
202
203 case 0x05: save (count, operand); break;
204 case 0x06: restore (count, operand); break;
205 case 0x07: restart (); break;
206 case 0x08: ret (stack[sp++]); break;
207 case 0x09: get_fp (); break;
208 case 0x0a: halt = TRUE; break;
209 case 0x0b: new_line (); break;
210 case 0x0c: display_status_line (); break;
211 case 0x0d: verify (); break;
212
213 case 0x0f: conditional_jump (TRUE); break;
214
215 default: fatal ("Illegal operation");
216 }
217 }
218 }
219 }
220
221 return (interpreter_status);
222
223 }/* interpret */
224