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
|
#pragma once
#include <stdbool.h>
#include <stdint.h>
#define UNUSED __attribute__((unused))
#define INLINE __attribute__((always_inline)) inline
#ifdef __cplusplus
#define CONSTEXPR constexpr
#else
#define CONSTEXPR
#endif
struct bitslice_run {
int8_t inpos, outpos, len;
};
struct bitslice {
int8_t nruns;
struct bitslice_run runs[6];
};
struct dis_data_operand {
bool out;
const struct bitslice *n;
};
static inline CONSTEXPR int sext(unsigned val, int bits) {
return val & (1 << (bits - 1)) ? ((int)val - (1 << bits)) : (int)val;
}
static inline CONSTEXPR unsigned bs_get(const struct bitslice *bs, unsigned op) {
unsigned ret = 0;
for(int i = 0; i < bs->nruns; i++) {
const struct bitslice_run *run = &bs->runs[i];
unsigned val = (op >> run->inpos) & ((1 << run->len) - 1);
ret |= val << run->outpos;
}
return ret;
}
static inline CONSTEXPR unsigned bs_set(const struct bitslice *bs, unsigned new_, unsigned op) {
for(int i = 0; i < bs->nruns; i++) {
const struct bitslice_run *run = &bs->runs[i];
unsigned mask = (1 << run->len) - 1;
unsigned val = (new_ >> run->outpos) & mask;
op = (op & ~(mask << run->inpos)) | (val << run->inpos);
}
return op;
}
static inline CONSTEXPR struct bitslice bs_slice(const struct bitslice *bs, int lo, int size) {
struct bitslice obs
#ifdef __cplusplus
{}
#endif
;
obs.nruns = 0;
for(int i = 0; i < bs->nruns; i++) {
struct bitslice_run inr = bs->runs[i];
inr.outpos -= lo;
if(inr.outpos < 0) {
inr.len += inr.outpos;
inr.inpos -= inr.outpos;
inr.outpos = 0;
}
if(inr.outpos + inr.len > size)
inr.len = size - inr.outpos;
if(inr.len > 0)
obs.runs[obs.nruns++] = inr;
}
return obs;
}
#ifdef __cplusplus
#define staticify(ty, ...) [&](){ constexpr static ty bs = __VA_ARGS__; return &bs; }()
#define r(nn) staticify(struct dis_data_operand, {.n = nn, .out = false})
#define rs(nn, l, s) staticify(struct dis_data_operand, {.n = staticify(struct bitslice, bs_slice(nn, l, s)), .out = false})
#define rout(nn) staticify(struct dis_data_operand, {.n = nn, .out = true})
#define rsout(nn, l, s) staticify(struct dis_data_operand, {.n = staticify(struct bitslice, bs_slice(nn, l, s)), .out = true})
#define data(...) return P(data)<__VA_ARGS__>(ctx);
typedef const struct bitslice *BSP;
#endif
|