;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; This file is part of 'M', a MIPS system emulator. ;; ;; ;; ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;; ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;; ;; ;; ;; You do not have, nor can you ever acquire the right to use, copy or ;; ;; distribute this software ; Should you use this software for any purpose, ;; ;; or copy and distribute it to anyone or in any manner, you are breaking ;; ;; the laws of whatever soi-disant jurisdiction, and you promise to ;; ;; continue doing so for the indefinite future. In any case, please ;; ;; always : read and understand any software ; verify any PGP signatures ;; ;; that you use - for any purpose. ;; ;; ;; ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;----------------------------------------------------------------------------- ; Helper macros for MIPS instruction operands. ; All presume that current MIPS instruction is found in r_I. ; Note that variable shifts on x86 require slide amount to reside in CL. ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; These constants are fixed for the MIPS32 architecture and will NEVER change: ;----------------------------------------------------------------------------- ; Masks for Instruction Fields: %define rD_Mask 0xF800 ; Mask for rD Field %define rS_Mask 0x3E00000 ; Mask for rS Field %define rT_Mask 0x1F0000 ; Mask for rT Field %define Imm_Mask 0xFFFF ; Mask for Imm Field %define Shamt_Mask 0x7C0 ; Mask for Shamt Field %define J_Mask 0x3FFFFFF ; Mask for J Field %define Q_Mask 0x7 ; Mask for Q Field (MFC0/MTC0 instructions) ;----------------------------------------------------------------------------- ; Shifts for Instruction Fields (Imm doesn't need one) : %define rD_Shr 11 ; Right Shift for rD Field %define rS_Shr 21 ; Right Shift for rS Field %define rT_Shr 16 ; Right Shift for rT Field %define Shamt_Shr 6 ; Right Shift for Shamt Field %define J_Shl 2 ; Left Shift for J Field ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Register Placements ;----------------------------------------------------------------------------- ; To point to MIPS state: %define M_Base_64 rbp ; Pointer to base of MIPS data structure %define M_Base_32 ebp ; 32-bit component of above ;----------------------------------------------------------------------------- ; Scratch Registers used inside Opcodes: ;----------------------------------------------------------------------------- %define rD eax ; Where to extract rD Field %define Imm rD ; Where IType's Imm goes (they have no rD) %define JTarg rD ; Where JType's J field goes ; x86 is braindamaged and DEMANDS variable shift slides in CL. So rS is ECX. %define rS ecx ; Where to extract rS Field %define rS_LowByte cl ; Low byte of rS, for some 'flag' ops %define r_Shamt rS ; must be also this (see above) %define r_Q rS ; Q field in the coprocessor instructions %define rT ebx ; Where to extract rT Field ; Scratch Register for intermediates: %define TMP edx ; Scratch register used in all ops %define TMP_LowByte dl ; Low byte of TMP, for some 'flag' ops ; After we decode all fields, we no longer need the original instruction : %define r_I TMP ; Copy of currently-executing instruction ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Instruction Field Manipulations. Arranged so as to satisfy the x86 pipeline. ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract rD, rS, rT fields from the currently-executing MIPS instruction ; For instructions encoded as ???? ??ss ssst tttt dddd d??? ???? ???? ;----------------------------------------------------------------------------- %macro RType 0 ; no params mov rD, rD_Mask ; Mask for rD Field mov rS, rS_Mask ; Mask for rS Field mov rT, rT_Mask ; Mask for rT Field and rD, r_I ; Mask orig. inst. to get rD Field and rS, r_I ; Mask orig. inst. to get rS Field and rT, r_I ; Mask orig. inst. to get rT Field shr rD, rD_Shr ; rD is now rD Index shr rS, rS_Shr ; rS is now rS Index shr rT, rT_Shr ; rT is now rT Index %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract only rS field from the currently-executing MIPS instruction ; For instructions encoded as ???? ??ss sss? ???? ???? ???? ???? ???? ;----------------------------------------------------------------------------- %macro RType_S_Only 0 ; no params mov rS, rS_Mask ; Mask for rS Field and rS, r_I ; Mask orig. inst. to get rS Field shr rS, rS_Shr ; rS is now rS Index %endmacro ;----------------------------------------------------------------------------- ; Works same %define IType_S_Only RType_S_Only ;----------------------------------------------------------------------------- ; Extract only rS and rT fields from the currently-executing MIPS instruction ; For instructions encoded as ???? ??ss ssst tttt ???? ???? ???? ???? ;----------------------------------------------------------------------------- %macro RType_S_T_Only 0 ; no params mov rS, rS_Mask ; Mask for rS Field mov rT, rT_Mask ; Mask for rT Field and rS, r_I ; Mask orig. inst. to get rS Field and rT, r_I ; Mask orig. inst. to get rT Field shr rS, rS_Shr ; rS is now rS Index shr rT, rT_Shr ; rT is now rT Index %endmacro ;----------------------------------------------------------------------------- ; Works same %define IType_S_T_Only RType_S_T_Only ;----------------------------------------------------------------------------- ; Extract only rS and rD fields from the currently-executing MIPS instruction ; For instructions encoded as ???? ??ss sss? ???? dddd d??? ???? ???? ;----------------------------------------------------------------------------- %macro RType_S_D_Only 0 ; no params mov rD, rD_Mask ; Mask for rD Field mov rS, rS_Mask ; Mask for rS Field and rD, r_I ; Mask orig. inst. to get rD Field and rS, r_I ; Mask orig. inst. to get rS Field shr rD, rD_Shr ; rD is now rD Index shr rS, rS_Shr ; rS is now rS Index %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract only rD field from the currently-executing MIPS instruction ; For instructions encoded as ???? ???? ???? ???? dddd d??? ???? ???? ;----------------------------------------------------------------------------- %macro RType_D_Only 0 ; no params mov rD, rD_Mask ; Mask for rD Field and rD, r_I ; Mask orig. inst. to get rD Field shr rD, rD_Shr ; rD is now rD Index %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract rD, rT, Shamt fields from the currently-executing MIPS instruction ; For instructions encoded as ???? ???? ???t tttt dddd dhhh hh?? ???? ;----------------------------------------------------------------------------- %macro RType_D_T_Shamt 0 ; no params mov rD, rD_Mask ; Mask for rD Field mov r_Shamt, Shamt_Mask ; Mask for Shamt Field mov rT, rT_Mask ; Mask for rT Field and rD, r_I ; Mask orig. inst. to get rD Field and r_Shamt, r_I ; Mask orig. inst. to get Shamt Field and rT, r_I ; Mask orig. inst. to get rT Field shr rD, rD_Shr ; rD is now rD Index shr r_Shamt, Shamt_Shr ; r_Shamt is now Shamt value shr rT, rT_Shr ; rT is now rT Index %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract rD, rT, Q fields from the currently-executing MIPS instruction ; For MFC/MTC instructions encoded as 0100 0000 ?00t tttt dddd d000 0000 0qqq ;----------------------------------------------------------------------------- %macro CPType 0 ; no params mov rD, rD_Mask ; Mask for rD Field mov r_Q, Q_Mask ; Mask for Q Field mov rT, rT_Mask ; Mask for rT Field and rD, r_I ; Mask orig. inst. to get rD Field and r_Q, r_I ; Mask orig. inst. to get Q Field and rT, r_I ; Mask orig. inst. to get rT Field shr rD, rD_Shr ; rD is now rD Index shr rT, rT_Shr ; rT is now rT Index %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract Imm, rS, rT fields from the currently-executing MIPS instruction ;----------------------------------------------------------------------------- %macro IType 0 ; no params mov Imm, Imm_Mask ; Mask for Imm Field; needs no shift mov rS, rS_Mask ; Mask for rS Field mov rT, rT_Mask ; Mask for rT Field and Imm, r_I ; Mask orig. inst. to get Imm Field and rS, r_I ; Mask orig. inst. to get rS Field and rT, r_I ; Mask orig. inst. to get rT Field shr rS, rS_Shr ; rS is now rS Index shr rT, rT_Shr ; rT is now rT Index %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract only Imm, rS fields from the currently-executing MIPS instruction ;----------------------------------------------------------------------------- %macro IType_I_S_Only 0 ; no params mov Imm, Imm_Mask ; Mask for Imm Field; needs no shift mov rS, rS_Mask ; Mask for rS Field and Imm, r_I ; Mask orig. inst. to get Imm Field and rS, r_I ; Mask orig. inst. to get rS Field shr rS, rS_Shr ; rS is now rS Index %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract only Imm field from the currently-executing MIPS instruction ;----------------------------------------------------------------------------- %macro IType_I_Only 0 ; no params mov Imm, Imm_Mask ; Mask for Imm Field; needs no shift and Imm, r_I ; Mask orig. inst. to get Imm Field %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract Imm, rT fields from the currently-executing MIPS instruction ;----------------------------------------------------------------------------- %macro IType_I_T_Only 0 ; no params mov Imm, Imm_Mask ; Mask for Imm Field; needs no shift mov rT, rT_Mask ; Mask for rT Field and Imm, r_I ; Mask orig. inst. to get Imm Field and rT, r_I ; Mask orig. inst. to get rT Field shr rT, rT_Shr ; rT is now rT Index %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Extract J field from the currently-executing MIPS instruction ; Encoding: ???? 11ii iiii iiii iiii iiii iiii iiii ;----------------------------------------------------------------------------- %macro JType 0 ; no params mov JTarg, J_Mask ; Mask for J Field; needs no shift and JTarg, r_I ; Mask orig. inst. to get J Field shl JTarg, J_Shl ; Shift the J Field to get Target Address %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Sign-Extend((16bit Address) * 4) (where 18th bit is considered 'sign') ;----------------------------------------------------------------------------- %macro SX18_4N 1 ; param is A, the address to extend shl %1, 16 ; upper 16 bits are now equal to A sar %1, 14 ; Shift back to A*4, extending sign bit. %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Sign-Extend(16bit Address) (where 16th bit is considered 'sign') ;----------------------------------------------------------------------------- %macro SX16 1 ; param is A, the address to extend shl %1, 16 ; upper 16 bits are now equal to A sar %1, 16 ; Shift back to A, extending sign bit. %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Denote privileged (permitted in Kernel-Mode strictly) instructions. ;----------------------------------------------------------------------------- %macro PRIVILEGED 0 bt CP0_Status, CP0St_UM ; CF := CP0St_UM Flag jnc %%proceed ; If UM = 0: Kernel Mode, proceed. test CP0_Status, (1 << CP0St_EXL) | (1 << CP0St_ERL) ; EXL or ERL jnz %%proceed ; If EXL && ERL: Kernel Mode, proceed. ;; We are NOT in kernel mode, but trying to execute a privileged inst: SetEXC EXC_RI ; Set the 'Reserved Instr.' Exception. jmp _Handle_Exception ; Go straight to exception handler. %%proceed ; We're in Kernel Mode, so proceed with the privileged instruction. %endmacro ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Store the significant 32 bits of locative ;----------------------------------------------------------------------------- %macro A32 1 ; %1: locative dd %1 %endmacro ;-----------------------------------------------------------------------------