View Javadoc

1   package com.tapina.robe.runtime;
2   
3   import com.tapina.robe.runtime.instruction.*;
4   import com.tapina.robe.swi.SWIError;
5   
6   /***
7    * Created by IntelliJ IDEA.
8    * User: gareth
9    * Date: Aug 21, 2003
10   * Time: 8:07:59 AM
11   */
12  final class Decoder {
13      private static final Operator[] operators = new Operator[] {
14          DataProcessingInstruction.AND,
15          DataProcessingInstruction.EOR,
16          DataProcessingInstruction.SUB,
17          DataProcessingInstruction.RSB,
18          DataProcessingInstruction.ADD,
19          DataProcessingInstruction.ADC,
20          DataProcessingInstruction.SBC,
21          DataProcessingInstruction.RSC,
22          DataProcessingInstruction.TST,
23          DataProcessingInstruction.TEQ,
24          DataProcessingInstruction.CMP,
25          DataProcessingInstruction.CMN,
26          DataProcessingInstruction.ORR,
27          DataProcessingInstruction.MOV,
28          DataProcessingInstruction.BIC,
29          DataProcessingInstruction.MVN
30      };
31      private static final Condition[] conditions = new Condition[] {
32          Condition.EQ, Condition.NE,
33          Condition.CS, Condition.CC,
34          Condition.MI, Condition.PL,
35          Condition.VS, Condition.VC,
36          Condition.HI, Condition.LS,
37          Condition.GE, Condition.LT,
38          Condition.GT, Condition.LE,
39          Condition.AL, Condition.NV
40      };
41  
42      public final static Instruction decode(int word) throws DecoderException {
43          final Instruction instruction;
44          final int conditionNumber = (word & 0xf0000000) >>> 28;
45          final Condition condition = conditions[conditionNumber];
46          if ((word & 0x0f000000) == 0x0f000000) {
47              instruction = new SWI(condition, word & 0xffffff);
48          } else if ((word & 0x0e000000) == 0x0a000000) {
49              // Branch instruction
50              instruction = new Branch(condition, (word & 0x01000000) == 0x01000000, ((word & 0x00ffffff) << 8) >> 6);
51          } else if ((word & 0x0fc000f0) == 0x00000090) {
52              // Multiplication instruction
53              final int Rd = (word & 0x000f0000) >> 16;
54              final int Rs = (word & 0x00000f00) >> 8;
55              final int Rm = (word & 0x0000000f);
56              final boolean setConditionCodes = (word & 0x00100000) == 0x00100000;
57              if ((word & 0x00200000)== 0x00200000) {
58                  final int Rn = (word & 0x0000f000) >> 12;
59                  instruction = new MultiplyAccumulateInstruction(condition, Rd, Rn, Rm, Rs, setConditionCodes);
60              } else {
61                  instruction = new MultiplyInstruction(condition, Rd, Rm, Rs, setConditionCodes);
62              }
63          } else if ((word & 0x0c000000) == 0x04000000) {
64              // Data transfer instruction
65              final int Rd = (word & 0x0000f000) >> 12; // destination register
66              final int Rn = (word & 0x000f0000) >> 16; // base register
67              final Transfer transfer = getDataTransfer(word);
68              final IndexedAddressSource addressSource;
69              Operand offset = getDataTransferOffset(word);
70              if ((word & 0x01000000) == 0x01000000) {
71                  if ((word & 0x00200000) == 0x00200000) {
72                      addressSource = new AutoPreIndexedAddressSource(Rn, offset);
73                  } else {
74                      addressSource = new PreIndexedAddressSource(Rn, offset);
75                  }
76              } else {
77                  addressSource = new PostIndexedAddressSource(Rn, offset);
78              }
79              instruction = new DataTransferInstruction(condition, transfer, Rd, addressSource);
80          } else if ((word & 0x0e000000) == 0x08000000) {
81              // Multiple data transfer instruction
82              final int Rn = (word & 0x000f0000) >> 16; // base register
83              final MultipleTransfer transfer = ((word & 0x00100000) == 0x00100000)?
84                      MultipleTransferInstruction.LDM : MultipleTransferInstruction.STM;
85              int[] registers = getMultipleRegisterList(word);
86              final boolean increment = ((word & 0x00800000) == 0x00800000);
87              final boolean before = ((word & 0x01000000) == 0x01000000);
88              final boolean writeBack = ((word & 0x00200000) == 0x00200000);
89              final boolean psrForceUser = ((word & 0x00400000) == 0x00400000);
90              final MultipleAddressSource multipleAddressSource;
91              final int writeBackOffset = writeBack? (increment? 4 : -4) * registers.length : 0;
92              if (increment) {
93                  multipleAddressSource = new MultipleAddressSource(Rn, before? 4 : 0, writeBackOffset);
94              } else {
95                  multipleAddressSource = new MultipleAddressSource(Rn, before?
96                                                                      -4 * registers.length
97                                                                    : -4 * (registers.length - 1), writeBackOffset);
98              }
99              final boolean useInitialBaseRegisterValue = Rn == registers[0];
100             instruction = new MultipleTransferInstruction(condition, transfer, registers, multipleAddressSource,
101                     useInitialBaseRegisterValue, psrForceUser);
102         } else if ((word & 0x0c000000) == 0x00000000) {
103             // Data processing instruction
104             final int opNum = (word & 0x01e00000) >> 21;
105             final Operator operator = operators[opNum];
106             final int Rd = (word & 0x0000f000) >> 12;
107             final int Rn = (word & 0x000f0000) >> 16;
108             Operand op2 = getDataProcessingOp2(word);
109             final boolean setConditionCodes = (word & 0x00100000) == 0x00100000;
110             instruction = new DataProcessingInstruction(condition, operator, Rd, Rn, op2, (opNum < 8 || opNum > 11),
111                                                         setConditionCodes);
112         } else {
113             throw new UndefinedInstructionException(word);
114         }
115         return instruction;
116     }
117 
118     private static int[] getMultipleRegisterList(int word) {
119         int registerCount = 0;
120         for (int r = 0; r < 16; r++) {
121             if ((word & (1<<r)) != 0) {
122                 registerCount++;
123             }
124         }
125         final int[] registers = new int[registerCount];
126         registerCount = 0;
127         for (int r = 0; r < 16; r++) {
128             if ((word & (1<<r)) != 0) {
129                 registers[registerCount++] = r;
130             }
131         }
132         return registers;
133     }
134 
135     private static Transfer getDataTransfer(int word) {
136         final boolean isByte = (word & 0x00400000) == 0x00400000;
137         final Transfer transfer;
138         if ((word & 0x00100000) == 0x00100000) {
139             transfer = isByte? DataTransferInstruction.LDRB : DataTransferInstruction.LDR;
140         } else {
141             transfer = isByte? DataTransferInstruction.STRB : DataTransferInstruction.STR;
142         }
143         return transfer;
144     }
145 
146     private static Operand getDataTransferOffset(int word) {
147         Operand offset;
148         if ((word & 0x02000000) == 0x00000000) {
149             offset = new ImmediateOperand(word & 0xfff);
150         } else {
151             Operand shiftValue = new ImmediateOperand((word & 0xf80) >> 7);
152             offset = new RegisterOperand(word & 0xf, (word & 0x60) >> 5, shiftValue);
153         }
154         if ((word & 0x00800000) != 0x00800000) {
155             offset = new Negative(offset);
156         }
157         return offset;
158     }
159 
160     private static Operand getDataProcessingOp2(int word) {
161         final Operand op2;
162         if ((word & 0x02000000) == 0x02000000) {
163             op2 = new ImmediateOperand(word & 0xff, (word & 0xf00) >> 7);
164         } else {
165             final Operand shiftValue;
166             if ((word & 0x10) == 0x10) {
167                 shiftValue = new RegisterOperand((word & 0xf00) >> 8);
168             } else {
169                 shiftValue = new ImmediateOperand((word & 0xf80) >> 7);
170             }
171             op2 = new RegisterOperand(word & 0xf, (word & 0x60) >> 5, shiftValue);
172         }
173         return op2;
174     }
175 }