View Javadoc

1   /*
2    * $Id: Short1Instruction.java,v 1.23 2005/10/25 06:46:13 weiju Exp $
3    * 
4    * Created on 03.10.2005
5    * Copyright 2005 by Wei-ju Wu
6    *
7    * This file is part of The Z-machine Preservation Project (ZMPP).
8    *
9    * ZMPP is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as published by
11   * the Free Software Foundation; either version 2 of the License, or
12   * (at your option) any later version.
13   *
14   * ZMPP is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with ZMPP; if not, write to the Free Software
21   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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; // Versions 1-4
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     // Unconditional jump
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 }