Nugget
encoder.hh
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2021 PCSX-Redux authors
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 
27 #pragma once
28 
29 #include <stdint.h>
30 
31 namespace Mips {
32 namespace Encoder {
33 
34 // clang-format off
35 enum class Reg {
36  R0, AT, V0, V1, A0, A1, A2, A3, // 00 to 07
37  T0, T1, T2, T3, T4, T5, T6, T7, // 08 to 0f
38  S0, S1, S2, S3, S4, S5, S6, S7, // 10 to 17
39  T8, T9, K0, K1, GP, SP, S8, RA, // 18 to 1f
40 };
41 // clang-format on
42 
43 constexpr uint32_t iclass(uint32_t v) { return v << 26; }
44 constexpr uint32_t dstVal(Reg r) { return uint32_t(r) << 11; }
45 constexpr uint32_t tgtVal(Reg r) { return uint32_t(r) << 16; }
46 constexpr uint32_t srcVal(Reg r) { return uint32_t(r) << 21; }
47 
48 // ALU
49 constexpr uint32_t add(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100000; }
50 constexpr uint32_t addu(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100001; }
51 constexpr uint32_t addi(Reg tgt, Reg src, int16_t value) {
52  uint32_t v = value;
53  v &= 0xffff;
54  return iclass(0b001000) | srcVal(src) | tgtVal(tgt) | v;
55 }
56 constexpr uint32_t addiu(Reg tgt, Reg src, int16_t value) {
57  uint32_t v = value;
58  v &= 0xffff;
59  return iclass(0b001001) | srcVal(src) | tgtVal(tgt) | v;
60 }
61 constexpr uint32_t andd(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100100; }
62 constexpr uint32_t andi(Reg tgt, Reg src, uint16_t value) {
63  return iclass(0b001100) | srcVal(src) | tgtVal(tgt) | value;
64 }
65 constexpr uint32_t lui(Reg tgt, uint16_t value) { return iclass(0b001111) | tgtVal(tgt) | value; }
66 constexpr uint32_t nor(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100111; }
67 constexpr uint32_t orr(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100101; }
68 constexpr uint32_t ori(Reg tgt, Reg src, uint16_t value) {
69  return iclass(0b001101) | srcVal(src) | tgtVal(tgt) | value;
70 }
71 constexpr uint32_t slt(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b101010; }
72 constexpr uint32_t sltu(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b101011; }
73 constexpr uint32_t slti(Reg tgt, Reg src, int16_t value) {
74  uint32_t v = value;
75  v &= 0xffff;
76  return iclass(0b001010) | srcVal(src) | tgtVal(tgt) | v;
77 }
78 constexpr uint32_t sltiu(Reg tgt, Reg src, uint16_t value) {
79  return iclass(0b001011) | srcVal(src) | tgtVal(tgt) | value;
80 }
81 constexpr uint32_t sub(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100010; }
82 constexpr uint32_t subu(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100011; }
83 constexpr uint32_t xorr(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100110; }
84 constexpr uint32_t xori(Reg tgt, Reg src, uint16_t value) {
85  return iclass(0b001110) | srcVal(src) | tgtVal(tgt) | value;
86 }
87 
88 // shifts
89 constexpr uint32_t sll(Reg dst, Reg tgt, uint16_t sa) { return dstVal(dst) | tgtVal(tgt) | (sa << 6) | 0b000000; }
90 constexpr uint32_t sllv(Reg dst, Reg tgt, Reg src) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b000100; }
91 constexpr uint32_t sra(Reg dst, Reg tgt, uint16_t sa) { return dstVal(dst) | tgtVal(tgt) | (sa << 6) | 0b000011; }
92 constexpr uint32_t srav(Reg dst, Reg tgt, Reg src) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b000111; }
93 constexpr uint32_t srl(Reg dst, Reg tgt, uint16_t sa) { return dstVal(dst) | tgtVal(tgt) | (sa << 6) | 0b000010; }
94 constexpr uint32_t srlv(Reg dst, Reg tgt, Reg src) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b000110; }
95 
96 // mults
97 constexpr uint32_t div(Reg src, Reg tgt) { return tgtVal(tgt) | srcVal(src) | 0b011010; }
98 constexpr uint32_t divu(Reg src, Reg tgt) { return tgtVal(tgt) | srcVal(src) | 0b011011; }
99 constexpr uint32_t mfhi(Reg dst) { return dstVal(dst) | 0b010000; }
100 constexpr uint32_t mflo(Reg dst) { return dstVal(dst) | 0b010010; }
101 constexpr uint32_t mthi(Reg dst) { return dstVal(dst) | 0b010001; }
102 constexpr uint32_t mtlo(Reg dst) { return dstVal(dst) | 0b010011; }
103 constexpr uint32_t mult(Reg src, Reg tgt) { return tgtVal(tgt) | srcVal(src) | 0b011000; }
104 constexpr uint32_t multu(Reg src, Reg tgt) { return tgtVal(tgt) | srcVal(src) | 0b011001; }
105 
106 // branches
107 constexpr uint32_t beq(Reg src, Reg tgt, int16_t offset) {
108  uint32_t o = offset >> 2;
109  o &= 0xffff;
110  return iclass(0b000100) | tgtVal(tgt) | srcVal(src) | o;
111 }
112 constexpr uint32_t bgez(Reg src, int16_t offset) {
113  uint32_t o = offset >> 2;
114  o &= 0xffff;
115  return iclass(0b000001) | tgtVal(Reg(0b00001)) | srcVal(src) | o;
116 }
117 constexpr uint32_t bgezal(Reg src, int16_t offset) {
118  uint32_t o = offset >> 2;
119  o &= 0xffff;
120  return iclass(0b000001) | tgtVal(Reg(0b10001)) | srcVal(src) | o;
121 }
122 constexpr uint32_t bgtz(Reg src, int16_t offset) {
123  uint32_t o = offset >> 2;
124  o &= 0xffff;
125  return iclass(0b000111) | tgtVal(Reg(0b00000)) | srcVal(src) | o;
126 }
127 constexpr uint32_t blez(Reg src, int16_t offset) {
128  uint32_t o = offset >> 2;
129  o &= 0xffff;
130  return iclass(0b000110) | tgtVal(Reg(0b00000)) | srcVal(src) | o;
131 }
132 constexpr uint32_t bltz(Reg src, int16_t offset) {
133  uint32_t o = offset >> 2;
134  o &= 0xffff;
135  return iclass(0b000001) | tgtVal(Reg(0b00000)) | srcVal(src) | o;
136 }
137 constexpr uint32_t bltzal(Reg src, int16_t offset) {
138  uint32_t o = offset >> 2;
139  o &= 0xffff;
140  return iclass(0b000001) | tgtVal(Reg(0b10000)) | srcVal(src) | o;
141 }
142 constexpr uint32_t bne(Reg src, Reg tgt, int16_t offset) {
143  uint32_t o = offset >> 2;
144  o &= 0xffff;
145  return iclass(0b000101) | tgtVal(tgt) | srcVal(src) | o;
146 }
147 constexpr uint32_t brk(uint32_t code) { return (code << 6) | 0b001101; }
148 constexpr uint32_t j(uint32_t addr) { return iclass(0b000010) | ((addr >> 2) & 0x03ffffff); }
149 constexpr uint32_t jal(uint32_t addr) { return iclass(0b000011) | ((addr >> 2) & 0x03ffffff); }
150 constexpr uint32_t jalr(Reg src, Reg dst = Reg::RA) { return dstVal(dst) | srcVal(src) | 0b001001; }
151 constexpr uint32_t jr(Reg src) { return srcVal(src) | 0b001000; }
152 constexpr uint32_t syscall() { return 0b001100; }
153 
154 // memory
155 constexpr uint32_t lb(Reg tgt, int16_t offset, Reg src) {
156  uint32_t o = offset;
157  o &= 0xffff;
158  return iclass(0b100000) | tgtVal(tgt) | srcVal(src) | o;
159 }
160 constexpr uint32_t lbu(Reg tgt, int16_t offset, Reg src) {
161  uint32_t o = offset;
162  o &= 0xffff;
163  return iclass(0b100100) | tgtVal(tgt) | srcVal(src) | o;
164 }
165 constexpr uint32_t lh(Reg tgt, int16_t offset, Reg src) {
166  uint32_t o = offset;
167  o &= 0xffff;
168  return iclass(0b100001) | tgtVal(tgt) | srcVal(src) | o;
169 }
170 constexpr uint32_t lhu(Reg tgt, int16_t offset, Reg src) {
171  uint32_t o = offset;
172  o &= 0xffff;
173  return iclass(0b100101) | tgtVal(tgt) | srcVal(src) | o;
174 }
175 constexpr uint32_t lw(Reg tgt, int16_t offset, Reg src) {
176  uint32_t o = offset;
177  o &= 0xffff;
178  return iclass(0b100011) | tgtVal(tgt) | srcVal(src) | o;
179 }
180 constexpr uint32_t lwl(Reg tgt, int16_t offset, Reg src) {
181  uint32_t o = offset;
182  o &= 0xffff;
183  return iclass(0b100010) | tgtVal(tgt) | srcVal(src) | o;
184 }
185 constexpr uint32_t lwr(Reg tgt, int16_t offset, Reg src) {
186  uint32_t o = offset;
187  o &= 0xffff;
188  return iclass(0b100110) | tgtVal(tgt) | srcVal(src) | o;
189 }
190 constexpr uint32_t sb(Reg tgt, int16_t offset, Reg src) {
191  uint32_t o = offset;
192  o &= 0xffff;
193  return iclass(0b101000) | tgtVal(tgt) | srcVal(src) | o;
194 }
195 constexpr uint32_t sh(Reg tgt, int16_t offset, Reg src) {
196  uint32_t o = offset;
197  o &= 0xffff;
198  return iclass(0b101001) | tgtVal(tgt) | srcVal(src) | o;
199 }
200 constexpr uint32_t sw(Reg tgt, int16_t offset, Reg src) {
201  uint32_t o = offset;
202  o &= 0xffff;
203  return iclass(0b101011) | tgtVal(tgt) | srcVal(src) | o;
204 }
205 constexpr uint32_t swl(Reg tgt, int16_t offset, Reg src) {
206  uint32_t o = offset;
207  o &= 0xffff;
208  return iclass(0b101010) | tgtVal(tgt) | srcVal(src) | o;
209 }
210 constexpr uint32_t swr(Reg tgt, int16_t offset, Reg src) {
211  uint32_t o = offset;
212  o &= 0xffff;
213  return iclass(0b101110) | tgtVal(tgt) | srcVal(src) | o;
214 }
215 
216 // cop0
217 constexpr uint32_t mfc0(Reg tgt, uint8_t dst) { return iclass(0b010000) | tgtVal(tgt) | (dst << 11); }
218 constexpr uint32_t mtc0(Reg tgt, uint8_t dst) { return iclass(0b010000) | (4 << 21) | tgtVal(tgt) | (dst << 11); }
219 constexpr uint32_t rfe() { return 0x42000010; }
220 
221 // pseudo
222 constexpr uint32_t nop() { return 0; }
223 
224 } // namespace Encoder
225 } // namespace Mips