1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.zmpp.vm;
24
25
26
27 /***
28 * This class represents instructions of type SHORT, 1OP.
29 *
30 * @author Wei-ju Wu
31 * @version 1.0
32 */
33 public class Short1Instruction extends AbstractInstruction {
34
35 /***
36 * List of opcodes. See Z-Machine Standards document 1.0 for
37 * explanations.
38 */
39 public static final int OP_JZ = 0x00;
40 public static final int OP_GET_SIBLING = 0x01;
41 public static final int OP_GET_CHILD = 0x02;
42 public static final int OP_GET_PARENT = 0x03;
43 public static final int OP_GET_PROP_LEN = 0x04;
44 public static final int OP_INC = 0x05;
45 public static final int OP_DEC = 0x06;
46 public static final int OP_PRINT_ADDR = 0x07;
47 public static final int OP_REMOVE_OBJ = 0x09;
48 public static final int OP_PRINT_OBJ = 0x0a;
49 public static final int OP_RET = 0x0b;
50 public static final int OP_JUMP = 0x0c;
51 public static final int OP_PRINT_PADDR = 0x0d;
52 public static final int OP_LOAD = 0x0e;
53 public static final int OP_NOT = 0x0f;
54
55 /***
56 * Constructor.
57 *
58 * @param machineState a reference to the MachineState object
59 * @param opcode the instruction's opcode
60 */
61 public Short1Instruction(Machine machineState, int opcode) {
62
63 super(machineState, opcode);
64 }
65
66 /***
67 * {@inheritDoc}
68 */
69 public void execute() {
70
71 switch (getOpcode()) {
72 case OP_JZ:
73 jz();
74 break;
75 case OP_GET_SIBLING:
76 getSibling();
77 break;
78 case OP_GET_CHILD:
79 getChild();
80 break;
81 case OP_GET_PARENT:
82 getParent();
83 break;
84 case OP_GET_PROP_LEN:
85 getPropLen();
86 break;
87 case OP_INC:
88 inc();
89 break;
90 case OP_DEC:
91 dec();
92 break;
93 case OP_PRINT_ADDR:
94 printAddr();
95 break;
96 case OP_REMOVE_OBJ:
97 removeObj();
98 break;
99 case OP_PRINT_OBJ:
100 printObj();
101 break;
102 case OP_JUMP:
103 jump();
104 break;
105 case OP_RET:
106 ret();
107 break;
108 case OP_PRINT_PADDR:
109 printPaddr();
110 break;
111 case OP_LOAD:
112 load();
113 break;
114 case OP_NOT:
115 not();
116 break;
117 default:
118 throwInvalidOpcode();
119 }
120 }
121
122 /***
123 * {@inheritDoc}
124 */
125 public InstructionForm getInstructionForm() {
126
127 return InstructionForm.SHORT;
128 }
129
130 /***
131 * {@inheritDoc}
132 */
133 public OperandCount getOperandCount() {
134
135 return OperandCount.C1OP;
136 }
137
138 /***
139 * {@inheritDoc}
140 */
141 public boolean storesResult() {
142
143 switch (getOpcode()) {
144
145 case OP_GET_SIBLING:
146 case OP_GET_CHILD:
147 case OP_GET_PARENT:
148 case OP_GET_PROP_LEN:
149 case OP_LOAD:
150 case OP_NOT:
151 return true;
152 default:
153 return false;
154 }
155 }
156
157 /***
158 * {@inheritDoc}
159 */
160 public boolean isBranch() {
161
162 switch (getOpcode()) {
163 case OP_JZ:
164 case OP_GET_SIBLING:
165 case OP_GET_CHILD:
166 return true;
167 default:
168 return false;
169 }
170 }
171
172 /***
173 * inc instruction.
174 */
175 private void inc() {
176
177 short varNum = getValue(0);
178 short value = getMachine().getVariable(varNum);
179 getMachine().setVariable(varNum, (short) (value + 1));
180 nextInstruction();
181 }
182
183 /***
184 * dec instruction.
185 */
186 private void dec() {
187
188 short varNum = getValue(0);
189 short value = (short) getMachine().getVariable(varNum);
190 getMachine().setVariable(varNum, (short) (value - 1));
191 nextInstruction();
192 }
193
194 /***
195 * not instruction.
196 */
197 private void not() {
198
199 int notvalue = ~getUnsignedValue(0);
200 storeResult((short) (notvalue & 0xffff));
201 nextInstruction();
202 }
203
204 /***
205 * get_parent instruction.
206 */
207 private void getParent() {
208
209 int obj = getUnsignedValue(0);
210 ZObject zobj = getMachine().getObjectTree().getObject(obj);
211 int parent = zobj.getParent();
212 storeResult((short) (parent & 0xffff));
213 nextInstruction();
214 }
215
216 /***
217 * jump instruction. The offset can be negative.
218 */
219 private void jump() {
220
221
222 getMachine().setProgramCounter(
223 getMachine().getProgramCounter() + getValue(0) + 1);
224 }
225
226 /***
227 * load instruction.
228 */
229 private void load() {
230
231 int varnum = getValue(0);
232 short value = varnum == 0 ? getMachine().getStackTopElement() :
233 getMachine().getVariable(varnum);
234 storeResult(value);
235 nextInstruction();
236 }
237
238 /***
239 * jz instruction.
240 */
241 private void jz() {
242
243 branchOnTest(getValue(0) == 0);
244 }
245
246 private void getSibling() {
247
248 int obj = getUnsignedValue(0);
249 ZObject zobj = getMachine().getObjectTree().getObject(obj);
250 int sibling = zobj.getSibling();
251 storeResult((short) (sibling & 0xffff));
252 branchOnTest(sibling > 0);
253 }
254
255 private void getChild() {
256
257 int obj = getUnsignedValue(0);
258 ZObject zobj = getMachine().getObjectTree().getObject(obj);
259 int child = zobj.getChild();
260 storeResult((short) (child & 0xffff));
261 branchOnTest(child > 0);
262 }
263
264 private void printAddr() {
265
266 getMachine().printZsciiString(getUnsignedValue(0));
267 nextInstruction();
268 }
269
270 private void printPaddr() {
271
272 getMachine().printZsciiString(
273 getMachine().translatePackedAddress(getUnsignedValue(0)));
274 nextInstruction();
275 }
276
277 private void ret() {
278
279 returnFromRoutine(getValue(0));
280 }
281
282 private void printObj() {
283
284 int obj = getUnsignedValue(0);
285 ZObject zobj = getMachine().getObjectTree().getObject(obj);
286 getMachine().printZsciiString(zobj.getPropertiesDescriptionAddress());
287 nextInstruction();
288 }
289
290 private void removeObj() {
291
292 int obj = getUnsignedValue(0);
293 getMachine().getObjectTree().removeObject(obj);
294 nextInstruction();
295 }
296
297 private void getPropLen() {
298
299 int propertyAddress = getUnsignedValue(0);
300 short proplen = (short)
301 getMachine().getObjectTree().getPropertyLength(propertyAddress);
302 storeResult(proplen);
303 nextInstruction();
304 }
305 }