agileRTOS (zrtos)  Version 0.8.0 (ghostbuster)
vm.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 ykat UG (haftungsbeschraenkt) - All Rights Reserved
3  *
4  * Permission for non-commercial use is hereby granted,
5  * free of charge, without warranty of any kind.
6  */
7 #ifndef ZRTOS_VM_H
8 #define ZRTOS_VM_H
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 
14 #include <zrtos/types.h>
15 #include <zrtos/error.h>
16 #include <zrtos/stack.h>
17 #include <zrtos/mem.h>
18 #include <zrtos/assert.h>
19 
20 struct _zrtos_vm_t;
21 
22 #include <zrtos/vm_io.h>
24 
25 
26 typedef enum{
28 
42 
45 
50 
56 
63 
65 
69 
71 
73 
76 
77 ZRTOS_ASSERT__STATIC(sizeof(zrtos_vm_op_t) == sizeof(uint8_t));
78 
79 typedef struct _zrtos_vm_t{
84 }zrtos_vm_t;
85 
87  zrtos_vm_t *thiz
91 ){
92  thiz->stack = stack;
93  thiz->program = program;
94  thiz->functions = functions;
95  thiz->is_interrupted = false;
96 
97  return true;
98 }
99 
100 typedef struct _zrtos_vm_value_t{
101  union{
103  uint16_t v_u16;
104  uint32_t v_u32;
105  uint64_t v_u64;
106 
107  int8_t v_s8;
108  int16_t v_s16;
109  int32_t v_s32;
110  int64_t v_s64;
111 
112  float v_f32;
113  double v_f64;
114  }value;
118 
120  switch(thiz->type){
122  thiz->value.v_s64 = (int64_t)thiz->value.v_s8;
123  break;
125  thiz->value.v_s64 = (int64_t)thiz->value.v_s16;
126  break;
128  thiz->value.v_s64 = (int64_t)thiz->value.v_s32;
129  break;
137  break;
138  }
139 }
140 
141 typedef struct{
144 }__attribute__((packed))zrtos_vm_ioop_t;
145 
149  &thiz->functions
150  ,id
151  );
152  if(fn){
154  thiz
155  ,fn
156  );
157  }
158  return ret;
159 }
160 
161 
162 #define ZRTOS_VM_OP_WITHOUT_FLOAT(op)\
163  case ZRTOS_VM_IO_TYPE__INT8:\
164  a.value.v_s8 = a.value.v_s8 op b.value.v_s8;\
165  break;\
166  case ZRTOS_VM_IO_TYPE__INT16:\
167  a.value.v_s16 = a.value.v_s16 op b.value.v_s16;\
168  break;\
169  case ZRTOS_VM_IO_TYPE__INT32:\
170  a.value.v_s32 = a.value.v_s32 op b.value.v_s32;\
171  break;\
172  case ZRTOS_VM_IO_TYPE__INT64:\
173  a.value.v_s64 = a.value.v_s64 op b.value.v_s64;\
174  break;\
175  case ZRTOS_VM_IO_TYPE__UINT8:\
176  a.value.v_u8 = a.value.v_u8 op b.value.v_u8;\
177  break;\
178  case ZRTOS_VM_IO_TYPE__UINT16:\
179  a.value.v_u16 = a.value.v_u16 op b.value.v_u16;\
180  break;\
181  case ZRTOS_VM_IO_TYPE__UINT32:\
182  a.value.v_u32 = a.value.v_u32 op b.value.v_u32;\
183  break;\
184  case ZRTOS_VM_IO_TYPE__UINT64:\
185  a.value.v_u64 = a.value.v_u64 op b.value.v_u64;\
186  break;
187 
188 #define ZRTOS_VM_OP(op)\
189  ZRTOS_VM_OP_WITHOUT_FLOAT(op)\
190  case ZRTOS_VM_IO_TYPE__FLOAT:\
191  a.value.v_f32 = a.value.v_f32 op b.value.v_f32;\
192  break;\
193  case ZRTOS_VM_IO_TYPE__DOUBLE:\
194  a.value.v_f64 = a.value.v_f64 op b.value.v_f64;\
195  break;
196 
197 #define ZRTOS_VM_OP_NOT(op)\
198  case ZRTOS_VM_IO_TYPE__FLOAT:\
199  a.value.v_f32 = op a.value.v_f32;\
200  break;\
201  case ZRTOS_VM_IO_TYPE__DOUBLE:\
202  a.value.v_f64 = op a.value.v_f64;\
203  break;\
204  case ZRTOS_VM_IO_TYPE__INT8:\
205  case ZRTOS_VM_IO_TYPE__INT16:\
206  case ZRTOS_VM_IO_TYPE__INT32:\
207  case ZRTOS_VM_IO_TYPE__INT64:\
208  case ZRTOS_VM_IO_TYPE__UINT8:\
209  case ZRTOS_VM_IO_TYPE__UINT16:\
210  case ZRTOS_VM_IO_TYPE__UINT32:\
211  case ZRTOS_VM_IO_TYPE__UINT64:\
212  a.value.v_u64 = op a.value.v_u64;\
213  break;
214 
215 #define ZRTOS_VM_OP_BOOLEAN(op)\
216  case ZRTOS_VM_IO_TYPE__INT8:\
217  case ZRTOS_VM_IO_TYPE__INT16:\
218  case ZRTOS_VM_IO_TYPE__INT32:\
219  case ZRTOS_VM_IO_TYPE__INT64:\
220  a.value.v_u8 = a.value.v_s64 op b.value.v_s64;\
221  break;\
222  case ZRTOS_VM_IO_TYPE__UINT8:\
223  case ZRTOS_VM_IO_TYPE__UINT16:\
224  case ZRTOS_VM_IO_TYPE__UINT32:\
225  case ZRTOS_VM_IO_TYPE__UINT64:\
226  a.value.v_u8 = a.value.v_u64 op b.value.v_u64;\
227  break;\
228  case ZRTOS_VM_IO_TYPE__FLOAT:\
229  a.value.v_u8 = a.value.v_f32 op b.value.v_f32;\
230  break;\
231  case ZRTOS_VM_IO_TYPE__DOUBLE:\
232  a.value.v_u8 = a.value.v_f64 op b.value.v_f64;\
233  break;
234 
235 
237  zrtos_stack_t *stack = &thiz->stack;
238  zrtos_stack_t *program = &thiz->program;
239  zrtos_stack_t *set_offset_stack;
243  zrtos_vm_io_type_t io_type;
244  zrtos_vm_io_source_t io_src;
245  size_t length;
246  zrtos_vm_ioop_t ioop;
247  zrtos_vm_value_t *dest;
248 
249  while(!thiz->is_interrupted
250  && zrtos_stack__shift(program,&ioop,2)
251  ){
252  io_type = (ioop.io & ZRTOS_VM_IO_TYPE__MASK);
253  io_src = (ioop.io & ZRTOS_VM_IO_SOURCE__MASK);
254  length = zrtos_vm_io_type__get_length(io_type);
255 
256  zrtos_mem__zero(&a.value,sizeof(a.value));
257  zrtos_mem__zero(&b.value,sizeof(b.value));
258 
259  a.type = b.type = io_type;
260 
261  //input
262  dest = &a;
263  while((io_src & ZRTOS_VM_IO_SOURCE__MASK)){
264  if((io_src & ZRTOS_VM_IO_SOURCE__A_PROGRAM) > 0){
265  if(!zrtos_stack__shift(program,&dest->value,length)){
266  goto L_RETURN__EFAULT;
267  }
268  }else if((io_src & ZRTOS_VM_IO_SOURCE__A_STACK) > 0){
269  if(!zrtos_stack__pop(stack,&dest->value,length)){
270  goto L_RETURN__EFAULT;
271  }
272  }else if((io_src & ZRTOS_VM_IO_SOURCE__A_ADDRESS) > 0){
274  &dest->address.address
275  ,sizeof(dest->address.address)
276  );
277  if(zrtos_stack__shift(program,&dest->address.type,1)
279  program
280  ,&dest->address.address
282  )
285  ? program
286  : stack)
287  ,&dest->value
288  ,length
292  )){
293  goto L_INPUT_NORMALIZE;
294  }
295  goto L_RETURN__EFAULT;
296  }else{
297  goto L_INPUT__NEXT;
298  }
299 
300 
301 
302 L_INPUT_NORMALIZE:
304 L_INPUT__NEXT:
305  dest = &b;
306  ///@todo shift left
307  io_src >>= 2;
308  }
309 
310  //process
311  switch(ioop.op){
317  a.value.v_s64 = (int64_t)a.value.v_u64;
318  }else if(zrtos_vm_io_type__is_float(a.type)){
319  a.value.v_s64 = (int64_t)a.value.v_f32;
320  }else if(zrtos_vm_io_type__is_double(a.type)){
321  a.value.v_s64 = (int64_t)a.value.v_f64;
322  }else{//} if(zrtos_vm_io_type__is_int(a.type)){
323 
324  }
325  goto L_OUTPUT__CAST;
331 
332  }else if(zrtos_vm_io_type__is_float(a.type)){
333  a.value.v_u64 = (uint64_t)a.value.v_f32;
334  }else if(zrtos_vm_io_type__is_double(a.type)){
335  a.value.v_u64 = (uint64_t)a.value.v_f64;
336  }else{//} if(zrtos_vm_io_type__is_int(a.type)){
337  a.value.v_u64 = (uint64_t)a.value.v_s64;
338  }
339  goto L_OUTPUT__CAST;
342  a.value.v_f32 = (float)a.value.v_u64;
343  }else if(zrtos_vm_io_type__is_float(a.type)){
344 
345  }else if(zrtos_vm_io_type__is_double(a.type)){
346  a.value.v_f32 = (float)a.value.v_f64;
347  }else{//} if(zrtos_vm_io_type__is_int(a.type)){
348  a.value.v_f32 = (float)a.value.v_s64;
349  }
350  goto L_OUTPUT__CAST;
353  a.value.v_f64 = (double)a.value.v_u64;
354  }else if(zrtos_vm_io_type__is_float(a.type)){
355  a.value.v_f64 = (double)a.value.v_f32;
356  }else if(zrtos_vm_io_type__is_double(a.type)){
357 
358  }else{//} if(zrtos_vm_io_type__is_int(a.type)){
359  a.value.v_f64 = (double)a.value.v_s64;
360  }
361  goto L_OUTPUT__CAST;
362 
363  case ZRTOS_VM_OP__PUSH:
364  goto L_OUTPUT__PUSH_TYPE;
365  case ZRTOS_VM_OP__POP:
366  goto L_OUTPUT__END;
367 
368 
369 
370  case ZRTOS_VM_OP__AND:
371  a.value.v_u64 &= b.value.v_u64;
372  goto L_OUTPUT__PUSH_TYPE;
373  case ZRTOS_VM_OP__OR:
374  a.value.v_u64 |= b.value.v_u64;
375  goto L_OUTPUT__PUSH_TYPE;
376  case ZRTOS_VM_OP__XOR:
377  a.value.v_u64 ^= b.value.v_u64;
378  goto L_OUTPUT__PUSH_TYPE;
379  case ZRTOS_VM_OP__NEG:
380  a.value.v_u64 = ~a.value.v_u64;
381  goto L_OUTPUT__PUSH_TYPE;
382 
383  case ZRTOS_VM_OP__ADD:
384  switch(io_type){
385  ZRTOS_VM_OP(+)
386  }
387  goto L_OUTPUT__PUSH_TYPE;
388  case ZRTOS_VM_OP__SUB:
389  switch(io_type){
390  ZRTOS_VM_OP(-)
391  }
392  goto L_OUTPUT__PUSH_TYPE;
393  case ZRTOS_VM_OP__MUL:
394  switch(io_type){
395  ZRTOS_VM_OP(*)
396  }
397  goto L_OUTPUT__PUSH_TYPE;
398  case ZRTOS_VM_OP__DIV:
399  switch(io_type){
400  ZRTOS_VM_OP(/)
401  }
402  goto L_OUTPUT__PUSH_TYPE;
403  case ZRTOS_VM_OP__MOD:
404  switch(io_type){
408  goto L_RETURN__EINVAL;
409  }
410  goto L_OUTPUT__PUSH_TYPE;
411 
412  case ZRTOS_VM_OP__NOT:
413  switch(io_type){
414  ZRTOS_VM_OP_NOT(!)
415  }
416  goto L_OUTPUT__PUSH_BOOL;
417  case ZRTOS_VM_OP__EQ:
418  switch(io_type){
420  }
421  goto L_OUTPUT__PUSH_BOOL;
422  case ZRTOS_VM_OP__LT:
423  switch(io_type){
425  }
426  goto L_OUTPUT__PUSH_BOOL;
427  case ZRTOS_VM_OP__GT:
428  switch(io_type){
430  }
431  goto L_OUTPUT__PUSH_BOOL;
432  case ZRTOS_VM_OP__LE:
433  switch(io_type){
435  }
436  goto L_OUTPUT__PUSH_BOOL;
437  case ZRTOS_VM_OP__GE:
438  switch(io_type){
440  }
441  goto L_OUTPUT__PUSH_BOOL;
442 
443 
444  case ZRTOS_VM_OP__IF:
445  if(b.value.v_u8 == 0){
446  goto L_OUTPUT__SET_PROGRAM_OFFSET;
447  }
448  goto L_OUTPUT__END;
449 
450  case ZRTOS_VM_OP__ICALL:
451  ret = zrtos_vm__icall(thiz,a.value.v_u64);
452  if(ret != 0){
453  goto L_RETURN__END;
454  }
455  goto L_OUTPUT__END;
456 
457  case ZRTOS_VM_OP__CALL:
458  case ZRTOS_VM_OP__RET:
459  goto L_OUTPUT__SET_PROGRAM_OFFSET;
460 
461  case ZRTOS_VM_OP__SET_SP:
462  goto L_OUTPUT__SET_STACK_OFFSET;
463 
464  case ZRTOS_VM_OP__NOP:
465  goto L_OUTPUT__END;
466  }
467 
468  goto L_OUTPUT__END;
469 
470  //output
471 L_OUTPUT__CAST:
472  a.type = ioop.op - ZRTOS_VM_OP__CAST;
473  goto L_OUTPUT__PUSH_TYPE;
474 L_OUTPUT__PUSH_BOOL:
476 L_OUTPUT__PUSH_TYPE:
477  if((io_src & ZRTOS_VM_IO_SOURCE__A_ADDRESS) > 0){
479  stack
480  ,&a.value
485  )){
486  goto L_OUTPUT__END;
487  }
488  }else if(zrtos_stack__push(
489  stack
490  ,&a.value
492  )){
493  goto L_OUTPUT__END;
494  }
495  goto L_RETURN__EFAULT;
496 L_OUTPUT__SET_PROGRAM_OFFSET:
497  set_offset_stack = program;
498  goto L_OUTPUT__SET_OFFSET;
499 L_OUTPUT__SET_STACK_OFFSET:
500  set_offset_stack = stack;
501 L_OUTPUT__SET_OFFSET:
503  set_offset_stack
504  ,a.value.v_u64 >> 2
505  ,(a.value.v_u64 & 0x1) > 0
506  ,(a.value.v_u64 & 0x2) > 0
507  )){
508  goto L_RETURN__EFAULT;
509  }
510  goto L_OUTPUT__END;
511 L_OUTPUT__END:
512  continue;
513  }
514 
515 L_RETURN__EINVAL:
516  ret = ZRTOS_ERROR__INVAL;
517  goto L_RETURN__END;
518 L_RETURN__EFAULT:
519  ret = ZRTOS_ERROR__FAULT;
520  goto L_RETURN__END;
521 L_RETURN__END:
522  return ret;
523 }
524 
525 #undef ZRTOS_VM_OP_WITHOUT_FLOAT
526 #undef ZRTOS_VM_OP
527 #undef ZRTOS_VM_OP_NOT
528 #undef ZRTOS_VM_OP_BOOLEAN
529 
530 
531 #ifdef __cplusplus
532 }
533 #endif
534 #endif
zrtos_vm_op_t op
Definition: vm.h:143
int64_t v_s64
Definition: vm.h:110
void zrtos_vm_value__normalize(zrtos_vm_value_t *thiz)
Definition: vm.h:119
uint16_t v_u16
Definition: vm.h:103
struct _zrtos_vm_t zrtos_vm_t
size_t zrtos_vm_io_address__get_address(zrtos_vm_io_address_t *thiz)
Definition: vm_io.h:106
bool zrtos_vm_io_address__is_negative(zrtos_vm_io_address_t *thiz)
Definition: vm_io.h:110
zrtos_vm_function_index_t functions
Definition: vm.h:82
zrtos_vm_io_address_t address
Definition: vm.h:116
int16_t v_s16
Definition: vm.h:108
#define ZRTOS_VM_OP(op)
Definition: vm.h:188
bool is_interrupted
Definition: vm.h:83
int32_t v_s32
Definition: vm.h:109
zrtos_error_t zrtos_vm__icall(zrtos_vm_t *thiz, zrtos_vm_function_id_t id)
Definition: vm.h:146
void zrtos_mem__zero(void *dest, size_t len)
Definition: mem.h:144
bool zrtos_vm_io_type__is_double(zrtos_vm_io_type_t type)
Definition: vm_io.h:64
#define ZRTOS_VM_OP_WITHOUT_FLOAT(op)
Definition: vm.h:162
bool zrtos_vm__init(zrtos_vm_t *thiz, zrtos_stack_t stack, zrtos_stack_t program, zrtos_vm_function_index_t functions)
Definition: vm.h:86
zrtos_vm_function_callback_t zrtos_vm_function__get_callback(zrtos_vm_function_t *thiz)
Definition: vm_function.h:44
int8_t v_s8
Definition: vm.h:107
#define ZRTOS_VM_OP_NOT(op)
Definition: vm.h:197
bool zrtos_stack__push(zrtos_stack_t *thiz, void *data, size_t length)
Definition: stack.h:179
size_t zrtos_vm_io_type__get_length(zrtos_vm_io_type_t type)
Definition: vm_io.h:68
float v_f32
Definition: vm.h:112
zrtos_vm_io_type_t type
Definition: vm.h:115
uint8_t io
Definition: vm.h:142
zrtos_vm_io_address_type_t type
Definition: vm_io.h:101
double v_f64
Definition: vm.h:113
bool zrtos_stack__read_ex(zrtos_stack_t *thiz, void *data, size_t length, size_t offset, bool is_relative, bool is_negative)
Definition: stack.h:115
zrtos_vm_op_t
Definition: vm.h:26
Definition: vm.h:79
ZRTOS_ASSERT__STATIC(sizeof(zrtos_vm_op_t)==sizeof(uint8_t))
uint64_t v_u64
Definition: vm.h:105
bool zrtos_vm_io_type__is_uint(zrtos_vm_io_type_t type)
Definition: vm_io.h:47
bool zrtos_stack__pop(zrtos_stack_t *thiz, void *data, size_t length)
Definition: stack.h:201
uint32_t v_u32
Definition: vm.h:104
union _zrtos_vm_value_t::@0 value
zrtos_error_t zrtos_vm__run(zrtos_vm_t *thiz)
Definition: vm.h:236
Successful program execution status.
Definition: error.h:22
Bad address.
Definition: error.h:38
Invalid argument.
Definition: error.h:46
zrtos_stack_t stack
Definition: vm.h:80
uint8_t v_u8
Definition: vm.h:102
size_t zrtos_vm_function_id_t
Definition: vm_function.h:17
struct _zrtos_vm_value_t zrtos_vm_value_t
zrtos_stack_t program
Definition: vm.h:81
#define ZRTOS_VM_OP_BOOLEAN(op)
Definition: vm.h:215
bool zrtos_stack__shift(zrtos_stack_t *thiz, void *data, size_t length)
Definition: stack.h:222
zrtos_vm_function_t * zrtos_vm_function_index__get_function(zrtos_vm_function_index_t *thiz, zrtos_vm_function_id_t id)
static uint8_t
Definition: mcp2515.h:159
bool zrtos_vm_io_address__is_relative(zrtos_vm_io_address_t *thiz)
Definition: vm_io.h:114
zrtos_vm_io_source_t
Definition: vm_io.h:17
bool zrtos_vm_io_address__is_source_program(zrtos_vm_io_address_t *thiz)
Definition: vm_io.h:122
zrtos_error_t
Definition: error.h:20
size_t zrtos_vm_io_address__get_length(zrtos_vm_io_address_t *thiz)
Definition: vm_io.h:118
bool zrtos_stack__set_offset_ex(zrtos_stack_t *thiz, size_t offset, bool is_relative, bool is_negative)
Definition: stack.h:82
bool zrtos_vm_io_type__is_float(zrtos_vm_io_type_t type)
Definition: vm_io.h:60
bool zrtos_stack__write_ex(zrtos_stack_t *thiz, void *data, size_t length, size_t offset, bool is_relative, bool is_negative)
Definition: stack.h:156
zrtos_vm_io_type_t
Definition: vm_io.h:29