-
Notifications
You must be signed in to change notification settings - Fork 0
/
prelude.ursl
95 lines (78 loc) · 2.86 KB
/
prelude.ursl
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
// __unary__, __binary__ and __branching__ are internal unstable syntax!
//
// __unary__ is used to declare two overloads of:
//
// &a -> &a
// <&a> -> &out
//
// __binary__ is used to declare three overloads of:
//
// &a <&b> -> &a
// <&a> &b -> &b
// <&a> <&b> -> &out
//
// __branching__ does the same as __binary__ but provides a branch <&a> <&b> -> :dest overload as well
//
// the reason these overloads are necessary is so that certain combinations of aliased allocations and
// stack items containing literals can be optimized to a single instruction without needing to emit redundant MOVs.
//
// these specific overloads are a very common pattern for custom instructions, used for almost everything
// here in the prelude, hence the shorthand syntax. they can't be the default behaviour, because more
// complex translations like repeated addition for `mult` cannot fit all these overloads at once.
//
// the absence or presence of these overloads are not visible at all to user code.
// they do absolutely nothing other than optimize code size/speed slightly.
// that is why this syntax doesn't need to be officially documented in the README.
//
// honestly i'll probably keep this syntax for a while, if not forever, but please do not use it as
// it is purely intended for my own use in this file to reduce repetitive code.
// especially if you're writing tooling that autogenerates instructions
// please generate overloads and not the internal syntax!
inst nop [] -> []
inst pop [a] -> []
inst dup [a] -> [a a]
inst swap [a b] -> [b a]
inst over [a b] -> [a b a]
inst null -> $0 {}
__unary__ load -> LOD;
inst store <&out> <&src> { STR &out &src }
inst copy <&out> <&src> { CPY &out &src }
__unary__ bool -> SETNZ;
__unary__ not -> NOT;
branch bool <&src> -> :dest { BNZ :dest &src }
// this is comparing to @MAX because it's bitwise NOT, and not logical NOT
// for logical NOT, that would be `bool not`, which is equivalent for the trivial 0 or @MAX case
branch not <&src> -> :dest { BNE :dest &src @MAX }
__binary__ xor -> XOR;
__binary__ xnor -> XNOR;
__binary__ and -> AND;
__binary__ nand -> NAND;
__binary__ or -> OR;
__binary__ nor -> NOR;
__binary__ add -> ADD;
__binary__ sub -> SUB;
__unary__ inc -> INC;
__unary__ dec -> DEC;
__unary__ neg -> NEG;
__binary__ mult -> MLT;
__binary__ div -> DIV;
__binary__ sdiv -> SDIV;
__binary__ mod -> MOD;
__binary__ smod -> SMOD;
__unary__ rsh -> RSH;
__unary__ ash -> SRS;
__unary__ lsh -> LSH;
__binary__ brsh -> BSR;
__binary__ bash -> BSS;
__binary__ blsh -> BSL;
__branching__ carry -> SETC + BRC;
__branching__ eq -> SETE + BRE;
__branching__ ne -> SETNE + BNE;
__branching__ gt -> SETG + BRG;
__branching__ gte -> SETGE + BGE;
__branching__ lt -> SETL + BRL;
__branching__ lte -> SETLE + BLE;
__branching__ sgt -> SSETG + SBRG;
__branching__ sgte -> SSETGE + SBGE;
__branching__ slt -> SSETL + SBRL;
__branching__ slte -> SSETLE + SBLE;