diff options
| author | Nicolas "Pixel" Noble <pixel@nobis-crew.org> | 2009-09-28 17:22:06 +0200 | 
|---|---|---|
| committer | Nicolas "Pixel" Noble <pixel@nobis-crew.org> | 2009-09-28 17:22:06 +0200 | 
| commit | 2f38d1ad1cdd495da2a4d47530ab7c8b897fb89b (patch) | |
| tree | 857e91c6142bca48c4f7bcb7e2f4a827b374b2e4 /Cpu | |
| parent | 48df755c00a19a71e5583480b15091dc5c1e8df1 (diff) | |
Work in progress.
Diffstat (limited to 'Cpu')
| -rw-r--r-- | Cpu/cpu-mips.cpp | 1166 | 
1 files changed, 1166 insertions, 0 deletions
diff --git a/Cpu/cpu-mips.cpp b/Cpu/cpu-mips.cpp index e69de29..d7fcb8b 100644 --- a/Cpu/cpu-mips.cpp +++ b/Cpu/cpu-mips.cpp @@ -0,0 +1,1166 @@ +/* Code HIGHLY ripped off^W^W inspired from PCSX. */ + +enum registers { +    Rzr, Rat, Rv0, Rv1, Ra0, Ra1, Ra2, Ra3, +    Rt0, Rt1, Rt2, Rt3, Rt4, Rt5, Rt6, Rt7, +    Rs0, Rs1, Rs2, Rs3, Rs4, Rs5, Rs6, Rs7, +    Rt8, Rt9, Rk0, Rk1, Rgp, Rsp, Rfp, Rra, +    Rhi, Rlo, +}; + +char * GPRregisters[] = { +     "0", "at", "v0", "v1", "a0", "a1", "a2", "a3", +    "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", +    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", +    "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra", +    "hi", "lo", +}; + +char * CP0registers[] = { +    "Index"     , "Random"    , "EntryLo0", "EntryLo1", "Context" , "PageMask"  , "Wired"     , "*Check me*", +    "BadVAddr"  , "Count"     , "EntryHi" , "Compare" , "Status"  , "Cause"     , "ExceptPC"  , "PRevID"    , +    "Config"    , "LLAddr"    , "WatchLo" , "WatchHi" , "XContext", "*RES*"     , "*RES*"     , "*RES*"     , +    "*RES*"     , "*RES* "    , "PErr"    , "CacheErr", "TagLo"   , "TagHi"     , "ErrorEPC"  , "*RES*"     }; + +typedef void (*TdisR3000AF)(TDis *, Uint32 code, Uint32 pc); + +// These macros are used to assemble the disassembler functions +#define MakeDisF(fn, b) \ +    static void fn(TDis * d, Uint32 code, Uint32 pc) { \ +        d->pc = pc; \ +        b; \ +    } + +#define _Funct_  ((code      ) & 0x3F) // The funct part of the instruction register  +#define _Rd_     ((code >> 11) & 0x1F) // The rd part of the instruction register  +#define _Rt_     ((code >> 16) & 0x1F) // The rt part of the instruction register  +#define _Rs_     ((code >> 21) & 0x1F) // The rs part of the instruction register  +#define _Sa_     ((code >>  6) & 0x1F) // The sa part of the instruction register +#define _Im_     ( code & 0xFFFF)      // The immediate part of the instruction register +                                       // The signed immediate part of the instruction register +#define _sIm_    (code & 0x8000 ? - (((~code) & 0x7FFF) + 1) : ( code & 0x7FFF)) + +#define _Target_  (0x80000000 + ((code & 0x03ffffff) * 4)) +#define _Branch_  (pc + 4 + ((short)_Im_ * 4)) +#define _OfB_     _Im_, _nRs_ + +#define dName(n)    { d->Name(n); } +#define dGPR(i)     { d->PushGPReg(i); } +#define dCP0(i)     { d->PushCPReg(i); } +#define dImm()      { d->PushImm(_Im_); } +#define dTarget()   { d->PushTarget(_Target_); } +#define dSa()       { d->PushSa(_Sa_); } +#define dOfB() { \ +    d->PushOfB(_Rs_, _Im_, width); \ +} +#define dOffset() { \ +    d->PushOffset(_Branch_); \ +} + +#define dFull(full) { \ +    d->PushFull(full); \ +    d->Comment("MaybeRefTo..."); \ +} + +#define sep + +#define dInvalid() { \ +    d->Invalid(); \ +} + +#define dSuspect() { \ +    d->Suspect(); \ +} + +#define Invalidate(reg) { \ +    if (!reg) \ +        dSuspect(); \ +} + +#define SetReg(reg, val) { \ +    if (!reg) \ +        dSuspect(); \ +} + +#define MarkFunction(target) { \ +    d->add_function(target); \ +} + +#define Branch(branch) { \ +    d->add_branch(branch); \ +} + +#define Jump(target) { \ +    d->add_jump(target); \ +} + +#define Stop(target) { \ +    d->SetTag(target, STOP, true); \ +} + +/********************************************************* +* Arithmetic with immediate operand                      * +* Format:  OP rt, rs, immediate                          * +*********************************************************/ + +MakeDisF(disADDI, +    dName("addi"); +     +    dGPR(_Rt_); sep; +    if (_Rt_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dImm(); +     +    if (isInvalid(_Rs_)) { +        Invalidate(_Rt_); +    } else { +        SetRegS(_Rt_, GetRegS(_Rs_) + _sIm_); +    } +     +    d->Comment("Add immediate"); +) + +MakeDisF(disADDIU, +    if (!_Rs_) { +        dName("li"); +         +        dGPR(_Rt_); sep; +        dImm(); +         +        SetRegS(_Rt_, _sIm_); +         +        d->Comment("Load immediate"); +    } else { +        dName("addiu"); + +        dGPR(_Rt_); sep; +        if (_Rt_ != _Rs_) { +            dGPR(_Rs_); sep; +        } +        dImm(); + +        if (isInvalid(_Rs_) { +            Invalidate(_Rt_); +        } else { +            SetRegS(_Rt_, GetRegS(_Rs_) + _sIm_); +        } + +        d->Comment("Add immediate"); +    } +) + +MakeDisF(disANDI, +    dName("andi"); +     +    dGPR(_Rt_); sep; +    if (_Rt_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dImm(); +     +    if (isInvalid(_Rs_) { +        Invalidate(_Rt_); +    } else { +        SetReg(_Rt_, GetReg(_Rs_) & _Im_); +    } +     +    d->Comment("And immediate"); +) + +MakeDisF(disORI, +    if (!_Rs_) { +        dName("liu"); +         +        dGPR(_Rt_); sep; +        dImm(); +        SetReg(_Rt_, _Im_); +         +        d->Comment("Load immediate without sign extension"); +    } else { +        dName("ori"); +     +        dGPR(_Rt_); sep; +        if (_Rt_ != _Rs_) { +            dGPR(_Rs_); sep; +        } +        dImm(); +         +        if (isInvalid(_Rs_)) { +            Invalidate(_Rt_); +        } else { +            SetReg(_Rt_, GetReg(_Rs_) | _Im_); +        } +        d->Comment("Or immediate"); +    } +) + +MakeDisF(disSLTI, +    dName("slti"); +     +    dGPR(_Rt_); sep; +    if (_Rt_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dImm(); +     +    if (isInvalid(_Rs_)) { +        Invalidate(_Rt_); +    } else { +        SetReg(_Rt_, GetRegS(_Rs_) < _sIm_ ? 1 : 0); +    } +     +    d->Comment(registers[_Rt_] + String(" = ") + registers[_Rs_] + " < immediate ? 1 : 0 (signed)"); +) + +MakeDisF(disSLTIU, +    dName("sltiu"); +     +    dGPR(_Rt_); sep; +    if (_Rt_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dImm(); + +    if (isInvalid(_Rs_)) { +        Invalidate(_Rt_); +    } else { +        SetReg(_Rt_, GetReg(_Rs_) < _Im_ ? 1 : 0); +    } +     +    d->Comment(registers[_Rt_] + String(" = ") + registers[_Rs_] + " < immediate ? 1 : 0 (unsigned)"); +) + +MakeDisF(disXORI, +    dName("xori"); +     +    dGPR(_Rt_); sep; +    if (_Rt_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dImm(); + +    if (isInvalid(_Rs_)) { +        Invalidate(_Rt_); +    } else { +        SetReg(_Rt_, GetReg(_Rs_) ^ _Im_); +    } +     +    d->Comment("XOr immediate"); +) + +/********************************************************* +* Register arithmetic                                    * +* Format:  OP rd, rs, rt                                 * +*********************************************************/ +MakeDisF(disADD, +    dName("add"); + +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +     +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetRegS(_Rd_, GetRegS(_Rs_) + GetRegS(_Rt_)); +    } +     +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); +) + +MakeDisF(disADDU, +    if (!_Rt_) { +        dName("move"); + +        dGPR(_Rd_); sep; +        dGPR(_Rs_); +        if (_Rs_) { +            if (isInvalid(_Rs_)) { +                Invalidate(_Rd_); +            } else { +                SetReg(_Rd_, _Rs_); +            } +        } else { +            SetReg(_Rd_, 0); +        } +        d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_]); +    } else { +        dName("addu"); +     +        dGPR(_Rd_); sep; +        if (_Rd_ != _Rs_) { +            dGPR(_Rs_); sep; +        } +        dGPR(_Rt_); +        if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +            Invalidate(_Rd_); +        } else { +            SetRegS(_Rd_, GetRegS(_Rs_) + GetRegS(_Rt_)); +        } +        d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " + " + registers[_Rt_]); +    } +) + +MakeDisF(disAND, +    dName("and"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(_Rs_) & GetReg(_Rt_)); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " & " + registers[_Rt_]); +) + +MakeDisF(disNOR, +    dName("nor"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, ~(GetReg(_Rs_) | GetReg(_Rt_))); +    } +    d->Comment(String(registers[_Rd_]) + " = ~(" + registers[_Rs_] + " | " + registers[_Rt_] + ")"); +) + +MakeDisF(disOR, +    dName("or"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(_Rs_) | GetReg(_Rt_)); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " | " + registers[_Rt_]); +) + +MakeDisF(disSLT, +    dName("slt"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetRegS(_Rs_) < GetRegS(_Rt_) ? 1 : 0); +    } +    d->Comment(registers[_Rd_] + String(" = ") + registers[_Rs_] + " < " + registers[_Rt_] + " ? 1 : 0 (signed)"); +) + +MakeDisF(disSLTU, +    dName("sltu"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(_Rs_) < GetReg(_Rt_) ? 1 : 0); +    } +    d->Comment(registers[_Rd_] + String(" = ") + registers[_Rs_] + " < " + registers[_Rt_] + " ? 1 : 0 (unsigned)"); +) + +MakeDisF(disSUB, +    dName("sub"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetRegS(_Rd_, GetRegS(_Rs_) - GetRegS(_Rt_)); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); +) + +MakeDisF(disSUBU, +    dName("subu"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetRegS(_Rd_, GetRegS(_Rs_) - GetRegS(_Rt_)); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " - " + registers[_Rt_]); +) + +MakeDisF(disXOR, +    dName("xor"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rs_) { +        dGPR(_Rs_); sep; +    } +    dGPR(_Rt_); +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(_Rs_) ^ GetReg(_Rt_)); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rs_] + " ^ " + registers[_Rt_]); +) + +/********************************************************* +* Register arithmetic & Register trap logic              * +* Format:  OP rs, rt                                     * +*********************************************************/ +MakeDisF(disDIV, +    dName("div"); + +    dGPR(_Rs_); sep; +    dGPR(_Rt_); +     +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(Rhi); +        Invalidate(Rlo); +    } else { +        int32 lo, hi, rs, rt; +        rs = GetRegS(_Rs_); +        rt = GetRegS(_Rt_); +        lo = rs / rt; +        hi = rs % rt; +        SetRegS(Rlo, lo); +        SetRegS(Rhi, hi); +    } +    String c1 = String(registers[_Rs_]) + " / " + registers[_Rt_]; +    String c2 = String(registers[_Rs_]) + " %% " + registers[_Rt_]; +     +    d->Comment("lo = " + c1 + "; hi = " + c2); +) + +MakeDisF(disDIVU, +    dName("divu"); + +    dGPR(_Rs_); sep; +    dGPR(_Rt_); + +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(Rhi); +        Invalidate(Rlo); +    } else { +        Uint32 lo, hi, rs, rt; +        rs = GetReg(_Rs_); +        rt = GetReg(_Rt_); +        lo = rs / rt; +        hi = rs % rt; +        SetReg(Rlo, lo); +        SetReg(Rhi, hi); +    } +    String c1 = String(registers[_Rs_]) + " / " + registers[_Rt_]; +    String c2 = String(registers[_Rs_]) + " %% " + registers[_Rt_]; +     +    d->Comment("lo = " + c1 + "; hi = " + c2); +) + +MakeDisF(disMULT, +    dName("mult"); +     +    dGPR(_Rs_); sep; +    dGPR(_Rt_); +     +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(Rhi); +        Invalidate(Rlo); +    } else { +        int64 res; +        Uint32 lo, hi; +        res = ((int64) GetRegS(_Rs_)) * ((int64) GetRegS(_Rt_)); +        lo = (Uint32) (((Uint64) res) & 0xffffffffUL); +        hi = (Uint32) (((Uint64) res >> 32) & 0xffffffffUL); +        SetReg(Rlo, lo); +        SetReg(Rhi, hi); +    } +     +    d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); +) + +MakeDisF(disMULTU, +    dName("multu"); +     +    dGPR(_Rs_); sep; +    dGPR(_Rt_); + +    if (isInvalid(_Rs_) || isInvalid(_Rt_)) { +        Invalidate(Rhi); +        Invalidate(Rlo); +    } else { +        Uint64 res; +        Uint32 lo, hi; +        res = ((Uint64) GetReg(_Rs_)) * ((Uint64) GetReg(_Rt_)); +        lo = (Uint32) (res & 0xffffffffUL); +        hi = (Uint32) ((res >> 32) & 0xffffffffUL); +        SetReg(Rlo, lo); +        SetReg(Rhi, hi); +    } +     +    d->Comment(String("hilo = ") + registers[_Rs_] + " * " + registers[_Rt_]); +) + +/********************************************************* +* Register branch logic                                  * +* Format:  OP rs, offset                                 * +*********************************************************/ +MakeDisF(disBGEZ, +    dName("bgez"); +     +    dGPR(_Rs_); sep; +    dOffset(); +    Branch(_Branch_); +    d->Comment("Branch if " + String(registers[_Rs_]) + " >= 0"); +) + +MakeDisF(disBGEZAL, +    if (_Rs_) { +        dName("bgezal"); +     +        dGPR(_Rs_); sep; +        dOffset(); +        Call(_Branch_); +        d->Comment("Branch and link if " + String(registers[_Rs_]) + " >= 0"); +    } else { +        dName("bal"); +     +        dOffset(); +        Call(_Branch_); +        d->Comment("Branch and link"); +    } +) + +MakeDisF(disBGTZ, +    dName("bgtz"); +     +    dGPR(_Rs_); sep; +    dOffset(); +    Branch(_Branch_); +    d->Comment("Branch if " + String(registers[_Rs_]) + " > 0"); +) + +MakeDisF(disBLEZ, +    dName("blez"); +     +    dGPR(_Rs_); sep; +    dOffset(); +    Branch(_Branch_); +    d->Comment("Branch if " + String(registers[_Rs_]) + " <= 0"); +) + +MakeDisF(disBLTZ, +    dName("bltz"); +     +    dGPR(_Rs_); sep; +    dOffset(); +    Branch(_Branch_); +    d->Comment("Branch if " + String(registers[_Rs_]) + " < 0"); +) + +MakeDisF(disBLTZAL, +    dName("bltzal"); +     +    dGPR(_Rs_); sep; +    dOffset(); +    Call(_Branch_); +    d->Comment("Branch and link if " + String(registers[_Rs_]) + " < 0"); +) + +/********************************************************* +* Shift arithmetic with constant shift                   * +* Format:  OP rd, rt, sa                                 * +*********************************************************/ +MakeDisF(disSLL, +    if ((!_Rd_) && (!_Rt_)) { +        dName("nop"); +        if (code) { +            dSuspect(); +        } +    } else { +        dName("sll"); +         +        dGPR(_Rd_); sep; +        if (_Rd_ != _Rt_) { +            dGPR(_Rt_); sep; +        } +        dSa(); +        if (isInvalid(_Rt_)) { +            Invalidate(_Rd_); +        } else { +            SetReg(_Rd_, GetReg(_Rt_) << _Sa_); +        } +        d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << immediate"); +    } +) + +MakeDisF(disSRA, +    dName("sra"); + +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rt_) { +        dGPR(_Rt_); sep; +    } +    dSa(); +    if (isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetRegS(_Rd_, GetRegS(_Rt_) << _Sa_); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (arithmetic)"); +) + +MakeDisF(disSRL, +    dName("srl"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rt_) { +        dGPR(_Rt_); sep; +    } +    dSa(); +    if (isInvalid(_Rt_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(_Rt_) << _Sa_); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> immediate (logical)"); +) + +/********************************************************* +* Shift arithmetic with variant register shift           * +* Format:  OP rd, rt, rs                                 * +*********************************************************/ +MakeDisF(disSLLV, +    dName("sllv"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rt_) { +        dGPR(_Rt_); sep; +    } +    dGPR(_Rs_); +    if (isInvalid(_Rt_) || isInvalid(_Rs_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(_Rt_) << GetReg(_Rs_)); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " << " + registers[_Rs_]); +) + +MakeDisF(disSRAV, +    dName("srav"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rt_) { +        dGPR(_Rt_); sep; +    } +    dGPR(_Rs_); +    if (isInvalid(_Rt_) || isInvalid(_Rs_)) { +        Invalidate(_Rd_); +    } else { +        SetRegS(_Rd_, GetRegS(_Rt_) >> GetReg(_Rs_)); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> " + registers[_Rs_] + " (arithmetic)"); +) + +MakeDisF(disSRLV, +    dName("srlv"); +     +    dGPR(_Rd_); sep; +    if (_Rd_ != _Rt_) { +        dGPR(_Rt_); sep; +    } +    dGPR(_Rs_); +    if (isInvalid(_Rt_) || isInvalid(_Rs_)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(_Rt_) >> GetReg(_Rs_)); +    } +    d->Comment(String(registers[_Rd_]) + " = " + registers[_Rt_] + " >> " + registers[_Rs_] + " (logical)"); +) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm  * +* Format:  OP rt, immediate                              * +*********************************************************/ +MakeDisF(disLUI, +    dName("lui"); +     +    dGPR(_Rt_); sep; +    dImm(); +     +    SetReg(_Rt_, _Imm_ << 16) +     +    d->Comment("Load upper immediate"); +) + +/********************************************************* +* Move from HI/LO to GPR                                 * +* Format:  OP rd                                         * +*********************************************************/ +MakeDisF(disMFHI, +    dName("mfhi"); + +    dGPR(_Rd_); +    if (isInvalid(Rhi)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(Rhi)); +    } +     +    d->Comment(String(registers[_Rd_]) + " = hi"); +) + +MakeDisF(disMFLO, +    dName("mflo"); + +    dGPR(_Rd_); +    if (isInvalid(Rlo)) { +        Invalidate(_Rd_); +    } else { +        SetReg(_Rd_, GetReg(Rlo)); +    } + +    d->Comment(String(registers[_Rd_]) + " = lo"); +) + +/********************************************************* +* Move from GPR to HI/LO                                 * +* Format:  OP rd                                         * +*********************************************************/ +MakeDisF(disMTHI, +    dName("mthi"); +     +    dGPR(_Rd_); +    if (isInvalid(_Rd_)) { +        Invalidate(Rhi); +    } else { +        SetReg(Rhi, GetReg(_Rd_)); +    } + +    d->Comment("hi = " + String(registers[_Rd_])); +) + +MakeDisF(disMTLO, +    dName("mtlo"); +     +    dGPR(_Rd_); +    if (isInvalid(_Rd_)) { +        Invalidate(Rlo); +    } else { +        SetReg(Rlo, GetReg(_Rd_)); +    } + + +    d->Comment("lo = " + String(registers[_Rd_])); +) + +/********************************************************* +* Special purpose instructions                           * +* Format:  OP                                            * +*********************************************************/ +MakeDisF(disBREAK, +    dName("break"); +     +    Stop(pc + 4); +     +    d->Comment("Stops the machine"); +) +MakeDisF(disRFE,        dName("rfe")) + +MakeDisF(disSYSCALL, +    int syscall; +    dName("syscall"); +    syscall = code & 0xfffff; +     +    Syscall(syscall); +     +    d->Comment(String("Syscall number ") + syscall); +) + +MakeDisF(disHLE,        dName("hle")) + +MakeDisF(disRTPS,       dName("rtps")) +MakeDisF(disOP,         dName("op")) +MakeDisF(disNCLIP,      dName("nclip")) +MakeDisF(disDPCS,       dName("dpcs")) +MakeDisF(disINTPL,      dName("intpl")) +MakeDisF(disMVMVA,      dName("mvmva")) +MakeDisF(disNCDS,       dName("ncds")) +MakeDisF(disCDP,        dName("cdp")) +MakeDisF(disNCDT,       dName("ncdt")) +MakeDisF(disNCCS,       dName("nccs")) +MakeDisF(disCC,         dName("cc")) +MakeDisF(disNCS,        dName("ncs")) +MakeDisF(disNCT,        dName("nct")) +MakeDisF(disSQR,        dName("sqr")) +MakeDisF(disDCPL,       dName("dcpl")) +MakeDisF(disDPCT,       dName("dpct")) +MakeDisF(disAVSZ3,      dName("avsz3")) +MakeDisF(disAVSZ4,      dName("avsz4")) +MakeDisF(disRTPT,       dName("rtpt")) +MakeDisF(disGPF,        dName("gpf")) +MakeDisF(disGPL,        dName("gpl")) +MakeDisF(disNCCT,       dName("ncct")) + +MakeDisF(disMFC2,       dName("mfc2"); dGPR(_Rt_); Invalidate(_Rt_); ) +MakeDisF(disCFC2,       dName("cfc2"); dGPR(_Rt_); Invalidate(_Rt_); ) +MakeDisF(disMTC2,       dName("mtc2"); dGPR(_Rt_);) +MakeDisF(disCTC2,       dName("ctc2"); dGPR(_Rt_);) + +/********************************************************* +* Register branch logic                                  * +* Format:  OP rs, rt, offset                             * +*********************************************************/ +MakeDisF(disBEQ, +    if ((!_Rt_) && (!_Rs_)) { +        dName("b"); + +        dOffset(); +        Branch(_Branch_); +        Stop(pc + 8); + +        d->Comment("Branch always"); +    } +    if (!_Rt_) { +        dName("bez"); +     +        dGPR(_Rs_); sep; +        dOffset(); +        Branch(_Branch_); + +        d->Comment(String("Branch if ") + registers[_Rs_] + " == 0"); +    } else { +        dName("beq"); +     +        dGPR(_Rs_); sep; +        dGPR(_Rt_); sep; +        dOffset(); +        Branch(_Branch_); + +        d->Comment(String("Branch if ") + registers[_Rs_] + " == " + registers[_Rt_]); +    } +) + +MakeDisF(disBNE, +    if (!_Rt_) { +        dName("bnz"); +     +        dGPR(_Rs_); sep; +        dOffset(); +        Branch(_Branch_); + +        d->Comment(String("Branch if ") + registers[_Rs_] + " != 0"); +    } else { +        dName("bne"); +     +        dGPR(_Rs_); sep; +        dGPR(_Rt_); sep; +        dOffset(); +        Branch(_Branch_); + +        d->Comment(String("Branch if ") + registers[_Rs_] + " != " + registers[_Rt_]); +    } +) + +/********************************************************* +* Jump to target                                         * +* Format:  OP target                                     * +*********************************************************/ +MakeDisF(disJ, +    dName("j"); +     +    dTarget(); +    Jump(_Target_); +    Stop(pc + 8); + +    d->Comment("Jump always"); +) + +MakeDisF(disJAL, +    dName("jal"); + +    dTarget(); +    Invalidate(Rra); +    MarkFunction(_Target_); + +    d->Comment("Jump and link (function call)"); +) + +/********************************************************* +* Register jump                                          * +* Format:  OP rs, rd                                     * +*********************************************************/ +MakeDisF(disJR, +    dName("jr"); +    dGPR(_Rs_); +    Stop(pc + 8); + +    d->Comment("Jump register"); +) + +MakeDisF(disJALR, +    dName("jalr"); +     +    dGPR(_Rs_); +     +    if ((_Rd_) != Rra) { +        sep; dGPR(_Rd_); +    } +     +    Invalidate(_Rd_); + +    d->Comment("Jump and link register (function call)"); +) + +/********************************************************* +* Load and store for GPR                                 * +* Format:  OP rt, offset(base)                           * +*********************************************************/ +MakeDisF(disLB, +    int width = 8; +    dName("lb"); +     +    dGPR(_Rt_); sep; +    dOfB(); +     +    Invalidate(_Rt_); +    d->Comment("Load signed byte"); +) + +MakeDisF(disLBU, +    int width = 8; +    dName("lbu"); +     +    dGPR(_Rt_); sep; +    dOfB(); + +    Invalidate(_Rt_); +    d->Comment("Load unsigned byte"); +) + +MakeDisF(disLH, +    int width = 16; +    dName("lh"); +     +    dGPR(_Rt_); sep; +    dOfB(); + +    Invalidate(_Rt_); +    d->Comment("Load signed half"); +) + +MakeDisF(disLHU, +    int width = 16; +    dName("lhu"); +     +    dGPR(_Rt_); sep; +    dOfB(); +     +    Invalidate(_Rt_); +    d->Comment("Load unsigned half"); +) + +MakeDisF(disLW, +    int width = 32; +    dName("lw"); +     +    dGPR(_Rt_); sep; +    dOfB(); +     +    Invalidate(_Rt_); +    d->Comment("Load word"); +) + +MakeDisF(disLWL, +    int width = 32; +    dName("lwl"); +     +    dGPR(_Rt_); sep; +    dOfB(); +     +    Invalidate(_Rt_); +    d->Comment("Load word left"); +) + +MakeDisF(disLWR, +    int width = 32; +    dName("lwr"); +     +    dGPR(_Rt_); sep; +    dOfB(); +     +    Invalidate(_Rt_); +    d->Comment("Load word right"); +) + +MakeDisF(disLWC2, +    int width = 32; +    dName("lwc2"); +     +    dCP0(_Rt_); sep; +    dOfB(); +) + +MakeDisF(disSB, +    int width = 8; +    dName("sb"); +     +    dGPR(_Rt_); sep; +    dOfB(); +    d->Comment("Store byte"); +) + +MakeDisF(disSH, +    int width = 16; +    dName("sh"); +     +    dGPR(_Rt_); sep; +    dOfB(); +    d->Comment("Store half"); +) + +MakeDisF(disSW, +    int width = 32; +    dName("sw"); +     +    dGPR(_Rt_); sep; +    dOfB(); +    d->Comment("Store word"); +) + +MakeDisF(disSWL, +    int width = 32; +    dName("swl"); +     +    dGPR(_Rt_); sep; +    dOfB(); +    d->Comment("Store word left"); +) + +MakeDisF(disSWR, +    int width = 32; +    dName("swr"); +     +    dGPR(_Rt_); sep; +    dOfB(); +    d->Comment("Store word right"); +) + +MakeDisF(disSWC2, +    int width = 32; +    dName("swc2"); +     +    dGPR(_Rt_); sep; +    dOfB(); +) + +/********************************************************* +* Moves between GPR and COPx                             * +* Format:  OP rt, fs                                     * +*********************************************************/ +MakeDisF(disMFC0,       dName("mfc0"); dGPR(_Rt_); sep; dCP0(_Rd_); Invalidate(_Rt_);) +MakeDisF(disMTC0,       dName("mtc0"); dCP0(_Rd_); sep; dGPR(_Rt_);) +MakeDisF(disCFC0,       dName("cfc0"); dGPR(_Rt_); sep; dCP0(_Rd_); Invalidate(_Rt_);) +MakeDisF(disCTC0,       dName("ctc0"); dCP0(_Rd_); sep; dGPR(_Rt_);) + +/********************************************************* +* Unknow instruction (would generate an exception)       * +* Format:  ?                                             * +*********************************************************/ +MakeDisF(disNULL, +    dName("*** Bad OP ***"); +    dInvalid(); +) + + +TdisR3000AF disR3000A_SPECIAL[] = { // Subset of disSPECIAL +    disSLL , disNULL , disSRL , disSRA , disSLLV   , disNULL  , disSRLV  , disSRAV , +    disJR  , disJALR , disNULL, disNULL, disSYSCALL, disBREAK , disNULL  , disNULL , +    disMFHI, disMTHI , disMFLO, disMTLO, disNULL   , disNULL  , disNULL  , disNULL , +    disMULT, disMULTU, disDIV , disDIVU, disNULL   , disNULL  , disNULL  , disNULL , +    disADD , disADDU , disSUB , disSUBU, disAND    , disOR    , disXOR   , disNOR  , +    disNULL, disNULL , disSLT , disSLTU, disNULL   , disNULL  , disNULL  , disNULL , +    disNULL, disNULL , disNULL, disNULL, disNULL   , disNULL  , disNULL  , disNULL , +    disNULL, disNULL , disNULL, disNULL, disNULL   , disNULL  , disNULL  , disNULL ,}; + +MakeDisF(disSPECIAL,    disR3000A_SPECIAL[_Funct_](d, code, pc)) + +TdisR3000AF disR3000A_BCOND[] = { // Subset of disBCOND +    disBLTZ  , disBGEZ  , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +    disNULL  , disNULL  , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +    disBLTZAL, disBGEZAL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +    disNULL  , disNULL  , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,}; + +MakeDisF(disBCOND,      disR3000A_BCOND[_Rt_](d, code, pc)) + +TdisR3000AF disR3000A_COP0[] = { // Subset of disCOP0 +    disMFC0, disNULL, disCFC0, disNULL, disMTC0, disNULL, disCTC0, disNULL, +    disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +    disRFE , disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +    disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,}; + +MakeDisF(disCOP0,       disR3000A_COP0[_Rs_](d, code, pc)) + +TdisR3000AF disR3000A_BASIC[] = { // Subset of disBASIC (based on rs) +    disMFC2, disNULL, disCFC2, disNULL, disMTC2, disNULL, disCTC2, disNULL, +    disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +    disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, +    disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL, disNULL,}; + +MakeDisF(disBASIC,      disR3000A_BASIC[_Rs_](d, code, pc)) + +TdisR3000AF disR3000A_COP2[] = { // Subset of disR3000F_COP2 (based on funct) +    disBASIC, disRTPS , disNULL , disNULL , disNULL, disNULL , disNCLIP, disNULL, +    disNULL , disNULL , disNULL , disNULL , disOP  , disNULL , disNULL , disNULL, +    disDPCS , disINTPL, disMVMVA, disNCDS , disCDP , disNULL , disNCDT , disNULL, +    disNULL , disNULL , disNULL , disNCCS , disCC  , disNULL , disNCS  , disNULL, +    disNCT  , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, +    disSQR  , disDCPL , disDPCT , disNULL , disNULL, disAVSZ3, disAVSZ4, disNULL, +    disRTPT , disNULL , disNULL , disNULL , disNULL, disNULL , disNULL , disNULL, +    disNULL , disNULL , disNULL , disNULL , disNULL, disGPF  , disGPL  , disNCCT,}; + +MakeDisF(disCOP2,       disR3000A_COP2[_Funct_](d, code, pc)) + +TdisR3000AF disR3000A[] = { +    disSPECIAL    , disBCOND     , disJ       , disJAL  , disBEQ , disBNE , disBLEZ , disBGTZ , +    disADDI       , disADDIU     , disSLTI    , disSLTIU, disANDI, disORI , disXORI , disLUI  , +    disCOP0       , disNULL      , disCOP2    , disNULL , disNULL, disNULL, disNULL , disNULL , +    disNULL       , disNULL      , disNULL    , disNULL , disNULL, disNULL, disNULL , disNULL , +    disLB         , disLH        , disLWL     , disLW   , disLBU , disLHU , disLWR  , disNULL , +    disSB         , disSH        , disSWL     , disSW   , disNULL, disNULL, disSWR  , disNULL , +    disNULL       , disNULL      , disLWC2    , disNULL , disNULL, disNULL, disNULL , disNULL , +    disNULL       , disNULL      , disSWC2    , disHLE  , disNULL, disNULL, disNULL , disNULL ,}; + +//MakeDisFg(disR3000AF,	disR3000A[code >> 26](code, pc)) + +void decode(TDis * d, Uint32 pc) { +    Uint32 code = d->getmem()->Read32(pc); +    disR3000A[code >> 26](d, code, pc); +}  | 
