mips_encoder.h (9552B)
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 Sourced from https://raw.githubusercontent.com/grumpycoders/pcsx-redux/main/src/mips/common/util/encoder.hh 26 27 */ 28 29 #pragma once 30 31 #include <stdint.h> 32 33 namespace Mips { 34 namespace Encoder { 35 36 // clang-format off 37 enum class Reg { 38 R0, AT, V0, V1, A0, A1, A2, A3, // 00 to 07 39 T0, T1, T2, T3, T4, T5, T6, T7, // 08 to 0f 40 S0, S1, S2, S3, S4, S5, S6, S7, // 10 to 17 41 T8, T9, K0, K1, GP, SP, S8, RA, // 18 to 1f 42 }; 43 // clang-format on 44 45 constexpr uint32_t iclass(uint32_t v) { return v << 26; } 46 constexpr uint32_t dstVal(Reg r) { return uint32_t(r) << 11; } 47 constexpr uint32_t tgtVal(Reg r) { return uint32_t(r) << 16; } 48 constexpr uint32_t srcVal(Reg r) { return uint32_t(r) << 21; } 49 50 // ALU 51 constexpr uint32_t add(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100000; } 52 constexpr uint32_t addu(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100001; } 53 constexpr uint32_t addi(Reg tgt, Reg src, int16_t value) { 54 uint32_t v = value; 55 v &= 0xffff; 56 return iclass(0b001000) | srcVal(src) | tgtVal(tgt) | v; 57 } 58 constexpr uint32_t addiu(Reg tgt, Reg src, int16_t value) { 59 uint32_t v = value; 60 v &= 0xffff; 61 return iclass(0b001001) | srcVal(src) | tgtVal(tgt) | v; 62 } 63 constexpr uint32_t andd(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100100; } 64 constexpr uint32_t andi(Reg tgt, Reg src, uint16_t value) { 65 return iclass(0b001100) | srcVal(src) | tgtVal(tgt) | value; 66 } 67 constexpr uint32_t lui(Reg tgt, uint16_t value) { return iclass(0b001111) | tgtVal(tgt) | value; } 68 constexpr uint32_t nor(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100111; } 69 constexpr uint32_t orr(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100101; } 70 constexpr uint32_t ori(Reg tgt, Reg src, uint16_t value) { 71 return iclass(0b001101) | srcVal(src) | tgtVal(tgt) | value; 72 } 73 constexpr uint32_t slt(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b101010; } 74 constexpr uint32_t sltu(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b101011; } 75 constexpr uint32_t slti(Reg tgt, Reg src, int16_t value) { 76 uint32_t v = value; 77 v &= 0xffff; 78 return iclass(0b001010) | srcVal(src) | tgtVal(tgt) | v; 79 } 80 constexpr uint32_t sltiu(Reg tgt, Reg src, uint16_t value) { 81 return iclass(0b001011) | srcVal(src) | tgtVal(tgt) | value; 82 } 83 constexpr uint32_t sub(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100010; } 84 constexpr uint32_t subu(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100011; } 85 constexpr uint32_t xorr(Reg dst, Reg src, Reg tgt) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b100110; } 86 constexpr uint32_t xori(Reg tgt, Reg src, uint16_t value) { 87 return iclass(0b001110) | srcVal(src) | tgtVal(tgt) | value; 88 } 89 90 // shifts 91 constexpr uint32_t sll(Reg dst, Reg tgt, uint16_t sa) { return dstVal(dst) | tgtVal(tgt) | (sa << 6) | 0b000000; } 92 constexpr uint32_t sllv(Reg dst, Reg tgt, Reg src) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b000100; } 93 constexpr uint32_t sra(Reg dst, Reg tgt, uint16_t sa) { return dstVal(dst) | tgtVal(tgt) | (sa << 6) | 0b000011; } 94 constexpr uint32_t srav(Reg dst, Reg tgt, Reg src) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b000111; } 95 constexpr uint32_t srl(Reg dst, Reg tgt, uint16_t sa) { return dstVal(dst) | tgtVal(tgt) | (sa << 6) | 0b000010; } 96 constexpr uint32_t srlv(Reg dst, Reg tgt, Reg src) { return dstVal(dst) | tgtVal(tgt) | srcVal(src) | 0b000110; } 97 98 // mults 99 constexpr uint32_t div(Reg src, Reg tgt) { return tgtVal(tgt) | srcVal(src) | 0b011010; } 100 constexpr uint32_t divu(Reg src, Reg tgt) { return tgtVal(tgt) | srcVal(src) | 0b011011; } 101 constexpr uint32_t mfhi(Reg dst) { return dstVal(dst) | 0b010000; } 102 constexpr uint32_t mflo(Reg dst) { return dstVal(dst) | 0b010010; } 103 constexpr uint32_t mthi(Reg dst) { return dstVal(dst) | 0b010001; } 104 constexpr uint32_t mtlo(Reg dst) { return dstVal(dst) | 0b010011; } 105 constexpr uint32_t mult(Reg src, Reg tgt) { return tgtVal(tgt) | srcVal(src) | 0b011000; } 106 constexpr uint32_t multu(Reg src, Reg tgt) { return tgtVal(tgt) | srcVal(src) | 0b011001; } 107 108 // branches 109 constexpr uint32_t beq(Reg src, Reg tgt, int16_t offset) { 110 uint32_t o = offset >> 2; 111 o &= 0xffff; 112 return iclass(0b000100) | tgtVal(tgt) | srcVal(src) | o; 113 } 114 constexpr uint32_t bgez(Reg src, int16_t offset) { 115 uint32_t o = offset >> 2; 116 o &= 0xffff; 117 return iclass(0b000001) | tgtVal(Reg(0b00001)) | srcVal(src) | o; 118 } 119 constexpr uint32_t bgezal(Reg src, int16_t offset) { 120 uint32_t o = offset >> 2; 121 o &= 0xffff; 122 return iclass(0b000001) | tgtVal(Reg(0b10001)) | srcVal(src) | o; 123 } 124 constexpr uint32_t bgtz(Reg src, int16_t offset) { 125 uint32_t o = offset >> 2; 126 o &= 0xffff; 127 return iclass(0b000111) | tgtVal(Reg(0b00000)) | srcVal(src) | o; 128 } 129 constexpr uint32_t blez(Reg src, int16_t offset) { 130 uint32_t o = offset >> 2; 131 o &= 0xffff; 132 return iclass(0b000110) | tgtVal(Reg(0b00000)) | srcVal(src) | o; 133 } 134 constexpr uint32_t bltz(Reg src, int16_t offset) { 135 uint32_t o = offset >> 2; 136 o &= 0xffff; 137 return iclass(0b000001) | tgtVal(Reg(0b00000)) | srcVal(src) | o; 138 } 139 constexpr uint32_t bltzal(Reg src, int16_t offset) { 140 uint32_t o = offset >> 2; 141 o &= 0xffff; 142 return iclass(0b000001) | tgtVal(Reg(0b10000)) | srcVal(src) | o; 143 } 144 constexpr uint32_t bne(Reg src, Reg tgt, int16_t offset) { 145 uint32_t o = offset >> 2; 146 o &= 0xffff; 147 return iclass(0b000101) | tgtVal(tgt) | srcVal(src) | o; 148 } 149 constexpr uint32_t brk(uint32_t code) { return (code << 6) | 0b001101; } 150 constexpr uint32_t j(uint32_t addr) { return iclass(0b000010) | ((addr >> 2) & 0x03ffffff); } 151 constexpr uint32_t jal(uint32_t addr) { return iclass(0b000011) | ((addr >> 2) & 0x03ffffff); } 152 constexpr uint32_t jalr(Reg src, Reg dst = Reg::RA) { return dstVal(dst) | srcVal(src) | 0b001001; } 153 constexpr uint32_t jr(Reg src) { return srcVal(src) | 0b001000; } 154 constexpr uint32_t syscall() { return 0b001100; } 155 156 // memory 157 constexpr uint32_t lb(Reg tgt, int16_t offset, Reg src) { 158 uint32_t o = offset; 159 o &= 0xffff; 160 return iclass(0b100000) | tgtVal(tgt) | srcVal(src) | o; 161 } 162 constexpr uint32_t lbu(Reg tgt, int16_t offset, Reg src) { 163 uint32_t o = offset; 164 o &= 0xffff; 165 return iclass(0b100100) | tgtVal(tgt) | srcVal(src) | o; 166 } 167 constexpr uint32_t lh(Reg tgt, int16_t offset, Reg src) { 168 uint32_t o = offset; 169 o &= 0xffff; 170 return iclass(0b100001) | tgtVal(tgt) | srcVal(src) | o; 171 } 172 constexpr uint32_t lhu(Reg tgt, int16_t offset, Reg src) { 173 uint32_t o = offset; 174 o &= 0xffff; 175 return iclass(0b100101) | tgtVal(tgt) | srcVal(src) | o; 176 } 177 constexpr uint32_t lw(Reg tgt, int16_t offset, Reg src) { 178 uint32_t o = offset; 179 o &= 0xffff; 180 return iclass(0b100011) | tgtVal(tgt) | srcVal(src) | o; 181 } 182 constexpr uint32_t lwl(Reg tgt, int16_t offset, Reg src) { 183 uint32_t o = offset; 184 o &= 0xffff; 185 return iclass(0b100010) | tgtVal(tgt) | srcVal(src) | o; 186 } 187 constexpr uint32_t lwr(Reg tgt, int16_t offset, Reg src) { 188 uint32_t o = offset; 189 o &= 0xffff; 190 return iclass(0b100110) | tgtVal(tgt) | srcVal(src) | o; 191 } 192 constexpr uint32_t sb(Reg tgt, int16_t offset, Reg src) { 193 uint32_t o = offset; 194 o &= 0xffff; 195 return iclass(0b101000) | tgtVal(tgt) | srcVal(src) | o; 196 } 197 constexpr uint32_t sh(Reg tgt, int16_t offset, Reg src) { 198 uint32_t o = offset; 199 o &= 0xffff; 200 return iclass(0b101001) | tgtVal(tgt) | srcVal(src) | o; 201 } 202 constexpr uint32_t sw(Reg tgt, int16_t offset, Reg src) { 203 uint32_t o = offset; 204 o &= 0xffff; 205 return iclass(0b101011) | tgtVal(tgt) | srcVal(src) | o; 206 } 207 constexpr uint32_t swl(Reg tgt, int16_t offset, Reg src) { 208 uint32_t o = offset; 209 o &= 0xffff; 210 return iclass(0b101010) | tgtVal(tgt) | srcVal(src) | o; 211 } 212 constexpr uint32_t swr(Reg tgt, int16_t offset, Reg src) { 213 uint32_t o = offset; 214 o &= 0xffff; 215 return iclass(0b101110) | tgtVal(tgt) | srcVal(src) | o; 216 } 217 218 // cop0 219 constexpr uint32_t mfc0(Reg tgt, uint8_t dst) { return iclass(0b010000) | tgtVal(tgt) | (dst << 11); } 220 constexpr uint32_t mtc0(Reg tgt, uint8_t dst) { return iclass(0b010000) | (4 << 21) | tgtVal(tgt) | (dst << 11); } 221 constexpr uint32_t rfe() { return 0x42000010; } 222 223 // pseudo 224 constexpr uint32_t nop() { return 0; } 225 226 } // namespace Encoder 227 } // namespace Mips