├── .gitattributes
├── .gitignore
├── ChocolateARM.sln
├── ChocolateARM
├── ARM11
│ ├── ARM
│ │ ├── AddressingModes
│ │ │ ├── DataProcessing.cs
│ │ │ └── LoadAndStore.cs
│ │ └── Instructions
│ │ │ ├── ARM
│ │ │ ├── Arithmetic
│ │ │ │ ├── Addition.cs
│ │ │ │ ├── Multiplication.cs
│ │ │ │ ├── Saturation.cs
│ │ │ │ └── Subtraction.cs
│ │ │ ├── Branch.cs
│ │ │ ├── Compare.cs
│ │ │ ├── Coprocessor.cs
│ │ │ ├── Exception.cs
│ │ │ ├── LoadAndStore.cs
│ │ │ ├── LoadAndStore
│ │ │ │ ├── Load.cs
│ │ │ │ └── Store.cs
│ │ │ ├── Logical.cs
│ │ │ └── Move.cs
│ │ │ └── Thumb
│ │ │ ├── Arithmetic.cs
│ │ │ ├── Branch.cs
│ │ │ ├── Compare.cs
│ │ │ ├── Exception.cs
│ │ │ ├── LoadAndStore.cs
│ │ │ ├── Logical.cs
│ │ │ └── Move.cs
│ ├── ARMCore.cs
│ ├── Bus.cs
│ ├── Condition.cs
│ ├── Coprocessor15.cs
│ ├── Registers.cs
│ └── Utils.cs
├── App.config
├── ChocolateARM.csproj
├── FrmMain.Designer.cs
├── FrmMain.cs
├── FrmMain.resx
├── FrmUARTOutput.Designer.cs
├── FrmUARTOutput.cs
├── FrmUARTOutput.resx
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
└── RPi
│ ├── IO32.cs
│ ├── Memory.cs
│ ├── Peripherals
│ ├── RPiDMA.cs
│ ├── RPiMiniUART.cs
│ ├── RPiTimer.cs
│ └── RPiUART.cs
│ ├── RPiCore.cs
│ └── VideoCore.cs
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
19 | !packages/*/build/
20 |
21 | # MSTest test Results
22 | [Tt]est[Rr]esult*/
23 | [Bb]uild[Ll]og.*
24 |
25 | *_i.c
26 | *_p.c
27 | *.ilk
28 | *.meta
29 | *.obj
30 | *.pch
31 | *.pdb
32 | *.pgc
33 | *.pgd
34 | *.rsp
35 | *.sbr
36 | *.tlb
37 | *.tli
38 | *.tlh
39 | *.tmp
40 | *.tmp_proj
41 | *.log
42 | *.vspscc
43 | *.vssscc
44 | .builds
45 | *.pidb
46 | *.log
47 | *.scc
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 | *.cachefile
56 |
57 | # Visual Studio profiler
58 | *.psess
59 | *.vsp
60 | *.vspx
61 |
62 | # Guidance Automation Toolkit
63 | *.gpState
64 |
65 | # ReSharper is a .NET coding add-in
66 | _ReSharper*/
67 | *.[Rr]e[Ss]harper
68 |
69 | # TeamCity is a build add-in
70 | _TeamCity*
71 |
72 | # DotCover is a Code Coverage Tool
73 | *.dotCover
74 |
75 | # NCrunch
76 | *.ncrunch*
77 | .*crunch*.local.xml
78 |
79 | # Installshield output folder
80 | [Ee]xpress/
81 |
82 | # DocProject is a documentation generator add-in
83 | DocProject/buildhelp/
84 | DocProject/Help/*.HxT
85 | DocProject/Help/*.HxC
86 | DocProject/Help/*.hhc
87 | DocProject/Help/*.hhk
88 | DocProject/Help/*.hhp
89 | DocProject/Help/Html2
90 | DocProject/Help/html
91 |
92 | # Click-Once directory
93 | publish/
94 |
95 | # Publish Web Output
96 | *.Publish.xml
97 |
98 | # NuGet Packages Directory
99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
100 | #packages/
101 |
102 | # Windows Azure Build Output
103 | csx
104 | *.build.csdef
105 |
106 | # Windows Store app package directory
107 | AppPackages/
108 |
109 | # Others
110 | sql/
111 | *.Cache
112 | ClientBin/
113 | [Ss]tyle[Cc]op.*
114 | ~$*
115 | *~
116 | *.dbmdl
117 | *.[Pp]ublish.xml
118 | *.pfx
119 | *.publishsettings
120 |
121 | # RIA/Silverlight projects
122 | Generated_Code/
123 |
124 | # Backup & report files from converting an old project file to a newer
125 | # Visual Studio version. Backup files are not needed, because we have git ;-)
126 | _UpgradeReport_Files/
127 | Backup*/
128 | UpgradeLog*.XML
129 | UpgradeLog*.htm
130 |
131 | # SQL Server files
132 | App_Data/*.mdf
133 | App_Data/*.ldf
134 |
135 |
136 | #LightSwitch generated files
137 | GeneratedArtifacts/
138 | _Pvt_Extensions/
139 | ModelManifest.xml
140 |
141 | # =========================
142 | # Windows detritus
143 | # =========================
144 |
145 | # Windows image file caches
146 | Thumbs.db
147 | ehthumbs.db
148 |
149 | # Folder config file
150 | Desktop.ini
151 |
152 | # Recycle Bin used on file shares
153 | $RECYCLE.BIN/
154 |
155 | # Mac desktop service store files
156 | .DS_Store
157 |
--------------------------------------------------------------------------------
/ChocolateARM.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChocolateARM", "ChocolateARM\ChocolateARM.csproj", "{47232F73-385B-43D6-8751-10B289DAEBE1}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {47232F73-385B-43D6-8751-10B289DAEBE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {47232F73-385B-43D6-8751-10B289DAEBE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {47232F73-385B-43D6-8751-10B289DAEBE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {47232F73-385B-43D6-8751-10B289DAEBE1}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/AddressingModes/DataProcessing.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Decodes the Operand value from the Shifter Operand.
7 | ///
8 | /// True if the Carry flag should be updated with the shifting operations, false otherwise
9 | /// The decoded Operand value
10 | private uint ARM_GetShifterOperand(bool S)
11 | {
12 | bool I = IsOpcodeBitSet(25);
13 | uint ShifterOperand = Opcode & 0xfff;
14 |
15 | if (I) //Immediate
16 | {
17 | int Rotate = (int)((ShifterOperand >> 8) << 1);
18 | uint Operand = ROR(ShifterOperand & 0xff, Rotate);
19 | if (S && Rotate > 0) Registers.SetFlag(ARMFlag.Carry, (Operand & 0x80000000) != 0);
20 | return Operand;
21 | }
22 | else //Register
23 | {
24 | uint Operand = 0;
25 | bool Carry = false;
26 | int Rm = (int)(ShifterOperand & 0xf);
27 | uint Shifter = (Opcode >> 5) & 3;
28 |
29 | int Shift;
30 | bool Register = IsOpcodeBitSet(4);
31 | if (Register)
32 | {
33 | int Rs = (int)((ShifterOperand >> 8) & 0xf);
34 | Shift = (int)(Registers[Rs] & 0xff);
35 | }
36 | else
37 | {
38 | Shift = (int)((ShifterOperand >> 7) & 0x1f);
39 | if (Shift == 0 && (Shifter == 1 || Shifter == 2)) Shift = 32;
40 | }
41 |
42 | if (Shift > 0 && Shift <= 32)
43 | {
44 | switch (Shifter)
45 | {
46 | case 0: //LSL
47 | Operand = Shift < 32 ? Registers[Rm] << Shift : 0;
48 | Carry = (Registers[Rm] & (1 << (32 - Shift))) != 0;
49 | break;
50 |
51 | case 1: //LSR
52 | Operand = Shift < 32 ? Registers[Rm] >> Shift : 0;
53 | Carry = (Registers[Rm] & (1 << (Shift - 1))) != 0;
54 | break;
55 |
56 | case 2: //ASR
57 | int RmValue = (int)Registers[Rm];
58 | Operand = (uint)((long)RmValue >> Shift);
59 | Carry = (RmValue & (1 << (Shift - 1))) != 0;
60 | break;
61 |
62 | case 3: //ROR
63 | if (Register) Shift &= 0x1f;
64 | Operand = ROR(Registers[Rm], Shift);
65 | if (Shift > 0)
66 | Carry = (Registers[Rm] & (1 << (Shift - 1))) != 0;
67 | else
68 | Carry = (Registers[Rm] & 0x80000000) != 0;
69 | break;
70 | }
71 | }
72 | else
73 | {
74 | if (Shift == 0)
75 | {
76 | Operand = Registers[Rm];
77 | Carry = Registers.IsFlagSet(ARMFlag.Carry);
78 |
79 | if (!Register && Shifter == 3) //RRX
80 | {
81 | Operand = (Operand >> 1) | (Carry ? 0x80000000 : 0);
82 | Carry = (Registers[Rm] & 1) != 0;
83 | }
84 | }
85 | else if (Shifter > 1)
86 | {
87 | Carry = (Registers[Rm] & 0x80000000) != 0;
88 | Operand = Carry ? 0xffffffff : 0;
89 | }
90 | }
91 |
92 | if (S) Registers.SetFlag(ARMFlag.Carry, Carry);
93 | return Operand;
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/AddressingModes/LoadAndStore.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Gets the Address used for the general Load and Store instructions.
7 | ///
8 | /// The Base Address to Load or Store
9 | private uint ARM_GetLoadAndStoreAddress()
10 | {
11 | int Rn = (int)((Opcode >> 16) & 0xf);
12 | bool W = IsOpcodeBitSet(21);
13 | bool U = IsOpcodeBitSet(23);
14 | bool P = IsOpcodeBitSet(24);
15 | bool I = IsOpcodeBitSet(25);
16 |
17 | ARMMode OldMode = Registers.Mode;
18 | if (!P && W) Registers.Mode = ARMMode.User;
19 | uint Offset = 0;
20 | if (I) //Register
21 | {
22 | int Rm = (int)(Opcode & 0xf);
23 | uint Shift = (Opcode >> 5) & 3;
24 | int ShiftImmediate = (int)((Opcode >> 7) & 0x1f);
25 |
26 | switch (Shift)
27 | {
28 | case 0: Offset = Registers[Rm] << ShiftImmediate; break; //LSL
29 | case 1: Offset = ShiftImmediate != 0 ? Registers[Rm] >> ShiftImmediate : 0; break; //LSR
30 |
31 | case 2: //ASR
32 | if (ShiftImmediate == 0)
33 | Offset = (Registers[Rm] & 0x80000000) != 0 ? 0xffffffff : 0;
34 | else
35 | Offset = Registers[Rm] >> ShiftImmediate;
36 | break;
37 |
38 | case 3: //ROR
39 | if (ShiftImmediate == 0)
40 | Offset = (Registers[Rm] >> 1) | (Registers.IsFlagSet(ARMFlag.Carry) ? 0x80000000 : 0);
41 | else
42 | Offset = ROR(Registers[Rm], ShiftImmediate);
43 | break;
44 | }
45 | }
46 | else //Immediate
47 | Offset = Opcode & 0xfff;
48 |
49 | uint Address = 0;
50 | if (P)
51 | {
52 | if (W) //Pre-Indexed
53 | {
54 | if (U)
55 | Registers[Rn] += Offset;
56 | else
57 | Registers[Rn] -= Offset;
58 |
59 | Address = Registers[Rn];
60 | }
61 | else //Offset
62 | Address = U ? Registers[Rn] + Offset : Registers[Rn] - Offset;
63 | }
64 | else
65 | {
66 | if (!W) //Post-Indexed
67 | {
68 | Address = Registers[Rn];
69 |
70 | if (U)
71 | Registers[Rn] += Offset;
72 | else
73 | Registers[Rn] -= Offset;
74 | }
75 | }
76 |
77 | Registers.Mode = OldMode;
78 | return Address;
79 | }
80 |
81 | ///
82 | /// Gets the Address used to Load or Store on the Coprocessor-related instructions.
83 | ///
84 | /// The Base Address to Load or Store
85 | private uint ARM_GetLoadAndStoreCPAddress()
86 | {
87 | uint Offset = (Opcode & 0xff) << 2;
88 | int Rn = (int)((Opcode >> 16) & 0xf);
89 | bool W = IsOpcodeBitSet(21);
90 | bool U = IsOpcodeBitSet(23);
91 | bool P = IsOpcodeBitSet(24);
92 |
93 | uint Address;
94 | if (P)
95 | {
96 | if (W) //Pre-Indexed
97 | {
98 | if (U)
99 | Registers[Rn] += Offset;
100 | else
101 | Registers[Rn] -= Offset;
102 |
103 | Address = Registers[Rn];
104 | }
105 | else //Offset
106 | Address = U ? Registers[Rn] + Offset : Registers[Rn] - Offset;
107 | }
108 | else
109 | {
110 | if (W) //Post-Indexed
111 | {
112 | Address = Registers[Rn];
113 |
114 | if (U)
115 | Registers[Rn] += Offset;
116 | else
117 | Registers[Rn] -= Offset;
118 | }
119 | else //Unindexed
120 | Address = Registers[Rn];
121 | }
122 |
123 | return Address;
124 | }
125 |
126 | ///
127 | /// Gets the Address used on Load or Store instruction that uses values bigger or smaller than 32-bits.
128 | ///
129 | /// The Base Address to Load or Store
130 | private uint ARM_GetLoadAndStoreNonWordAddress()
131 | {
132 | int Rn = (int)((Opcode >> 16) & 0xf);
133 | bool W = IsOpcodeBitSet(21);
134 | bool I = IsOpcodeBitSet(22);
135 | bool U = IsOpcodeBitSet(23);
136 | bool P = IsOpcodeBitSet(24);
137 |
138 | uint Offset;
139 | if (I) //Immediate
140 | Offset = (Opcode & 0xf) | ((Opcode >> 4) & 0xf0);
141 | else //Register
142 | Offset = Registers[(int)(Opcode & 0xf)];
143 |
144 | uint Address = 0;
145 | if (P)
146 | {
147 | if (W) //Pre-Indexed
148 | {
149 | if (U)
150 | Registers[Rn] += Offset;
151 | else
152 | Registers[Rn] -= Offset;
153 |
154 | Address = Registers[Rn];
155 | }
156 | else //Offset
157 | Address = U ? Registers[Rn] + Offset : Registers[Rn] - Offset;
158 | }
159 | else
160 | {
161 | if (!W) //Post-Indexed
162 | {
163 | Address = Registers[Rn];
164 |
165 | if (U)
166 | Registers[Rn] += Offset;
167 | else
168 | Registers[Rn] -= Offset;
169 | }
170 | }
171 |
172 | return Address;
173 | }
174 |
175 | ///
176 | /// Gets the Address used on Load or Store Multiple instructions.
177 | ///
178 | /// The Base Address to Load or Store
179 | private uint ARM_GetLoadAndStoreMultipleAddress()
180 | {
181 | ushort RegisterList = (ushort)(Opcode & 0xffff);
182 | int Rn = (int)((Opcode >> 16) & 0xf);
183 | bool W = IsOpcodeBitSet(21);
184 | bool U = IsOpcodeBitSet(23);
185 | bool P = IsOpcodeBitSet(24);
186 |
187 | uint Count = 0;
188 | for (int Index = 0; Index < 16; Index++)
189 | {
190 | if ((RegisterList & (1 << Index)) != 0) Count += 4;
191 | }
192 |
193 | uint Address;
194 | if (U)
195 | Address = Registers[Rn] + (uint)(P ? 4 : 0);
196 | else
197 | Address = Registers[Rn] - Count + (uint)(P ? 0 : 4);
198 |
199 | if (W)
200 | {
201 | if (U)
202 | Registers[Rn] += Count;
203 | else
204 | Registers[Rn] -= Count;
205 | }
206 |
207 | return Address;
208 | }
209 |
210 | ///
211 | /// Gets the Address used by the SRS (Store Return State) instruction.
212 | ///
213 | /// The Base Address to Store
214 | private uint ARM_GetSRSAddress()
215 | {
216 | int Rn = (int)((Opcode >> 16) & 0xf);
217 | bool W = IsOpcodeBitSet(21);
218 | bool U = IsOpcodeBitSet(23);
219 | bool P = IsOpcodeBitSet(24);
220 |
221 | uint Address;
222 | if (U)
223 | Address = Registers[Rn] + (uint)(P ? 4 : 0);
224 | else
225 | Address = Registers[Rn] - 8 + (uint)(P ? 0 : 4);
226 |
227 | if (W)
228 | {
229 | if (U)
230 | Registers[Rn] += 8;
231 | else
232 | Registers[Rn] -= 8;
233 | }
234 |
235 | return Address;
236 | }
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/Arithmetic/Saturation.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | /*
6 | * Instructions
7 | */
8 |
9 | //Signed
10 |
11 | ///
12 | /// Signed Saturate.
13 | ///
14 | private void ARM_SSAT()
15 | {
16 | int Rm = (int)(Opcode & 0xf);
17 | bool Shift = IsOpcodeBitSet(6);
18 | int ShiftImmediate = (int)((Opcode >> 7) & 0x1f);
19 | int Rd = (int)((Opcode >> 12) & 0xf);
20 | int SaturateImmediate = (int)(((Opcode >> 16) & 0x1f) + 1);
21 |
22 | int RmValue = (int)Registers[Rm];
23 | if (Shift)
24 | RmValue >>= ShiftImmediate == 0 ? 32 : ShiftImmediate;
25 | else
26 | RmValue <<= ShiftImmediate;
27 |
28 | Registers[Rd] = SignedSaturate(RmValue, SaturateImmediate);
29 | }
30 |
31 | ///
32 | /// Signed Saturate 16-bits.
33 | ///
34 | private void ARM_SSAT16()
35 | {
36 | int Rm = (int)(Opcode & 0xf);
37 | int Rd = (int)((Opcode >> 12) & 0xf);
38 | int SaturateImmediate = (int)(((Opcode >> 16) & 0xf) + 1);
39 |
40 | Registers[Rd] = SignedSaturate((int)(Registers[Rm] & 0xffff), SaturateImmediate);
41 | Registers[Rd] |= SignedSaturate((int)(Registers[Rm] >> 16), SaturateImmediate) << 16;
42 | }
43 |
44 | //Unsigned
45 |
46 | ///
47 | /// Unsigned Saturate.
48 | ///
49 | private void ARM_USAT()
50 | {
51 | int Rm = (int)(Opcode & 0xf);
52 | bool Shift = IsOpcodeBitSet(6);
53 | int ShiftImmediate = (int)((Opcode >> 7) & 0x1f);
54 | int Rd = (int)((Opcode >> 12) & 0xf);
55 | int SaturateImmediate = (int)(((Opcode >> 16) & 0x1f) + 1);
56 |
57 | int RmValue = (int)Registers[Rm];
58 | if (Shift)
59 | RmValue >>= ShiftImmediate == 0 ? 32 : ShiftImmediate;
60 | else
61 | RmValue <<= ShiftImmediate;
62 |
63 | Registers[Rd] = UnsignedSaturate(RmValue, SaturateImmediate);
64 | }
65 |
66 | ///
67 | /// Unsigned Saturate 16-bits.
68 | ///
69 | private void ARM_USAT16()
70 | {
71 | int Rm = (int)(Opcode & 0xf);
72 | int Rd = (int)((Opcode >> 12) & 0xf);
73 | int SaturateImmediate = (int)(((Opcode >> 16) & 0xf) + 1);
74 |
75 | Registers[Rd] = UnsignedSaturate((int)(Registers[Rm] & 0xffff), SaturateImmediate);
76 | Registers[Rd] |= UnsignedSaturate((int)(Registers[Rm] >> 16), SaturateImmediate) << 16;
77 | }
78 |
79 | /*
80 | * Utils
81 | */
82 |
83 | ///
84 | /// Saturates a signed 32-bits Value into a given range of Bits.
85 | ///
86 | /// The value that should be saturated
87 | /// The bit-range to saturate the value into
88 | /// The saturated value
89 | private uint SignedSaturate(int Value, int Bits)
90 | {
91 | uint Mask = (uint)((1 << Bits) - 1);
92 | int High = Value >> Bits;
93 | if (High > 0 || High < -1)
94 | {
95 | Registers.SetFlag(ARMFlag.Saturation, true);
96 | return High > 0 ? Mask : ~Mask;
97 | }
98 | else
99 | return (uint)Value;
100 | }
101 |
102 | ///
103 | /// Saturates a unsigned 32-bits Value into a given range of Bits.
104 | ///
105 | /// The value that should be saturated
106 | /// The bit-range to saturate the value into
107 | /// The saturated value
108 | private uint UnsignedSaturate(int Value, int Bits)
109 | {
110 | uint Mask = (uint)((1 << Bits) - 1);
111 | if (Value > Mask || (Value & 0x80000000) != 0)
112 | {
113 | Registers.SetFlag(ARMFlag.Saturation, true);
114 | return Value > Mask ? Mask : 0;
115 | }
116 | else
117 | return (uint)Value;
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/Branch.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Branch.
7 | ///
8 | private void ARM_B()
9 | {
10 | int Value = SignExtend24(Opcode & 0xffffff);
11 | bool L = IsOpcodeBitSet(24);
12 |
13 | if (L) Registers[14] = Registers[15] - 4;
14 | Registers[15] = (uint)(Registers[15] + (Value << 2));
15 | }
16 |
17 | ///
18 | /// Branch with Link and Exchange (1).
19 | ///
20 | private void ARM_BLX()
21 | {
22 | int Value = SignExtend24(Opcode & 0xffffff);
23 | uint H = (Opcode >> 24) & 1;
24 |
25 | Registers[15] = (uint)(Registers[15] + (Value << 2) + (H << 1));
26 | }
27 |
28 | ///
29 | /// Branch with Link and Exchange (2).
30 | ///
31 | private void ARM_BLX_2()
32 | {
33 | int Rm = (int)(Opcode & 0xf);
34 |
35 | Registers[14] = Registers[15] - 4;
36 | Registers[15] = Registers[Rm] & 0xfffffffe;
37 | Registers.SetFlag(ARMFlag.Thumb, (Registers[Rm] & 1) != 0);
38 | }
39 |
40 | ///
41 | /// Branch and Exchange.
42 | ///
43 | private void ARM_BX()
44 | {
45 | int Rm = (int)(Opcode & 0xf);
46 |
47 | Registers[15] = Registers[Rm] & 0xfffffffe;
48 | Registers.SetFlag(ARMFlag.Thumb, (Registers[Rm] & 1) != 0);
49 | }
50 |
51 | ///
52 | /// Branch and Exchange to Jazelle state.
53 | ///
54 | private void ARM_BXJ()
55 | {
56 | //Note: This processor doesn't support Jazelle, act as BX.
57 | ARM_BX();
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/Compare.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Compare Negative.
7 | ///
8 | private void ARM_CMN()
9 | {
10 | int Rn = (int)((Opcode >> 16) & 0xf);
11 | uint ShifterOperand = ARM_GetShifterOperand(true);
12 |
13 | Add(Registers[Rn], ShifterOperand, false, true);
14 | }
15 |
16 | ///
17 | /// Compare.
18 | ///
19 | private void ARM_CMP()
20 | {
21 | int Rn = (int)((Opcode >> 16) & 0xf);
22 | uint ShifterOperand = ARM_GetShifterOperand(true);
23 |
24 | Subtract(Registers[Rn], ShifterOperand, false, true);
25 | }
26 |
27 | ///
28 | /// Test Equivalence.
29 | ///
30 | private void ARM_TEQ()
31 | {
32 | int Rn = (int)((Opcode >> 16) & 0xf);
33 | uint ShifterOperand = ARM_GetShifterOperand(true);
34 |
35 | SetZNFlags(Registers[Rn] ^ ShifterOperand);
36 | }
37 |
38 | ///
39 | /// Test.
40 | ///
41 | private void ARM_TST()
42 | {
43 | int Rn = (int)((Opcode >> 16) & 0xf);
44 | uint ShifterOperand = ARM_GetShifterOperand(true);
45 |
46 | SetZNFlags(Registers[Rn] & ShifterOperand);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/Coprocessor.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | /*
6 | * Note: Most of those instructions are just stubs, since coprocessors aren't implemented,
7 | * except for a few stuff of CP15. It have just the enough to make basic stuff work.
8 | */
9 |
10 | ///
11 | /// Coprocessor Data Processing.
12 | ///
13 | private void ARM_CDP()
14 | {
15 | int CRm = (int)(Opcode & 0xf);
16 | uint Opcode2 = (Opcode >> 5) & 7;
17 | uint CoprocessorIndex = (Opcode >> 8) & 0xf;
18 | int CRd = (int)((Opcode >> 12) & 0xf);
19 | int CRn = (int)((Opcode >> 16) & 0xf);
20 | uint Opcode1 = (Opcode >> 20) & 0xf;
21 | }
22 |
23 | ///
24 | /// Load Coprocessor.
25 | ///
26 | private void ARM_LDC()
27 | {
28 | uint CoprocessorIndex = (Opcode >> 8) & 0xf;
29 | int CRd = (int)((Opcode >> 12) & 0xf);
30 | bool N = (Opcode & 0x400000) != 0;
31 | uint Address = ARM_GetLoadAndStoreCPAddress();
32 | }
33 |
34 | ///
35 | /// Move to Coprocessor from Register.
36 | ///
37 | private void ARM_MCR()
38 | {
39 | int CRm = (int)(Opcode & 0xf);
40 | uint Opcode2 = (Opcode >> 5) & 7;
41 | uint CoprocessorIndex = (Opcode >> 8) & 0xf;
42 | int Rd = (int)((Opcode >> 12) & 0xf);
43 | int CRn = (int)((Opcode >> 16) & 0xf);
44 | uint Opcode1 = (Opcode >> 21) & 7;
45 |
46 | if (CoprocessorIndex == 15) CP15.Write(CRn, Opcode1, CRm, Opcode2, Registers[Rd]);
47 | }
48 |
49 | ///
50 | /// Move to Coprocessor from two Registers.
51 | ///
52 | private void ARM_MCRR()
53 | {
54 | int CRm = (int)(Opcode & 0xf);
55 | uint CoprocessorOpcode = (Opcode >> 4) & 0xf;
56 | uint CoprocessorIndex = (Opcode >> 8) & 0xf;
57 | int Rd = (int)((Opcode >> 12) & 0xf);
58 | int Rn = (int)((Opcode >> 16) & 0xf);
59 | }
60 |
61 | ///
62 | /// Move to Register from Coprocessor.
63 | ///
64 | private void ARM_MRC()
65 | {
66 | int CRm = (int)(Opcode & 0xf);
67 | uint Opcode2 = (Opcode >> 5) & 7;
68 | uint CoprocessorIndex = (Opcode >> 8) & 0xf;
69 | int Rd = (int)((Opcode >> 12) & 0xf);
70 | int CRn = (int)((Opcode >> 16) & 0xf);
71 | uint Opcode1 = (Opcode >> 21) & 7;
72 |
73 | if (CoprocessorIndex == 15)
74 | {
75 | uint Value = CP15.Read(CRn, Opcode1, CRm, Opcode2);
76 |
77 | if (Rd == 15)
78 | Registers.CPSR = (Registers.CPSR & 0xfffffff) | (Value & 0xf0000000);
79 | else
80 | Registers[Rd] = Value;
81 | }
82 | }
83 |
84 | ///
85 | /// Move to two Registers from Coprocessor.
86 | ///
87 | private void ARM_MRRC()
88 | {
89 | int CRm = (int)(Opcode & 0xf);
90 | uint CoprocessorOpcode = (Opcode >> 4) & 0xf;
91 | uint CoprocessorIndex = (Opcode >> 8) & 0xf;
92 | int Rd = (int)((Opcode >> 12) & 0xf);
93 | int Rn = (int)((Opcode >> 16) & 0xf);
94 | }
95 |
96 | ///
97 | /// Store Coprocessor.
98 | ///
99 | private void ARM_STC()
100 | {
101 | uint CoprocessorIndex = (Opcode >> 8) & 0xf;
102 | int CRd = (int)((Opcode >> 12) & 0xf);
103 | bool N = IsOpcodeBitSet(22);
104 | uint Address = ARM_GetLoadAndStoreCPAddress();
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/Exception.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpARM.ARM11
4 | {
5 | ///
6 | /// Arguments returned by the BKPT instruction.
7 | ///
8 | public class BreakpointEventArgs : EventArgs
9 | {
10 | ///
11 | /// Code set by the Program with the Break exception.
12 | ///
13 | public ushort BreakCode;
14 |
15 | ///
16 | /// Creates a new Breakpoint event argument with the given Break Code.
17 | ///
18 | /// 16-bits BKPT code set by the Program
19 | public BreakpointEventArgs(ushort BreakCode)
20 | {
21 | this.BreakCode = BreakCode;
22 | }
23 | }
24 |
25 | ///
26 | /// Arguments returned by the SWI instruction.
27 | ///
28 | public class SoftwareInterruptEventArgs : EventArgs
29 | {
30 | ///
31 | /// Code set by the Program with the Software Interrupt.
32 | ///
33 | public uint InterruptCode;
34 |
35 | ///
36 | /// Creates a new Software Interrupt event argument with the given Break Code.
37 | ///
38 | /// 24-bits SWI code set by the Program
39 | public SoftwareInterruptEventArgs(uint InterruptCode)
40 | {
41 | this.InterruptCode = InterruptCode;
42 | }
43 | }
44 |
45 | public partial class ARMCore
46 | {
47 | ///
48 | /// Breakpoint.
49 | ///
50 | private void ARM_BKPT()
51 | {
52 | uint SPSR = Registers.CPSR;
53 | Registers.Mode = ARMMode.Abort;
54 | Registers[14] = Registers[15] - 4;
55 | Registers.SPSR = SPSR;
56 | Registers.SetFlag(ARMFlag.Thumb, false);
57 | Registers.SetFlag(ARMFlag.IRQDisable, true);
58 | Registers.SetFlag(ARMFlag.AbortDisable, true);
59 | Registers.SetFlag(ARMFlag.Endianness, false);
60 |
61 | Registers[15] = HighVectors ? 0xffff000c : 0xc;
62 |
63 | if (OnBreakpoint != null)
64 | {
65 | ushort Code = (ushort)(((Opcode >> 4) & 0xfff0) | (Opcode & 0xf));
66 | OnBreakpoint(this, new BreakpointEventArgs(Code));
67 | }
68 | }
69 |
70 | ///
71 | /// Change Processor State.
72 | ///
73 | private void ARM_CPS()
74 | {
75 | ARMMode Mode = (ARMMode)(Opcode & 0x1f);
76 | bool mmod = IsOpcodeBitSet(17);
77 | uint imod = (Opcode >> 18) & 3;
78 |
79 | if ((imod & 2) != 0)
80 | {
81 | bool Value = (imod & 1) != 0;
82 | if (IsOpcodeBitSet(6)) Registers.SetFlag(ARMFlag.FIQDisable, Value);
83 | if (IsOpcodeBitSet(7)) Registers.SetFlag(ARMFlag.IRQDisable, Value);
84 | if (IsOpcodeBitSet(8)) Registers.SetFlag(ARMFlag.AbortDisable, Value);
85 | }
86 | else
87 | if (mmod) Registers.Mode = Mode;
88 | }
89 |
90 | ///
91 | /// Return from Exception.
92 | ///
93 | private void ARM_RFE()
94 | {
95 | uint Address = ARM_GetLoadAndStoreMultipleAddress();
96 |
97 | Registers[15] = ReadUInt32(Address);
98 | if (Registers.Mode != ARMMode.User) Registers.CPSR = ReadUInt32(Address + 4);
99 | }
100 |
101 | ///
102 | /// Software Interrupt.
103 | ///
104 | private void ARM_SWI()
105 | {
106 | uint SPSR = Registers.CPSR;
107 | Registers.Mode = ARMMode.Supervisor;
108 | Registers[14] = Registers[15] - 4;
109 | Registers.SPSR = SPSR;
110 | Registers.SetFlag(ARMFlag.Thumb, false);
111 | Registers.SetFlag(ARMFlag.IRQDisable, true);
112 | Registers.SetFlag(ARMFlag.Endianness, false);
113 |
114 | Registers[15] = HighVectors ? 0xffff0008 : 8;
115 |
116 | if (OnSoftwareInterrupt != null)
117 | {
118 | uint Code = Opcode & 0xffffff;
119 | OnSoftwareInterrupt(this, new SoftwareInterruptEventArgs(Code));
120 | }
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/LoadAndStore.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | uint ExclusiveTag;
6 | bool ExclusiveEnabled;
7 |
8 | const uint ERGMask = 0xfffffff8;
9 |
10 | ///
11 | /// Preload Data.
12 | ///
13 | private void ARM_PLD()
14 | {
15 | uint Address = ARM_GetLoadAndStoreAddress();
16 |
17 | //Nothing to do here...
18 | //But if you know how memory access may be optimized with PLD, go ahead and implement it! :)
19 | }
20 |
21 | ///
22 | /// Set Endian.
23 | ///
24 | private void ARM_SETEND()
25 | {
26 | Registers.SetFlag(ARMFlag.Endianness, IsOpcodeBitSet(9));
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/LoadAndStore/Load.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Load Multiple.
7 | ///
8 | private void ARM_LDM()
9 | {
10 | ushort RegisterList = (ushort)(Opcode & 0xffff);
11 | bool PC = (RegisterList & 0x8000) != 0;
12 | int Rn = (int)((Opcode >> 16) & 0xf);
13 | bool W = IsOpcodeBitSet(21);
14 | bool S = IsOpcodeBitSet(22);
15 |
16 | ARMMode OldMode = Registers.Mode;
17 | if (S && !PC) Registers.Mode = ARMMode.User;
18 | uint Address = ARM_GetLoadAndStoreMultipleAddress() & 0xfffffffc;
19 | for (int Index = 0; Index < 15; Index++)
20 | {
21 | if ((RegisterList & (1 << Index)) != 0)
22 | {
23 | Registers[Index] = ReadUInt32E(Address);
24 | Address += 4;
25 | }
26 | }
27 | Registers.Mode = OldMode;
28 |
29 | if (PC)
30 | {
31 | uint Value = ReadUInt32E(Address);
32 | Registers[15] = Value & 0xfffffffe;
33 | Registers.SetFlag(ARMFlag.Thumb, (Value & 1) != 0);
34 | if (S) Registers.CPSR = Registers.SPSR;
35 | }
36 | }
37 |
38 | ///
39 | /// Load Register.
40 | ///
41 | private void ARM_LDR()
42 | {
43 | int Rd = (int)((Opcode >> 12) & 0xf);
44 |
45 | uint Address = ARM_GetLoadAndStoreAddress();
46 | uint Value = ROR(ReadUInt32E(Address & 0xfffffffc), (int)(Address & 3) << 3);
47 | if (Rd == 15)
48 | {
49 | Registers[15] = Value & 0xfffffffe;
50 | Registers.SetFlag(ARMFlag.Thumb, (Value & 1) != 0);
51 | }
52 | else
53 | Registers[Rd] = Value;
54 | }
55 |
56 | ///
57 | /// Load Register Byte.
58 | ///
59 | private void ARM_LDRB()
60 | {
61 | int Rd = (int)((Opcode >> 12) & 0xf);
62 |
63 | uint Address = ARM_GetLoadAndStoreAddress();
64 | byte Value = Bus.ReadUInt8(Address);
65 | Registers[Rd] = Value;
66 | }
67 |
68 | ///
69 | /// Load Register Doubleword.
70 | ///
71 | private void ARM_LDRD()
72 | {
73 | int Rd = (int)((Opcode >> 12) & 0xf);
74 |
75 | if (Rd != 15)
76 | {
77 | uint Address = ARM_GetLoadAndStoreNonWordAddress();
78 | Registers[Rd] = ReadUInt32E(Address);
79 | Registers[Rd + 1] = ReadUInt32E(Address + 4);
80 | }
81 | }
82 |
83 | ///
84 | /// Load Register Exclusive.
85 | ///
86 | private void ARM_LDREX()
87 | {
88 | int Rd = (int)((Opcode >> 12) & 0xf);
89 | int Rn = (int)((Opcode >> 16) & 0xf);
90 |
91 | uint Address = Registers[Rn];
92 | uint Value = ReadUInt32E(Address);
93 | Registers[Rd] = Value;
94 | ExclusiveTag = Address & ERGMask;
95 | ExclusiveEnabled = true;
96 | }
97 |
98 | ///
99 | /// Load Register Halfword.
100 | ///
101 | private void ARM_LDRH()
102 | {
103 | int Rd = (int)((Opcode >> 12) & 0xf);
104 |
105 | uint Address = ARM_GetLoadAndStoreNonWordAddress();
106 | Registers[Rd] = ReadUInt16E(Address);
107 | }
108 |
109 | ///
110 | /// Load Register Signed Byte.
111 | ///
112 | private void ARM_LDRSB()
113 | {
114 | int Rd = (int)((Opcode >> 12) & 0xf);
115 |
116 | uint Address = ARM_GetLoadAndStoreNonWordAddress();
117 | sbyte Value = (sbyte)Bus.ReadUInt8(Address);
118 | Registers[Rd] = (uint)Value;
119 | }
120 |
121 | ///
122 | /// Load Register Signed Halfword.
123 | ///
124 | private void ARM_LDRSH()
125 | {
126 | int Rd = (int)((Opcode >> 12) & 0xf);
127 |
128 | uint Address = ARM_GetLoadAndStoreNonWordAddress();
129 | short Value = (short)ReadUInt16E(Address);
130 | Registers[Rd] = (uint)Value;
131 | }
132 | }
133 | }
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/LoadAndStore/Store.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Store Return State.
7 | ///
8 | private void ARM_SRS()
9 | {
10 | uint Address = ARM_GetSRSAddress();
11 |
12 | ARMMode OldMode = Registers.Mode;
13 | Registers.Mode = (ARMMode)(Opcode & 0x1f);
14 |
15 | WriteUInt32E(Address, Registers[14]);
16 | WriteUInt32E(Address + 4, Registers.SPSR);
17 |
18 | Registers.Mode = OldMode;
19 | }
20 |
21 | ///
22 | /// Store Multiple.
23 | ///
24 | private void ARM_STM()
25 | {
26 | ushort RegisterList = (ushort)(Opcode & 0xffff);
27 | int Rn = (int)((Opcode >> 16) & 0xf);
28 | bool W = IsOpcodeBitSet(21);
29 | bool S = IsOpcodeBitSet(22);
30 | bool U = IsOpcodeBitSet(23);
31 | bool P = IsOpcodeBitSet(24);
32 |
33 | uint Address;
34 | if (U)
35 | Address = Registers[Rn] + (uint)(P ? 4 : 0);
36 | else
37 | {
38 | Address = Registers[Rn] + (uint)(P ? 0 : 4);
39 | for (int Index = 0; Index < 16; Index++)
40 | {
41 | if ((RegisterList & (1 << Index)) != 0) Address -= 4;
42 | }
43 | }
44 |
45 | uint Count = 0;
46 | ARMMode OldMode = Registers.Mode;
47 | if (S) Registers.Mode = ARMMode.User;
48 | for (int Index = 0; Index < 16; Index++)
49 | {
50 | if ((RegisterList & (1 << Index)) != 0)
51 | {
52 | WriteUInt32E(Address + Count, Registers[Index]);
53 | Count += 4;
54 | }
55 | }
56 | Registers.Mode = OldMode;
57 |
58 | if (W)
59 | {
60 | if (U)
61 | Registers[Rn] += Count;
62 | else
63 | Registers[Rn] -= Count;
64 | }
65 | }
66 |
67 | ///
68 | /// Store Register.
69 | ///
70 | private void ARM_STR()
71 | {
72 | int Rd = (int)((Opcode >> 12) & 0xf);
73 |
74 | uint Address = ARM_GetLoadAndStoreAddress();
75 | uint Value = ReadUInt32E(Address);
76 | WriteUInt32E(Address, Registers[Rd]);
77 | }
78 |
79 | ///
80 | /// Store Register Byte.
81 | ///
82 | private void ARM_STRB()
83 | {
84 | int Rd = (int)((Opcode >> 12) & 0xf);
85 |
86 | uint Address = ARM_GetLoadAndStoreAddress();
87 | Bus.WriteUInt8(Address, (byte)Registers[Rd]);
88 | }
89 |
90 | ///
91 | /// Store Register Doubleword.
92 | ///
93 | private void ARM_STRD()
94 | {
95 | int Rd = (int)((Opcode >> 12) & 0xf);
96 |
97 | if (Rd != 15)
98 | {
99 | uint Address = ARM_GetLoadAndStoreNonWordAddress();
100 | WriteUInt32E(Address, Registers[Rd]);
101 | WriteUInt32E(Address + 4, Registers[Rd + 1]);
102 | }
103 | }
104 |
105 | ///
106 | /// Store Register Exclusive.
107 | ///
108 | private void ARM_STREX()
109 | {
110 | int Rm = (int)(Opcode & 0xf);
111 | int Rd = (int)((Opcode >> 12) & 0xf);
112 | int Rn = (int)((Opcode >> 16) & 0xf);
113 |
114 | uint Address = Registers[Rn];
115 | if (ExclusiveEnabled && ExclusiveTag == (Address & ERGMask))
116 | {
117 | WriteUInt32E(Address, Registers[Rm]);
118 | ExclusiveEnabled = false;
119 | Registers[Rd] = 0;
120 | }
121 | else
122 | Registers[Rd] = 1;
123 | }
124 |
125 | ///
126 | /// Store Register Halfword.
127 | ///
128 | private void ARM_STRH()
129 | {
130 | int Rd = (int)((Opcode >> 12) & 0xf);
131 |
132 | uint Address = ARM_GetLoadAndStoreNonWordAddress();
133 | WriteUInt16E(Address, (ushort)Registers[Rd]);
134 | }
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/Logical.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// And.
7 | ///
8 | private void ARM_AND()
9 | {
10 | int Rd = (int)((Opcode >> 12) & 0xf);
11 | int Rn = (int)((Opcode >> 16) & 0xf);
12 | bool S = IsOpcodeBitSet(20);
13 | uint ShifterOperand = ARM_GetShifterOperand(S && Rd != 15);
14 |
15 | Registers[Rd] = Registers[Rn] & ShifterOperand;
16 |
17 | if (S)
18 | {
19 | if (Rd != 15)
20 | SetZNFlags(Registers[Rd]);
21 | else
22 | Registers.CPSR = Registers.SPSR;
23 | }
24 | }
25 |
26 | ///
27 | /// Bit Clear.
28 | ///
29 | private void ARM_BIC()
30 | {
31 | int Rd = (int)((Opcode >> 12) & 0xf);
32 | int Rn = (int)((Opcode >> 16) & 0xf);
33 | bool S = IsOpcodeBitSet(20);
34 | uint ShifterOperand = ARM_GetShifterOperand(S && Rd != 15);
35 |
36 | Registers[Rd] = Registers[Rn] & ~ShifterOperand;
37 |
38 | if (S)
39 | {
40 | if (Rd != 15)
41 | SetZNFlags(Registers[Rd]);
42 | else
43 | Registers.CPSR = Registers.SPSR;
44 | }
45 | }
46 |
47 | ///
48 | /// Count Leading Zeros.
49 | ///
50 | private void ARM_CLZ()
51 | {
52 | int Rm = (int)(Opcode & 0xf);
53 | int Rd = (int)((Opcode >> 12) & 0xf);
54 |
55 | if (Registers[Rm] == 0)
56 | Registers[Rd] = 32;
57 | else
58 | {
59 | for (int Count = 31; Count >= 0; Count--)
60 | {
61 | if ((Registers[Rm] & (1 << Count)) != 0)
62 | {
63 | Registers[Rd] = (uint)(31 - Count);
64 | break;
65 | }
66 | }
67 | }
68 | }
69 |
70 | ///
71 | /// Exclusive Or.
72 | ///
73 | private void ARM_EOR()
74 | {
75 | int Rd = (int)((Opcode >> 12) & 0xf);
76 | int Rn = (int)((Opcode >> 16) & 0xf);
77 | bool S = IsOpcodeBitSet(20);
78 | uint ShifterOperand = ARM_GetShifterOperand(S && Rd != 15);
79 |
80 | Registers[Rd] = Registers[Rn] ^ ShifterOperand;
81 |
82 | if (S)
83 | {
84 | if (Rd != 15)
85 | SetZNFlags(Registers[Rd]);
86 | else
87 | Registers.CPSR = Registers.SPSR;
88 | }
89 | }
90 |
91 | ///
92 | /// Or.
93 | ///
94 | private void ARM_ORR()
95 | {
96 | int Rd = (int)((Opcode >> 12) & 0xf);
97 | int Rn = (int)((Opcode >> 16) & 0xf);
98 | bool S = IsOpcodeBitSet(20);
99 | uint ShifterOperand = ARM_GetShifterOperand(S && Rd != 15);
100 |
101 | Registers[Rd] = Registers[Rn] | ShifterOperand;
102 |
103 | if (S)
104 | {
105 | if (Rd != 15)
106 | SetZNFlags(Registers[Rd]);
107 | else
108 | Registers.CPSR = Registers.SPSR;
109 | }
110 | }
111 |
112 | ///
113 | /// Pack Halfword Bottom Top.
114 | ///
115 | private void ARM_PKHBT()
116 | {
117 | int Rm = (int)(Opcode & 0xf);
118 | int ShiftImmediate = (int)((Opcode >> 7) & 0x1f);
119 | int Rd = (int)((Opcode >> 12) & 0xf);
120 | int Rn = (int)((Opcode >> 16) & 0xf);
121 |
122 | Registers[Rd] = (Registers[Rn] & 0xffff);
123 | Registers[Rd] |= ((Registers[Rm] << ShiftImmediate) & 0xffff0000);
124 | }
125 |
126 | ///
127 | /// Pack Halfword Top Bottom.
128 | ///
129 | private void ARM_PKHTB()
130 | {
131 | int Rm = (int)(Opcode & 0xf);
132 | int ShiftImmediate = (int)((Opcode >> 7) & 0x1f);
133 | int Rd = (int)((Opcode >> 12) & 0xf);
134 | int Rn = (int)((Opcode >> 16) & 0xf);
135 |
136 | Registers[Rd] = (Registers[Rn] & 0xffff0000);
137 |
138 | if (ShiftImmediate == 0)
139 | Registers[Rd] |= (uint)((Registers[Rm] & 0x80000000) != 0 ? 0xffff : 0);
140 | else
141 | Registers[Rd] |= ((Registers[Rm] >> ShiftImmediate) & 0xffff);
142 | }
143 |
144 | ///
145 | /// Byte-Reverse Word.
146 | ///
147 | private void ARM_REV()
148 | {
149 | int Rm = (int)(Opcode & 0xf);
150 | int Rd = (int)((Opcode >> 12) & 0xf);
151 |
152 | Registers[Rd] = (Registers[Rm] >> 24) |
153 | ((Registers[Rm] >> 8) & 0xff00) |
154 | ((Registers[Rm] & 0xff00) << 8) |
155 | ((Registers[Rm] & 0xff) << 24);
156 | }
157 |
158 | ///
159 | /// Byte-Reverse Packed Halfword.
160 | ///
161 | private void ARM_REV16()
162 | {
163 | int Rm = (int)(Opcode & 0xf);
164 | int Rd = (int)((Opcode >> 12) & 0xf);
165 |
166 | Registers[Rd] = ((Registers[Rm] >> 8) & 0xff0000) |
167 | ((Registers[Rm] & 0xff0000) << 8) |
168 | ((Registers[Rm] >> 8) & 0xff) |
169 | ((Registers[Rm] & 0xff) << 8);
170 | }
171 |
172 | ///
173 | /// Byte-Reverse Signed Halfword.
174 | ///
175 | private void ARM_REVSH()
176 | {
177 | int Rm = (int)(Opcode & 0xf);
178 | int Rd = (int)((Opcode >> 12) & 0xf);
179 |
180 | Registers[Rd] = ((Registers[Rm] >> 8) & 0xff) | ((Registers[Rm] & 0xff) << 8);
181 | if ((Registers[Rm] & 0x80) != 0) Registers[Rd] |= 0xffff0000;
182 | }
183 |
184 | ///
185 | /// Select.
186 | ///
187 | private void ARM_SEL()
188 | {
189 | int Rm = (int)(Opcode & 0xf);
190 | int Rd = (int)((Opcode >> 12) & 0xf);
191 | int Rn = (int)((Opcode >> 16) & 0xf);
192 |
193 | Registers[Rd] = (Registers.GE & 1) != 0 ? Registers[Rn] & 0xff : Registers[Rm] & 0xff;
194 | Registers[Rd] |= (Registers.GE & 2) != 0 ? Registers[Rn] & 0xff00 : Registers[Rm] & 0xff00;
195 | Registers[Rd] |= (Registers.GE & 4) != 0 ? Registers[Rn] & 0xff0000 : Registers[Rm] & 0xff0000;
196 | Registers[Rd] |= (Registers.GE & 8) != 0 ? Registers[Rn] & 0xff000000 : Registers[Rm] & 0xff000000;
197 | }
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/ARM/Move.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | const uint UserMask = 0xf80f0200;
6 | const uint PrivilegedMask = 0x1df;
7 | const uint StateMask = 0x1000020;
8 |
9 | ///
10 | /// Move.
11 | ///
12 | private void ARM_MOV()
13 | {
14 | int Rd = (int)((Opcode >> 12) & 0xf);
15 | bool S = IsOpcodeBitSet(20);
16 | uint ShifterOperand = ARM_GetShifterOperand(S && Rd != 15);
17 |
18 | Registers[Rd] = ShifterOperand;
19 | if (S)
20 | {
21 | if (Rd != 15)
22 | SetZNFlags(Registers[Rd]);
23 | else
24 | Registers.CPSR = Registers.SPSR;
25 | }
26 | }
27 |
28 | ///
29 | /// Move General-Purpose Register to Status Register.
30 | ///
31 | private void ARM_MRS()
32 | {
33 | int Rd = (int)((Opcode >> 12) & 0xf);
34 | bool R = IsOpcodeBitSet(22);
35 |
36 | Registers[Rd] = R ? Registers.SPSR : Registers.CPSR;
37 | }
38 |
39 | ///
40 | /// Move Status Register to General-Purpose Register.
41 | ///
42 | private void ARM_MSR()
43 | {
44 | uint Mask = (Opcode >> 16) & 0xf;
45 | bool R = IsOpcodeBitSet(22);
46 | bool I = IsOpcodeBitSet(25);
47 |
48 | uint ByteMask = 0;
49 | if ((Mask & 1) != 0) ByteMask |= 0xff;
50 | if ((Mask & 2) != 0) ByteMask |= 0xff00;
51 | if ((Mask & 4) != 0) ByteMask |= 0xff0000;
52 | if ((Mask & 8) != 0) ByteMask |= 0xff000000;
53 |
54 | uint Value;
55 | if (I)
56 | {
57 | uint Immediate = Opcode & 0xff;
58 | int Rotate = (int)((Opcode >> 7) & 0x1e);
59 | Value = ROR(Immediate, Rotate);
60 | }
61 | else
62 | {
63 | int Rm = (int)(Opcode & 0xf);
64 | Value = Registers[Rm];
65 | }
66 |
67 | if (R)
68 | {
69 | Mask = ByteMask & (UserMask | PrivilegedMask | StateMask);
70 | Registers.SPSR = (Registers.SPSR & ~Mask) | (Value & Mask);
71 | }
72 | else
73 | {
74 | Mask = ByteMask & (Registers.Mode == ARMMode.User ? UserMask : UserMask | PrivilegedMask);
75 | Registers.CPSR = (Registers.CPSR & ~Mask) | (Value & Mask);
76 | }
77 | }
78 |
79 | ///
80 | /// Move Not.
81 | ///
82 | private void ARM_MVN()
83 | {
84 | int Rd = (int)((Opcode >> 12) & 0xf);
85 | bool S = IsOpcodeBitSet(20);
86 | uint ShifterOperand = ARM_GetShifterOperand(S && Rd != 15);
87 |
88 | Registers[Rd] = ~ShifterOperand;
89 | if (S)
90 | {
91 | if (Rd != 15)
92 | SetZNFlags(Registers[Rd]);
93 | else
94 | Registers.CPSR = Registers.SPSR;
95 | }
96 | }
97 |
98 | ///
99 | /// Swap.
100 | ///
101 | private void ARM_SWP()
102 | {
103 | int Rm = (int)(Opcode & 0xf);
104 | int Rd = (int)((Opcode >> 12) & 0xf);
105 | int Rn = (int)((Opcode >> 16) & 0xf);
106 |
107 | uint Value = ReadUInt32E(Registers[Rn]);
108 | WriteUInt32E(Registers[Rn], Registers[Rm]);
109 | Registers[Rd] = Value;
110 | }
111 |
112 | ///
113 | /// Swap Byte.
114 | ///
115 | private void ARM_SWPB()
116 | {
117 | int Rm = (int)(Opcode & 0xf);
118 | int Rd = (int)((Opcode >> 12) & 0xf);
119 | int Rn = (int)((Opcode >> 16) & 0xf);
120 |
121 | byte Value = Bus.ReadUInt8(Registers[Rn]);
122 | Bus.WriteUInt8(Registers[Rn], (byte)Registers[Rm]);
123 | Registers[Rd] = Value;
124 | }
125 |
126 | ///
127 | /// Signed Extend Accumulate Byte.
128 | ///
129 | private void ARM_SXTAB()
130 | {
131 | int Rm = (int)(Opcode & 0xf);
132 | int Rotate = (int)((Opcode >> 10) & 3);
133 | int Rd = (int)((Opcode >> 12) & 0xf);
134 | int Rn = (int)((Opcode >> 16) & 0xf);
135 |
136 | uint Operand = ROR(Registers[Rm], Rotate << 3);
137 | Registers[Rd] = (uint)(Registers[Rn] + (sbyte)Operand);
138 | }
139 |
140 | ///
141 | /// Signed Extend Accumulate Byte 16-bits.
142 | ///
143 | private void ARM_SXTAB16()
144 | {
145 | int Rm = (int)(Opcode & 0xf);
146 | int Rotate = (int)((Opcode >> 10) & 3);
147 | int Rd = (int)((Opcode >> 12) & 0xf);
148 | int Rn = (int)((Opcode >> 16) & 0xf);
149 |
150 | uint Operand = ROR(Registers[Rm], Rotate << 3);
151 | Registers[Rd] = (ushort)(Registers[Rn] + (sbyte)Operand);
152 | Registers[Rd] |= (uint)((Registers[Rn] + (sbyte)(Operand >> 16)) << 16);
153 | }
154 |
155 | ///
156 | /// Signed Extend Accumulate Halfword.
157 | ///
158 | private void ARM_SXTAH()
159 | {
160 | int Rm = (int)(Opcode & 0xf);
161 | int Rotate = (int)((Opcode >> 10) & 3);
162 | int Rd = (int)((Opcode >> 12) & 0xf);
163 | int Rn = (int)((Opcode >> 16) & 0xf);
164 |
165 | uint Operand = ROR(Registers[Rm], Rotate << 3);
166 | Registers[Rd] = (uint)(Registers[Rn] + (short)Operand);
167 | }
168 |
169 | ///
170 | /// Signed Extend Byte.
171 | ///
172 | private void ARM_SXTB()
173 | {
174 | int Rm = (int)(Opcode & 0xf);
175 | int Rotate = (int)((Opcode >> 10) & 3);
176 | int Rd = (int)((Opcode >> 12) & 0xf);
177 |
178 | sbyte Operand = (sbyte)ROR(Registers[Rm], Rotate << 3);
179 | Registers[Rd] = (uint)Operand;
180 | }
181 |
182 | ///
183 | /// Signed Extend Byte 16-bits.
184 | ///
185 | private void ARM_SXTB16()
186 | {
187 | int Rm = (int)(Opcode & 0xf);
188 | int Rotate = (int)((Opcode >> 10) & 3);
189 | int Rd = (int)((Opcode >> 12) & 0xf);
190 | int Rn = (int)((Opcode >> 16) & 0xf);
191 |
192 | uint Operand = ROR(Registers[Rm], Rotate << 3);
193 | Registers[Rd] = (ushort)((short)Operand);
194 | Registers[Rd] |= (uint)((short)(Operand >> 16) << 16);
195 | }
196 |
197 | ///
198 | /// Signed Extend Halfword.
199 | ///
200 | private void ARM_SXTH()
201 | {
202 | int Rm = (int)(Opcode & 0xf);
203 | int Rotate = (int)((Opcode >> 10) & 3);
204 | int Rd = (int)((Opcode >> 12) & 0xf);
205 | int Rn = (int)((Opcode >> 16) & 0xf);
206 |
207 | short Operand = (short)ROR(Registers[Rm], Rotate << 3);
208 | Registers[Rd] = (uint)Operand;
209 | }
210 |
211 | ///
212 | /// Unsigned Extend Accumulate Byte.
213 | ///
214 | private void ARM_UXTAB()
215 | {
216 | int Rm = (int)(Opcode & 0xf);
217 | int Rotate = (int)((Opcode >> 10) & 3);
218 | int Rd = (int)((Opcode >> 12) & 0xf);
219 | int Rn = (int)((Opcode >> 16) & 0xf);
220 |
221 | uint Operand = ROR(Registers[Rm], Rotate << 3);
222 | Registers[Rd] = Registers[Rn] + (byte)Operand;
223 | }
224 |
225 | ///
226 | /// Unsigned Extend Accumulate Byte 16-bits.
227 | ///
228 | private void ARM_UXTAB16()
229 | {
230 | int Rm = (int)(Opcode & 0xf);
231 | int Rotate = (int)((Opcode >> 10) & 3);
232 | int Rd = (int)((Opcode >> 12) & 0xf);
233 | int Rn = (int)((Opcode >> 16) & 0xf);
234 |
235 | uint Operand = ROR(Registers[Rm], Rotate << 3);
236 | Registers[Rd] = (ushort)(Registers[Rn] + (byte)Operand);
237 | Registers[Rd] |= (Registers[Rn] + (byte)(Operand >> 16)) << 16;
238 | }
239 |
240 | ///
241 | /// Unsigned Extend Accumulate Halfword.
242 | ///
243 | private void ARM_UXTAH()
244 | {
245 | int Rm = (int)(Opcode & 0xf);
246 | int Rotate = (int)((Opcode >> 10) & 3);
247 | int Rd = (int)((Opcode >> 12) & 0xf);
248 | int Rn = (int)((Opcode >> 16) & 0xf);
249 |
250 | uint Operand = ROR(Registers[Rm], Rotate << 3);
251 | Registers[Rd] = Registers[Rn] + (ushort)Operand;
252 | }
253 |
254 | ///
255 | /// Unsigned Extend Byte.
256 | ///
257 | private void ARM_UXTB()
258 | {
259 | int Rm = (int)(Opcode & 0xf);
260 | int Rotate = (int)((Opcode >> 10) & 3);
261 | int Rd = (int)((Opcode >> 12) & 0xf);
262 |
263 | Registers[Rd] = ROR(Registers[Rm], Rotate << 3) & 0xff;
264 | }
265 |
266 | ///
267 | /// Unsigned Extend Byte 16-bits.
268 | ///
269 | private void ARM_UXTB16()
270 | {
271 | int Rm = (int)(Opcode & 0xf);
272 | int Rotate = (int)((Opcode >> 10) & 3);
273 | int Rd = (int)((Opcode >> 12) & 0xf);
274 | int Rn = (int)((Opcode >> 16) & 0xf);
275 |
276 | Registers[Rd] = ROR(Registers[Rm], Rotate << 3) & 0xff00ff;
277 | }
278 |
279 | ///
280 | /// Unsigned Extend Halfword.
281 | ///
282 | private void ARM_UXTH()
283 | {
284 | int Rm = (int)(Opcode & 0xf);
285 | int Rotate = (int)((Opcode >> 10) & 3);
286 | int Rd = (int)((Opcode >> 12) & 0xf);
287 | int Rn = (int)((Opcode >> 16) & 0xf);
288 |
289 | Registers[Rd] = ROR(Registers[Rm], Rotate << 3) & 0xffff;
290 | }
291 | }
292 | }
293 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/Thumb/Arithmetic.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | //Addition
6 |
7 | ///
8 | /// Add with Carry.
9 | ///
10 | private void Thumb_ADC()
11 | {
12 | int Rd = (int)(Opcode & 7);
13 | int Rm = (int)((Opcode >> 3) & 7);
14 |
15 | Registers[Rd] = Add(Registers[Rd], Registers[Rm], true, true);
16 | }
17 |
18 | ///
19 | /// Add (1).
20 | ///
21 | private void Thumb_ADD()
22 | {
23 | int Rd = (int)(Opcode & 7);
24 | int Rn = (int)((Opcode >> 3) & 7);
25 | uint Immediate = (Opcode >> 6) & 7;
26 |
27 | Registers[Rd] = Add(Registers[Rn], Immediate, false, true);
28 | }
29 |
30 | ///
31 | /// Add (2).
32 | ///
33 | private void Thumb_ADD_2()
34 | {
35 | uint Immediate = Opcode & 0xff;
36 | int Rd = (int)((Opcode >> 8) & 7);
37 |
38 | Registers[Rd] = Add(Registers[Rd], Immediate, false, true);
39 | }
40 |
41 | ///
42 | /// Add (3).
43 | ///
44 | private void Thumb_ADD_3()
45 | {
46 | int Rd = (int)(Opcode & 7);
47 | int Rn = (int)((Opcode >> 3) & 7);
48 | int Rm = (int)((Opcode >> 6) & 7);
49 |
50 | Registers[Rd] = Add(Registers[Rn], Registers[Rm], false, true);
51 | }
52 |
53 | ///
54 | /// Add (4).
55 | ///
56 | private void Thumb_ADD_4()
57 | {
58 | int Rd = (int)(Opcode & 7);
59 | int Rm = (int)((Opcode >> 3) & 7);
60 |
61 | if (IsOpcodeBitSet(7)) Rd += 8;
62 | if (IsOpcodeBitSet(6)) Rm += 8;
63 | Registers[Rd] = Add(Registers[Rd], Registers[Rm], false, false);
64 | }
65 |
66 | ///
67 | /// Add (5).
68 | ///
69 | private void Thumb_ADD_5()
70 | {
71 | uint Immediate = Opcode & 0xff;
72 | int Rd = (int)((Opcode >> 8) & 7);
73 |
74 | Registers[Rd] = Add(Registers[15] & 0xfffffffc, Immediate << 2, false, false);
75 | }
76 |
77 | ///
78 | /// Add (6).
79 | ///
80 | private void Thumb_ADD_6()
81 | {
82 | uint Immediate = Opcode & 0xff;
83 | int Rd = (int)((Opcode >> 8) & 7);
84 |
85 | Registers[Rd] = Add(Registers[13], Immediate << 2, false, false);
86 | }
87 |
88 | ///
89 | /// Add (7).
90 | ///
91 | private void Thumb_ADD_7()
92 | {
93 | uint Immediate = Opcode & 0x7f;
94 |
95 | Registers[13] = Add(Registers[13], Immediate << 2, false, false);
96 | }
97 |
98 | //Miscellaneous
99 |
100 | ///
101 | /// Arithmetic Shift Right (1).
102 | ///
103 | private void Thumb_ASR()
104 | {
105 | int Rd = (int)(Opcode & 7);
106 | int Rm = (int)((Opcode >> 3) & 7);
107 | int Shift = (int)((Opcode >> 6) & 0x1f);
108 |
109 | if (Shift == 0) Shift = 32;
110 | int RmValue = (int)Registers[Rm];
111 | Registers[Rd] = (uint)((long)RmValue >> Shift);
112 | Registers.SetFlag(ARMFlag.Carry, (RmValue & (1 << (Shift - 1))) != 0);
113 |
114 | SetZNFlags(Registers[Rd]);
115 | }
116 |
117 | ///
118 | /// Arithmetic Shift Right (2).
119 | ///
120 | private void Thumb_ASR_2()
121 | {
122 | int Rd = (int)(Opcode & 7);
123 | int Rs = (int)((Opcode >> 3) & 7);
124 |
125 | int Shift = (int)(Registers[Rs] & 0xff);
126 | if (Shift > 0)
127 | {
128 | bool Carry = false;
129 | if (Shift <= 32)
130 | {
131 | int RdValue = (int)Registers[Rd];
132 | Registers[Rd] = (uint)((long)RdValue >> Shift);
133 | Carry = (RdValue & (1 << (Shift - 1))) != 0;
134 | }
135 | else
136 | {
137 | Carry = (Registers[Rd] & 0x80000000) != 0;
138 | Registers[Rd] = Carry ? 0xffffffff : 0;
139 | }
140 |
141 | Registers.SetFlag(ARMFlag.Carry, Carry);
142 | }
143 |
144 | SetZNFlags(Registers[Rd]);
145 | }
146 |
147 | ///
148 | /// Multiply.
149 | ///
150 | private void Thumb_MUL()
151 | {
152 | int Rd = (int)(Opcode & 7);
153 | int Rm = (int)((Opcode >> 3) & 7);
154 |
155 | Registers[Rd] *= Registers[Rm];
156 | SetZNFlags(Registers[Rd]);
157 | }
158 |
159 | //Subtraction
160 |
161 | ///
162 | /// Negate.
163 | ///
164 | private void Thumb_NEG()
165 | {
166 | int Rd = (int)(Opcode & 7);
167 | int Rm = (int)((Opcode >> 3) & 7);
168 |
169 | Registers[Rd] = Subtract(0, Registers[Rm], false, true);
170 | }
171 |
172 | ///
173 | /// Subtract with Carry.
174 | ///
175 | private void Thumb_SBC()
176 | {
177 | int Rd = (int)(Opcode & 7);
178 | int Rm = (int)((Opcode >> 3) & 7);
179 |
180 | Registers[Rd] = Subtract(Registers[Rd], Registers[Rm], true, true);
181 | }
182 |
183 | ///
184 | /// Subtract (1).
185 | ///
186 | private void Thumb_SUB()
187 | {
188 | int Rd = (int)(Opcode & 7);
189 | int Rn = (int)((Opcode >> 3) & 7);
190 | uint Immediate = (Opcode >> 6) & 7;
191 |
192 | Registers[Rd] = Subtract(Registers[Rn], Immediate, false, true);
193 | }
194 |
195 | ///
196 | /// Subtract (2).
197 | ///
198 | private void Thumb_SUB_2()
199 | {
200 | uint Immediate = Opcode & 0xff;
201 | int Rd = (int)((Opcode >> 8) & 7);
202 |
203 | Registers[Rd] = Subtract(Registers[Rd], Immediate, false, true);
204 | }
205 |
206 | ///
207 | /// Subtract (3).
208 | ///
209 | private void Thumb_SUB_3()
210 | {
211 | int Rd = (int)(Opcode & 7);
212 | int Rn = (int)((Opcode >> 3) & 7);
213 | int Rm = (int)((Opcode >> 6) & 7);
214 |
215 | Registers[Rd] = Subtract(Registers[Rn], Registers[Rm], false, true);
216 | }
217 |
218 | ///
219 | /// Subtract (4).
220 | ///
221 | private void Thumb_SUB_4()
222 | {
223 | uint Immediate = Opcode & 0x7f;
224 |
225 | Registers[13] = Subtract(Registers[13], Immediate << 2, false, false);
226 | }
227 | }
228 | }
229 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/Thumb/Branch.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Branch (1).
7 | ///
8 | private void Thumb_B()
9 | {
10 | sbyte Immediate = (sbyte)(Opcode & 0xff);
11 |
12 | ARMCondition Condition = (ARMCondition)((Opcode >> 8) & 0xf);
13 | if (IsConditionMet(Condition)) Registers[15] = (uint)(Registers[15] + (Immediate << 1));
14 | }
15 |
16 | ///
17 | /// Branch (2).
18 | ///
19 | private void Thumb_B_2()
20 | {
21 | int Immediate = SignExtend12((Opcode & 0x7ff) << 1);
22 |
23 | Registers[15] = (uint)(Registers[15] + Immediate);
24 | }
25 |
26 | ///
27 | /// Branch with Link and Exchange (1).
28 | ///
29 | private void Thumb_BLX()
30 | {
31 | uint Immediate = Opcode & 0x7ff;
32 | uint H = (Opcode >> 11) & 3;
33 |
34 | if (H > 0)
35 | {
36 | if (H != 2)
37 | {
38 | uint LR = (Registers[15] - 2) | 1;
39 | Registers[15] = Registers[14] + (Immediate << 1);
40 | Registers[14] = LR;
41 |
42 | if (H == 1)
43 | {
44 | Registers[15] &= 0xfffffffc;
45 | Registers.SetFlag(ARMFlag.Thumb, false);
46 | }
47 | }
48 | else
49 | Registers[14] = (uint)(Registers[15] + (SignExtend11(Immediate) << 12));
50 | }
51 | }
52 |
53 | ///
54 | /// Branch with Link and Exchange (2).
55 | ///
56 | private void Thumb_BLX_2()
57 | {
58 | int Rm = (int)((Opcode >> 3) & 7);
59 |
60 | Registers[14] = (Registers[15] - 2) | 1;
61 | Registers[15] = Registers[Rm] & 0xfffffffe;
62 | Registers.SetFlag(ARMFlag.Thumb, (Registers[Rm] & 1) != 0);
63 | }
64 |
65 | ///
66 | /// Branch and Exchange.
67 | ///
68 | private void Thumb_BX()
69 | {
70 | int Rm = (int)((Opcode >> 3) & 0xf);
71 |
72 | Registers[15] = Registers[Rm] & 0xfffffffe;
73 | Registers.SetFlag(ARMFlag.Thumb, (Registers[Rm] & 1) != 0);
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/Thumb/Compare.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Compare Negative.
7 | ///
8 | private void Thumb_CMN()
9 | {
10 | int Rn = (int)(Opcode & 7);
11 | int Rm = (int)((Opcode >> 3) & 7);
12 |
13 | Add(Registers[Rn], Registers[Rm], false, true);
14 | }
15 |
16 | ///
17 | /// Compare (1).
18 | ///
19 | private void Thumb_CMP()
20 | {
21 | uint Immediate = Opcode & 0xff;
22 | int Rn = (int)((Opcode >> 8) & 7);
23 |
24 | Subtract(Registers[Rn], Immediate, false, true);
25 | }
26 |
27 | ///
28 | /// Compare (2).
29 | ///
30 | private void Thumb_CMP_2()
31 | {
32 | int Rn = (int)(Opcode & 7);
33 | int Rm = (int)((Opcode >> 3) & 7);
34 |
35 | Subtract(Registers[Rn], Registers[Rm], false, true);
36 | }
37 |
38 | ///
39 | /// Compare (3).
40 | ///
41 | private void Thumb_CMP_3()
42 | {
43 | int Rn = (int)(Opcode & 7);
44 | int Rm = (int)((Opcode >> 3) & 7);
45 |
46 | if (IsOpcodeBitSet(7)) Rn += 8;
47 | if (IsOpcodeBitSet(6)) Rm += 8;
48 | Subtract(Registers[Rn], Registers[Rm], false, true);
49 | }
50 |
51 | ///
52 | /// Test.
53 | ///
54 | private void Thumb_TST()
55 | {
56 | int Rn = (int)(Opcode & 7);
57 | int Rm = (int)((Opcode >> 3) & 7);
58 |
59 | SetZNFlags(Registers[Rn] & Registers[Rm]);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/Thumb/Exception.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Breakpoint.
7 | ///
8 | private void Thumb_BKPT()
9 | {
10 | uint SPSR = Registers.CPSR;
11 | Registers.Mode = ARMMode.Abort;
12 | Registers[14] = Registers[15] - 2;
13 | Registers.SPSR = SPSR;
14 | Registers.SetFlag(ARMFlag.Thumb, false);
15 | Registers.SetFlag(ARMFlag.IRQDisable, true);
16 | Registers.SetFlag(ARMFlag.AbortDisable, true);
17 | Registers.SetFlag(ARMFlag.Endianness, false);
18 |
19 | Registers[15] = HighVectors ? 0xffff000c : 0xc;
20 |
21 | if (OnBreakpoint != null)
22 | {
23 | ushort Code = (ushort)(Opcode & 0xff);
24 | OnBreakpoint(this, new BreakpointEventArgs(Code));
25 | }
26 | }
27 |
28 | ///
29 | /// Change Processor State.
30 | ///
31 | private void Thumb_CPS()
32 | {
33 | if (Registers.Mode != ARMMode.User)
34 | {
35 | bool Value = IsOpcodeBitSet(4);
36 | if (IsOpcodeBitSet(0)) Registers.SetFlag(ARMFlag.FIQDisable, Value);
37 | if (IsOpcodeBitSet(1)) Registers.SetFlag(ARMFlag.IRQDisable, Value);
38 | if (IsOpcodeBitSet(2)) Registers.SetFlag(ARMFlag.AbortDisable, Value);
39 | }
40 | }
41 |
42 | ///
43 | /// Software Interrupt.
44 | ///
45 | private void Thumb_SWI()
46 | {
47 | uint SPSR = Registers.CPSR;
48 | Registers.Mode = ARMMode.Supervisor;
49 | Registers[14] = Registers[15] - 2;
50 | Registers.SPSR = SPSR;
51 | Registers.SetFlag(ARMFlag.Thumb, false);
52 | Registers.SetFlag(ARMFlag.IRQDisable, true);
53 | Registers.SetFlag(ARMFlag.Endianness, false);
54 |
55 | Registers[15] = HighVectors ? 0xffff0008 : 8;
56 |
57 | if (OnSoftwareInterrupt != null)
58 | {
59 | uint Code = Opcode & 0xff;
60 | OnSoftwareInterrupt(this, new SoftwareInterruptEventArgs(Code));
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/Thumb/LoadAndStore.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | //Load
6 |
7 | ///
8 | /// Load Multiple Increment After.
9 | ///
10 | private void Thumb_LDMIA()
11 | {
12 | byte RegisterList = (byte)(Opcode & 0xff);
13 | int Rn = (int)((Opcode >> 8) & 7);
14 |
15 | uint Count = 0;
16 | for (int Index = 0; Index < 8; Index++)
17 | {
18 | if ((RegisterList & (1 << Index)) != 0) Count += 4;
19 | }
20 |
21 | uint Address = Registers[Rn];
22 | Registers[Rn] += Count;
23 |
24 | for (int Index = 0; Index < 8; Index++)
25 | {
26 | if ((RegisterList & (1 << Index)) != 0)
27 | {
28 | Registers[Index] = ReadUInt32E(Address);
29 | Address += 4;
30 | }
31 | }
32 | }
33 |
34 | ///
35 | /// Load Register (1).
36 | ///
37 | private void Thumb_LDR()
38 | {
39 | int Rd = (int)(Opcode & 7);
40 | int Rn = (int)((Opcode >> 3) & 7);
41 | uint Immediate = (Opcode >> 6) & 0x1f;
42 |
43 | uint Address = Registers[Rn] + (Immediate << 2);
44 | Registers[Rd] = ROR(ReadUInt32E(Address & 0xfffffffc), (int)(Address & 3) << 3);
45 | }
46 |
47 | ///
48 | /// Load Register (2).
49 | ///
50 | private void Thumb_LDR_2()
51 | {
52 | int Rd = (int)(Opcode & 7);
53 | int Rn = (int)((Opcode >> 3) & 7);
54 | int Rm = (int)((Opcode >> 6) & 7);
55 |
56 | uint Address = Registers[Rn] + Registers[Rm];
57 | Registers[Rd] = ROR(ReadUInt32E(Address & 0xfffffffc), (int)(Address & 3) << 3);
58 | }
59 |
60 | ///
61 | /// Load Register (3).
62 | ///
63 | private void Thumb_LDR_3()
64 | {
65 | uint Immediate = Opcode & 0xff;
66 | int Rd = (int)((Opcode >> 8) & 7);
67 |
68 | uint Address = (Registers[15] & 0xfffffffc) + (Immediate << 2);
69 | Registers[Rd] = ROR(ReadUInt32E(Address & 0xfffffffc), (int)(Address & 3) << 3);
70 | }
71 |
72 | ///
73 | /// Load Register (4).
74 | ///
75 | private void Thumb_LDR_4()
76 | {
77 | uint Immediate = Opcode & 0xff;
78 | int Rd = (int)((Opcode >> 8) & 7);
79 |
80 | uint Address = Registers[13] + (Immediate << 2);
81 | Registers[Rd] = ROR(ReadUInt32E(Address & 0xfffffffc), (int)(Address & 3) << 3);
82 | }
83 |
84 | ///
85 | /// Load Register Byte (1).
86 | ///
87 | private void Thumb_LDRB()
88 | {
89 | int Rd = (int)(Opcode & 7);
90 | int Rn = (int)((Opcode >> 3) & 7);
91 | uint Immediate = (Opcode >> 6) & 0x1f;
92 |
93 | uint Address = Registers[Rn] + Immediate;
94 | Registers[Rd] = Bus.ReadUInt8(Address);
95 | }
96 |
97 | ///
98 | /// Load Register Byte (2).
99 | ///
100 | private void Thumb_LDRB_2()
101 | {
102 | int Rd = (int)(Opcode & 7);
103 | int Rn = (int)((Opcode >> 3) & 7);
104 | int Rm = (int)((Opcode >> 6) & 7);
105 |
106 | uint Address = Registers[Rn] + Registers[Rm];
107 | Registers[Rd] = Bus.ReadUInt8(Address);
108 | }
109 |
110 | ///
111 | /// Load Register Halfword (1).
112 | ///
113 | private void Thumb_LDRH()
114 | {
115 | int Rd = (int)(Opcode & 7);
116 | int Rn = (int)((Opcode >> 3) & 7);
117 | uint Immediate = (Opcode >> 6) & 0x1f;
118 |
119 | uint Address = Registers[Rn] + (Immediate << 1);
120 | Registers[Rd] = ReadUInt16E(Address);
121 | }
122 |
123 | ///
124 | /// Load Register Halfword (2).
125 | ///
126 | private void Thumb_LDRH_2()
127 | {
128 | int Rd = (int)(Opcode & 7);
129 | int Rn = (int)((Opcode >> 3) & 7);
130 | int Rm = (int)((Opcode >> 6) & 7);
131 |
132 | uint Address = Registers[Rn] + Registers[Rm];
133 | Registers[Rd] = ReadUInt16E(Address);
134 | }
135 |
136 | ///
137 | /// Load Register Signed Byte.
138 | ///
139 | private void Thumb_LDRSB()
140 | {
141 | int Rd = (int)(Opcode & 7);
142 | int Rn = (int)((Opcode >> 3) & 7);
143 | int Rm = (int)((Opcode >> 6) & 7);
144 |
145 | uint Address = Registers[Rn] + Registers[Rm];
146 | sbyte Value = (sbyte)Bus.ReadUInt8(Address);
147 | Registers[Rd] = (uint)Value;
148 | }
149 |
150 | ///
151 | /// Load Register Signed Halfword.
152 | ///
153 | private void Thumb_LDRSH()
154 | {
155 | int Rd = (int)(Opcode & 7);
156 | int Rn = (int)((Opcode >> 3) & 7);
157 | int Rm = (int)((Opcode >> 6) & 7);
158 |
159 | uint Address = Registers[Rn] + Registers[Rm];
160 | short Value = (short)ReadUInt16E(Address);
161 | Registers[Rd] = (uint)Value;
162 | }
163 |
164 | ///
165 | /// Set Endian.
166 | ///
167 | private void Thumb_SETEND()
168 | {
169 | Registers.SetFlag(ARMFlag.Endianness, IsOpcodeBitSet(3));
170 | }
171 |
172 | //Store
173 |
174 | ///
175 | /// Store Multiple Increment After.
176 | ///
177 | private void Thumb_STMIA()
178 | {
179 | byte RegisterList = (byte)(Opcode & 0xff);
180 | int Rn = (int)((Opcode >> 8) & 7);
181 |
182 | uint Count = 0;
183 | for (int Index = 0; Index < 8; Index++)
184 | {
185 | if ((RegisterList & (1 << Index)) != 0) Count++;
186 | }
187 |
188 | uint Address = Registers[Rn];
189 | Registers[Rn] += Count << 2;
190 |
191 | for (int Index = 0; Index < 8; Index++)
192 | {
193 | if ((RegisterList & (1 << Index)) != 0)
194 | {
195 | WriteUInt32E(Address, Registers[Index]);
196 | Address += 4;
197 | }
198 | }
199 | }
200 |
201 | ///
202 | /// Store Register (1).
203 | ///
204 | private void Thumb_STR()
205 | {
206 | int Rd = (int)(Opcode & 7);
207 | int Rn = (int)((Opcode >> 3) & 7);
208 | uint Immediate = (Opcode >> 6) & 0x1f;
209 |
210 | uint Address = Registers[Rn] + (Immediate << 2);
211 | WriteUInt32(Address, Registers[Rd]);
212 | }
213 |
214 | ///
215 | /// Store Register (2).
216 | ///
217 | private void Thumb_STR_2()
218 | {
219 | int Rd = (int)(Opcode & 7);
220 | int Rn = (int)((Opcode >> 3) & 7);
221 | int Rm = (int)((Opcode >> 6) & 7);
222 |
223 | uint Address = Registers[Rn] + Registers[Rm];
224 | WriteUInt32E(Address, Registers[Rd]);
225 | }
226 |
227 | ///
228 | /// Store Register (3).
229 | ///
230 | private void Thumb_STR_3()
231 | {
232 | uint Immediate = Opcode & 0xff;
233 | int Rd = (int)((Opcode >> 8) & 7);
234 |
235 | uint Address = Registers[13] + (Immediate << 2);
236 | WriteUInt32E(Address, Registers[Rd]);
237 | }
238 |
239 | ///
240 | /// Store Register Byte (1).
241 | ///
242 | private void Thumb_STRB()
243 | {
244 | int Rd = (int)(Opcode & 7);
245 | int Rn = (int)((Opcode >> 3) & 7);
246 | uint Immediate = (Opcode >> 6) & 0x1f;
247 |
248 | uint Address = Registers[Rn] + Immediate;
249 | Bus.WriteUInt8(Address, (byte)Registers[Rd]);
250 | }
251 |
252 | ///
253 | /// Store Register Byte (2).
254 | ///
255 | private void Thumb_STRB_2()
256 | {
257 | int Rd = (int)(Opcode & 7);
258 | int Rn = (int)((Opcode >> 3) & 7);
259 | int Rm = (int)((Opcode >> 6) & 7);
260 |
261 | uint Address = Registers[Rn] + Registers[Rm];
262 | Bus.WriteUInt8(Address, (byte)Registers[Rd]);
263 | }
264 |
265 | ///
266 | /// Store Register Halfword (1).
267 | ///
268 | private void Thumb_STRH()
269 | {
270 | int Rd = (int)(Opcode & 7);
271 | int Rn = (int)((Opcode >> 3) & 7);
272 | uint Immediate = (Opcode >> 6) & 0x1f;
273 |
274 | uint Address = Registers[Rn] + (Immediate << 1);
275 | WriteUInt16E(Address, (ushort)Registers[Rd]);
276 | }
277 |
278 | ///
279 | /// Store Register Halfword (2).
280 | ///
281 | private void Thumb_STRH_2()
282 | {
283 | int Rd = (int)(Opcode & 7);
284 | int Rn = (int)((Opcode >> 3) & 7);
285 | int Rm = (int)((Opcode >> 6) & 7);
286 |
287 | uint Address = Registers[Rn] + Registers[Rm];
288 | WriteUInt16E(Address, (ushort)Registers[Rd]);
289 | }
290 | }
291 | }
292 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/Thumb/Logical.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// And.
7 | ///
8 | private void Thumb_AND()
9 | {
10 | int Rd = (int)(Opcode & 7);
11 | int Rm = (int)((Opcode >> 3) & 7);
12 |
13 | Registers[Rd] &= Registers[Rm];
14 | SetZNFlags(Registers[Rd]);
15 | }
16 |
17 | ///
18 | /// Bit Clear.
19 | ///
20 | private void Thumb_BIC()
21 | {
22 | int Rd = (int)(Opcode & 7);
23 | int Rm = (int)((Opcode >> 3) & 7);
24 |
25 | Registers[Rd] &= ~Registers[Rm];
26 | SetZNFlags(Registers[Rd]);
27 | }
28 |
29 | ///
30 | /// Exclusive Or.
31 | ///
32 | private void Thumb_EOR()
33 | {
34 | int Rd = (int)(Opcode & 7);
35 | int Rm = (int)((Opcode >> 3) & 7);
36 |
37 | Registers[Rd] ^= Registers[Rm];
38 | SetZNFlags(Registers[Rd]);
39 | }
40 |
41 | ///
42 | /// Logical Shift Left (1).
43 | ///
44 | private void Thumb_LSL()
45 | {
46 | int Rd = (int)(Opcode & 7);
47 | int Rm = (int)((Opcode >> 3) & 7);
48 | int Shift = (int)((Opcode >> 6) & 0x1f);
49 |
50 | if (Shift > 0) Registers.SetFlag(ARMFlag.Carry, (Registers[Rm] & (1 << (32 - Shift))) != 0);
51 | Registers[Rd] = Registers[Rm] << Shift;
52 |
53 | SetZNFlags(Registers[Rd]);
54 | }
55 |
56 | ///
57 | /// Logical Shift Left (2).
58 | ///
59 | private void Thumb_LSL_2()
60 | {
61 | int Rd = (int)(Opcode & 7);
62 | int Rs = (int)((Opcode >> 3) & 7);
63 |
64 | int Shift = (int)(Registers[Rs] & 0xff);
65 | if (Shift > 0)
66 | {
67 | bool Carry = false;
68 | if (Shift <= 32)
69 | {
70 | Carry = (Registers[Rd] & (1 << (32 - Shift))) != 0;
71 | Registers[Rd] = (uint)((ulong)Registers[Rd] << Shift);
72 | }
73 | else
74 | Registers[Rd] = 0;
75 |
76 | Registers.SetFlag(ARMFlag.Carry, Carry);
77 | }
78 |
79 | SetZNFlags(Registers[Rd]);
80 | }
81 |
82 | ///
83 | /// Logical Shift Right (1).
84 | ///
85 | private void Thumb_LSR()
86 | {
87 | int Rd = (int)(Opcode & 7);
88 | int Rm = (int)((Opcode >> 3) & 7);
89 | int Shift = (int)((Opcode >> 6) & 0x1f);
90 |
91 | if (Shift == 0) Shift = 32;
92 | Registers.SetFlag(ARMFlag.Carry, (Registers[Rm] & (1 << (Shift - 1))) != 0);
93 | Registers[Rd] = (uint)((ulong)Registers[Rm] >> Shift);
94 |
95 | SetZNFlags(Registers[Rd]);
96 | }
97 |
98 | ///
99 | /// Logical Shift Right (2).
100 | ///
101 | private void Thumb_LSR_2()
102 | {
103 | int Rd = (int)(Opcode & 7);
104 | int Rs = (int)((Opcode >> 3) & 7);
105 |
106 | int Shift = (int)(Registers[Rs] & 0xff);
107 | if (Shift > 0)
108 | {
109 | bool Carry = false;
110 | if (Shift <= 32)
111 | {
112 | Carry = (Registers[Rd] & (1 << (Shift - 1))) != 0;
113 | Registers[Rd] = (uint)((ulong)Registers[Rd] >> Shift);
114 | }
115 | else
116 | Registers[Rd] = 0;
117 |
118 | Registers.SetFlag(ARMFlag.Carry, Carry);
119 | }
120 |
121 | SetZNFlags(Registers[Rd]);
122 | }
123 |
124 | ///
125 | /// Or.
126 | ///
127 | private void Thumb_ORR()
128 | {
129 | int Rd = (int)(Opcode & 7);
130 | int Rm = (int)((Opcode >> 3) & 7);
131 |
132 | Registers[Rd] |= Registers[Rm];
133 | SetZNFlags(Registers[Rd]);
134 | }
135 |
136 | ///
137 | /// Byte-Reverse Word.
138 | ///
139 | private void Thumb_REV()
140 | {
141 | int Rd = (int)(Opcode & 7);
142 | int Rn = (int)((Opcode >> 3) & 7);
143 |
144 | Registers[Rd] = (Registers[Rn] >> 24) |
145 | ((Registers[Rn] >> 8) & 0xff00) |
146 | ((Registers[Rn] & 0xff00) << 8) |
147 | ((Registers[Rn] & 0xff) << 24);
148 | }
149 |
150 | ///
151 | /// Byte-Reverse Packed Halfword.
152 | ///
153 | private void Thumb_REV16()
154 | {
155 | int Rd = (int)(Opcode & 7);
156 | int Rn = (int)((Opcode >> 3) & 7);
157 |
158 | Registers[Rd] = ((Registers[Rn] >> 8) & 0xff0000) |
159 | ((Registers[Rn] & 0xff0000) << 8) |
160 | ((Registers[Rn] >> 8) & 0xff) |
161 | ((Registers[Rn] & 0xff) << 8);
162 | }
163 |
164 | ///
165 | /// Byte-Reverse Signed Halfword.
166 | ///
167 | private void Thumb_REVSH()
168 | {
169 | int Rd = (int)(Opcode & 7);
170 | int Rn = (int)((Opcode >> 3) & 7);
171 |
172 | Registers[Rd] = ((Registers[Rn] >> 8) & 0xff) | ((Registers[Rn] & 0xff) << 8);
173 | if ((Registers[Rn] & 0x80) != 0) Registers[Rd] |= 0xffff0000;
174 | }
175 |
176 | ///
177 | /// Rotate Right.
178 | ///
179 | private void Thumb_ROR()
180 | {
181 | int Rd = (int)(Opcode & 7);
182 | int Rs = (int)((Opcode >> 3) & 7);
183 |
184 | int Shift = (int)(Registers[Rs] & 0xff);
185 | if (Shift > 0)
186 | {
187 | Shift &= 0x1f;
188 | if (Shift > 0)
189 | {
190 | Registers.SetFlag(ARMFlag.Carry, (Registers[Rd] & (1 << (Shift - 1))) != 0);
191 | Registers[Rd] = ROR(Registers[Rd], Shift);
192 | }
193 | else
194 | Registers.SetFlag(ARMFlag.Carry, (Registers[Rd] & 0x80000000) != 0);
195 | }
196 |
197 | SetZNFlags(Registers[Rd]);
198 | }
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/ARM/Instructions/Thumb/Move.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Copy.
7 | ///
8 | private void Thumb_CPY()
9 | {
10 | int Rd = (int)(Opcode & 7);
11 | int Rm = (int)((Opcode >> 3) & 7);
12 | bool H2 = IsOpcodeBitSet(6);
13 | bool H1 = IsOpcodeBitSet(7);
14 |
15 | if (H1) Rd += 8;
16 | if (H2) Rm += 8;
17 | Registers[Rd] = Registers[Rm];
18 | if (Rd == 15) Registers[Rd] &= 0xfffffffe;
19 | }
20 |
21 | ///
22 | /// Move (1).
23 | ///
24 | private void Thumb_MOV()
25 | {
26 | uint Immediate = Opcode & 0xff;
27 | int Rd = (int)((Opcode >> 8) & 7);
28 |
29 | Registers[Rd] = Immediate;
30 | SetZNFlags(Registers[Rd]);
31 | }
32 |
33 | ///
34 | /// Move (2).
35 | ///
36 | private void Thumb_MOV_2()
37 | {
38 | int Rd = (int)(Opcode & 7);
39 | int Rn = (int)((Opcode >> 3) & 7);
40 |
41 | Registers[Rd] = Registers[Rn];
42 | SetZNFlags(Registers[Rd]);
43 | }
44 |
45 | ///
46 | /// Move Not.
47 | ///
48 | private void Thumb_MVN()
49 | {
50 | int Rd = (int)(Opcode & 7);
51 | int Rm = (int)((Opcode >> 3) & 7);
52 |
53 | Registers[Rd] = ~Registers[Rm];
54 | SetZNFlags(Registers[Rd]);
55 | }
56 |
57 | ///
58 | /// Pop.
59 | ///
60 | private void Thumb_POP()
61 | {
62 | for (int Index = 0; Index < 8; Index++)
63 | {
64 | if ((Opcode & (1 << Index)) != 0)
65 | {
66 | Registers[Index] = ReadUInt32E(Registers[13]);
67 | Registers[13] += 4;
68 | }
69 | }
70 |
71 | if (IsOpcodeBitSet(8))
72 | {
73 | uint Value = ReadUInt32E(Registers[13]);
74 | Registers[15] = Value & 0xfffffffe;
75 | Registers.SetFlag(ARMFlag.Thumb, (Value & 1) != 0);
76 | Registers[13] += 4;
77 | }
78 | }
79 |
80 | ///
81 | /// Push.
82 | ///
83 | private void Thumb_PUSH()
84 | {
85 | if (IsOpcodeBitSet(8))
86 | {
87 | Registers[13] -= 4;
88 | WriteUInt32E(Registers[13], Registers[14]);
89 | }
90 |
91 | for (int Index = 7; Index >= 0; Index--)
92 | {
93 | if ((Opcode & (1 << Index)) != 0)
94 | {
95 | Registers[13] -= 4;
96 | WriteUInt32E(Registers[13], Registers[Index]);
97 | }
98 | }
99 | }
100 |
101 | ///
102 | /// Signed Extend Byte.
103 | ///
104 | private void Thumb_SXTB()
105 | {
106 | int Rd = (int)(Opcode & 7);
107 | int Rm = (int)((Opcode >> 3) & 7);
108 |
109 | sbyte RmValue = (sbyte)Registers[Rm];
110 | Registers[Rd] = (uint)RmValue;
111 | }
112 |
113 | ///
114 | /// Signed Extend Halfword.
115 | ///
116 | private void Thumb_SXTH()
117 | {
118 | int Rd = (int)(Opcode & 7);
119 | int Rm = (int)((Opcode >> 3) & 7);
120 |
121 | short RmValue = (short)Registers[Rm];
122 | Registers[Rd] = (uint)RmValue;
123 | }
124 |
125 | ///
126 | /// Unsigned Extend Byte.
127 | ///
128 | private void Thumb_UXTB()
129 | {
130 | int Rd = (int)(Opcode & 7);
131 | int Rm = (int)((Opcode >> 3) & 7);
132 |
133 | Registers[Rd] = Registers[Rm] & 0xff;
134 | }
135 |
136 | ///
137 | /// Unsigned Extend Halfword.
138 | ///
139 | private void Thumb_UXTH()
140 | {
141 | int Rd = (int)(Opcode & 7);
142 | int Rm = (int)((Opcode >> 3) & 7);
143 |
144 | Registers[Rd] = Registers[Rm] & 0xffff;
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/Bus.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | ///
4 | /// ARM Bus interface for Memory access.
5 | ///
6 | public interface IBus
7 | {
8 | ///
9 | /// Reads a 8-bits value from the Memory.
10 | ///
11 | /// Address to read the data from
12 | /// Data on the address
13 | byte ReadUInt8(uint Address);
14 |
15 | ///
16 | /// Writes a 8-bits value to the Memory.
17 | ///
18 | /// Address to write the data on
19 | /// Value to be written
20 | void WriteUInt8(uint Address, byte Value);
21 | }
22 |
23 | public partial class ARMCore
24 | {
25 | //Read
26 |
27 | ///
28 | /// Reads a 16-bits Little Endian value from the Memory.
29 | ///
30 | /// Address to read the data from
31 | /// Data on the address
32 | private ushort ReadUInt16(uint Address)
33 | {
34 | return (ushort)(Bus.ReadUInt8(Address) |
35 | (Bus.ReadUInt8(Address + 1) << 8));
36 | }
37 |
38 | ///
39 | /// Reads a 32-bits Little Endian value from the Memory.
40 | ///
41 | /// Address to read the data from
42 | /// Data on the address
43 | private uint ReadUInt32(uint Address)
44 | {
45 | return (uint)(Bus.ReadUInt8(Address) |
46 | (Bus.ReadUInt8(Address + 1) << 8) |
47 | (Bus.ReadUInt8(Address + 2) << 16) |
48 | (Bus.ReadUInt8(Address + 3) << 24));
49 | }
50 |
51 | ///
52 | /// Reads a 16-bits value from the Memory on Little or Big Endian, depending on the E-bit setting.
53 | ///
54 | /// Address to read the data from
55 | /// Data on the address
56 | private ushort ReadUInt16E(uint Address)
57 | {
58 | if (Registers.IsFlagSet(ARMFlag.Endianness))
59 | return (ushort)((Bus.ReadUInt8(Address) << 8) |
60 | Bus.ReadUInt8(Address + 1));
61 | else
62 | return ReadUInt16(Address);
63 | }
64 |
65 | ///
66 | /// Reads a 32-bits value from the Memory on Little or Big Endian, depending on the E-bit setting.
67 | ///
68 | /// Address to read the data from
69 | /// Data on the address
70 | private uint ReadUInt32E(uint Address)
71 | {
72 | if (Registers.IsFlagSet(ARMFlag.Endianness))
73 | return (uint)((Bus.ReadUInt8(Address) << 24) |
74 | (Bus.ReadUInt8(Address + 1) << 16) |
75 | (Bus.ReadUInt8(Address + 2) << 8) |
76 | Bus.ReadUInt8(Address + 3));
77 | else
78 | return ReadUInt32(Address);
79 | }
80 |
81 | //Write
82 |
83 | ///
84 | /// Writes a 16-bits Little Endian value to the Memory.
85 | ///
86 | /// Address to write the data on
87 | /// Value to be written
88 | private void WriteUInt16(uint Address, ushort Value)
89 | {
90 | Bus.WriteUInt8(Address, (byte)Value);
91 | Bus.WriteUInt8(Address + 1, (byte)(Value >> 8));
92 | }
93 |
94 | ///
95 | /// Writes a 32-bits Little Endian value to the Memory.
96 | ///
97 | /// Address to write the data on
98 | /// Value to be written
99 | public void WriteUInt32(uint Address, uint Value)
100 | {
101 | Bus.WriteUInt8(Address, (byte)Value);
102 | Bus.WriteUInt8(Address + 1, (byte)(Value >> 8));
103 | Bus.WriteUInt8(Address + 2, (byte)(Value >> 16));
104 | Bus.WriteUInt8(Address + 3, (byte)(Value >> 24));
105 | }
106 |
107 | ///
108 | /// Writes a 16-bits value to the Memory on Little or Big Endian, depending on the E-bit setting.
109 | ///
110 | /// Address to write the data on
111 | /// Value to be written
112 | private void WriteUInt16E(uint Address, ushort Value)
113 | {
114 | if (Registers.IsFlagSet(ARMFlag.Endianness))
115 | {
116 | Bus.WriteUInt8(Address, (byte)(Value >> 8));
117 | Bus.WriteUInt8(Address + 1, (byte)Value);
118 | }
119 | else
120 | WriteUInt16(Address, Value);
121 | }
122 |
123 | ///
124 | /// Writes a 32-bits value to the Memory on Little or Big Endian, depending on the E-bit setting.
125 | ///
126 | /// Address to write the data on
127 | /// Value to be written
128 | private void WriteUInt32E(uint Address, uint Value)
129 | {
130 | if (Registers.IsFlagSet(ARMFlag.Endianness))
131 | {
132 | Bus.WriteUInt8(Address, (byte)(Value >> 24));
133 | Bus.WriteUInt8(Address + 1, (byte)(Value >> 16));
134 | Bus.WriteUInt8(Address + 2, (byte)(Value >> 8));
135 | Bus.WriteUInt8(Address + 3, (byte)Value);
136 | }
137 | else
138 | WriteUInt32(Address, Value);
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/Condition.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// ARM CPU conditions.
7 | ///
8 | private enum ARMCondition
9 | {
10 | Equal = 0,
11 | NotEqual = 1,
12 | CarrySet = 2,
13 | CarryClear = 3,
14 | Minus = 4,
15 | Plus = 5,
16 | Overflow = 6,
17 | NoOverflow = 7,
18 | UnsignedHigher = 8,
19 | UnsignedLowerOrSame = 9,
20 | SignedGreaterThanOrEqual = 0xa,
21 | SignedLessThan = 0xb,
22 | SignedGreaterThan = 0xc,
23 | SignedLessThanOrEqual = 0xd,
24 | Always = 0xe,
25 | Unconditional = 0xf
26 | }
27 |
28 | ///
29 | /// Checks whenever the Condition of a Opcode matches the current Status Register, to see if the condition is true.
30 | ///
31 | /// The Condition of the Opcode
32 | /// If the condition is true or not
33 | private bool IsConditionMet(ARMCondition Condition)
34 | {
35 | switch (Condition)
36 | {
37 | case ARMCondition.Equal: return Registers.IsFlagSet(ARMFlag.Zero);
38 | case ARMCondition.NotEqual: return Registers.IsFlagClear(ARMFlag.Zero);
39 | case ARMCondition.CarrySet: return Registers.IsFlagSet(ARMFlag.Carry);
40 | case ARMCondition.CarryClear: return Registers.IsFlagClear(ARMFlag.Carry);
41 | case ARMCondition.Minus: return Registers.IsFlagSet(ARMFlag.Negative);
42 | case ARMCondition.Plus: return Registers.IsFlagClear(ARMFlag.Negative);
43 | case ARMCondition.Overflow: return Registers.IsFlagSet(ARMFlag.Overflow);
44 | case ARMCondition.NoOverflow: return Registers.IsFlagClear(ARMFlag.Overflow);
45 | case ARMCondition.UnsignedHigher: return ConditionHI();
46 | case ARMCondition.UnsignedLowerOrSame: return ConditionLS();
47 | case ARMCondition.SignedGreaterThanOrEqual: return ConditionGE();
48 | case ARMCondition.SignedLessThan: return ConditionLT();
49 | case ARMCondition.SignedGreaterThan: return Registers.IsFlagClear(ARMFlag.Zero) && ConditionGE();
50 | case ARMCondition.SignedLessThanOrEqual: return Registers.IsFlagSet(ARMFlag.Zero) || ConditionLT();
51 | case ARMCondition.Always: return true;
52 | }
53 |
54 | return false;
55 | }
56 |
57 | ///
58 | /// Checks if the Unsigned Higher condition is met, based on the values of the Status register.
59 | ///
60 | /// True if the condition is met, false otherwise
61 | private bool ConditionHI()
62 | {
63 | return Registers.IsFlagSet(ARMFlag.Carry) && Registers.IsFlagClear(ARMFlag.Zero);
64 | }
65 |
66 | ///
67 | /// Checks if the Unsigned Lower or Same condition is met, based on the values of the Status register.
68 | ///
69 | /// True if the condition is met, false otherwise
70 | private bool ConditionLS()
71 | {
72 | return Registers.IsFlagClear(ARMFlag.Carry) || Registers.IsFlagSet(ARMFlag.Zero);
73 | }
74 |
75 | ///
76 | /// Checks if the Greater Than or Equal condition is met, based on the values of the Status register.
77 | ///
78 | /// True if the condition is met, false otherwise
79 | private bool ConditionGE()
80 | {
81 | return Registers.IsFlagSet(ARMFlag.Negative) == Registers.IsFlagSet(ARMFlag.Overflow);
82 | }
83 |
84 | ///
85 | /// Checks if the Less Than condition is met, based on the values of the Status register.
86 | ///
87 | /// True if the condition is met, false otherwise
88 | private bool ConditionLT()
89 | {
90 | return Registers.IsFlagSet(ARMFlag.Negative) != Registers.IsFlagSet(ARMFlag.Overflow);
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/Coprocessor15.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | class Coprocessor15
4 | {
5 | //ARM1176 CP15 setup
6 |
7 | private const uint CP15_MainId = 0x410FB767;
8 | private const uint CP15_CacheType = 0x10152152;
9 | private const uint CP15_TCMStatus = 0x20002;
10 | private const uint CP15_TLBType = 0x800;
11 |
12 | private const uint CP15_ProcessorFeature0 = 0x111;
13 | private const uint CP15_ProcessorFeature1 = 0x11;
14 | private const uint CP15_DebugFeature0 = 0x33;
15 | private const uint CP15_AuxiliaryFeature0 = 0;
16 | private const uint CP15_MemoryModelFeature0 = 0x1130003;
17 | private const uint CP15_MemoryModelFeature1 = 0x10030302;
18 | private const uint CP15_MemoryModelFeature2 = 0x1222100;
19 | private const uint CP15_MemoryModelFeature3 = 0;
20 |
21 | private const uint CP15_InstructionSetFeatureAttribute0 = 0x140011;
22 | private const uint CP15_InstructionSetFeatureAttribute1 = 0x12002111;
23 | private const uint CP15_InstructionSetFeatureAttribute2 = 0x11231121;
24 | private const uint CP15_InstructionSetFeatureAttribute3 = 0x1102131;
25 | private const uint CP15_InstructionSetFeatureAttribute4 = 0x1141;
26 | private const uint CP15_InstructionSetFeatureAttribute5 = 0;
27 |
28 | private uint CP15_Control;
29 | private uint CP15_AuxiliaryControl;
30 | private uint CP15_CoprocessorAccessControl;
31 |
32 | ///
33 | /// Reads a value from the "CP15" Coprocessor.
34 | ///
35 | /// The CRn register index
36 | /// The Opcode 1 value
37 | /// The CRm register index
38 | /// The Opcode 2 value
39 | /// The value at the given register
40 | public uint Read(int CRn, uint Op1, int CRm, uint Op2)
41 | {
42 | if (Op1 == 0)
43 | {
44 | switch (CRn)
45 | {
46 | case 0:
47 | switch (CRm)
48 | {
49 | case 0:
50 | switch (Op2)
51 | {
52 | case 0: return CP15_MainId;
53 | case 1: return CP15_CacheType;
54 | case 2: return CP15_TCMStatus;
55 | case 3: return CP15_TLBType;
56 | }
57 | break;
58 | case 1:
59 | switch (Op2)
60 | {
61 | case 0: return CP15_ProcessorFeature0;
62 | case 1: return CP15_ProcessorFeature1;
63 | case 2: return CP15_DebugFeature0;
64 | case 3: return CP15_AuxiliaryFeature0;
65 | case 4: return CP15_MemoryModelFeature0;
66 | case 5: return CP15_MemoryModelFeature1;
67 | case 6: return CP15_MemoryModelFeature2;
68 | case 7: return CP15_MemoryModelFeature3;
69 | }
70 | break;
71 | case 2:
72 | switch (Op2)
73 | {
74 | case 0: return CP15_InstructionSetFeatureAttribute0;
75 | case 1: return CP15_InstructionSetFeatureAttribute1;
76 | case 2: return CP15_InstructionSetFeatureAttribute2;
77 | case 3: return CP15_InstructionSetFeatureAttribute3;
78 | case 4: return CP15_InstructionSetFeatureAttribute4;
79 | case 5: return CP15_InstructionSetFeatureAttribute5;
80 | }
81 | break;
82 | }
83 | break;
84 | case 2:
85 | switch (CRm)
86 | {
87 | case 0:
88 | switch (Op2)
89 | {
90 | case 0: return CP15_Control;
91 | case 1: return CP15_AuxiliaryControl;
92 | case 2: return CP15_CoprocessorAccessControl;
93 | }
94 | break;
95 | }
96 | break;
97 | }
98 | }
99 |
100 | return 0;
101 | }
102 |
103 | ///
104 | /// Writes a value to the "CP15" Coprocessor.
105 | ///
106 | /// The CRn register index
107 | /// The Opcode 1 value
108 | /// The CRm register index
109 | /// The Opcode 2 value
110 | /// Value to be written
111 | public void Write(int CRn, uint Op1, int CRm, uint Op2, uint Value)
112 | {
113 | if (Op1 == 0)
114 | {
115 | switch (CRn)
116 | {
117 | case 2:
118 | switch (CRm)
119 | {
120 | case 0:
121 | switch (Op2)
122 | {
123 | case 0: CP15_Control = Value; break;
124 | case 1: CP15_AuxiliaryControl = Value; break;
125 | case 2: CP15_CoprocessorAccessControl = Value; break;
126 | }
127 | break;
128 | }
129 | break;
130 | }
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/Registers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SharpARM.ARM11
4 | {
5 | public partial class ARMCore
6 | {
7 | ///
8 | /// Flags used on the registers CPSR and SPSR.
9 | ///
10 | public enum ARMFlag : uint
11 | {
12 | Thumb = 0x20, //T
13 | FIQDisable = 0x40, //F
14 | IRQDisable = 0x80, //I
15 | AbortDisable = 0x100, //A
16 | Endianness = 0x200, //E
17 | Saturation = 0x8000000, //Q
18 | Overflow = 0x10000000, //V
19 | Carry = 0x20000000, //C
20 | Zero = 0x40000000, //Z
21 | Negative = 0x80000000 //N
22 | }
23 |
24 | ///
25 | /// ARM CPU executions modes.
26 | ///
27 | public enum ARMMode
28 | {
29 | User = 0x10,
30 | FIQ = 0x11,
31 | IRQ = 0X12,
32 | Supervisor = 0x13,
33 | Abort = 0x17,
34 | Undefined = 0x1b,
35 | System = 0x1f
36 | }
37 |
38 | ///
39 | /// Represents all the 37 ARM Registers.
40 | ///
41 | public class ARMRegisters
42 | {
43 | /*
44 | * General purpose registers
45 | * R13 = Stack pointer
46 | * R14 = Link register
47 | * R15 = Program counter
48 | */
49 | private uint[] R = new uint[16];
50 |
51 | private uint R8_FIQ;
52 | private uint R9_FIQ;
53 | private uint R10_FIQ;
54 | private uint R11_FIQ;
55 | private uint R12_FIQ;
56 | private uint R13_FIQ;
57 | private uint R14_FIQ;
58 |
59 | private uint R13_IRQ;
60 | private uint R14_IRQ;
61 |
62 | private uint R13_SVC;
63 | private uint R14_SVC;
64 |
65 | private uint R13_ABT;
66 | private uint R14_ABT;
67 |
68 | private uint R13_UNDEF;
69 | private uint R14_UNDEF;
70 |
71 | /*
72 | * Status registers
73 | */
74 |
75 | ///
76 | /// Current Processor Status Register.
77 | ///
78 | public uint CPSR;
79 | private uint SPSR_FIQ;
80 | private uint SPSR_IRQ;
81 | private uint SPSR_SVC;
82 | private uint SPSR_ABT;
83 | private uint SPSR_UNDEF;
84 |
85 | ///
86 | /// This flag is set to true every time the value of R15 is changed.
87 | /// It needs to be set to false manually. Useful for handling the 3-stage pipeline.
88 | ///
89 | public bool PCChanged;
90 |
91 | ///
92 | /// Gets or sets the value of the SPSR register of the current mode.
93 | ///
94 | public uint SPSR
95 | {
96 | get
97 | {
98 | switch (Mode)
99 | {
100 | case ARMMode.FIQ: return SPSR_FIQ;
101 | case ARMMode.IRQ: return SPSR_IRQ;
102 | case ARMMode.Supervisor: return SPSR_SVC;
103 | case ARMMode.Abort: return SPSR_ABT;
104 | case ARMMode.Undefined: return SPSR_UNDEF;
105 | }
106 |
107 | return 0;
108 | }
109 | set
110 | {
111 | switch (Mode)
112 | {
113 | case ARMMode.FIQ: SPSR_FIQ = value; break;
114 | case ARMMode.IRQ: SPSR_IRQ = value; break;
115 | case ARMMode.Supervisor: SPSR_SVC = value; break;
116 | case ARMMode.Abort: SPSR_ABT = value; break;
117 | case ARMMode.Undefined: SPSR_UNDEF = value; break;
118 | }
119 | }
120 | }
121 |
122 | ///
123 | /// Gets or sets the current CPU execution mode.
124 | ///
125 | public ARMMode Mode
126 | {
127 | get
128 | {
129 | return (ARMMode)(CPSR & 0x1f);
130 | }
131 | set
132 | {
133 | CPSR = (uint)(CPSR & ~0x1f) | (uint)value;
134 | }
135 | }
136 |
137 |
138 | ///
139 | /// Gets or sets the Greater than or Equal bits on the CPSR Register.
140 | ///
141 | public byte GE
142 | {
143 | get
144 | {
145 | return (byte)((CPSR >> 16) & 0xf);
146 | }
147 | set
148 | {
149 | CPSR = (CPSR & 0xfff0ffff) | (uint)(value << 16);
150 | }
151 | }
152 |
153 | ///
154 | /// ARM General purpose registers, accessible by Index number.
155 | ///
156 | /// The Index number of the Register to work with
157 | /// The value of the Register with the specified Index
158 | public uint this[int RegisterIndex]
159 | {
160 | get
161 | {
162 | switch (Mode)
163 | {
164 | case ARMMode.User:
165 | case ARMMode.System:
166 | return R[RegisterIndex];
167 |
168 | case ARMMode.FIQ:
169 | if (RegisterIndex < 8 || RegisterIndex == 15)
170 | return R[RegisterIndex];
171 | else
172 | {
173 | switch (RegisterIndex)
174 | {
175 | case 8: return R8_FIQ;
176 | case 9: return R9_FIQ;
177 | case 10: return R10_FIQ;
178 | case 11: return R11_FIQ;
179 | case 12: return R12_FIQ;
180 | case 13: return R13_FIQ;
181 | case 14: return R14_FIQ;
182 | }
183 | }
184 | break;
185 |
186 | case ARMMode.IRQ:
187 | if (RegisterIndex < 13 || RegisterIndex == 15)
188 | return R[RegisterIndex];
189 | else
190 | {
191 | switch (RegisterIndex)
192 | {
193 | case 13: return R13_IRQ;
194 | case 14: return R14_IRQ;
195 | }
196 | }
197 | break;
198 |
199 | case ARMMode.Supervisor:
200 | if (RegisterIndex < 13 || RegisterIndex == 15)
201 | return R[RegisterIndex];
202 | else
203 | {
204 | switch (RegisterIndex)
205 | {
206 | case 13: return R13_SVC;
207 | case 14: return R14_SVC;
208 | }
209 | }
210 | break;
211 |
212 | case ARMMode.Abort:
213 | if (RegisterIndex < 13 || RegisterIndex == 15)
214 | return R[RegisterIndex];
215 | else
216 | {
217 | switch (RegisterIndex)
218 | {
219 | case 13: return R13_ABT;
220 | case 14: return R14_ABT;
221 | }
222 | }
223 | break;
224 |
225 | case ARMMode.Undefined:
226 | if (RegisterIndex < 13 || RegisterIndex == 15)
227 | return R[RegisterIndex];
228 | else
229 | {
230 | switch (RegisterIndex)
231 | {
232 | case 13: return R13_UNDEF;
233 | case 14: return R14_UNDEF;
234 | }
235 | }
236 | break;
237 |
238 | default: throw new Exception("SharpARM: Invalid CPSR ARM execution Mode!");
239 | }
240 |
241 | return 0;
242 | }
243 | set
244 | {
245 | switch (Mode)
246 | {
247 | case ARMMode.User:
248 | case ARMMode.System:
249 | R[RegisterIndex] = value;
250 | break;
251 |
252 | case ARMMode.FIQ:
253 | if (RegisterIndex < 8 || RegisterIndex == 15)
254 | R[RegisterIndex] = value;
255 | else
256 | {
257 | switch (RegisterIndex)
258 | {
259 | case 8: R8_FIQ = value; break;
260 | case 9: R9_FIQ = value; break;
261 | case 10: R10_FIQ = value; break;
262 | case 11: R11_FIQ = value; break;
263 | case 12: R12_FIQ = value; break;
264 | case 13: R13_FIQ = value; break;
265 | case 14: R14_FIQ = value; break;
266 | }
267 | }
268 | break;
269 |
270 | case ARMMode.IRQ:
271 | if (RegisterIndex < 13 || RegisterIndex == 15)
272 | R[RegisterIndex] = value;
273 | else
274 | {
275 | switch (RegisterIndex)
276 | {
277 | case 13: R13_IRQ = value; break;
278 | case 14: R14_IRQ = value; break;
279 | }
280 | }
281 | break;
282 |
283 | case ARMMode.Supervisor:
284 | if (RegisterIndex < 13 || RegisterIndex == 15)
285 | R[RegisterIndex] = value;
286 | else
287 | {
288 | switch (RegisterIndex)
289 | {
290 | case 13: R13_SVC = value; break;
291 | case 14: R14_SVC = value; break;
292 | }
293 | }
294 | break;
295 |
296 | case ARMMode.Abort:
297 | if (RegisterIndex < 13 || RegisterIndex == 15)
298 | R[RegisterIndex] = value;
299 | else
300 | {
301 | switch (RegisterIndex)
302 | {
303 | case 13: R13_ABT = value; break;
304 | case 14: R14_ABT = value; break;
305 | }
306 | }
307 | break;
308 |
309 | case ARMMode.Undefined:
310 | if (RegisterIndex < 13 || RegisterIndex == 15)
311 | R[RegisterIndex] = value;
312 | else
313 | {
314 | switch (RegisterIndex)
315 | {
316 | case 13: R13_UNDEF = value; break;
317 | case 14: R14_UNDEF = value; break;
318 | }
319 | }
320 | break;
321 |
322 | default: throw new Exception("SharpARM: Invalid CPSR ARM execution Mode!");
323 | }
324 |
325 | if (RegisterIndex == 15) PCChanged = true;
326 | }
327 | }
328 |
329 | ///
330 | /// Checks if a Flag is set on the Status register.
331 | ///
332 | /// Flag that should be checked
333 | /// True if the flag is set, false otherwise
334 | public bool IsFlagSet(ARMFlag Flag)
335 | {
336 | return (CPSR & (uint)Flag) != 0;
337 | }
338 |
339 | ///
340 | /// Check if a Flag is cleared on the Status register.
341 | ///
342 | /// Flag that should be checked
343 | /// True if the flag is cleared, false otherwise
344 | public bool IsFlagClear(ARMFlag Flag)
345 | {
346 | return (CPSR & (uint)Flag) == 0;
347 | }
348 |
349 | ///
350 | /// Set the value of a given ARM Flag.
351 | ///
352 | /// The affected Flag
353 | /// The bit value that should be set (True = Set or False = Cleared)
354 | public void SetFlag(ARMFlag Flag, bool Value)
355 | {
356 | if (Value) CPSR |= (uint)Flag; else CPSR &= ~(uint)Flag;
357 | }
358 | }
359 | }
360 | }
361 |
--------------------------------------------------------------------------------
/ChocolateARM/ARM11/Utils.cs:
--------------------------------------------------------------------------------
1 | namespace SharpARM.ARM11
2 | {
3 | public partial class ARMCore
4 | {
5 | ///
6 | /// Checks whenever a bit on the 32-bits Opcode value is set or not.
7 | ///
8 | /// The bit that should be tested
9 | /// True if the bit is set, false otherwise
10 | private bool IsOpcodeBitSet(int Bit)
11 | {
12 | return (Opcode & (1 << Bit)) != 0;
13 | }
14 |
15 | ///
16 | /// Shift the bits to the right, and make the exceeding bits fill the other way around.
17 | /// Example: For a 8 bits value, ROR(0b00000011, 1) = 0b10000001.
18 | ///
19 | /// Value that should be shifted
20 | /// Number of bits to shift
21 | /// The shifted value
22 | private uint ROR(uint Value, int Shift)
23 | {
24 | return (Value >> Shift) | (Value << (32 - Shift));
25 | }
26 |
27 | ///
28 | /// Sets the Zero flag if the value is zero, and clear it otherwise.
29 | /// Sets the Negative flag if the value is negative (most heavy bit set), and clear it otherwise.
30 | ///
31 | /// The resulting 32-bits value that should be tested
32 | private void SetZNFlags(uint Value)
33 | {
34 | Registers.SetFlag(ARMFlag.Zero, Value == 0);
35 | Registers.SetFlag(ARMFlag.Negative, (Value & 0x80000000) != 0);
36 | }
37 |
38 | ///
39 | /// Sign extends a 11-bits value to a signed 32-bits value.
40 | ///
41 | /// The 11-bits value that should be extended
42 | /// The value extended into 32-bits
43 | private int SignExtend11(uint Value)
44 | {
45 | if ((Value & 0x400) != 0)
46 | return (int)(Value | 0xfffff800);
47 | else
48 | return (int)Value;
49 | }
50 |
51 | ///
52 | /// Sign extends a 12-bits value to a signed 32-bits value.
53 | ///
54 | /// The 12-bits value that should be extended
55 | /// The value extended into 32-bits
56 | private int SignExtend12(uint Value)
57 | {
58 | if ((Value & 0x800) != 0)
59 | return (int)(Value | 0xfffff000);
60 | else
61 | return (int)Value;
62 | }
63 |
64 | ///
65 | /// Sign extends a 24-bits value to a signed 32-bits value.
66 | ///
67 | /// The 24-bits value that should be extended
68 | /// The value extended into 32-bits
69 | private int SignExtend24(uint Value)
70 | {
71 | if ((Value & 0x800000) != 0)
72 | return (int)(Value | 0xff000000);
73 | else
74 | return (int)Value;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/ChocolateARM/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ChocolateARM/ChocolateARM.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {47232F73-385B-43D6-8751-10B289DAEBE1}
8 | WinExe
9 | Properties
10 | ChocolateARM
11 | ChocolateARM
12 | v4.5.2
13 | 512
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | x64
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 | false
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 | Form
80 |
81 |
82 | FrmMain.cs
83 |
84 |
85 | Form
86 |
87 |
88 | FrmUARTOutput.cs
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | FrmMain.cs
102 |
103 |
104 | FrmUARTOutput.cs
105 |
106 |
107 | ResXFileCodeGenerator
108 | Resources.Designer.cs
109 | Designer
110 |
111 |
112 | True
113 | Resources.resx
114 |
115 |
116 | SettingsSingleFileGenerator
117 | Settings.Designer.cs
118 |
119 |
120 | True
121 | Settings.settings
122 | True
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
137 |
--------------------------------------------------------------------------------
/ChocolateARM/FrmMain.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ChocolateARM
2 | {
3 | partial class FrmMain
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.components = new System.ComponentModel.Container();
32 | this.Screen = new System.Windows.Forms.PictureBox();
33 | this.MenuBar = new System.Windows.Forms.MenuStrip();
34 | this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
35 | this.MnuLoadKernelImage = new System.Windows.Forms.ToolStripMenuItem();
36 | this.MnuTools = new System.Windows.Forms.ToolStripMenuItem();
37 | this.MnuDumpSDRAM = new System.Windows.Forms.ToolStripMenuItem();
38 | this.MnuShowUART = new System.Windows.Forms.ToolStripMenuItem();
39 | this.StatusBar = new System.Windows.Forms.StatusStrip();
40 | this.ScreenRefresh = new System.Windows.Forms.Timer(this.components);
41 | this.MnuARMDbg = new System.Windows.Forms.ToolStripMenuItem();
42 | ((System.ComponentModel.ISupportInitialize)(this.Screen)).BeginInit();
43 | this.MenuBar.SuspendLayout();
44 | this.SuspendLayout();
45 | //
46 | // Screen
47 | //
48 | this.Screen.BackColor = System.Drawing.Color.Black;
49 | this.Screen.Location = new System.Drawing.Point(0, 24);
50 | this.Screen.Name = "Screen";
51 | this.Screen.Size = new System.Drawing.Size(640, 480);
52 | this.Screen.TabIndex = 2;
53 | this.Screen.TabStop = false;
54 | //
55 | // MenuBar
56 | //
57 | this.MenuBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
58 | this.fileToolStripMenuItem,
59 | this.MnuTools});
60 | this.MenuBar.Location = new System.Drawing.Point(0, 0);
61 | this.MenuBar.Name = "MenuBar";
62 | this.MenuBar.Size = new System.Drawing.Size(640, 24);
63 | this.MenuBar.TabIndex = 3;
64 | this.MenuBar.Text = "menuStrip1";
65 | //
66 | // fileToolStripMenuItem
67 | //
68 | this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
69 | this.MnuLoadKernelImage});
70 | this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
71 | this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
72 | this.fileToolStripMenuItem.Text = "&File";
73 | //
74 | // MnuLoadKernelImage
75 | //
76 | this.MnuLoadKernelImage.Name = "MnuLoadKernelImage";
77 | this.MnuLoadKernelImage.Size = new System.Drawing.Size(172, 22);
78 | this.MnuLoadKernelImage.Text = "&Load Kernel image";
79 | this.MnuLoadKernelImage.Click += new System.EventHandler(this.MnuLoadKernelImage_Click);
80 | //
81 | // MnuTools
82 | //
83 | this.MnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
84 | this.MnuDumpSDRAM,
85 | this.MnuShowUART,
86 | this.MnuARMDbg});
87 | this.MnuTools.Name = "MnuTools";
88 | this.MnuTools.Size = new System.Drawing.Size(47, 20);
89 | this.MnuTools.Text = "&Tools";
90 | //
91 | // MnuDumpSDRAM
92 | //
93 | this.MnuDumpSDRAM.Name = "MnuDumpSDRAM";
94 | this.MnuDumpSDRAM.Size = new System.Drawing.Size(152, 22);
95 | this.MnuDumpSDRAM.Text = "&Dump SDRAM";
96 | this.MnuDumpSDRAM.Click += new System.EventHandler(this.MnuDumpSDRAM_Click);
97 | //
98 | // MnuShowUART
99 | //
100 | this.MnuShowUART.Name = "MnuShowUART";
101 | this.MnuShowUART.Size = new System.Drawing.Size(152, 22);
102 | this.MnuShowUART.Text = "&UART output";
103 | this.MnuShowUART.Click += new System.EventHandler(this.MnuShowUART_Click);
104 | //
105 | // StatusBar
106 | //
107 | this.StatusBar.Location = new System.Drawing.Point(0, 504);
108 | this.StatusBar.Name = "StatusBar";
109 | this.StatusBar.Size = new System.Drawing.Size(640, 22);
110 | this.StatusBar.TabIndex = 4;
111 | this.StatusBar.Text = "statusStrip1";
112 | //
113 | // ScreenRefresh
114 | //
115 | this.ScreenRefresh.Interval = 16;
116 | this.ScreenRefresh.Tick += new System.EventHandler(this.ScreenRefresh_Tick);
117 | //
118 | // MnuARMDbg
119 | //
120 | this.MnuARMDbg.Name = "MnuARMDbg";
121 | this.MnuARMDbg.Size = new System.Drawing.Size(152, 22);
122 | this.MnuARMDbg.Text = "&ARM Debug";
123 | this.MnuARMDbg.Click += new System.EventHandler(this.MnuARMDbg_Click);
124 | //
125 | // FrmMain
126 | //
127 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
128 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
129 | this.ClientSize = new System.Drawing.Size(640, 526);
130 | this.Controls.Add(this.StatusBar);
131 | this.Controls.Add(this.Screen);
132 | this.Controls.Add(this.MenuBar);
133 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
134 | this.MainMenuStrip = this.MenuBar;
135 | this.MaximizeBox = false;
136 | this.Name = "FrmMain";
137 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
138 | this.Text = "ChocolatePi Alpha";
139 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmMain_FormClosing);
140 | this.Load += new System.EventHandler(this.FrmMain_Load);
141 | ((System.ComponentModel.ISupportInitialize)(this.Screen)).EndInit();
142 | this.MenuBar.ResumeLayout(false);
143 | this.MenuBar.PerformLayout();
144 | this.ResumeLayout(false);
145 | this.PerformLayout();
146 |
147 | }
148 |
149 | #endregion
150 |
151 | private System.Windows.Forms.PictureBox Screen;
152 | private System.Windows.Forms.MenuStrip MenuBar;
153 | private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
154 | private System.Windows.Forms.ToolStripMenuItem MnuLoadKernelImage;
155 | private System.Windows.Forms.StatusStrip StatusBar;
156 | private System.Windows.Forms.ToolStripMenuItem MnuTools;
157 | private System.Windows.Forms.ToolStripMenuItem MnuDumpSDRAM;
158 | private System.Windows.Forms.Timer ScreenRefresh;
159 | private System.Windows.Forms.ToolStripMenuItem MnuShowUART;
160 | private System.Windows.Forms.ToolStripMenuItem MnuARMDbg;
161 | }
162 | }
163 |
164 |
--------------------------------------------------------------------------------
/ChocolateARM/FrmMain.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.IO;
4 | using System.Windows.Forms;
5 |
6 | using ChocolateARM.RPi;
7 |
8 | namespace ChocolateARM
9 | {
10 | public partial class FrmMain : Form
11 | {
12 | RPiCore RaspberryPi;
13 |
14 | public FrmMain()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | private int ScreenDifferenceWidth;
20 | private int ScreenDifferenceHeight;
21 |
22 | private void FrmMain_Load(object sender, EventArgs e)
23 | {
24 | ScreenDifferenceWidth = Width - Screen.Width;
25 | ScreenDifferenceHeight = Height - Screen.Height;
26 |
27 | RaspberryPi = new RPiCore();
28 | RaspberryPi.Memory.Video.OnScreenSetup += ScreenSetupCallback;
29 | SetupScreen = new ScreenSetupDelegate(ScreenSetup);
30 |
31 | Show();
32 | }
33 |
34 | private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
35 | {
36 | RaspberryPi.Stop();
37 | }
38 |
39 | private void ScreenSetupCallback()
40 | {
41 | BeginInvoke(SetupScreen);
42 | }
43 |
44 | private ScreenSetupDelegate SetupScreen;
45 | private delegate void ScreenSetupDelegate();
46 |
47 | private void ScreenSetup()
48 | {
49 | Screen.Width = (int)RaspberryPi.Memory.Video.ScreenVirtualWidth;
50 | Screen.Height = (int)RaspberryPi.Memory.Video.ScreenVirtualHeight;
51 | Width = Screen.Width + ScreenDifferenceWidth;
52 | Height = Screen.Height + ScreenDifferenceHeight;
53 | CenterToScreen();
54 | ScreenRefresh.Enabled = true;
55 | }
56 |
57 | private void MnuLoadKernelImage_Click(object sender, EventArgs e)
58 | {
59 | using (OpenFileDialog OpenDialog = new OpenFileDialog())
60 | {
61 | OpenDialog.Title = "Load Kernel.img";
62 | OpenDialog.Filter = "Image|*.img";
63 |
64 | if (OpenDialog.ShowDialog() == DialogResult.OK && File.Exists(OpenDialog.FileName))
65 | {
66 | RaspberryPi.Load(OpenDialog.FileName, 0x8000, true);
67 | RaspberryPi.RunAsync();
68 | }
69 | }
70 | }
71 |
72 | private void MnuDumpSDRAM_Click(object sender, EventArgs e)
73 | {
74 | File.WriteAllBytes(@"D:\pimem.bin", RaspberryPi.Memory.SDRAM);
75 | }
76 |
77 | private void ScreenRefresh_Tick(object sender, EventArgs e)
78 | {
79 | Bitmap Img = RaspberryPi.Memory.Video.GetImage();
80 | if (Img != null) Screen.Image = Img;
81 | }
82 |
83 | private void MnuShowUART_Click(object sender, EventArgs e)
84 | {
85 | FrmUARTOutput Form = new FrmUARTOutput(RaspberryPi);
86 | Form.Show();
87 | }
88 |
89 | private void MnuARMDbg_Click(object sender, EventArgs e)
90 | {
91 | RaspberryPi.CPU.Debug = !RaspberryPi.CPU.Debug;
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/ChocolateARM/FrmMain.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
124 | 118, 17
125 |
126 |
127 | 341, 17
128 |
129 |
--------------------------------------------------------------------------------
/ChocolateARM/FrmUARTOutput.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace ChocolateARM
2 | {
3 | partial class FrmUARTOutput
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.Tabs = new System.Windows.Forms.TabControl();
32 | this.TabMiniUART = new System.Windows.Forms.TabPage();
33 | this.TabUART = new System.Windows.Forms.TabPage();
34 | this.BtnOk = new System.Windows.Forms.Button();
35 | this.TxtMiniUART = new System.Windows.Forms.TextBox();
36 | this.TxtUART = new System.Windows.Forms.TextBox();
37 | this.BtnClear = new System.Windows.Forms.Button();
38 | this.BtnClearAll = new System.Windows.Forms.Button();
39 | this.Tabs.SuspendLayout();
40 | this.TabMiniUART.SuspendLayout();
41 | this.TabUART.SuspendLayout();
42 | this.SuspendLayout();
43 | //
44 | // Tabs
45 | //
46 | this.Tabs.Controls.Add(this.TabMiniUART);
47 | this.Tabs.Controls.Add(this.TabUART);
48 | this.Tabs.Dock = System.Windows.Forms.DockStyle.Top;
49 | this.Tabs.Location = new System.Drawing.Point(0, 0);
50 | this.Tabs.Name = "Tabs";
51 | this.Tabs.SelectedIndex = 0;
52 | this.Tabs.Size = new System.Drawing.Size(584, 319);
53 | this.Tabs.TabIndex = 0;
54 | //
55 | // TabMiniUART
56 | //
57 | this.TabMiniUART.Controls.Add(this.TxtMiniUART);
58 | this.TabMiniUART.Location = new System.Drawing.Point(4, 22);
59 | this.TabMiniUART.Name = "TabMiniUART";
60 | this.TabMiniUART.Padding = new System.Windows.Forms.Padding(3);
61 | this.TabMiniUART.Size = new System.Drawing.Size(576, 293);
62 | this.TabMiniUART.TabIndex = 0;
63 | this.TabMiniUART.Text = "Mini UART";
64 | this.TabMiniUART.UseVisualStyleBackColor = true;
65 | //
66 | // TabUART
67 | //
68 | this.TabUART.Controls.Add(this.TxtUART);
69 | this.TabUART.Location = new System.Drawing.Point(4, 22);
70 | this.TabUART.Name = "TabUART";
71 | this.TabUART.Padding = new System.Windows.Forms.Padding(3);
72 | this.TabUART.Size = new System.Drawing.Size(576, 293);
73 | this.TabUART.TabIndex = 1;
74 | this.TabUART.Text = "UART (PL011)";
75 | this.TabUART.UseVisualStyleBackColor = true;
76 | //
77 | // BtnOk
78 | //
79 | this.BtnOk.Location = new System.Drawing.Point(481, 325);
80 | this.BtnOk.Name = "BtnOk";
81 | this.BtnOk.Size = new System.Drawing.Size(96, 24);
82 | this.BtnOk.TabIndex = 1;
83 | this.BtnOk.Text = "&OK";
84 | this.BtnOk.UseVisualStyleBackColor = true;
85 | this.BtnOk.Click += new System.EventHandler(this.BtnOk_Click);
86 | //
87 | // TxtMiniUART
88 | //
89 | this.TxtMiniUART.BackColor = System.Drawing.Color.Black;
90 | this.TxtMiniUART.Dock = System.Windows.Forms.DockStyle.Fill;
91 | this.TxtMiniUART.ForeColor = System.Drawing.Color.White;
92 | this.TxtMiniUART.Location = new System.Drawing.Point(3, 3);
93 | this.TxtMiniUART.Multiline = true;
94 | this.TxtMiniUART.Name = "TxtMiniUART";
95 | this.TxtMiniUART.ReadOnly = true;
96 | this.TxtMiniUART.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
97 | this.TxtMiniUART.Size = new System.Drawing.Size(570, 287);
98 | this.TxtMiniUART.TabIndex = 0;
99 | //
100 | // TxtUART
101 | //
102 | this.TxtUART.BackColor = System.Drawing.Color.Black;
103 | this.TxtUART.Dock = System.Windows.Forms.DockStyle.Fill;
104 | this.TxtUART.ForeColor = System.Drawing.Color.White;
105 | this.TxtUART.Location = new System.Drawing.Point(3, 3);
106 | this.TxtUART.Multiline = true;
107 | this.TxtUART.Name = "TxtUART";
108 | this.TxtUART.ReadOnly = true;
109 | this.TxtUART.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
110 | this.TxtUART.Size = new System.Drawing.Size(570, 287);
111 | this.TxtUART.TabIndex = 1;
112 | //
113 | // BtnClear
114 | //
115 | this.BtnClear.Location = new System.Drawing.Point(7, 325);
116 | this.BtnClear.Name = "BtnClear";
117 | this.BtnClear.Size = new System.Drawing.Size(96, 24);
118 | this.BtnClear.TabIndex = 2;
119 | this.BtnClear.Text = "&Clear";
120 | this.BtnClear.UseVisualStyleBackColor = true;
121 | this.BtnClear.Click += new System.EventHandler(this.BtnClear_Click);
122 | //
123 | // BtnClearAll
124 | //
125 | this.BtnClearAll.Location = new System.Drawing.Point(109, 325);
126 | this.BtnClearAll.Name = "BtnClearAll";
127 | this.BtnClearAll.Size = new System.Drawing.Size(96, 24);
128 | this.BtnClearAll.TabIndex = 3;
129 | this.BtnClearAll.Text = "&Clear all";
130 | this.BtnClearAll.UseVisualStyleBackColor = true;
131 | this.BtnClearAll.Click += new System.EventHandler(this.BtnClearAll_Click);
132 | //
133 | // FrmUARTOutput
134 | //
135 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
136 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
137 | this.ClientSize = new System.Drawing.Size(584, 361);
138 | this.Controls.Add(this.BtnClearAll);
139 | this.Controls.Add(this.BtnClear);
140 | this.Controls.Add(this.BtnOk);
141 | this.Controls.Add(this.Tabs);
142 | this.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
143 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
144 | this.MaximizeBox = false;
145 | this.Name = "FrmUARTOutput";
146 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
147 | this.Text = "UART Output";
148 | this.Load += new System.EventHandler(this.FrmUARTOutput_Load);
149 | this.Tabs.ResumeLayout(false);
150 | this.TabMiniUART.ResumeLayout(false);
151 | this.TabMiniUART.PerformLayout();
152 | this.TabUART.ResumeLayout(false);
153 | this.TabUART.PerformLayout();
154 | this.ResumeLayout(false);
155 |
156 | }
157 |
158 | #endregion
159 |
160 | private System.Windows.Forms.TabControl Tabs;
161 | private System.Windows.Forms.TabPage TabMiniUART;
162 | private System.Windows.Forms.TextBox TxtMiniUART;
163 | private System.Windows.Forms.TabPage TabUART;
164 | private System.Windows.Forms.TextBox TxtUART;
165 | private System.Windows.Forms.Button BtnOk;
166 | private System.Windows.Forms.Button BtnClear;
167 | private System.Windows.Forms.Button BtnClearAll;
168 | }
169 | }
--------------------------------------------------------------------------------
/ChocolateARM/FrmUARTOutput.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | using ChocolateARM.RPi;
5 | using ChocolateARM.RPi.Peripherals;
6 |
7 | namespace ChocolateARM
8 | {
9 | public partial class FrmUARTOutput : Form
10 | {
11 | RPiCore RaspberryPi;
12 |
13 | public FrmUARTOutput(RPiCore RaspberryPi)
14 | {
15 | this.RaspberryPi = RaspberryPi;
16 |
17 | InitializeComponent();
18 | }
19 |
20 | private void FrmUARTOutput_Load(object sender, EventArgs e)
21 | {
22 | Show();
23 |
24 | CharacterReceived = new CharacterReceivedDelegate(ReceiveCharacter);
25 |
26 | //Update texts
27 | TxtMiniUART.AppendText(RaspberryPi.Memory.MiniUART.BufferedOutput ?? "");
28 | TxtUART.AppendText(RaspberryPi.Memory.UART.BufferedOutput ?? "");
29 |
30 | //And subscribe for new characters
31 | RaspberryPi.Memory.MiniUART.OnCharacterReceived += MU_CharacterReceived;
32 | RaspberryPi.Memory.UART.OnCharacterReceived += UART_CharacterReceived;
33 | }
34 |
35 | private CharacterReceivedDelegate CharacterReceived;
36 | private delegate void CharacterReceivedDelegate(TextBox Target, char Character);
37 |
38 | private void MU_CharacterReceived(object sender, CharacterReceivedEventArgs e)
39 | {
40 | BeginInvoke(CharacterReceived, TxtMiniUART, e.Character);
41 | }
42 |
43 | private void UART_CharacterReceived(object sender, CharacterReceivedEventArgs e)
44 | {
45 | BeginInvoke(CharacterReceived, TxtUART, e.Character);
46 | }
47 |
48 | private void ReceiveCharacter(TextBox Target, char Character)
49 | {
50 | Target.AppendText(Character.ToString());
51 | }
52 |
53 | private void BtnOk_Click(object sender, EventArgs e)
54 | {
55 | Close();
56 | }
57 |
58 | private void BtnClear_Click(object sender, EventArgs e)
59 | {
60 | if (Tabs.SelectedIndex == 0)
61 | TxtMiniUART.Clear();
62 | else
63 | TxtUART.Clear();
64 | }
65 |
66 | private void BtnClearAll_Click(object sender, EventArgs e)
67 | {
68 | TxtMiniUART.Clear();
69 | TxtUART.Clear();
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/ChocolateARM/FrmUARTOutput.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/ChocolateARM/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace ChocolateARM
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// The main entry point for the application.
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault(false);
19 | Application.Run(new FrmMain());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ChocolateARM/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ChocolateARM")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ChocolateARM")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("47232f73-385b-43d6-8751-10b289daebe1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ChocolateARM/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ChocolateARM.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ChocolateARM.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ChocolateARM/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/ChocolateARM/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace ChocolateARM.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ChocolateARM/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ChocolateARM/RPi/IO32.cs:
--------------------------------------------------------------------------------
1 | namespace ChocolateARM.RPi
2 | {
3 | ///
4 | /// "Converts" a sequence of 8-bits writes (or reads) into 32-bits values.
5 | /// This class must be inherited, and the ProcessRead and ProcessWrite methods overloaded.
6 | ///
7 | public abstract class IO32
8 | {
9 | private uint ReadValue;
10 | private uint WriteValue;
11 |
12 | ///
13 | /// Reads Data from the IO region.
14 | ///
15 | /// The Address that is being read
16 | /// The Data on the Address
17 | public byte Read(uint Address)
18 | {
19 | switch (Address & 3)
20 | {
21 | case 0:
22 | ReadValue = ProcessRead(Address);
23 | return (byte)ReadValue;
24 | case 1: return (byte)(ReadValue >> 8);
25 | case 2: return (byte)(ReadValue >> 16);
26 | case 3: return (byte)(ReadValue >> 24);
27 | }
28 |
29 | return 0;
30 | }
31 |
32 | ///
33 | /// Writes Data to the IO region.
34 | ///
35 | /// The Address where the Value is being written
36 | /// The Value that is being written
37 | public void Write(uint Address, byte Value)
38 | {
39 | switch (Address & 3)
40 | {
41 | case 0: WriteValue = Value; break;
42 | case 1: WriteValue |= (uint)(Value << 8); break;
43 | case 2: WriteValue |= (uint)(Value << 16); break;
44 | case 3:
45 | WriteValue |= (uint)(Value << 24);
46 | ProcessWrite(Address & 0xfffffffc, WriteValue);
47 | break;
48 | }
49 | }
50 |
51 | ///
52 | /// This method is called whenever a new Read request has arrived.
53 | ///
54 | /// The Address where the Read operation was made
55 | /// The Data on the Address
56 | public abstract uint ProcessRead(uint Address);
57 |
58 | ///
59 | /// This method is called whenever a new Write operation is made.
60 | ///
61 | /// The Address where the Write operation was made
62 | /// The value being written
63 | public abstract void ProcessWrite(uint Address, uint Value);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/ChocolateARM/RPi/Memory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using SharpARM.ARM11;
4 |
5 | using ChocolateARM.RPi.Peripherals;
6 |
7 | namespace ChocolateARM.RPi
8 | {
9 | ///
10 | /// Represents the Memory and IO of the BCM2835 SoC.
11 | ///
12 | public class Memory : IBus
13 | {
14 | const uint KB = 1024;
15 | const uint MB = 1024 * KB;
16 |
17 | public byte[] SDRAM;
18 |
19 | public RPiDMA DMA;
20 | public RPiTimer Timer;
21 | public VideoCore Video;
22 | public RPiUART UART;
23 | public RPiMiniUART MiniUART;
24 |
25 | ///
26 | /// Creates a new instance of the RaspberryPi memory manager.
27 | ///
28 | public Memory()
29 | {
30 | SDRAM = new byte[256 * MB];
31 |
32 | DMA = new RPiDMA(this);
33 | Timer = new RPiTimer();
34 | Video = new VideoCore(this);
35 | UART = new RPiUART();
36 | MiniUART = new RPiMiniUART(this);
37 | }
38 |
39 | ///
40 | /// Reads 8-bits from Memory.
41 | ///
42 | /// The Address to read
43 | /// The value at the given Address
44 | public byte ReadUInt8(uint Address)
45 | {
46 | Address &= 0x3fffffff;
47 |
48 | if (Address < SDRAM.Length)
49 | return SDRAM[Address];
50 | else if (Address >= 0x20007000 && Address < 0x20008000)
51 | return DMA.Read(Address);
52 | else if (Address >= 0x2000b400 && Address < 0x2000b424)
53 | return Timer.Read(Address);
54 | else if (Address >= 0x2000b880 && Address < 0x2000b8b0)
55 | return Video.Read(Address);
56 | else if (Address >= 0x20201000 && Address < 0x20201090)
57 | return UART.Read(Address);
58 | else if (Address >= 0x20215000 && Address < 0x20215080)
59 | return MiniUART.Read(Address);
60 |
61 | return 0;
62 | }
63 |
64 | ///
65 | /// Reads 32-bits from Memory.
66 | ///
67 | /// The Address to read
68 | /// The value at the given Address
69 | public uint ReadUInt32(uint Address)
70 | {
71 | return (uint)(ReadUInt8(Address) |
72 | (ReadUInt8(Address + 1) << 8) |
73 | (ReadUInt8(Address + 2) << 16) |
74 | (ReadUInt8(Address + 3) << 24));
75 | }
76 |
77 | ///
78 | /// Writes 8-bits to Memory.
79 | ///
80 | /// The Address to write the value into
81 | /// The value to be written
82 | public void WriteUInt8(uint Address, byte Value)
83 | {
84 | Address &= 0x3fffffff;
85 |
86 | if (Address < SDRAM.Length)
87 | SDRAM[Address] = Value;
88 | else if (Address >= 0x20007000 && Address < 0x20008000)
89 | DMA.Write(Address, Value);
90 | else if (Address >= 0x2000b400 && Address < 0x2000b424)
91 | Timer.Write(Address, Value);
92 | else if (Address >= 0x2000b880 && Address < 0x2000b8b0)
93 | Video.Write(Address, Value);
94 | else if (Address >= 0x20201000 && Address < 0x20201090)
95 | UART.Write(Address, Value);
96 | else if (Address >= 0x20215000 && Address < 0x20215080)
97 | MiniUART.Write(Address, Value);
98 | }
99 |
100 | ///
101 | /// Writes 32-bits to Memory.
102 | ///
103 | /// The Address to write the value into
104 | /// The value to be written
105 | public void WriteUInt32(uint Address, uint Value)
106 | {
107 | WriteUInt8(Address, (byte)Value);
108 | WriteUInt8(Address + 1, (byte)(Value >> 8));
109 | WriteUInt8(Address + 2, (byte)(Value >> 16));
110 | WriteUInt8(Address + 3, (byte)(Value >> 24));
111 | }
112 |
113 | ///
114 | /// Copy data from one region to another of the Memory.
115 | ///
116 | /// The Source Address to start copying from
117 | /// Where the data should be placed
118 | /// Number of bytes to copy
119 | public void CopyData(uint Source, uint Destination, uint Length)
120 | {
121 | Buffer.BlockCopy(SDRAM, (int)Source, SDRAM, (int)Destination, (int)Length);
122 | }
123 |
124 | ///
125 | /// Gets a Buffer at a given Address of the SDRAM.
126 | ///
127 | /// The Address where the Buffer is located
128 | /// The length of the Buffer
129 | /// The Buffer
130 | public byte[] GetData(uint Address, uint Length)
131 | {
132 | Address &= 0x3fffffff;
133 |
134 | byte[] Output = new byte[Length];
135 | Buffer.BlockCopy(SDRAM, (int)Address, Output, 0, Output.Length);
136 | return Output;
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/ChocolateARM/RPi/Peripherals/RPiDMA.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ChocolateARM.RPi.Peripherals
4 | {
5 | ///
6 | /// Represents the DMA control of the BCM2835 SoC.
7 | ///
8 | public class RPiDMA : IO32
9 | {
10 | private Memory Parent;
11 |
12 | ///
13 | /// Creates a new instace of the RaspberryPi DMA manager.
14 | ///
15 | public RPiDMA(Memory Parent)
16 | {
17 | this.Parent = Parent;
18 | DMA = new DMA_Channel[16];
19 | }
20 |
21 | private struct DMA_Control
22 | {
23 | public bool IsActive;
24 | public bool IsFinished;
25 | public bool IsInterruptTriggered;
26 |
27 | ///
28 | /// Loads the value of the DMA Control from a UInt32.
29 | ///
30 | /// The UInt32 Control value
31 | public void Set(uint Value)
32 | {
33 | IsActive = (Value & 1) != 0;
34 | if ((Value & 2) != 0) IsFinished = false;
35 | if ((Value & 4) != 0) IsInterruptTriggered = false;
36 | }
37 |
38 | ///
39 | /// Creates a UInt32 from the values of the DMA Control.
40 | ///
41 | /// The Control value
42 | public uint Get()
43 | {
44 | uint Value = 0;
45 | if (IsActive) Value = 1;
46 | if (IsFinished) Value |= 2;
47 | if (IsInterruptTriggered) Value |= 4;
48 | if (!IsActive) Value |= 0x10;
49 | return Value;
50 | }
51 | }
52 |
53 | private struct DMA_Channel
54 | {
55 | public bool IsEnabled;
56 |
57 | public DMA_Control Control;
58 | public uint ControlBlockAddress;
59 | }
60 | private DMA_Channel[] DMA;
61 |
62 | ///
63 | /// Occurs when a interrupt is triggered.
64 | ///
65 | public event Action OnInterruptRequest;
66 |
67 | ///
68 | /// Reads a 32-bits value from the Register.
69 | ///
70 | /// The Address being read
71 | /// The value of the Register
72 | public override uint ProcessRead(uint Address)
73 | {
74 | uint Value = 0;
75 |
76 | if (Address >= 0x20007000 && Address < 0x20007f00)
77 | DMA_ProcessRead(Address, (Address >> 8) & 0xf);
78 | else if (Address == 0x20007ff0)
79 | {
80 | for (int Index = 0; Index < 16; Index++)
81 | {
82 | if (DMA[Index].IsEnabled) Value |= (uint)(1 << Index);
83 | }
84 | }
85 |
86 | return Value;
87 | }
88 |
89 | ///
90 | /// Writes a 32-bits value to a Register.
91 | ///
92 | /// The Address being written
93 | /// The value being written
94 | public override void ProcessWrite(uint Address, uint Value)
95 | {
96 | if (Address >= 0x20007000 && Address < 0x20007f00)
97 | DMA_ProcessWrite(Address, Value, (Address >> 8) & 0xf);
98 | else if (Address == 0x20007ff0)
99 | {
100 | for (int Index = 0; Index < 16; Index++)
101 | {
102 | DMA[Index].IsEnabled = (Value & (1 << Index)) != 0;
103 | }
104 | }
105 | }
106 |
107 | ///
108 | /// Reads a value from a DMA Channel.
109 | ///
110 | /// The Address being read
111 | /// The Channel being read
112 | /// The value of the Channel register being read
113 | private uint DMA_ProcessRead(uint Address, uint Channel)
114 | {
115 | Address &= 0xff;
116 |
117 | switch (Address)
118 | {
119 | case 0: return DMA[Channel].Control.Get();
120 | case 4: return DMA[Channel].ControlBlockAddress;
121 | case 0x20:
122 | uint Value = 0x4000000; //DMA Version (always 2)
123 | if (Channel > 6) Value |= 0x10000000; //Lite
124 | return Value;
125 | }
126 |
127 | return 0;
128 | }
129 |
130 | ///
131 | /// Writes a value to a DMA Channel.
132 | ///
133 | /// The Address being written
134 | /// The Value being written
135 | /// The Channel being written
136 | private void DMA_ProcessWrite(uint Address, uint Value, uint Channel)
137 | {
138 | Address &= 0xff;
139 |
140 | switch (Address)
141 | {
142 | case 0: DMA[Channel].Control.Set(Value); break;
143 | case 4: DMA[Channel].ControlBlockAddress = Value; break;
144 | }
145 |
146 | DMA_Transfer(Channel);
147 | }
148 |
149 | ///
150 | /// Performs a DMA transfer (if any is pending).
151 | ///
152 | /// The Channel that is transferring data
153 | private void DMA_Transfer(uint Channel)
154 | {
155 | if (DMA[Channel].IsEnabled && DMA[Channel].Control.IsActive)
156 | {
157 | while (DMA[Channel].ControlBlockAddress > 0)
158 | {
159 | uint Address = DMA[Channel].ControlBlockAddress;
160 |
161 | uint TransferInformation = Parent.ReadUInt32(Address);
162 | uint SrcAddress = Parent.ReadUInt32(Address + 4);
163 | uint DstAddress = Parent.ReadUInt32(Address + 8);
164 | uint Length = Parent.ReadUInt32(Address + 12);
165 | uint Stride = Parent.ReadUInt32(Address + 16);
166 | uint NextAddress = Parent.ReadUInt32(Address + 20);
167 |
168 | bool IsInterruptEnabled = (TransferInformation & 1) != 0;
169 | bool Is2DModeEnabled = (TransferInformation & 2) != 0;
170 |
171 | if (Channel < 7)
172 | {
173 | if (Is2DModeEnabled)
174 | {
175 | //2D Array transfer
176 | short SrcStride = (short)Stride;
177 | short DstStride = (short)(Stride >> 16);
178 |
179 | ushort XLength = (ushort)Length;
180 | ushort YLength = (ushort)(Length >> 16);
181 |
182 | for (int Y = 0; Y < YLength; Y++)
183 | {
184 | Parent.CopyData(SrcAddress, DstAddress, XLength);
185 |
186 | SrcAddress = (uint)(SrcAddress + XLength + SrcStride);
187 | DstAddress = (uint)(DstAddress + XLength + DstStride);
188 | }
189 | }
190 | else
191 | Parent.CopyData(SrcAddress, DstAddress, Length); //Normal 1D transfer
192 | }
193 | else
194 | Parent.CopyData(SrcAddress, DstAddress, (ushort)Length); //Lite, always 1D with 16-bits length
195 |
196 | //Trigger interrupts if needed
197 | if (IsInterruptEnabled)
198 | {
199 | if (OnInterruptRequest != null) OnInterruptRequest();
200 | DMA[Channel].Control.IsInterruptTriggered = true;
201 | }
202 |
203 | DMA[Channel].ControlBlockAddress = NextAddress;
204 | }
205 |
206 | DMA[Channel].Control.IsActive = false;
207 | DMA[Channel].Control.IsFinished = true;
208 | }
209 | }
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/ChocolateARM/RPi/Peripherals/RPiMiniUART.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ChocolateARM.RPi.Peripherals
5 | {
6 | ///
7 | /// Represents a new character that arrived at the UART.
8 | ///
9 | public class CharacterReceivedEventArgs : EventArgs
10 | {
11 | ///
12 | /// The new character that arrived on the UART.
13 | ///
14 | public char Character;
15 |
16 | ///
17 | /// Creates a new Argument with the character written to the UART.
18 | ///
19 | /// The new character
20 | public CharacterReceivedEventArgs(char Character)
21 | {
22 | this.Character = Character;
23 | }
24 | }
25 |
26 | ///
27 | /// Represents the Mini UART of the BCM2835 SoC.
28 | ///
29 | public class RPiMiniUART : IO32
30 | {
31 | private const uint AUX_ENB = 0x20215004;
32 | private const uint AUX_MU_IO_REG = 0x20215040;
33 | private const uint AUX_MU_IIR_REG = 0x20215044;
34 | private const uint AUX_MU_IER_REG = 0x20215048;
35 | private const uint AUX_MU_LCR_REG = 0x2021504c;
36 | private const uint AUX_MU_MCR_REG = 0x20215050;
37 | private const uint AUX_MU_LSR_REG = 0x20215054;
38 | private const uint AUX_MU_MSR_REG = 0x20215058;
39 | private const uint AUX_MU_SCRATCH = 0x2021505c;
40 | private const uint AUX_MU_CNTL_REG = 0x20215060;
41 | private const uint AUX_MU_STAT_REG = 0x20215064;
42 | private const uint AUX_MU_BAUD_REG = 0x20215068;
43 |
44 | private Memory Parent;
45 |
46 | private Queue Transmitter;
47 | private Queue Receiver;
48 |
49 | ///
50 | /// Creates a new instace of the RaspberryPi Mini UART.
51 | ///
52 | public RPiMiniUART(Memory Parent)
53 | {
54 | this.Parent = Parent;
55 | Transmitter = new Queue();
56 | Receiver = new Queue();
57 |
58 | MU_IsReceiverEnabled = true;
59 | MU_IsTransmitterEnabled = true;
60 | }
61 |
62 | private bool MU_IsEnabled;
63 | private bool SPI1_IsEnabled;
64 | private bool SPI2_IsEnabled;
65 |
66 | private bool MU_IsTransmitInterruptEnabled;
67 | private bool MU_IsReceiveInterruptEnabled;
68 | private bool MU_8BitsMode;
69 | private bool MU_DLAB;
70 | private bool MU_ReceiverOverrun;
71 | private byte MU_Scratch;
72 | private bool MU_IsReceiverEnabled;
73 | private bool MU_IsTransmitterEnabled;
74 | private ushort MU_BaudRate;
75 |
76 | ///
77 | /// Occurs when a interrupt is triggered.
78 | ///
79 | public event Action OnInterruptRequest;
80 |
81 | ///
82 | /// Occurs whenever a new character is written to the UART.
83 | ///
84 | public event EventHandler OnCharacterReceived;
85 |
86 | ///
87 | /// Contains a copy of all data written to the UART.
88 | ///
89 | public string BufferedOutput { get; private set; }
90 |
91 | ///
92 | /// Reads a 32-bits value from the Register.
93 | ///
94 | /// The Address being read
95 | /// The value of the Register
96 | public override uint ProcessRead(uint Address)
97 | {
98 | uint Value = 0;
99 |
100 | switch (Address)
101 | {
102 | case AUX_ENB:
103 | if (MU_IsEnabled) Value = 1;
104 | if (SPI1_IsEnabled) Value |= 2;
105 | if (SPI2_IsEnabled) Value |= 4;
106 | break;
107 |
108 | case AUX_MU_IO_REG:
109 | if (MU_DLAB)
110 | Value = (uint)(MU_BaudRate & 0xff);
111 | else if (Receiver.Count > 0)
112 | Value = Receiver.Dequeue();
113 | break;
114 |
115 | case AUX_MU_IIR_REG:
116 | if (MU_DLAB)
117 | Value = (uint)(MU_BaudRate >> 8);
118 | else
119 | {
120 | if (MU_IsReceiveInterruptEnabled) Value = 1;
121 | if (MU_IsTransmitInterruptEnabled) Value |= 2;
122 | }
123 | break;
124 |
125 | case AUX_MU_IER_REG:
126 | Value = 0xc1;
127 | if (Transmitter.Count == 0) Value |= 2;
128 | if (Receiver.Count > 0) Value |= 4;
129 | break;
130 |
131 | case AUX_MU_LCR_REG:
132 | if (MU_8BitsMode) Value = 1;
133 | if (MU_DLAB) Value |= 0x80;
134 | break;
135 |
136 | case AUX_MU_LSR_REG:
137 | if (Receiver.Count > 0) Value = 1;
138 | if (MU_ReceiverOverrun)
139 | {
140 | Value |= 2;
141 | MU_ReceiverOverrun = false;
142 | }
143 | if (Transmitter.Count < 8) Value |= 0x20;
144 | if (Transmitter.Count == 0) Value |= 0x40;
145 | break;
146 |
147 | case AUX_MU_SCRATCH: Value = MU_Scratch; break;
148 |
149 | case AUX_MU_CNTL_REG:
150 | if (MU_IsReceiverEnabled) Value = 1;
151 | if (MU_IsTransmitterEnabled) Value |= 2;
152 | break;
153 |
154 | case AUX_MU_STAT_REG:
155 | Value = 0xc;
156 | if (Receiver.Count > 0) Value |= 1;
157 | if (Transmitter.Count < 8) Value |= 2;
158 | if (MU_ReceiverOverrun) Value |= 0x10;
159 | if (Transmitter.Count == 8) Value |= 0x20;
160 | if (Transmitter.Count == 0) Value |= 0x300;
161 | Value |= (uint)((Receiver.Count & 0xf) << 16);
162 | Value |= (uint)((Transmitter.Count & 0xf) << 24);
163 | break;
164 |
165 | case AUX_MU_BAUD_REG: Value = MU_BaudRate; break;
166 | }
167 |
168 | return Value;
169 | }
170 |
171 | ///
172 | /// Writes a 32-bits value to a Register.
173 | ///
174 | /// The Address being written
175 | /// The value being written
176 | public override void ProcessWrite(uint Address, uint Value)
177 | {
178 | if (Address >= 0x20215040 && !MU_IsEnabled) return;
179 |
180 | switch (Address)
181 | {
182 | case AUX_ENB:
183 | MU_IsEnabled = (Value & 1) != 0;
184 | SPI1_IsEnabled = (Value & 2) != 0;
185 | SPI2_IsEnabled = (Value & 4) != 0;
186 | break;
187 |
188 | case AUX_MU_IO_REG:
189 | if (MU_DLAB)
190 | MU_BaudRate = (ushort)((MU_BaudRate & 0xff00) | (byte)Value);
191 | else if (Transmitter.Count < 8 && MU_IsTransmitterEnabled)
192 | {
193 | Transmitter.Enqueue((byte)Value);
194 | AppendCharacter();
195 | }
196 | break;
197 |
198 | case AUX_MU_IIR_REG:
199 | if (MU_DLAB)
200 | MU_BaudRate = (ushort)((MU_BaudRate & 0xff) | ((byte)Value << 8));
201 | else
202 | {
203 | MU_IsReceiveInterruptEnabled = (Value & 1) != 0;
204 | MU_IsTransmitInterruptEnabled = (Value & 2) != 0;
205 | }
206 | break;
207 |
208 | case AUX_MU_IER_REG:
209 | if ((Value & 2) != 0) Receiver.Clear();
210 | if ((Value & 4) != 0) Transmitter.Clear();
211 | break;
212 |
213 | case AUX_MU_LCR_REG:
214 | MU_8BitsMode = (Value & 1) != 0;
215 | MU_DLAB = (Value & 0x80) != 0;
216 | break;
217 |
218 | case AUX_MU_SCRATCH: MU_Scratch = (byte)Value; break;
219 |
220 | case AUX_MU_CNTL_REG:
221 | MU_IsReceiverEnabled = (Value & 1) != 0;
222 | MU_IsTransmitterEnabled = (Value & 2) != 0;
223 | break;
224 |
225 | case AUX_MU_BAUD_REG: MU_BaudRate = (ushort)Value; break;
226 | }
227 | }
228 |
229 | ///
230 | /// Appends a character on the console.
231 | ///
232 | private void AppendCharacter()
233 | {
234 | char Character = (char)Transmitter.Dequeue();
235 | if (OnCharacterReceived != null) OnCharacterReceived(this, new CharacterReceivedEventArgs(Character));
236 | BufferedOutput += Character;
237 |
238 | bool TriggerInterrupt = Transmitter.Count == 0 && MU_IsTransmitInterruptEnabled;
239 | if (TriggerInterrupt && OnInterruptRequest != null) OnInterruptRequest();
240 | }
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/ChocolateARM/RPi/Peripherals/RPiTimer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Timers;
3 |
4 | namespace ChocolateARM.RPi.Peripherals
5 | {
6 | ///
7 | /// Represents the Timer of the BCM2835 SoC.
8 | ///
9 | public class RPiTimer : IO32, IDisposable
10 | {
11 | const double ARMT_Frequency = 1000000; //1MHz
12 |
13 | private uint ARMT_LoadValue;
14 | private uint ARMT_Value;
15 | private uint ARMT_Control;
16 | private uint ARMT_Reload;
17 | private uint ARMT_PreDivider;
18 | private uint ARMT_FreeRunCounter;
19 |
20 | private Timer Countdown;
21 | private Timer FreeRun;
22 |
23 | ///
24 | /// Occurs when a interrupt is triggered.
25 | ///
26 | public event Action OnInterruptRequest;
27 |
28 | public void Dispose()
29 | {
30 | Dispose(true);
31 | GC.SuppressFinalize(this);
32 | }
33 |
34 | protected virtual void Dispose(bool Disposing)
35 | {
36 | if (Disposing)
37 | {
38 | Countdown.Dispose();
39 | FreeRun.Dispose();
40 | }
41 | }
42 |
43 | ///
44 | /// Creates a new instace of the RaspberryPi Timer.
45 | ///
46 | public RPiTimer()
47 | {
48 | ARMT_Control = 0x3e0020;
49 | ARMT_PreDivider = 0x7d;
50 |
51 | Countdown = new Timer();
52 | FreeRun = new Timer();
53 |
54 | Countdown.Elapsed += Countdown_Tick;
55 | FreeRun.Elapsed += FreeRun_Tick;
56 | }
57 |
58 | ///
59 | /// Reads a value from the Timer registers.
60 | ///
61 | /// The Address of the read
62 | /// The value at the Address
63 | public override uint ProcessRead(uint Address)
64 | {
65 | switch (Address)
66 | {
67 | case 0x2000b400: return ARMT_LoadValue;
68 | case 0x2000b404:
69 | if ((ARMT_Control & 2) != 0)
70 | ARMT_Value &= 0x7fffff;
71 | else
72 | ARMT_Value &= 0xffff;
73 | return ARMT_Value;
74 | case 0x2000b408: return ARMT_Control;
75 | case 0x2000b40c: return 0x544d5241;
76 | case 0x2000b410: return 0x3e0020;
77 | case 0x2000b414: return 0x3e0020;
78 | case 0x2000b418: return ARMT_Reload;
79 | case 0x2000b41c: return ARMT_PreDivider;
80 | case 0x2000b420: return ARMT_FreeRunCounter;
81 | }
82 |
83 | return 0;
84 | }
85 |
86 | ///
87 | /// Writes a value to the Timer registers.
88 | ///
89 | /// The Address of the write
90 | /// The value being written
91 | public override void ProcessWrite(uint Address, uint Value)
92 | {
93 | switch (Address)
94 | {
95 | case 0x2000b400:
96 | ARMT_LoadValue = Value;
97 | ARMT_Value = Value;
98 | break;
99 | case 0x2000b408:
100 | ARMT_Control = Value;
101 | switch ((Value >> 2) & 3)
102 | {
103 | case 1: Countdown.Interval = 1000d / (ARMT_Frequency / 16); break;
104 | case 2: Countdown.Interval = 1000d / (ARMT_Frequency / 256); break;
105 | default: Countdown.Interval = 1000d / ARMT_Frequency; break;
106 | }
107 | Countdown.Enabled = (Value & 0x80) != 0;
108 | FreeRun.Enabled = (Value & 0x200) != 0;
109 | FreeRun.Interval = 1000d / (ARMT_Frequency / (((Value >> 16) & 0xff) + 1));
110 | break;
111 | case 0x2000b418: ARMT_Reload = Value; break;
112 | case 0x2000b41c: ARMT_PreDivider = Value; break;
113 | case 0x2000b420: ARMT_FreeRunCounter = Value; break;
114 | }
115 | }
116 |
117 | private void Countdown_Tick(object sender, ElapsedEventArgs e)
118 | {
119 | if (ARMT_Value > 0)
120 | ARMT_Value--;
121 | else
122 | {
123 | ARMT_Value = ARMT_LoadValue;
124 | bool IsInterruptEnabled = (ARMT_Control & 0x20) != 0;
125 | if (IsInterruptEnabled && OnInterruptRequest != null) OnInterruptRequest();
126 | }
127 | }
128 |
129 | private void FreeRun_Tick(object sender, ElapsedEventArgs e)
130 | {
131 | ARMT_FreeRunCounter++;
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/ChocolateARM/RPi/Peripherals/RPiUART.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ChocolateARM.RPi.Peripherals
5 | {
6 | ///
7 | /// Represents the UART (PL011) of the BCM2835 SoC.
8 | ///
9 | public class RPiUART : IO32
10 | {
11 | private Queue Transmitter;
12 | private Queue Receiver;
13 |
14 | ///
15 | /// Occurs when a interrupt is triggered.
16 | ///
17 | public event Action OnInterruptRequest;
18 |
19 | ///
20 | /// Occurs whenever a new character is written to the UART.
21 | ///
22 | public event EventHandler OnCharacterReceived;
23 |
24 | ///
25 | /// Contains a copy of all data written to the UART.
26 | ///
27 | public string BufferedOutput { get; private set; }
28 |
29 | public RPiUART()
30 | {
31 | Transmitter = new Queue();
32 | Receiver = new Queue();
33 | }
34 |
35 | ///
36 | /// Reads a 32-bits value from the Register.
37 | ///
38 | /// The Address being read
39 | /// The value of the Register
40 | public override uint ProcessRead(uint Address)
41 | {
42 | switch (Address)
43 | {
44 | case 0x20201000: if (Receiver.Count > 0) return Receiver.Dequeue(); break;
45 | case 0x20201018:
46 | uint Value = 0;
47 | if (Receiver.Count == 0) Value = 0x10;
48 | if (Transmitter.Count == 8) Value |= 0x20;
49 | if (Receiver.Count == 8) Value |= 0x40;
50 | if (Transmitter.Count == 0) Value |= 0x80;
51 | return Value;
52 | }
53 |
54 | return 0;
55 | }
56 |
57 | ///
58 | /// Writes a 32-bits value to a Register.
59 | ///
60 | /// The Address being written
61 | /// The value being written
62 | public override void ProcessWrite(uint Address, uint Value)
63 | {
64 | switch (Address)
65 | {
66 | case 0x20201000:
67 | if (Transmitter.Count < 8)
68 | {
69 | Transmitter.Enqueue((byte)Value);
70 | AppendCharacter();
71 | }
72 | break;
73 | }
74 | }
75 |
76 | ///
77 | /// Appends a character on the console.
78 | ///
79 | private void AppendCharacter()
80 | {
81 | char Character = (char)Transmitter.Dequeue();
82 | if (OnCharacterReceived != null) OnCharacterReceived(this, new CharacterReceivedEventArgs(Character));
83 | BufferedOutput += Character;
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/ChocolateARM/RPi/RPiCore.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Threading;
3 |
4 | using SharpARM.ARM11;
5 |
6 | namespace ChocolateARM.RPi
7 | {
8 | ///
9 | /// Represents a Raspberry Pi (version 1).
10 | ///
11 | public class RPiCore
12 | {
13 | public ARMCore CPU;
14 | public Memory Memory;
15 |
16 | private bool IsExecuting;
17 |
18 | ///
19 | /// Creates a new instance of the Raspberry Pi emulator.
20 | ///
21 | /// The Picture Box to draw the video output
22 | public RPiCore()
23 | {
24 | Memory = new Memory();
25 | CPU = new ARMCore(Memory);
26 | }
27 |
28 | ///
29 | /// Loads a binary file into Memory.
30 | ///
31 | /// The full path to the file that should be loaded
32 | /// The Address to place the file into Memory
33 | /// Set the value of PC to the value of Address (where the binary is loaded)
34 | public void Load(string FileName, uint Address, bool SetPC = false)
35 | {
36 | byte[] Buffer = File.ReadAllBytes(FileName);
37 | for (uint i = 0; i < Buffer.Length; i++)
38 | {
39 | Memory.WriteUInt8(Address + i, Buffer[i]);
40 | }
41 |
42 | CPU.Reset();
43 | if (SetPC)
44 | {
45 | CPU.Registers[15] = Address;
46 | CPU.ReloadPipeline();
47 | }
48 | }
49 |
50 | ///
51 | /// Executes the program asynchronously until Stop is called.
52 | ///
53 | public void RunAsync()
54 | {
55 | Thread ExecutionThread = new Thread(Run);
56 | ExecutionThread.Start();
57 | }
58 |
59 | ///
60 | /// Executes instruction on a loop until Stop is called.
61 | ///
62 | private void Run()
63 | {
64 | IsExecuting = true;
65 | while (IsExecuting) CPU.Execute();
66 | }
67 |
68 | ///
69 | /// Stops executing the instructions.
70 | ///
71 | public void Stop()
72 | {
73 | IsExecuting = false;
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ChocolateARM
2 | Bare bones ARM1176 (ARMv6) emulator written in C#
3 |
4 | This is an ARMv6 emulator written in C#, with emulation of some parts of the Raspberry Pi hardware. The CPU was not well tested and probably still contains a lot of bugs. Only a very small portion of the Raspberry Pi hardware was implemented, so it can't run many stuff. Some of the "bare metal" RasPi demos does work. Speed is awfully slow as expected.
5 | You're free to improve or modify any portion of the code, but please give me the credits for what I wrote. Thanks :)
6 |
7 | TODO:
8 |
9 | - More CPU tests are needed
10 | - Implement VFP
11 | - Finish CP15 implementation
12 | - Implement interrupts
13 | - Finish UART
14 | - Add GPIO support and other inputs
15 |
--------------------------------------------------------------------------------