#pragma once
#include <PSX/Auxiliary/bits.hpp>

namespace JabyEngine {
    namespace MIPS {
        struct SR {
            static constexpr auto IEc = Bit(0);                   // Current Interrupt Enable  (0=Disable, 1=Enable)
            static constexpr auto KUc = Bit(1);                   // Current Kernel/User Mode  (0=Kernel, 1=User)
            static constexpr auto IEp = Bit(2);                   // Previous Interrupt Disable
            static constexpr auto KUp = Bit(3);                   // Previous Kernal/User Mode
            static constexpr auto IEo = Bit(4);                   // Old Interrupt Disable
            static constexpr auto KUo = Bit(5);                   // Old Kernal/User Mode
            static constexpr auto Im  = BitRange::from_to(8, 15); // 8 bit interrupt mask fields. When set the corresponding interrupts are allowed to cause an exception.
            static constexpr auto Isc = Bit(16);                  // Isolate Cache (0=No, 1=Isolate) When isolated, all load and store operations are targetted to the Data cache, and never the main memory. (Used by PSX Kernel, in combination with Port FFFE0130h)
            static constexpr auto Swc = Bit(17);                  // Swc Swapped cache mode (0=Normal, 1=Swapped) Instruction cache will act as Data cache and vice versa. Use only with Isc to access & invalidate Instr. cache entries. (Not used by PSX Kernel)
            static constexpr auto PZ  = Bit(18);                  // PZ  When set cache parity bits are written as 0.
            static constexpr auto CM  = Bit(19);                  // CM  Shows the result of the last load operation with the D-cache isolated. It gets set if the cache really contained data for the addressed memory location.
            static constexpr auto PE  = Bit(20);                  // Cache parity error (Does not cause exception)
            static constexpr auto TS  = Bit(21);                  // TLB shutdown. Gets set if a programm address simultaneously matches 2 TLB entries. (initial value on reset allows to detect extended CPU version?)
            static constexpr auto BEV = Bit(22);                  // Boot exception vectors in RAM/ROM (0=RAM/KSEG0, 1=ROM/KSEG1)
            static constexpr auto RE  = Bit(25);                  // Reverse endianness   (0=Normal endianness, 1=Reverse endianness) Reverses the byte order in which data is stored in memory. (lo-hi -> hi-lo) (Has affect only to User mode, not to Kernal mode) (?) (The bit doesn't exist in PSX ?)
            static constexpr auto CU0 = Bit(28);                  // COP0 Enable (0=Enable only in Kernal Mode, 1=Kernal and User Mode)
            static constexpr auto CU1 = Bit(29);                  // COP1 Enable (0=Disable, 1=Enable) (none such in PSX)
            static constexpr auto CU2 = Bit(30);                  // COP2 Enable (0=Disable, 1=Enable) (GTE in PSX)
            static constexpr auto CU3 = Bit(31);                  // COP3 Enable (0=Disable, 1=Enable) (none such in PSX)

            static uint32_t read() {
                uint32_t sr;
                __asm__("mfc0 %0, $12" : "=rm"(sr));
                return sr;
            }

            static void write(uint32_t sr) {
                __asm__("mtc0 %0, $12" :: "rm"(sr));
            }
        };
    }
}