| // -*- C -*- |
| |
| // Simulator definition for the Broadcom SiByte SB-1 CPU extensions. |
| // Copyright (C) 2002-2021 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.%<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))); |
| } |