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