| // -*- C -*- | 
 |  | 
 | // Simulator definition for the Broadcom SiByte SB-1 CPU extensions. | 
 | // Copyright (C) 2002-2024 Free Software Foundation, Inc. | 
 | // Contributed by Ed Satterthwaite and Chris Demetriou, of Broadcom | 
 | // Corporation (SiByte). | 
 | // | 
 | // This file is part of GDB, the GNU debugger. | 
 | // | 
 | // This program is free software; you can redistribute it and/or modify | 
 | // it under the terms of the GNU General Public License as published by | 
 | // the Free Software Foundation; either version 3 of the License, or | 
 | // (at your option) any later version. | 
 | // | 
 | // This program is distributed in the hope that it will be useful, | 
 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 | // GNU General Public License for more details. | 
 | // | 
 | // You should have received a copy of the GNU General Public License | 
 | // along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
 |  | 
 |  | 
 | // Helper: | 
 | // | 
 | // Check that the SB-1 extension instruction can currently be used, and | 
 | // signal a ReservedInstruction exception if not. | 
 | // | 
 |  | 
 | :function:::void:check_sbx:instruction_word insn | 
 | *sb1: | 
 | { | 
 |   if ((SR & status_SBX) == 0) | 
 |     SignalException(ReservedInstruction, insn); | 
 | } | 
 |  | 
 |  | 
 | //  MDMX ASE Instructions | 
 | //  --------------------- | 
 | // | 
 | //  The SB-1 implements the format OB subset of MDMX | 
 | //  and has three additions (pavg, pabsdiff, pabsdifc). | 
 | //  In addition, there are a couple of partial-decoding | 
 | //  issues for the read/write accumulator instructions. | 
 | // | 
 | //  This code is structured so that mdmx.igen can be used by | 
 | //  selecting the allowed instructions either via model, or by | 
 | //  using check_mdmx_fmtsel and check_mdmx_fmtop to cause an | 
 | //  exception if the instruction is not allowed. | 
 |  | 
 |  | 
 | :function:::void:check_mdmx:instruction_word insn | 
 | *sb1: | 
 | { | 
 |   if (!COP_Usable(1)) | 
 |     SignalExceptionCoProcessorUnusable(1); | 
 |   if ((SR & status_MX) == 0) | 
 |     SignalExceptionMDMX(); | 
 |   check_u64 (SD_, insn); | 
 | } | 
 |  | 
 | :function:::int:check_mdmx_fmtsel:instruction_word insn, int fmtsel | 
 | *sb1: | 
 | { | 
 |   switch (fmtsel & 0x03) | 
 |     { | 
 |     case 0x00:     /* ob */ | 
 |     case 0x02: | 
 |       return 1; | 
 |     case 0x01:     /* qh */ | 
 |     case 0x03:     /* UNPREDICTABLE */ | 
 |       SignalException (ReservedInstruction, insn); | 
 |       return 0; | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 | :function:::int:check_mdmx_fmtop:instruction_word insn, int fmtop | 
 | *sb1: | 
 | { | 
 |   switch (fmtop & 0x01) | 
 |     { | 
 |     case 0x00:     /* ob */ | 
 |       return 1; | 
 |     case 0x01:     /* qh */ | 
 |       SignalException (ReservedInstruction, insn); | 
 |       return 0; | 
 |     } | 
 |   return 0; | 
 | } | 
 |  | 
 |  | 
 | 011110,10,2.X!0,1.FMTOP,00000,00000,5.VD,111111:MDMX:64::RACH.sb1.fmt | 
 | "rach.?<X>.%s<FMTOP> v<VD>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_mdmx_fmtop (SD_, instruction_0, FMTOP); | 
 |   /* No op.  */ | 
 | } | 
 |  | 
 |  | 
 | 011110,00,2.X!0,1.FMTOP,00000,00000,5.VD,111111:MDMX:64::RACL.sb1.fmt | 
 | "racl.?<X>.%s<FMTOP> v<VD>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_mdmx_fmtop (SD_, instruction_0, FMTOP); | 
 |   /* No op.  */ | 
 | } | 
 |  | 
 |  | 
 | 011110,01,2.X!0,1.FMTOP,00000,00000,5.VD,111111:MDMX:64::RACM.sb1.fmt | 
 | "racm.?<X>.%s<FMTOP> v<VD>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_mdmx_fmtop (SD_, instruction_0, FMTOP); | 
 |   /* No op.  */ | 
 | } | 
 |  | 
 |  | 
 | 011110,2.X1!0!1!2,2.X2,1.FMTOP,00000,00000,5.VD,111111:MDMX:64::RAC.sb1.fmt | 
 | "rac?<X1>.?<X2> v<VD>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_mdmx_fmtop (SD_, instruction_0, FMTOP); | 
 |   /* No op.  */ | 
 | } | 
 |  | 
 |  | 
 | 011110,10,2.X!0,1.FMTOP,00000,5.VS,00000,111110:MDMX:64::WACH.sb1.fmt | 
 | "wach.?<X>.%s<FMTOP> v<VS>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_mdmx_fmtop (SD_, instruction_0, FMTOP); | 
 |   /* No op.  */ | 
 | } | 
 |  | 
 |  | 
 | 011110,00,2.X!0,1.FMTOP,5.VT,5.VS,00000,111110:MDMX:64::WACL.sb1.fmt | 
 | "wacl.?<X>.%s<FMTOP> v<VS>,v<VT>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_mdmx_fmtop (SD_, instruction_0, FMTOP); | 
 |   /* No op.  */ | 
 | } | 
 |  | 
 |  | 
 | 011110,2.X1!0!2,2.X2,1.FMTOP,5.VT,5.VS,00000,111110:MDMX:64::WAC.sb1.fmt | 
 | "wacl?<X1>.?<X2>.%s<FMTOP> v<VS>,v<VT>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_mdmx_fmtop (SD_, instruction_0, FMTOP); | 
 |   /* No op.  */ | 
 | } | 
 |  | 
 |  | 
 | 011110,5.FMTSEL,5.VT,5.VS,5.VD,001001:MDMX:64::PABSDIFF.fmt | 
 | "pabsdiff.%s<FMTSEL> v<VD>,v<VS>,v<VT>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_sbx (SD_, instruction_0); | 
 |   check_mdmx_fmtsel (SD_, instruction_0, FMTSEL); | 
 |   StoreFPR(VD,fmt_mdmx,MX_AbsDiff(ValueFPR(VS,fmt_mdmx),VT,FMTSEL)); | 
 | } | 
 |  | 
 |  | 
 | 011110,5.FMTSEL,5.VT,5.VS,00000,110101:MDMX:64::PABSDIFC.fmt | 
 | "pabsdifc.%s<FMTSEL> v<VS>,v<VT>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_sbx (SD_, instruction_0); | 
 |   check_mdmx_fmtsel (SD_, instruction_0, FMTSEL); | 
 |   MX_AbsDiffC(ValueFPR(VS,fmt_mdmx),VT,FMTSEL); | 
 | } | 
 |  | 
 |  | 
 | 011110,5.FMTSEL,5.VT,5.VS,5.VD,001000:MDMX:64::PAVG.fmt | 
 | "pavg.%s<FMTSEL> v<VD>,v<VS>,v<VT>" | 
 | *sb1: | 
 | { | 
 |   check_mdmx (SD_, instruction_0); | 
 |   check_sbx (SD_, instruction_0); | 
 |   check_mdmx_fmtsel (SD_, instruction_0, FMTSEL); | 
 |   StoreFPR(VD,fmt_mdmx,MX_Avg(ValueFPR(VS,fmt_mdmx),VT,FMTSEL)); | 
 | } | 
 |  | 
 |  | 
 | //  Paired-Single Extension Instructions | 
 | //  ------------------------------------ | 
 | // | 
 | //  The SB-1 implements several .PS format instructions that are | 
 | //  extensions to the MIPS64 architecture. | 
 |  | 
 | 010001,10,3.FMT=6,5.FT,5.FS,5.FD,000011:COP1:32,f::DIV.PS | 
 | "div.%s<FMT> f<FD>, f<FS>, f<FT>" | 
 | *sb1: | 
 | { | 
 |   int fmt = FMT; | 
 |   check_fpu (SD_); | 
 |   check_sbx (SD_, instruction_0); | 
 |   StoreFPR (FD, fmt, Divide (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); | 
 | } | 
 |  | 
 |  | 
 | 010001,10,3.FMT=6,00000,5.FS,5.FD,010101:COP1:32,f::RECIP.PS | 
 | "recip.%s<FMT> f<FD>, f<FS>" | 
 | *sb1: | 
 | { | 
 |   int fmt = FMT; | 
 |   check_fpu (SD_); | 
 |   check_sbx (SD_, instruction_0); | 
 |   StoreFPR (FD, fmt, Recip (ValueFPR (FS, fmt), fmt)); | 
 | } | 
 |  | 
 |  | 
 | 010001,10,3.FMT=6,00000,5.FS,5.FD,010110:COP1:32,f::RSQRT.PS | 
 | "rsqrt.%s<FMT> f<FD>, f<FS>" | 
 | *sb1: | 
 | { | 
 |   int fmt = FMT; | 
 |   check_fpu (SD_); | 
 |   check_sbx (SD_, instruction_0); | 
 |   StoreFPR (FD, fmt, RSquareRoot (ValueFPR (FS, fmt), fmt)); | 
 | } | 
 |  | 
 |  | 
 | 010001,10,3.FMT=6,00000,5.FS,5.FD,000100:COP1:32,f::SQRT.PS | 
 | "sqrt.%s<FMT> f<FD>, f<FS>" | 
 | *sb1: | 
 | { | 
 |   int fmt = FMT; | 
 |   check_fpu (SD_); | 
 |   check_sbx (SD_, instruction_0); | 
 |   StoreFPR (FD, fmt,  (SquareRoot (ValueFPR (FS, fmt), fmt))); | 
 | } |