summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ue1/protokoll.pdfbin283846 -> 283840 bytes
-rw-r--r--ue3/mycpu/cdisplay.h26
-rw-r--r--ue3/mycpu/cinstruction.cpp2
-rw-r--r--ue3/mycpu/instructions.cpp34
-rw-r--r--ue3/mycpu/test/memory11
-rw-r--r--ue3/mycpu/test/program113
-rwxr-xr-xue3/mycpu/test/test.sh4
-rw-r--r--ue3/protokoll.pdfbin0 -> 405263 bytes
-rw-r--r--ue3/protokoll/mycpu.pngbin0 -> 111899 bytes
-rw-r--r--ue3/protokoll/mycpu.vppbin0 -> 129025 bytes
-rw-r--r--ue3/protokoll/protokoll.tex144
11 files changed, 185 insertions, 39 deletions
diff --git a/ue1/protokoll.pdf b/ue1/protokoll.pdf
index d1a72ac..3682945 100644
--- a/ue1/protokoll.pdf
+++ b/ue1/protokoll.pdf
Binary files differ
diff --git a/ue3/mycpu/cdisplay.h b/ue3/mycpu/cdisplay.h
index 0a0a723..1523f68 100644
--- a/ue3/mycpu/cdisplay.h
+++ b/ue3/mycpu/cdisplay.h
@@ -1,7 +1,7 @@
1/** 1/**
2 * @module cdisplay 2 * @module cdisplay
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Abstract class for displays 4 * @brief Abstract template class for displays
5 * @date 10.05.2009 5 * @date 10.05.2009
6 */ 6 */
7 7
@@ -9,15 +9,16 @@
9#define CDISPLAY_H 1 9#define CDISPLAY_H 1
10 10
11/** 11/**
12 * @class CDisplay 12 * @class CDisplayT
13 * 13 *
14 * Abstract class for displays 14 * Abstract template class for displays
15 */ 15 */
16class CDisplay 16template <class T>
17class CDisplayT
17{ 18{
18 public: 19 public:
19 /** 20 /**
20 * @method CDisplay 21 * @method CDisplayT
21 * @brief Default ctor 22 * @brief Default ctor
22 * @param name name of display 23 * @param name name of display
23 * @return - 24 * @return -
@@ -25,12 +26,12 @@ class CDisplay
25 * @exception none 26 * @exception none
26 * @conditions none 27 * @conditions none
27 */ 28 */
28 CDisplay(std::string name) 29 CDisplayT(std::string name)
29 : m_name(name) 30 : m_name(name)
30 {} 31 {}
31 32
32 /** 33 /**
33 * @method ~CDisplay 34 * @method ~CDisplayT
34 * @brief Default dtor 35 * @brief Default dtor
35 * @param - 36 * @param -
36 * @return - 37 * @return -
@@ -38,7 +39,7 @@ class CDisplay
38 * @exception none 39 * @exception none
39 * @conditions none 40 * @conditions none
40 */ 41 */
41 virtual ~CDisplay() 42 virtual ~CDisplayT()
42 {} 43 {}
43 44
44 /** 45 /**
@@ -64,7 +65,7 @@ class CDisplay
64 * @exception none 65 * @exception none
65 * @conditions none 66 * @conditions none
66 */ 67 */
67 virtual void display(const CDat &value) = 0; 68 virtual void display(const T &value) = 0;
68 69
69 protected: 70 protected:
70 /* members */ 71 /* members */
@@ -72,6 +73,13 @@ class CDisplay
72 std::string m_name; 73 std::string m_name;
73}; 74};
74 75
76/**
77 * @class CDisplay
78 *
79 * Memory definition for CCPU
80 */
81typedef CDisplayT<CDat> CDisplay;
82
75#endif 83#endif
76 84
77/* vim: set et sw=2 ts=2: */ 85/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/cinstruction.cpp b/ue3/mycpu/cinstruction.cpp
index 5c1bd5c..a766015 100644
--- a/ue3/mycpu/cinstruction.cpp
+++ b/ue3/mycpu/cinstruction.cpp
@@ -8,6 +8,7 @@
8#include <sstream> 8#include <sstream>
9#include <stdexcept> 9#include <stdexcept>
10#include <boost/lexical_cast.hpp> 10#include <boost/lexical_cast.hpp>
11#include <assert.h>
11#include "cinstruction.h" 12#include "cinstruction.h"
12#include "ccpu.h" 13#include "ccpu.h"
13 14
@@ -35,6 +36,7 @@ const unsigned CInstruction::parseRegister(const std::string& str)
35 36
36inline void CInstruction::checkRegister(CCPU *cpu, const unsigned regidx) 37inline void CInstruction::checkRegister(CCPU *cpu, const unsigned regidx)
37{ 38{
39 assert(cpu != NULL);
38 if (regidx >= cpu->getRegisterCount()) 40 if (regidx >= cpu->getRegisterCount())
39 { 41 {
40 stringstream sstr; 42 stringstream sstr;
diff --git a/ue3/mycpu/instructions.cpp b/ue3/mycpu/instructions.cpp
index c2ce096..ef9e944 100644
--- a/ue3/mycpu/instructions.cpp
+++ b/ue3/mycpu/instructions.cpp
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8#include <map> 8#include <map>
9#include <assert.h>
9#include "instructions.h" 10#include "instructions.h"
10 11
11using namespace std; 12using namespace std;
@@ -22,6 +23,8 @@ void CInstructionInc::compile(std::list<std::string>& params)
22 23
23void CInstructionInc::execute(CCPU *cpu) 24void CInstructionInc::execute(CCPU *cpu)
24{ 25{
26 assert(cpu != NULL);
27 assert(cpu->getRegisters() != NULL);
25 checkRegister(cpu, m_regidx1); 28 checkRegister(cpu, m_regidx1);
26 cpu->getRegisters()[ m_regidx1 ]++; 29 cpu->getRegisters()[ m_regidx1 ]++;
27} 30}
@@ -40,6 +43,8 @@ void CInstructionDec::compile(std::list<std::string>& params)
40 43
41void CInstructionDec::execute(CCPU *cpu) 44void CInstructionDec::execute(CCPU *cpu)
42{ 45{
46 assert(cpu != NULL);
47 assert(cpu->getRegisters() != NULL);
43 checkRegister(cpu, m_regidx1); 48 checkRegister(cpu, m_regidx1);
44 cpu->getRegisters()[ m_regidx1 ]--; 49 cpu->getRegisters()[ m_regidx1 ]--;
45} 50}
@@ -62,6 +67,8 @@ void CInstructionAdd::compile(std::list<std::string>& params)
62 67
63void CInstructionAdd::execute(CCPU *cpu) 68void CInstructionAdd::execute(CCPU *cpu)
64{ 69{
70 assert(cpu != NULL);
71 assert(cpu->getRegisters() != NULL);
65 checkRegister(cpu, m_regidx1); 72 checkRegister(cpu, m_regidx1);
66 checkRegister(cpu, m_regidx2); 73 checkRegister(cpu, m_regidx2);
67 checkRegister(cpu, m_regidx3); 74 checkRegister(cpu, m_regidx3);
@@ -87,6 +94,8 @@ void CInstructionSub::compile(std::list<std::string>& params)
87 94
88void CInstructionSub::execute(CCPU *cpu) 95void CInstructionSub::execute(CCPU *cpu)
89{ 96{
97 assert(cpu != NULL);
98 assert(cpu->getRegisters() != NULL);
90 checkRegister(cpu, m_regidx1); 99 checkRegister(cpu, m_regidx1);
91 checkRegister(cpu, m_regidx2); 100 checkRegister(cpu, m_regidx2);
92 checkRegister(cpu, m_regidx3); 101 checkRegister(cpu, m_regidx3);
@@ -137,6 +146,8 @@ void CInstructionDiv::compile(std::list<std::string>& params)
137 146
138void CInstructionDiv::execute(CCPU *cpu) 147void CInstructionDiv::execute(CCPU *cpu)
139{ 148{
149 assert(cpu != NULL);
150 assert(cpu->getRegisters() != NULL);
140 checkRegister(cpu, m_regidx1); 151 checkRegister(cpu, m_regidx1);
141 checkRegister(cpu, m_regidx2); 152 checkRegister(cpu, m_regidx2);
142 checkRegister(cpu, m_regidx3); 153 checkRegister(cpu, m_regidx3);
@@ -160,6 +171,9 @@ void CInstructionLoad::compile(std::list<std::string>& params)
160 171
161void CInstructionLoad::execute(CCPU *cpu) 172void CInstructionLoad::execute(CCPU *cpu)
162{ 173{
174 assert(cpu != NULL);
175 assert(cpu->getRegisters() != NULL);
176 assert(cpu->getMemory() != NULL);
163 checkRegister(cpu, m_regidx1); 177 checkRegister(cpu, m_regidx1);
164 checkRegister(cpu, m_regidx2); 178 checkRegister(cpu, m_regidx2);
165 CDat val(cpu->getRegisters()[ m_regidx2 ]); 179 CDat val(cpu->getRegisters()[ m_regidx2 ]);
@@ -182,6 +196,9 @@ void CInstructionStore::compile(std::list<std::string>& params)
182 196
183void CInstructionStore::execute(CCPU *cpu) 197void CInstructionStore::execute(CCPU *cpu)
184{ 198{
199 assert(cpu != NULL);
200 assert(cpu->getRegisters() != NULL);
201 assert(cpu->getMemory() != NULL);
185 checkRegister(cpu, m_regidx1); 202 checkRegister(cpu, m_regidx1);
186 checkRegister(cpu, m_regidx2); 203 checkRegister(cpu, m_regidx2);
187 CDat val(cpu->getRegisters()[ m_regidx2 ]); 204 CDat val(cpu->getRegisters()[ m_regidx2 ]);
@@ -202,6 +219,8 @@ void CInstructionTest::compile(std::list<std::string>& params)
202 219
203void CInstructionTest::execute(CCPU *cpu) 220void CInstructionTest::execute(CCPU *cpu)
204{ 221{
222 assert(cpu != NULL);
223 assert(cpu->getRegisters() != NULL);
205 checkRegister(cpu, m_regidx1); 224 checkRegister(cpu, m_regidx1);
206 if (cpu->getRegisters()[ m_regidx1 ] == CDat(0)) 225 if (cpu->getRegisters()[ m_regidx1 ] == CDat(0))
207 cpu->setFlagZero(true); 226 cpu->setFlagZero(true);
@@ -223,6 +242,9 @@ void CInstructionJumpA::compile(std::list<std::string>& params)
223 242
224void CInstructionJumpA::execute(CCPU *cpu) 243void CInstructionJumpA::execute(CCPU *cpu)
225{ 244{
245 assert(cpu != NULL);
246 assert(cpu->getRegisters() != NULL);
247 assert(cpu->getProgram() != NULL);
226 if (m_addr.empty()) 248 if (m_addr.empty())
227 throw runtime_error("Empty address"); 249 throw runtime_error("Empty address");
228 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); 250 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
@@ -242,8 +264,13 @@ void CInstructionJumpZ::compile(std::list<std::string>& params)
242 264
243void CInstructionJumpZ::execute(CCPU *cpu) 265void CInstructionJumpZ::execute(CCPU *cpu)
244{ 266{
267 assert(cpu != NULL);
268 assert(cpu->getRegisters() != NULL);
269 assert(cpu->getProgram() != NULL);
245 if (!cpu->getFlagZero()) 270 if (!cpu->getFlagZero())
246 return; 271 return;
272 if (m_addr.empty())
273 throw runtime_error("Empty address");
247 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); 274 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
248} 275}
249 276
@@ -261,8 +288,13 @@ void CInstructionJumpS::compile(std::list<std::string>& params)
261 288
262void CInstructionJumpS::execute(CCPU *cpu) 289void CInstructionJumpS::execute(CCPU *cpu)
263{ 290{
291 assert(cpu != NULL);
292 assert(cpu->getRegisters() != NULL);
293 assert(cpu->getProgram() != NULL);
264 if (!cpu->getFlagSign()) 294 if (!cpu->getFlagSign())
265 return; 295 return;
296 if (m_addr.empty())
297 throw runtime_error("Empty address");
266 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); 298 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
267} 299}
268 300
@@ -282,6 +314,8 @@ void CInstructionWrite::compile(std::list<std::string>& params)
282 314
283void CInstructionWrite::execute(CCPU *cpu) 315void CInstructionWrite::execute(CCPU *cpu)
284{ 316{
317 assert(cpu != NULL);
318 assert(cpu->getRegisters() != NULL);
285 checkRegister(cpu, m_regidx1); 319 checkRegister(cpu, m_regidx1);
286 if (m_dev.empty()) 320 if (m_dev.empty())
287 throw runtime_error("Empty device"); 321 throw runtime_error("Empty device");
diff --git a/ue3/mycpu/test/memory1 b/ue3/mycpu/test/memory1
deleted file mode 100644
index 209e3ef..0000000
--- a/ue3/mycpu/test/memory1
+++ /dev/null
@@ -1 +0,0 @@
120
diff --git a/ue3/mycpu/test/program1 b/ue3/mycpu/test/program1
deleted file mode 100644
index ae5e9d2..0000000
--- a/ue3/mycpu/test/program1
+++ /dev/null
@@ -1,13 +0,0 @@
1# set R2 = 10
2LOAD R2, R1
3
4# start of loop
5label Loop:
6inc R3
7sub R4, R3, R2
8test R4
9jumpz EndLoop
10write WDEZ, R3
11jumpa Loop
12
13label EndLoop:
diff --git a/ue3/mycpu/test/test.sh b/ue3/mycpu/test/test.sh
index ad2ae4d..ff1076c 100755
--- a/ue3/mycpu/test/test.sh
+++ b/ue3/mycpu/test/test.sh
@@ -32,9 +32,11 @@ do
32 if [ "$md5_1" != "$md5_2" ] 32 if [ "$md5_1" != "$md5_2" ]
33 then 33 then
34 echo " ERROR: output and $reffile differ" 34 echo " ERROR: output and $reffile differ"
35 diff -Nau $reffile $tmpfile 35 diff -Naur "$reffile" "$tmpfile"
36 rm -rf "$tmpfile"
36 exit 1 37 exit 1
37 else 38 else
38 echo " SUCCESS" 39 echo " SUCCESS"
39 fi 40 fi
41 rm -rf "$tmpfile"
40done 42done
diff --git a/ue3/protokoll.pdf b/ue3/protokoll.pdf
new file mode 100644
index 0000000..3d8c5eb
--- /dev/null
+++ b/ue3/protokoll.pdf
Binary files differ
diff --git a/ue3/protokoll/mycpu.png b/ue3/protokoll/mycpu.png
new file mode 100644
index 0000000..570d50a
--- /dev/null
+++ b/ue3/protokoll/mycpu.png
Binary files differ
diff --git a/ue3/protokoll/mycpu.vpp b/ue3/protokoll/mycpu.vpp
new file mode 100644
index 0000000..1f4b264
--- /dev/null
+++ b/ue3/protokoll/mycpu.vpp
Binary files differ
diff --git a/ue3/protokoll/protokoll.tex b/ue3/protokoll/protokoll.tex
index 8b413e7..dd53735 100644
--- a/ue3/protokoll/protokoll.tex
+++ b/ue3/protokoll/protokoll.tex
@@ -38,44 +38,110 @@ Manuel Mausz, \matrnr 0728348\\
38 38
39Abbildung~\ref{fig:classdiagram1} zeigt das Klassendiagramm der Aufgabe. 39Abbildung~\ref{fig:classdiagram1} zeigt das Klassendiagramm der Aufgabe.
40 40
41TODO 41Als Datentyp für Register und Hauptspeicher der CPU wurde ein allgemeines
42Template implementiert, welche andere Datentypen oder Klasse umhüllen kann.
43Zudem wurden die gängigsten Operatoren definiert, die man sich von einem
44Datentyp erwarten kann. Gemäß der Aufgabenstellung wurde der Datentyp CDat als
45umhüllter Integer-Wert definiert.
46
47Der Hauptspeicher der CPU wurde als abgeleitetes Template \mbox{CVectorMem} des
48Templates \mbox{std::vector<T, Allocator>} implementiert, damit dieses um die
49Methode \mbox{initialize} und \mbox{dump} erweitert werden konnten. Erstere
50dient zur Initialisierung des Hauptspeichers bzw. Füllung des Vectors,
51zweiteres zur Debugausgabe. Der Datentyp CMem wurde via typedef als
52\mbox{CVectorMem} mit dem Templateargument CDat definiert. Somit enthält der
53Hauptspeicher nur Elemente des Typs CDat.
54
55Die geforderten zwei Display-Klassen \mbox{CDisplayWDEZ} und
56\mbox{CDisplayWHEX} wurden von der abstrakten Klasse CDisplay abgeleitet, welche
57selbst als Template CDisplayT mit dem Templateargument CDat definiert ist.
58
59Der Programmspeicher \mbox{CProgram} wurde vom Template
60\mbox{std::vector<CInstruction *>} abgeleitet. Somit ist diese Klasse, ähnlich
61wie CMem, selbst ein Vector. Zudem wurden weitere Methoden hinzugefügt. Die
62Methode \mbox{compile} dient zum Kompilieren bzw. Umwandeln des
63Syntax der Programmdatei in Instanzen der Klasse CInstruction, die später von
64der CPU ausgeführt werden. Zur Umwandlung werden bei der Instantiierung von
65\mbox{CProgram} sämtliche erlaubten Instruktionen (also Instanzen von
66\mbox{CInstruction}) in ein \mbox{std::set} eingefügt. Im Zuge der Methode
67\mbox{compile} wird durch Iterieren die jeweilige Instruktion gesucht und durch
68Anwendung des Designpattern \textit{Factory method pattern} die Instruktion
69dupliziert und in \mbox{CProgram} gespeichert. Labels werden zwecks Effizienz in
70einer \mbox{std::map} festgehalten.
71
72Die jeweiligen unterstützen Instruktionen wurden wie gefordert von der Klasse
73\mbox{CInstruction} abgeleitet. \mbox{CInstruction} fordert die
74Implementierung einer Methode \mbox{compile}, die während des parsens der
75Programmdatei von \mbox{CProgram} aufgerufen werden, als auch eine Methode
76\mbox{execute}, die im Zuge der Ausführung des Programms von CCPU
77aufgerufen werden.
78
79Die eigentliche CPU wird durch die Klasse \mbox{CCPU} implementiert. Diese
80dient hauptsächlich als Container für die einzelnen, notwendigen Teile
81(Hauptspeicher, Programmspeicher, Displays, ...) und besitzt daher entsprechend
82viele get- und set-Funktionen. Die Methode \mbox{run} dient zur Ausführung des
83Programms und ist eine Schleife, die über die Instruktionen iteriert und die
84Methode \mbox{execute} aufruft.
42 85
43%================================================================== 86%==================================================================
44\begin{figure}[htb] 87\begin{center}
45 \begin{center} 88 \begin{figure}[htb]
46 \epsfxsize=0.9\textwidth\epsfbox{mycpu.png} 89 \epsfxsize=1.6\textwidth\epsfbox{mycpu.png}
47 \end{center} 90 \caption{Klassendiagramm 1}
48 \caption{Klassendiagramm 1} 91 \label{fig:classdiagram1}
49 \label{fig:classdiagram1} 92 \end{figure}
50\end{figure} 93\end{center}
51%================================================================== 94%==================================================================
52 95
53\subsection{Verwaltung der Ressourcen} 96\subsection{Verwaltung der Ressourcen}
54 97
55TODO 98Alle Objekte, die im Konstruktor alloziert werden, werden im Destruktor wieder
99freigegeben. Die Objekte, die über die \textit{Factory method pattern}
100alloziert werden, werden im Zuge des Destruktor des Vectors bzw.
101von \mbox{CProgram} wieder freigegeben.
56 102
57\subsection{Fehlerbehandlung} 103\subsection{Fehlerbehandlung}
58 104
59TODO 105Es wurden keine eigenen Exceptions eingeführt. Statt dessen werden Exceptions
106meist in Exceptions des Typs \mbox{std::runtime\_error} umgewandelt. Da die
107Hierarchie nicht sehr tief ist, fängt lediglich \mbox{CPropram::compile}
108Exceptions des Typs \mbox{std::runtime\_error}, um zusätzliche Information an
109den ursprünglichen Aufrufer der Methode weiterzugeben. Dies geschieht ebenfalls
110per Exception des Typs \mbox{std::runtime\_error}.
60 111
61\subsection{Implementierung} 112\subsection{Implementierung}
62 113
63TODO 114Siehe Punkt~\ref{Design} und Abbildung~\ref{fig:classdiagram1} sowie
64 115Punkt~\ref{Listings}.\\
116Es wurde viel mit Templates gearbeitet.
65 117
66\section{Projektverlauf} 118\section{Projektverlauf}
67 119
68\subsection{Probleme und Fallstricke} 120\subsection{Probleme und Fallstricke}
69 121
70TODO 122Abgesehen von den mittlerweile üblichen Schwierigkeiten die Angabe bzw.
123die Gedanken dessen Verfassers verstehen zu wollen, arbeitete das erste Design
124noch vermehrt mit Text. Unter anderem hatte die Methode
125\mbox{CInstruction::execute} einen Parameter des Typs \mbox{std::string}, was
126zum dazu führte, das die Instruktion bei jeder Aufführung (zum Beispiel durch
127Jumps) erneut geparsed werden musste.
71 128
72\subsection{Arbeitsaufwand} 129\subsection{Arbeitsaufwand}
73 130
74\begin{tabular}{ll} 131\begin{tabular}{ll}
75 \toprule 132 \toprule
76 Entwicklungsschritt / Meilenstein & Arbeitsaufwand in Stunden\\ 133 Entwicklungsschritt / Meilenstein & Arbeitsaufwand\\
134 \midrule
135 Erstes Design & 3 Stunden\\
136 \hline
137 Implementierung & 3 Tage\\
138 \hline
139 Anpassung des Designs und der Implementierung & 4 Stunden\\
140 \hline
141 Dokumentation (Doxygen) und Überprüfung aller\\
142 Anforderungen gemäß der Programmierrichtlinien & 4 Stunden\\
77 \hline 143 \hline
78 TODO & TODO\\ 144 Erstellung des Protokolls & 3 Stunden\\
79 \bottomrule 145 \bottomrule
80\end{tabular} 146\end{tabular}
81 147
@@ -88,5 +154,53 @@ TODO
88\subsection{mycpu.cpp} 154\subsection{mycpu.cpp}
89\lstinputlisting{../mycpu/mycpu.cpp} 155\lstinputlisting{../mycpu/mycpu.cpp}
90 156
157\newpage
158\subsection{cdat.h}
159\lstinputlisting{../mycpu/cdat.h}
160
161\newpage
162\subsection{cmem.h}
163\lstinputlisting{../mycpu/cmem.h}
164
165\newpage
166\subsection{cinstruction.h}
167\lstinputlisting{../mycpu/cinstruction.h}
168
169\newpage
170\subsection{cinstruction.cpp}
171\lstinputlisting{../mycpu/cinstruction.cpp}
172
173\newpage
174\subsection{instructions.h}
175\lstinputlisting{../mycpu/instructions.h}
176
177\newpage
178\subsection{instructions.cpp}
179\lstinputlisting{../mycpu/instructions.cpp}
180
181\newpage
182\subsection{cdisplay.h}
183\lstinputlisting{../mycpu/cdisplay.h}
184
185\newpage
186\subsection{displays.h}
187\lstinputlisting{../mycpu/displays.h}
188
189\newpage
190\subsection{cprogram.h}
191\lstinputlisting{../mycpu/cprogram.h}
192
193\newpage
194\subsection{cprogram.cpp}
195\lstinputlisting{../mycpu/cprogram.cpp}
196
197\newpage
198\subsection{ccpu.h}
199\lstinputlisting{../mycpu/ccpu.h}
200
201\newpage
202\subsection{ccpu.cpp}
203\lstinputlisting{../mycpu/ccpu.cpp}
204
91\end{document} 205\end{document}
92 206