View Javadoc

1   package com.tapina.robe.runtime.instruction;
2   
3   import com.tapina.robe.runtime.CPU;
4   
5   import java.io.Writer;
6   import java.io.IOException;
7   
8   /***
9    * Created by IntelliJ IDEA.
10   * User: gareth
11   * Date: Aug 23, 2003
12   * Time: 10:54:20 PM
13   */
14  public final class RegisterOperand extends Operand {
15      public static final int SHIFT_LOGICAL_LEFT = 0;
16      public static final int SHIFT_LOGICAL_RIGHT = 1;
17      public static final int SHIFT_ARITHMETIC_RIGHT = 2;
18      public static final int SHIFT_ROTATE_RIGHT = 3;
19  
20      private final int registerNumber;
21      private final int shiftType;
22      private final Operand shiftValue;
23      private boolean shiftPerformed = false;
24      private boolean carryFlag = false;
25  
26      public RegisterOperand(int registerNumber) {
27          this(registerNumber, 0, new ImmediateOperand(0));
28      }
29  
30      public RegisterOperand(int registerNumber, int shiftType, Operand shiftValue) {
31          this.registerNumber = registerNumber;
32          this.shiftType = shiftType;
33          this.shiftValue = shiftValue;
34      }
35  
36      public final int getValue(CPU cpu) {
37          int[] R = cpu.R;
38  
39          // This applies to op1 only: registerNumber != 15? R[registerNumber] : cpu.getPC();
40          int value = R[registerNumber];
41          int shift = shiftValue.getValue(cpu) & 0xff;
42  
43          if (!(shiftType == SHIFT_LOGICAL_LEFT && shift == 0)) {
44              // Need to actually do a shift
45              shiftPerformed = true;
46              int carry = 0;
47              switch (shiftType) {
48                  // TODO: deal with carry bits properly.
49                  case SHIFT_LOGICAL_LEFT:
50                      // Carry is set to bit (32-shift) of the original value
51                      carry = value & (1 << (32 - shift)); // Shift cannot be zero at this point
52                      value <<= shift;
53                      break;
54                  case SHIFT_LOGICAL_RIGHT:
55                      if (shift == 0) {
56                          shift = 32;
57                      }
58                      carry = value & (1 << (shift - 1));
59                      value >>>= shift;
60                      break;
61                  case SHIFT_ARITHMETIC_RIGHT:
62                      if (shift == 0) {
63                          shift = 32;
64                      }
65                      // Carry is set to bit (shift - 1) of the original value
66                      carry = value & (1 << (shift - 1));
67                      value >>= shift;
68                      break;
69                  case SHIFT_ROTATE_RIGHT:
70                      carry = value & (1 << (shift));
71                      if (shift != 0) {
72                          value = (value >>> shift) | (value << (32-shift));
73                      } else {
74                          value = (value >>> 1);
75                      }
76              }
77              carryFlag = (carry != 0);
78          }
79  
80          return value;
81      }
82  
83      public void dumpJavaSource(String varName, Writer out) throws IOException {
84          out.write("final boolean " + varName + ";\n");
85          out.write("final boolean shiftPerformed;\n");
86          out.write("final boolean carryFlag;\n");
87          out.write("{\n");
88          out.write("final int carry;\n");
89          out.write("int value = R[" + registerNumber + "];\n");
90          shiftValue.dumpJavaSource("shift", out);
91          out.write("shiftValue &= 0xff;\n");
92          switch (shiftType) {
93              case SHIFT_LOGICAL_LEFT:
94                  out.write("if (shift != 0) {\n");
95                  out.write("carry = value & (1 << (32 - shift));\n");
96                  out.write("value <<= shift;\n");
97                  out.write("}\n");
98                  break;
99                  case SHIFT_LOGICAL_RIGHT:
100                 out.write("if (shift == 0) { shift = 32; }\n");
101                 out.write("carry = value & (1 << (shift - 1));\n");
102                 out.write("value >>>= shift;\n");
103                 break;
104             case SHIFT_ARITHMETIC_RIGHT:
105                 out.write("if (shift == 0) { shift = 32; }\n");
106                 out.write("carry = value & (1 << (shift - 1));\n");
107                 out.write("value >>= shift;\n");
108                 break;
109             case SHIFT_ROTATE_RIGHT:
110                 out.write("carry = value & (1 << shift);\n");
111                 out.write("if (shift != 0) {\n");
112                 out.write("value = (value >>> shift) | (value << (32 - shift));\n");
113                 out.write("} else {\n");
114                 out.write("value = (value >>> 1)\n");
115                 out.write("}\n");
116         }
117         out.write(varName + " = value;\n");
118         out.write("carryFlag = (carry != 0);\n");
119         if (shiftType == SHIFT_LOGICAL_LEFT) {
120             out.write("shiftPerformed = (shift != 0);\n");
121         } else {
122             out.write("shiftPerformed = true;\n");
123         }
124         out.write("}\n");
125     }
126 
127     public String getJavaExpression() {
128         return null;
129     }
130 
131     public final boolean isShiftPerformed() {
132         return shiftPerformed;
133     }
134 
135     public final boolean isCarryFlagSet() {
136         return carryFlag;
137     }
138 }