1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
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
110
111
112
113
114
115
116
117
118
|
#include <stdint.h>
#include <stdlib.h>
#include "panic.h"
#include "slice.h"
#include "value.h"
#include "encoding.h"
struct reader {
struct slice data;
int n;
};
static void advance(struct reader *r, int size)
{
r->data = slice1(r->data, size);
r->n += size;
}
static uint8_t parse_byte(struct reader *r)
{
if (r->data.size < 1) {
panicf("read byte: no data!\n");
}
uint8_t res = r->data.buf[0];
advance(r, 1);
return res;
}
static local parse_local(struct reader *r)
{
if (r->data.size < 1) {
panicf("local: no data!\n");
}
local res = r->data.buf[0];
if (res >= NUM_LOCALS) {
panicf("Invalid local (out of range): %d\n", res);
}
advance(r, 1);
return res;
}
static value parse_value(struct reader *r)
{
if (r->data.size < 8) {
panicf("value: no data!\n");
}
uint64_t res = *(uint64_t *) r->data.buf;
advance(r, 8);
return res;
}
static struct arg parse_arg(struct reader *r, bool is_const)
{
if (is_const) {
return (struct arg) { .constant = parse_value(r) };
}
return (struct arg) { .local = parse_local(r) };
}
static uint8_t parse_offset(struct reader *r)
{
if (r->data.size < 1) {
panicf("offset: no data!\n");
}
uint8_t res = r->data.buf[0];
advance(r, 1);
return res;
}
struct result parse(struct slice data)
{
struct reader r = { .data = data, .n = 0 };
uint8_t codeByte = parse_byte(&r);
enum opcode code = codeByte >> 2;
bool arg1_const = codeByte & 0x2;
// bool arg2_const = codeByte & 0x1;
struct op out = {
.code = code,
};
switch (code) {
case OALLOC:
out.alloc.out = parse_local(&r);
out.alloc.size = parse_arg(&r, arg1_const);
break;
case OCALL:
// No arguments.
break;
case OPOKE:
out.poke.offset = parse_offset(&r);
out.poke.pointer = parse_local(&r);
out.poke.value = parse_arg(&r, arg1_const);
break;
case OPEEK:
out.peek.out = parse_local(&r);
out.peek.offset = parse_offset(&r);
out.peek.value = parse_arg(&r, arg1_const);
break;
case OSHUF:
out.shuf.out = parse_local(&r);
out.shuf.value = parse_arg(&r, arg1_const);
break;
case OEXIT:
out.exit.value = parse_arg(&r, arg1_const);
break;
default:
panicf("Invalid code %d\n", code);
}
return (struct result) {
.op = out,
.n = r.n,
};
}
|