xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/cgen-utils.c (revision 88241920d21b339bf319c0e979ffda80c49a2936)
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