198b9484cSchristos /* Support code for various pieces of CGEN simulators. 2*88241920Schristos Copyright (C) 1996-2024 Free Software Foundation, Inc. 398b9484cSchristos Contributed by Cygnus Support. 498b9484cSchristos 598b9484cSchristos This file is part of GDB, the GNU debugger. 698b9484cSchristos 798b9484cSchristos This program is free software; you can redistribute it and/or modify 898b9484cSchristos it under the terms of the GNU General Public License as published by 998b9484cSchristos the Free Software Foundation; either version 3 of the License, or 1098b9484cSchristos (at your option) any later version. 1198b9484cSchristos 1298b9484cSchristos This program is distributed in the hope that it will be useful, 1398b9484cSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 1498b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598b9484cSchristos GNU General Public License for more details. 1698b9484cSchristos 1798b9484cSchristos You should have received a copy of the GNU General Public License 1898b9484cSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1998b9484cSchristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224b169a6bSchristos 2398b9484cSchristos #include "bfd.h" 2498b9484cSchristos #include "dis-asm.h" 2598b9484cSchristos 264b169a6bSchristos #include "sim-main.h" 274b169a6bSchristos #include "sim-signal.h" 284b169a6bSchristos 2998b9484cSchristos #define MEMOPS_DEFINE_INLINE 3098b9484cSchristos #include "cgen-mem.h" 3198b9484cSchristos 3298b9484cSchristos #define SEMOPS_DEFINE_INLINE 3398b9484cSchristos #include "cgen-ops.h" 3498b9484cSchristos 354b169a6bSchristos const char * const cgen_mode_names[] = { 3698b9484cSchristos "VOID", 3798b9484cSchristos "BI", 3898b9484cSchristos "QI", 3998b9484cSchristos "HI", 4098b9484cSchristos "SI", 4198b9484cSchristos "DI", 4298b9484cSchristos "UQI", 4398b9484cSchristos "UHI", 4498b9484cSchristos "USI", 4598b9484cSchristos "UDI", 4698b9484cSchristos "SF", 4798b9484cSchristos "DF", 4898b9484cSchristos "XF", 4998b9484cSchristos "TF", 5098b9484cSchristos 0, /* MODE_TARGET_MAX */ 5198b9484cSchristos "INT", 5298b9484cSchristos "UINT", 5398b9484cSchristos "PTR" 5498b9484cSchristos }; 5598b9484cSchristos 5698b9484cSchristos /* Opcode table for virtual insns used by the simulator. */ 5798b9484cSchristos 5898b9484cSchristos #define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL) 5998b9484cSchristos 6098b9484cSchristos static const CGEN_IBASE virtual_insn_entries[] = 6198b9484cSchristos { 6298b9484cSchristos { 634b169a6bSchristos VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, {} } 6498b9484cSchristos }, 6598b9484cSchristos { 664b169a6bSchristos VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, {} } 6798b9484cSchristos }, 6898b9484cSchristos { 694b169a6bSchristos VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, {} } 7098b9484cSchristos }, 7198b9484cSchristos { 724b169a6bSchristos VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, {} } 7398b9484cSchristos }, 7498b9484cSchristos { 754b169a6bSchristos VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, {} } 7698b9484cSchristos }, 7798b9484cSchristos { 784b169a6bSchristos VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, {} } 7998b9484cSchristos } 8098b9484cSchristos }; 8198b9484cSchristos 8298b9484cSchristos #undef V 8398b9484cSchristos 8498b9484cSchristos const CGEN_INSN cgen_virtual_insn_table[] = 8598b9484cSchristos { 8698b9484cSchristos { & virtual_insn_entries[0] }, 8798b9484cSchristos { & virtual_insn_entries[1] }, 8898b9484cSchristos { & virtual_insn_entries[2] }, 8998b9484cSchristos { & virtual_insn_entries[3] }, 9098b9484cSchristos { & virtual_insn_entries[4] }, 9198b9484cSchristos { & virtual_insn_entries[5] } 9298b9484cSchristos }; 9398b9484cSchristos 9498b9484cSchristos /* Return the name of insn number I. */ 9598b9484cSchristos 9698b9484cSchristos const char * 9798b9484cSchristos cgen_insn_name (SIM_CPU *cpu, int i) 9898b9484cSchristos { 9998b9484cSchristos return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i))); 10098b9484cSchristos } 10198b9484cSchristos 10298b9484cSchristos /* Return the maximum number of extra bytes required for a SIM_CPU struct. */ 10398b9484cSchristos 10498b9484cSchristos int 1054b169a6bSchristos cgen_cpu_max_extra_bytes (SIM_DESC sd) 10698b9484cSchristos { 1074b169a6bSchristos const SIM_MACH * const *machp; 10898b9484cSchristos int extra = 0; 10998b9484cSchristos 1104b169a6bSchristos SIM_ASSERT (STATE_MACHS (sd) != NULL); 1114b169a6bSchristos 1124b169a6bSchristos for (machp = STATE_MACHS (sd); *machp != NULL; ++machp) 11398b9484cSchristos { 1144b169a6bSchristos int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (*machp)); 11598b9484cSchristos if (size > extra) 11698b9484cSchristos extra = size; 11798b9484cSchristos } 11898b9484cSchristos return extra; 11998b9484cSchristos } 12098b9484cSchristos 12198b9484cSchristos #ifdef DI_FN_SUPPORT 12298b9484cSchristos 12398b9484cSchristos DI 12498b9484cSchristos ANDDI (a, b) 12598b9484cSchristos DI a, b; 12698b9484cSchristos { 12798b9484cSchristos SI ahi = GETHIDI (a); 12898b9484cSchristos SI alo = GETLODI (a); 12998b9484cSchristos SI bhi = GETHIDI (b); 13098b9484cSchristos SI blo = GETLODI (b); 13198b9484cSchristos return MAKEDI (ahi & bhi, alo & blo); 13298b9484cSchristos } 13398b9484cSchristos 13498b9484cSchristos DI 13598b9484cSchristos ORDI (a, b) 13698b9484cSchristos DI a, b; 13798b9484cSchristos { 13898b9484cSchristos SI ahi = GETHIDI (a); 13998b9484cSchristos SI alo = GETLODI (a); 14098b9484cSchristos SI bhi = GETHIDI (b); 14198b9484cSchristos SI blo = GETLODI (b); 14298b9484cSchristos return MAKEDI (ahi | bhi, alo | blo); 14398b9484cSchristos } 14498b9484cSchristos 14598b9484cSchristos DI 14698b9484cSchristos ADDDI (a, b) 14798b9484cSchristos DI a, b; 14898b9484cSchristos { 14998b9484cSchristos USI ahi = GETHIDI (a); 15098b9484cSchristos USI alo = GETLODI (a); 15198b9484cSchristos USI bhi = GETHIDI (b); 15298b9484cSchristos USI blo = GETLODI (b); 15398b9484cSchristos USI x = alo + blo; 15498b9484cSchristos return MAKEDI (ahi + bhi + (x < alo), x); 15598b9484cSchristos } 15698b9484cSchristos 15798b9484cSchristos DI 15898b9484cSchristos MULDI (a, b) 15998b9484cSchristos DI a, b; 16098b9484cSchristos { 16198b9484cSchristos USI ahi = GETHIDI (a); 16298b9484cSchristos USI alo = GETLODI (a); 16398b9484cSchristos USI bhi = GETHIDI (b); 16498b9484cSchristos USI blo = GETLODI (b); 16598b9484cSchristos USI rhi,rlo; 16698b9484cSchristos USI x0, x1, x2, x3; 16798b9484cSchristos 16898b9484cSchristos x0 = alo * blo; 16998b9484cSchristos x1 = alo * bhi; 17098b9484cSchristos x2 = ahi * blo; 17198b9484cSchristos x3 = ahi * bhi; 17298b9484cSchristos 17398b9484cSchristos #define SI_TYPE_SIZE 32 17498b9484cSchristos #define BITS4 (SI_TYPE_SIZE / 4) 17598b9484cSchristos #define ll_B (1L << (SI_TYPE_SIZE / 2)) 17698b9484cSchristos #define ll_lowpart(t) ((USI) (t) % ll_B) 17798b9484cSchristos #define ll_highpart(t) ((USI) (t) / ll_B) 17898b9484cSchristos x1 += ll_highpart (x0); /* this can't give carry */ 17998b9484cSchristos x1 += x2; /* but this indeed can */ 18098b9484cSchristos if (x1 < x2) /* did we get it? */ 18198b9484cSchristos x3 += ll_B; /* yes, add it in the proper pos. */ 18298b9484cSchristos 18398b9484cSchristos rhi = x3 + ll_highpart (x1); 18498b9484cSchristos rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0); 18598b9484cSchristos return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo); 18698b9484cSchristos } 18798b9484cSchristos 18898b9484cSchristos DI 18998b9484cSchristos SHLDI (val, shift) 19098b9484cSchristos DI val; 19198b9484cSchristos SI shift; 19298b9484cSchristos { 19398b9484cSchristos USI hi = GETHIDI (val); 19498b9484cSchristos USI lo = GETLODI (val); 19598b9484cSchristos /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 19698b9484cSchristos return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); 19798b9484cSchristos } 19898b9484cSchristos 19998b9484cSchristos DI 20098b9484cSchristos SLADI (val, shift) 20198b9484cSchristos DI val; 20298b9484cSchristos SI shift; 20398b9484cSchristos { 20498b9484cSchristos SI hi = GETHIDI (val); 20598b9484cSchristos USI lo = GETLODI (val); 20698b9484cSchristos /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 20798b9484cSchristos return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); 20898b9484cSchristos } 20998b9484cSchristos 21098b9484cSchristos DI 21198b9484cSchristos SRADI (val, shift) 21298b9484cSchristos DI val; 21398b9484cSchristos SI shift; 21498b9484cSchristos { 21598b9484cSchristos SI hi = GETHIDI (val); 21698b9484cSchristos USI lo = GETLODI (val); 21798b9484cSchristos /* We use SRASI because the result is implementation defined if hi < 0. */ 21898b9484cSchristos /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 21998b9484cSchristos return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift)); 22098b9484cSchristos } 22198b9484cSchristos 22298b9484cSchristos int 22398b9484cSchristos GEDI (a, b) 22498b9484cSchristos DI a, b; 22598b9484cSchristos { 22698b9484cSchristos SI ahi = GETHIDI (a); 22798b9484cSchristos USI alo = GETLODI (a); 22898b9484cSchristos SI bhi = GETHIDI (b); 22998b9484cSchristos USI blo = GETLODI (b); 23098b9484cSchristos if (ahi > bhi) 23198b9484cSchristos return 1; 23298b9484cSchristos if (ahi == bhi) 23398b9484cSchristos return alo >= blo; 23498b9484cSchristos return 0; 23598b9484cSchristos } 23698b9484cSchristos 23798b9484cSchristos int 23898b9484cSchristos LEDI (a, b) 23998b9484cSchristos DI a, b; 24098b9484cSchristos { 24198b9484cSchristos SI ahi = GETHIDI (a); 24298b9484cSchristos USI alo = GETLODI (a); 24398b9484cSchristos SI bhi = GETHIDI (b); 24498b9484cSchristos USI blo = GETLODI (b); 24598b9484cSchristos if (ahi < bhi) 24698b9484cSchristos return 1; 24798b9484cSchristos if (ahi == bhi) 24898b9484cSchristos return alo <= blo; 24998b9484cSchristos return 0; 25098b9484cSchristos } 25198b9484cSchristos 25298b9484cSchristos DI 25398b9484cSchristos CONVHIDI (val) 25498b9484cSchristos HI val; 25598b9484cSchristos { 25698b9484cSchristos if (val < 0) 25798b9484cSchristos return MAKEDI (-1, val); 25898b9484cSchristos else 25998b9484cSchristos return MAKEDI (0, val); 26098b9484cSchristos } 26198b9484cSchristos 26298b9484cSchristos DI 26398b9484cSchristos CONVSIDI (val) 26498b9484cSchristos SI val; 26598b9484cSchristos { 26698b9484cSchristos if (val < 0) 26798b9484cSchristos return MAKEDI (-1, val); 26898b9484cSchristos else 26998b9484cSchristos return MAKEDI (0, val); 27098b9484cSchristos } 27198b9484cSchristos 27298b9484cSchristos SI 27398b9484cSchristos CONVDISI (val) 27498b9484cSchristos DI val; 27598b9484cSchristos { 27698b9484cSchristos return GETLODI (val); 27798b9484cSchristos } 27898b9484cSchristos 27998b9484cSchristos #endif /* DI_FN_SUPPORT */ 28098b9484cSchristos 28198b9484cSchristos QI 2824b169a6bSchristos RORQI (QI val, int shift) 28398b9484cSchristos { 28498b9484cSchristos if (shift != 0) 28598b9484cSchristos { 28698b9484cSchristos int remain = 8 - shift; 28798b9484cSchristos int mask = (1 << shift) - 1; 28898b9484cSchristos QI result = (val & mask) << remain; 28998b9484cSchristos mask = (1 << remain) - 1; 29098b9484cSchristos result |= (val >> shift) & mask; 29198b9484cSchristos return result; 29298b9484cSchristos } 29398b9484cSchristos return val; 29498b9484cSchristos } 29598b9484cSchristos 29698b9484cSchristos QI 2974b169a6bSchristos ROLQI (QI val, int shift) 29898b9484cSchristos { 29998b9484cSchristos if (shift != 0) 30098b9484cSchristos { 30198b9484cSchristos int remain = 8 - shift; 30298b9484cSchristos int mask = (1 << remain) - 1; 30398b9484cSchristos QI result = (val & mask) << shift; 30498b9484cSchristos mask = (1 << shift) - 1; 30598b9484cSchristos result |= (val >> remain) & mask; 30698b9484cSchristos return result; 30798b9484cSchristos } 30898b9484cSchristos return val; 30998b9484cSchristos } 31098b9484cSchristos 31198b9484cSchristos HI 3124b169a6bSchristos RORHI (HI val, int shift) 31398b9484cSchristos { 31498b9484cSchristos if (shift != 0) 31598b9484cSchristos { 31698b9484cSchristos int remain = 16 - shift; 31798b9484cSchristos int mask = (1 << shift) - 1; 31898b9484cSchristos HI result = (val & mask) << remain; 31998b9484cSchristos mask = (1 << remain) - 1; 32098b9484cSchristos result |= (val >> shift) & mask; 32198b9484cSchristos return result; 32298b9484cSchristos } 32398b9484cSchristos return val; 32498b9484cSchristos } 32598b9484cSchristos 32698b9484cSchristos HI 3274b169a6bSchristos ROLHI (HI val, int shift) 32898b9484cSchristos { 32998b9484cSchristos if (shift != 0) 33098b9484cSchristos { 33198b9484cSchristos int remain = 16 - shift; 33298b9484cSchristos int mask = (1 << remain) - 1; 33398b9484cSchristos HI result = (val & mask) << shift; 33498b9484cSchristos mask = (1 << shift) - 1; 33598b9484cSchristos result |= (val >> remain) & mask; 33698b9484cSchristos return result; 33798b9484cSchristos } 33898b9484cSchristos return val; 33998b9484cSchristos } 34098b9484cSchristos 34198b9484cSchristos SI 3424b169a6bSchristos RORSI (SI val, int shift) 34398b9484cSchristos { 34498b9484cSchristos if (shift != 0) 34598b9484cSchristos { 34698b9484cSchristos int remain = 32 - shift; 34798b9484cSchristos int mask = (1 << shift) - 1; 34898b9484cSchristos SI result = (val & mask) << remain; 34998b9484cSchristos mask = (1 << remain) - 1; 35098b9484cSchristos result |= (val >> shift) & mask; 35198b9484cSchristos return result; 35298b9484cSchristos } 35398b9484cSchristos return val; 35498b9484cSchristos } 35598b9484cSchristos 35698b9484cSchristos SI 3574b169a6bSchristos ROLSI (SI val, int shift) 35898b9484cSchristos { 35998b9484cSchristos if (shift != 0) 36098b9484cSchristos { 36198b9484cSchristos int remain = 32 - shift; 36298b9484cSchristos int mask = (1 << remain) - 1; 36398b9484cSchristos SI result = (val & mask) << shift; 36498b9484cSchristos mask = (1 << shift) - 1; 36598b9484cSchristos result |= (val >> remain) & mask; 36698b9484cSchristos return result; 36798b9484cSchristos } 36898b9484cSchristos 36998b9484cSchristos return val; 37098b9484cSchristos } 37198b9484cSchristos 37298b9484cSchristos /* Emit an error message from CGEN RTL. */ 37398b9484cSchristos 37498b9484cSchristos void 37598b9484cSchristos cgen_rtx_error (SIM_CPU *cpu, const char * msg) 37698b9484cSchristos { 37798b9484cSchristos SIM_DESC sd = CPU_STATE (cpu); 37898b9484cSchristos 3794b169a6bSchristos sim_io_printf (sd, "%s", msg); 38098b9484cSchristos sim_io_printf (sd, "\n"); 38198b9484cSchristos 382212397c6Schristos sim_engine_halt (sd, cpu, NULL, CPU_PC_GET (cpu), sim_stopped, SIM_SIGTRAP); 38398b9484cSchristos } 384