aboutsummaryrefslogtreecommitdiff
path: root/lib/dis.h
blob: 9a87064cf40563692be6d0c49384229b19510298 (plain) (blame)
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