-
Notifications
You must be signed in to change notification settings - Fork 1
/
instruction.cs
214 lines (207 loc) · 7.1 KB
/
instruction.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GDBStub
{
// this class is the parent class of all
// the other instructions. The instuction types
// build off the methods in this class
class Instruction
{
// variable declarations
// initial state
public uint initialBytes { get; set; }
// breakdown of bytes
public uint Cond { get; set; }
public uint Type { get; set; }
public uint Rd { get; set; }
public uint Rn { get; set; }
public bool S { get; set; }
public bool N {get; set; }
public bool Z {get; set; }
public bool C {get; set; }
public bool F {get; set; }
public uint Rm { get; set; }
/// <summary>
/// Decode the instruction
/// </summary>
/// <param name="cmd"></param>
/// <returns></returns>
public static Instruction DecodeInstruction(Memory command)
{
Instruction i = new Instruction();
uint type = 0;
// get type
type = (uint)((command.ReadByte(3) & 0x0c) >> 2);
//Console.WriteLine(Convert.ToString(command.ReadWord(0),2));
switch (type)
{
case 0:
// Data Processing (00X)
if ((0x012FFF10 & command.ReadWord(0)) == 0x012FFF10)
{
i = new Branch();
}
else
{
i = new DataProcessing();
}
break;
case 1:
// Load / Store (01X)
if (command.TestFlag(0, 24) || !command.TestFlag(0, 21))
{
i = new LoadStore();
}
break;
case 2:
// Load / Store Multiple (100)
if (!command.TestFlag(0, 25))
{
//load store multiple
i = new LoadStoreMultiple();
}
// Branch Instruction (101)
else
{
if (command.TestFlag(0, 27) && !command.TestFlag(0, 26) && command.TestFlag(0, 25))
{
Logger.Instance.lastInstructionWasBranch = true;
i = new Branch();
}
}
break;
case 3:
//11
//Coprocessor
if (command.TestFlag(0, 26) && command.TestFlag(0, 25))
{
//interupt
}
break;
default:
break;
}
i.ParseCommand(command);
// get condition
i.Cond = (uint)command.ReadByte(3) >> 4;
// get type
i.Type = (uint)((command.ReadByte(3) & 0x0c) >> 2);
//
i.initialBytes = (uint)command.ReadWord(0);
// source
i.Rn = (uint)((command.ReadWord(0) & 0x000F0000) >> 16);
// destination
i.Rd = (uint)((command.ReadWord(0) & 0x0000F000) >> 12);
return i;
}
/// <summary>
/// Parent ParseCommand
/// Shouldn't ever be needed
/// </summary>
/// <param name="command"></param>
public virtual void ParseCommand(Memory command)
{
Logger.Instance.writeLog("Warning: Unkown Command");
}
/// <summary>
/// Parent Run
/// Shouldn't ever be needed
/// </summary>
/// <param name="reg"></param>
/// <param name="RAM"></param>
public virtual void Run(ref Register[] reg, ref Memory RAM)
{
Logger.Instance.writeLog("Warning: Unkown Command");
}
/// <summary>
/// This is responsible for the shifts that have
/// to take place at times in the operand2
/// </summary>
/// <param name="S"></param>
/// <param name="shifter"></param>
/// <param name="RmVal"></param>
/// <param name="reg"></param>
/// <returns></returns>
public Operand2 Shift(bool S, Operand2 shifter, uint RmVal, Register[] reg)
{
// Look at our magic bit to see what to do
if (!S)
{
// Check to see if shift is done on a register
if (shifter.b4 && !shifter.b7) { shifter.shiftRM(RmVal, reg[shifter.regShiftLength].ReadWord(0, true));}
// otherwise the shift is an immediate value
else {shifter.shiftRM(RmVal, shifter.regShiftImm);}
}
return shifter;
}
/// <summary>
/// This method checks the status of the flags and
/// returns true or false based on their condition
/// </summary>
/// <param name="flagArray"></param>
/// <returns></returns>
public bool checkCond(bool[] flagArray)
{
N = flagArray[0];
Z = flagArray[1];
C = flagArray[2];
F = flagArray[3];
switch (Cond)
{
case 0x0:
if (Z) { return true; }
break;
case 0x1:
if (!Z) { return true; }
break;
case 0x2:
if (C) { return true; }
break;
case 0x3:
if (!C) { return true; }
break;
case 0x4:
if (N) { return true; }
break;
case 0x5:
if (!N) { return true; }
break;
case 0x6:
if (F) { return true; }
break;
case 0x7:
if (!F) { return true; }
break;
case 0x8:
if ((C && !Z)) { return true; }
break;
case 0x9:
if ((!C || Z)) { return true; }
break;
case 0xa:
if ((N == F)) { return true; }
break;
case 0xb:
if ((N != F)) { return true; }
break;
case 0xc:
if ((!Z && N == F)) { return true; }
break;
case 0xd:
if ((Z || N != F)) { return true; }
break;
case 0xe:
return true;
case 0xf:
return false;
default:
return false;
}
// should never ever ever ever need this
// but C# doth compain if it is not here
return false;
}
}
}