duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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