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
50 instruction = new Branch(condition, (word & 0x01000000) == 0x01000000, ((word & 0x00ffffff) << 8) >> 6);
51 } else if ((word & 0x0fc000f0) == 0x00000090) {
52
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
65 final int Rd = (word & 0x0000f000) >> 12;
66 final int Rn = (word & 0x000f0000) >> 16;
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
82 final int Rn = (word & 0x000f0000) >> 16;
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
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 }