33// Licensed under the MIT license.
44
55#include <stdio.h>
6+ #include <string.h>
67#include "emulator.h"
78
89enum Opcode
@@ -33,23 +34,20 @@ static void emulator_on_output(Emulator instance, Word word)
3334void emulator (Emulator instance , Word memory [])
3435{
3536 instance -> memory = memory ;
37+ instance -> instruction = instance -> memory ;
3638 instance -> input = emulator_on_input ;
3739 instance -> output = emulator_on_output ;
38-
40+
3941 queue (& instance -> inputs , NULL , 0 );
4042 queue (& instance -> outputs , NULL , 0 );
4143}
4244
43- static void emulator_move (
44- Emulator instance ,
45- Word * instruction ,
46- Word result ,
47- int slot )
45+ static void emulator_move (Emulator instance , Word result , int slot )
4846{
49- instance -> memory [instruction [slot ]] = result ;
47+ instance -> memory [instance -> instruction [slot ]] = result ;
5048}
5149
52- static Word emulator_load (Emulator instance , Word * instruction , int slot )
50+ static Word emulator_load (Emulator instance , int slot )
5351{
5452 int denominator = 100 ;
5553
@@ -58,121 +56,132 @@ static Word emulator_load(Emulator instance, Word* instruction, int slot)
5856 denominator *= 10 ;
5957 }
6058
61- Word value = instruction [slot ];
59+ Word value = instance -> instruction [slot ];
6260
63- if ((* instruction / denominator ) % 10 == 0 )
61+ if ((* instance -> instruction / denominator ) % 10 == 0 )
6462 {
6563 return instance -> memory [value ];
6664 }
6765
6866 return value ;
6967}
7068
71- void emulator_execute (Emulator instance )
69+ bool emulator_execute (Emulator instance )
7270{
73- Word * instruction = instance -> memory ;
74-
7571 for (;;)
7672 {
77- Opcode opcode = * instruction % 100 ;
73+ Opcode opcode = * instance -> instruction % 100 ;
7874
7975 switch (opcode )
8076 {
8177 case OPCODE_ADD :
8278 {
83- Word a = emulator_load (instance , instruction , 1 );
84- Word b = emulator_load (instance , instruction , 2 );
79+ Word a = emulator_load (instance , 1 );
80+ Word b = emulator_load (instance , 2 );
8581
86- emulator_move (instance , instruction , a + b , 3 );
82+ emulator_move (instance , a + b , 3 );
8783
88- instruction += 4 ;
84+ instance -> instruction += 4 ;
8985 }
9086 break ;
9187
9288 case OPCODE_MULTIPLY :
9389 {
94- Word a = emulator_load (instance , instruction , 1 );
95- Word b = emulator_load (instance , instruction , 2 );
90+ Word a = emulator_load (instance , 1 );
91+ Word b = emulator_load (instance , 2 );
9692
97- emulator_move (instance , instruction , a * b , 3 );
93+ emulator_move (instance , a * b , 3 );
9894
99- instruction += 4 ;
95+ instance -> instruction += 4 ;
10096 }
10197 break ;
10298
10399 case OPCODE_INPUT :
104100 {
105101 Word input ;
106102
107- instance -> input (instance , & input );
108- emulator_move (instance , instruction , input , 1 );
103+ if (!instance -> input (instance , & input ))
104+ {
105+ return false;
106+ }
107+
108+ emulator_move (instance , input , 1 );
109109
110- instruction += 2 ;
110+ instance -> instruction += 2 ;
111111 }
112112 break ;
113113
114114 case OPCODE_OUTPUT :
115115 {
116- Word output = emulator_load (instance , instruction , 1 );
116+ Word output = emulator_load (instance , 1 );
117117
118118 instance -> output (instance , output );
119- instruction += 2 ;
119+ instance -> instruction += 2 ;
120120 }
121121 break ;
122122
123123 case OPCODE_JUMP_IF_TRUE :
124- if (emulator_load (instance , instruction , 1 ))
124+ if (emulator_load (instance , 1 ))
125125 {
126- Word label = emulator_load (instance , instruction , 2 );
126+ Word label = emulator_load (instance , 2 );
127127
128- instruction = instance -> memory + label ;
128+ instance -> instruction = instance -> memory + label ;
129129
130130 break ;
131131 }
132132
133- instruction += 3 ;
133+ instance -> instruction += 3 ;
134134 break ;
135135
136136 case OPCODE_JUMP_IF_FALSE :
137- if (!emulator_load (instance , instruction , 1 ))
137+ if (!emulator_load (instance , 1 ))
138138 {
139- Word label = emulator_load (instance , instruction , 2 );
139+ Word label = emulator_load (instance , 2 );
140140
141- instruction = instance -> memory + label ;
141+ instance -> instruction = instance -> memory + label ;
142142
143143 break ;
144144 }
145145
146- instruction += 3 ;
146+ instance -> instruction += 3 ;
147147 break ;
148148
149149 case OPCODE_LESS_THAN :
150150 {
151- Word a = emulator_load (instance , instruction , 1 );
152- Word b = emulator_load (instance , instruction , 2 );
151+ Word a = emulator_load (instance , 1 );
152+ Word b = emulator_load (instance , 2 );
153153
154- emulator_move (instance , instruction , a < b , 3 );
154+ emulator_move (instance , a < b , 3 );
155155
156- instruction += 4 ;
156+ instance -> instruction += 4 ;
157157 }
158158 break ;
159159
160160 case OPCODE_EQUALS :
161161 {
162- Word a = emulator_load (instance , instruction , 1 );
163- Word b = emulator_load (instance , instruction , 2 );
162+ Word a = emulator_load (instance , 1 );
163+ Word b = emulator_load (instance , 2 );
164164
165- emulator_move (instance , instruction , a == b , 3 );
165+ emulator_move (instance , a == b , 3 );
166166
167- instruction += 4 ;
167+ instance -> instruction += 4 ;
168168 }
169169 break ;
170170
171- case OPCODE_TERMINATE : return ;
171+ case OPCODE_TERMINATE : return true ;
172172 }
173173 }
174174}
175175
176+ void emulator_reimage (Emulator instance , Word image [], int imageSize )
177+ {
178+ instance -> instruction = instance -> memory ;
179+
180+ memcpy (instance -> memory , image , imageSize * sizeof (Word ));
181+ queue_clear (& instance -> inputs );
182+ queue_clear (& instance -> outputs );
183+ }
184+
176185void queue (Queue instance , Word buffer [], int capacity )
177186{
178187 instance -> items = buffer ;
@@ -225,3 +234,9 @@ bool queue_try_dequeue(Queue instance, Word* result)
225234
226235 return true;
227236}
237+
238+ void queue_clear (Queue instance )
239+ {
240+ instance -> first = -1 ;
241+ instance -> last = -1 ;
242+ }
0 commit comments