Browse code

add missing files

Nils Faerber authored on 19/03/2013 19:24:35
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,311 @@
1
+/*
2
+ *  EmbedVM - Embedded Virtual Machine for uC Applications
3
+ *
4
+ *  Copyright (C) 2011  Clifford Wolf <clifford@clifford.at>
5
+ *  
6
+ *  Permission to use, copy, modify, and/or distribute this software for any
7
+ *  purpose with or without fee is hereby granted, provided that the above
8
+ *  copyright notice and this permission notice appear in all copies.
9
+ *  
10
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
+ *
18
+ */
19
+
20
+#include "embedvm.h"
21
+
22
+static inline int16_t signext(uint16_t val, uint16_t mask)
23
+{
24
+	val = val & mask;
25
+	if ((val & ~(mask >> 1)) != 0)
26
+		val |= ~mask;
27
+	return val;
28
+}
29
+
30
+extern void embedvm_exec(struct embedvm_s *vm)
31
+{
32
+	uint8_t opcode = vm->mem_read(vm->ip, false, vm->user_ctx);
33
+	uint16_t addr = 0;
34
+	int16_t a = 0, b = 0;
35
+	int8_t sfa = 0;
36
+
37
+	switch (opcode)
38
+	{
39
+	case 0x00 ... 0x3f:
40
+		sfa = signext(opcode, 0x3f);
41
+		embedvm_push(vm, embedvm_local_read(vm, sfa));
42
+		vm->ip++;
43
+		break;
44
+	case 0x40 ... 0x7f:
45
+		sfa = signext(opcode, 0x3f);
46
+		embedvm_local_write(vm, sfa, embedvm_pop(vm));
47
+		vm->ip++;
48
+		break;
49
+	case 0x80+0 ... 0x80+11:
50
+	case 0xa8+0 ... 0xa8+5:
51
+		b = embedvm_pop(vm);
52
+	case 0x80+12 ... 0x80+14:
53
+		a = embedvm_pop(vm);
54
+		switch (opcode)
55
+		{
56
+			case 0x80 +  0: embedvm_push(vm, a + b);  break;
57
+			case 0x80 +  1: embedvm_push(vm, a - b);  break;
58
+			case 0x80 +  2: embedvm_push(vm, a * b);  break;
59
+			case 0x80 +  3: embedvm_push(vm, a / b);  break;
60
+			case 0x80 +  4: embedvm_push(vm, a % b);  break;
61
+			case 0x80 +  5: embedvm_push(vm, a << b); break;
62
+			case 0x80 +  6: embedvm_push(vm, a >> b); break;
63
+			case 0x80 +  7: embedvm_push(vm, a & b);  break;
64
+			case 0x80 +  8: embedvm_push(vm, a | b);  break;
65
+			case 0x80 +  9: embedvm_push(vm, a ^ b);  break;
66
+			case 0x80 + 10: embedvm_push(vm, a && b); break;
67
+			case 0x80 + 11: embedvm_push(vm, a || b); break;
68
+			case 0x80 + 12: embedvm_push(vm, ~a);     break;
69
+			case 0x80 + 13: embedvm_push(vm, -a);     break;
70
+			case 0x80 + 14: embedvm_push(vm, !a);     break;
71
+			case 0xa8 +  0: embedvm_push(vm, a <  b); break;
72
+			case 0xa8 +  1: embedvm_push(vm, a <= b); break;
73
+			case 0xa8 +  2: embedvm_push(vm, a == b); break;
74
+			case 0xa8 +  3: embedvm_push(vm, a != b); break;
75
+			case 0xa8 +  4: embedvm_push(vm, a >= b); break;
76
+			case 0xa8 +  5: embedvm_push(vm, a >  b); break;
77
+			
78
+		}
79
+		vm->ip++;
80
+		break;
81
+	case 0x90 ... 0x97:
82
+		a = signext(opcode, 0x07);
83
+		if ((a & 0x04) != 0)
84
+			a |= ~0x07;
85
+		embedvm_push(vm, a);
86
+		vm->ip++;
87
+		break;
88
+	case 0x98:
89
+		a = vm->mem_read(vm->ip+1, false, vm->user_ctx) & 0x00ff;
90
+		embedvm_push(vm, a);
91
+		vm->ip += 2;
92
+		break;
93
+	case 0x99:
94
+		a = vm->mem_read(vm->ip+1, false, vm->user_ctx) & 0x00ff;
95
+		embedvm_push(vm, signext(a, 0x00ff));
96
+		vm->ip += 2;
97
+		break;
98
+	case 0x9a:
99
+		a = vm->mem_read(vm->ip+1, true, vm->user_ctx);
100
+		embedvm_push(vm, a);
101
+		vm->ip += 3;
102
+		break;
103
+	case 0x9b:
104
+		a = embedvm_pop(vm);
105
+		if (0) {
106
+	case 0x9c:
107
+			a = 0;
108
+		}
109
+		vm->sp = vm->sfp;
110
+		vm->ip = embedvm_pop(vm);
111
+		vm->sfp = embedvm_pop(vm);
112
+		if ((vm->sfp & 1) != 0)
113
+			vm->sfp &= ~1;
114
+		else
115
+			embedvm_push(vm, a);
116
+		break;
117
+	case 0x9d:
118
+		embedvm_pop(vm);
119
+		vm->ip++;
120
+		break;
121
+	case 0x9e:
122
+		addr = embedvm_pop(vm);
123
+		if (vm->mem_read(vm->ip+1, false, vm->user_ctx) == 0x9d) {
124
+			embedvm_push(vm, vm->sfp | 1);
125
+			embedvm_push(vm, vm->ip + 2);
126
+		} else {
127
+			embedvm_push(vm, vm->sfp);
128
+			embedvm_push(vm, vm->ip + 1);
129
+		}
130
+		vm->sfp = vm->sp;
131
+		vm->ip = addr;
132
+		break;
133
+	case 0x9f:
134
+		vm->ip = embedvm_pop(vm);
135
+		break;
136
+	case 0xa0 ... 0xa0+7:
137
+		if ((opcode & 1) == 0) {
138
+			addr = vm->ip + signext(vm->mem_read(vm->ip+1, false, vm->user_ctx), 0x00ff);
139
+			vm->ip += 2;
140
+		} else {
141
+			addr = vm->ip + vm->mem_read(vm->ip+1, true, vm->user_ctx);
142
+			vm->ip += 3;
143
+		}
144
+		switch (opcode)
145
+		{
146
+		case 0xa0:
147
+		case 0xa1:
148
+			vm->ip = addr;
149
+			break;
150
+		case 0xa2:
151
+		case 0xa3:
152
+			if (vm->mem_read(vm->ip, false, vm->user_ctx) == 0x9d) {
153
+				embedvm_push(vm, vm->sfp | 1);
154
+				embedvm_push(vm, vm->ip + 1);
155
+			} else {
156
+				embedvm_push(vm, vm->sfp);
157
+				embedvm_push(vm, vm->ip);
158
+			}
159
+			vm->sfp = vm->sp;
160
+			vm->ip = addr;
161
+			break;
162
+		case 0xa4:
163
+		case 0xa5:
164
+			if (embedvm_pop(vm))
165
+				vm->ip = addr;
166
+			break;
167
+		case 0xa6:
168
+		case 0xa7:
169
+			if (!embedvm_pop(vm))
170
+				vm->ip = addr;
171
+			break;
172
+		}
173
+		break;
174
+	case 0xae:
175
+		embedvm_push(vm, vm->sp);
176
+		vm->ip++;
177
+		break;
178
+	case 0xaf:
179
+		embedvm_push(vm, vm->sfp);
180
+		vm->ip++;
181
+		break;
182
+	case 0xb0 ... 0xb0+15:
183
+		{
184
+			uint8_t argc = embedvm_pop(vm);
185
+			int16_t argv[argc];
186
+			for (sfa=0; sfa<argc; sfa++)
187
+				argv[sfa] = embedvm_pop(vm);
188
+			a = vm->call_user(opcode - 0xb0, argc, argv, vm->user_ctx);
189
+			embedvm_push(vm, a);
190
+		}
191
+		vm->ip++;
192
+		break;
193
+	case 0xc0 ... 0xef:
194
+		if ((opcode & 0x07) == 5) {
195
+			/* this is a "bury" instruction */
196
+			uint8_t depth = (opcode >> 3) & 0x07;
197
+			int16_t stack[depth+1];
198
+			for (sfa = 0; sfa <= depth; sfa++)
199
+				stack[sfa] = embedvm_pop(vm);
200
+			embedvm_push(vm, stack[0]);
201
+			for (sfa = depth; sfa > 0; sfa--)
202
+				embedvm_push(vm, stack[sfa]);
203
+			embedvm_push(vm, stack[0]);
204
+			vm->ip++;
205
+			break;
206
+		}
207
+		if ((opcode & 0x07) == 6) {
208
+			/* this is a "dig" instruction */
209
+			uint8_t depth = (opcode >> 3) & 0x07;
210
+			int16_t stack[depth+2];
211
+			for (sfa = 0; sfa < depth+2; sfa++)
212
+				stack[sfa] = embedvm_pop(vm);
213
+			for (sfa = depth+1; sfa > 0; sfa--)
214
+				embedvm_push(vm, stack[sfa-1]);
215
+			embedvm_push(vm, stack[depth+1]);
216
+			vm->ip++;
217
+			break;
218
+		}
219
+		sfa = ((opcode >> 3) & 0x07) == 4 || ((opcode >> 3) & 0x07) == 5 ? 1 : 0;
220
+		switch (opcode & 0x07)
221
+		{
222
+		case 0:
223
+			addr = vm->mem_read(vm->ip+1, false, vm->user_ctx) & 0x00ff;
224
+			vm->ip += 2;
225
+			break;
226
+		case 1:
227
+			addr = vm->mem_read(vm->ip+1, true, vm->user_ctx);
228
+			vm->ip += 3;
229
+			break;
230
+		case 2:
231
+			addr = embedvm_pop(vm);
232
+			vm->ip++;
233
+			break;
234
+		case 3:
235
+			addr = (embedvm_pop(vm) << sfa) + (vm->mem_read(vm->ip+1, false, vm->user_ctx) & 0x00ff);
236
+			vm->ip += 2;
237
+			break;
238
+		case 4:
239
+			addr = (embedvm_pop(vm) << sfa) + vm->mem_read(vm->ip+1, true, vm->user_ctx);
240
+			vm->ip += 3;
241
+			break;
242
+		}
243
+		switch ((opcode >> 3) & 0x07)
244
+		{
245
+		case 0:
246
+			embedvm_push(vm, vm->mem_read(addr, false, vm->user_ctx) & 0x00ff);
247
+			break;
248
+		case 1:
249
+			vm->mem_write(addr, embedvm_pop(vm), false, vm->user_ctx);
250
+			break;
251
+		case 2:
252
+			embedvm_push(vm, signext(vm->mem_read(addr, false, vm->user_ctx), 0x00ff));
253
+			break;
254
+		case 3:
255
+			vm->mem_write(addr, embedvm_pop(vm), false, vm->user_ctx);
256
+			break;
257
+		case 4:
258
+			embedvm_push(vm, vm->mem_read(addr, true, vm->user_ctx));
259
+			break;
260
+		case 5:
261
+			vm->mem_write(addr, embedvm_pop(vm), true, vm->user_ctx);
262
+			break;
263
+		}
264
+		break;
265
+	case 0xf0 ... 0xf7:
266
+		for (sfa = 0; sfa <= (opcode & 0x07); sfa++)
267
+			embedvm_push(vm, 0);
268
+		vm->ip++;
269
+		break;
270
+	case 0xf8 ... 0xff:
271
+		a = embedvm_pop(vm);
272
+		vm->sp += 2 + 2*(opcode & 0x07);
273
+		embedvm_push(vm, a);
274
+		vm->ip++;
275
+		break;
276
+	}
277
+}
278
+
279
+void embedvm_interrupt(struct embedvm_s *vm, uint16_t addr)
280
+{
281
+	embedvm_push(vm, vm->sfp | 1);
282
+	embedvm_push(vm, vm->ip);
283
+	vm->sfp = vm->sp;
284
+	vm->ip = addr;
285
+}
286
+
287
+int16_t embedvm_pop(struct embedvm_s *vm)
288
+{
289
+	int16_t value = vm->mem_read(vm->sp, true, vm->user_ctx);
290
+	vm->sp += 2;
291
+	return value;
292
+}
293
+
294
+void embedvm_push(struct embedvm_s *vm, int16_t value)
295
+{
296
+	vm->sp -= 2;
297
+	vm->mem_write(vm->sp, value, true, vm->user_ctx);
298
+}
299
+
300
+int16_t embedvm_local_read(struct embedvm_s *vm, int8_t sfa)
301
+{
302
+	uint16_t addr = vm->sfp - 2*sfa + (sfa < 0 ? +2 : -2);
303
+	return vm->mem_read(addr, true, vm->user_ctx);
304
+}
305
+
306
+void embedvm_local_write(struct embedvm_s *vm, int8_t sfa, int16_t value)
307
+{
308
+	uint16_t addr = vm->sfp - 2*sfa + (sfa < 0 ? +2 : -2);
309
+	vm->mem_write(addr, value, true, vm->user_ctx);
310
+}
311
+