1/* Support code for various pieces of CGEN simulators. 2 Copyright (C) 1996-2023 Free Software Foundation, Inc. 3 Contributed by Cygnus Support. 4 5This file is part of GDB, the GNU debugger. 6 7This program is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3 of the License, or 10(at your option) any later version. 11 12This program is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20/* This must come before any other includes. */ 21#include "defs.h" 22 23#include "bfd.h" 24#include "dis-asm.h" 25 26#include "sim-main.h" 27#include "sim-signal.h" 28 29#define MEMOPS_DEFINE_INLINE 30#include "cgen-mem.h" 31 32#define SEMOPS_DEFINE_INLINE 33#include "cgen-ops.h" 34 35const char * const cgen_mode_names[] = { 36 "VOID", 37 "BI", 38 "QI", 39 "HI", 40 "SI", 41 "DI", 42 "UQI", 43 "UHI", 44 "USI", 45 "UDI", 46 "SF", 47 "DF", 48 "XF", 49 "TF", 50 0, /* MODE_TARGET_MAX */ 51 "INT", 52 "UINT", 53 "PTR" 54}; 55 56/* Opcode table for virtual insns used by the simulator. */ 57 58#define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL) 59 60static const CGEN_IBASE virtual_insn_entries[] = 61{ 62 { 63 VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, {} } 64 }, 65 { 66 VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, {} } 67 }, 68 { 69 VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, {} } 70 }, 71 { 72 VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, {} } 73 }, 74 { 75 VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, {} } 76 }, 77 { 78 VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, {} } 79 } 80}; 81 82#undef V 83 84const CGEN_INSN cgen_virtual_insn_table[] = 85{ 86 { & virtual_insn_entries[0] }, 87 { & virtual_insn_entries[1] }, 88 { & virtual_insn_entries[2] }, 89 { & virtual_insn_entries[3] }, 90 { & virtual_insn_entries[4] }, 91 { & virtual_insn_entries[5] } 92}; 93 94/* Return the name of insn number I. */ 95 96const char * 97cgen_insn_name (SIM_CPU *cpu, int i) 98{ 99 return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i))); 100} 101 102/* Return the maximum number of extra bytes required for a SIM_CPU struct. */ 103 104int 105cgen_cpu_max_extra_bytes (SIM_DESC sd) 106{ 107 const SIM_MACH * const *machp; 108 int extra = 0; 109 110 SIM_ASSERT (STATE_MACHS (sd) != NULL); 111 112 for (machp = STATE_MACHS (sd); *machp != NULL; ++machp) 113 { 114 int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (*machp)); 115 if (size > extra) 116 extra = size; 117 } 118 return extra; 119} 120 121#ifdef DI_FN_SUPPORT 122 123DI 124ANDDI (a, b) 125 DI a, b; 126{ 127 SI ahi = GETHIDI (a); 128 SI alo = GETLODI (a); 129 SI bhi = GETHIDI (b); 130 SI blo = GETLODI (b); 131 return MAKEDI (ahi & bhi, alo & blo); 132} 133 134DI 135ORDI (a, b) 136 DI a, b; 137{ 138 SI ahi = GETHIDI (a); 139 SI alo = GETLODI (a); 140 SI bhi = GETHIDI (b); 141 SI blo = GETLODI (b); 142 return MAKEDI (ahi | bhi, alo | blo); 143} 144 145DI 146ADDDI (a, b) 147 DI a, b; 148{ 149 USI ahi = GETHIDI (a); 150 USI alo = GETLODI (a); 151 USI bhi = GETHIDI (b); 152 USI blo = GETLODI (b); 153 USI x = alo + blo; 154 return MAKEDI (ahi + bhi + (x < alo), x); 155} 156 157DI 158MULDI (a, b) 159 DI a, b; 160{ 161 USI ahi = GETHIDI (a); 162 USI alo = GETLODI (a); 163 USI bhi = GETHIDI (b); 164 USI blo = GETLODI (b); 165 USI rhi,rlo; 166 USI x0, x1, x2, x3; 167 168 x0 = alo * blo; 169 x1 = alo * bhi; 170 x2 = ahi * blo; 171 x3 = ahi * bhi; 172 173#define SI_TYPE_SIZE 32 174#define BITS4 (SI_TYPE_SIZE / 4) 175#define ll_B (1L << (SI_TYPE_SIZE / 2)) 176#define ll_lowpart(t) ((USI) (t) % ll_B) 177#define ll_highpart(t) ((USI) (t) / ll_B) 178 x1 += ll_highpart (x0); /* this can't give carry */ 179 x1 += x2; /* but this indeed can */ 180 if (x1 < x2) /* did we get it? */ 181 x3 += ll_B; /* yes, add it in the proper pos. */ 182 183 rhi = x3 + ll_highpart (x1); 184 rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0); 185 return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo); 186} 187 188DI 189SHLDI (val, shift) 190 DI val; 191 SI shift; 192{ 193 USI hi = GETHIDI (val); 194 USI lo = GETLODI (val); 195 /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 196 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); 197} 198 199DI 200SLADI (val, shift) 201 DI val; 202 SI shift; 203{ 204 SI hi = GETHIDI (val); 205 USI lo = GETLODI (val); 206 /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 207 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); 208} 209 210DI 211SRADI (val, shift) 212 DI val; 213 SI shift; 214{ 215 SI hi = GETHIDI (val); 216 USI lo = GETLODI (val); 217 /* We use SRASI because the result is implementation defined if hi < 0. */ 218 /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 219 return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift)); 220} 221 222int 223GEDI (a, b) 224 DI a, b; 225{ 226 SI ahi = GETHIDI (a); 227 USI alo = GETLODI (a); 228 SI bhi = GETHIDI (b); 229 USI blo = GETLODI (b); 230 if (ahi > bhi) 231 return 1; 232 if (ahi == bhi) 233 return alo >= blo; 234 return 0; 235} 236 237int 238LEDI (a, b) 239 DI a, b; 240{ 241 SI ahi = GETHIDI (a); 242 USI alo = GETLODI (a); 243 SI bhi = GETHIDI (b); 244 USI blo = GETLODI (b); 245 if (ahi < bhi) 246 return 1; 247 if (ahi == bhi) 248 return alo <= blo; 249 return 0; 250} 251 252DI 253CONVHIDI (val) 254 HI val; 255{ 256 if (val < 0) 257 return MAKEDI (-1, val); 258 else 259 return MAKEDI (0, val); 260} 261 262DI 263CONVSIDI (val) 264 SI val; 265{ 266 if (val < 0) 267 return MAKEDI (-1, val); 268 else 269 return MAKEDI (0, val); 270} 271 272SI 273CONVDISI (val) 274 DI val; 275{ 276 return GETLODI (val); 277} 278 279#endif /* DI_FN_SUPPORT */ 280 281QI 282RORQI (QI val, int shift) 283{ 284 if (shift != 0) 285 { 286 int remain = 8 - shift; 287 int mask = (1 << shift) - 1; 288 QI result = (val & mask) << remain; 289 mask = (1 << remain) - 1; 290 result |= (val >> shift) & mask; 291 return result; 292 } 293 return val; 294} 295 296QI 297ROLQI (QI val, int shift) 298{ 299 if (shift != 0) 300 { 301 int remain = 8 - shift; 302 int mask = (1 << remain) - 1; 303 QI result = (val & mask) << shift; 304 mask = (1 << shift) - 1; 305 result |= (val >> remain) & mask; 306 return result; 307 } 308 return val; 309} 310 311HI 312RORHI (HI val, int shift) 313{ 314 if (shift != 0) 315 { 316 int remain = 16 - shift; 317 int mask = (1 << shift) - 1; 318 HI result = (val & mask) << remain; 319 mask = (1 << remain) - 1; 320 result |= (val >> shift) & mask; 321 return result; 322 } 323 return val; 324} 325 326HI 327ROLHI (HI val, int shift) 328{ 329 if (shift != 0) 330 { 331 int remain = 16 - shift; 332 int mask = (1 << remain) - 1; 333 HI result = (val & mask) << shift; 334 mask = (1 << shift) - 1; 335 result |= (val >> remain) & mask; 336 return result; 337 } 338 return val; 339} 340 341SI 342RORSI (SI val, int shift) 343{ 344 if (shift != 0) 345 { 346 int remain = 32 - shift; 347 int mask = (1 << shift) - 1; 348 SI result = (val & mask) << remain; 349 mask = (1 << remain) - 1; 350 result |= (val >> shift) & mask; 351 return result; 352 } 353 return val; 354} 355 356SI 357ROLSI (SI val, int shift) 358{ 359 if (shift != 0) 360 { 361 int remain = 32 - shift; 362 int mask = (1 << remain) - 1; 363 SI result = (val & mask) << shift; 364 mask = (1 << shift) - 1; 365 result |= (val >> remain) & mask; 366 return result; 367 } 368 369 return val; 370} 371 372/* Emit an error message from CGEN RTL. */ 373 374void 375cgen_rtx_error (SIM_CPU *cpu, const char * msg) 376{ 377 SIM_DESC sd = CPU_STATE (cpu); 378 379 sim_io_printf (sd, "%s", msg); 380 sim_io_printf (sd, "\n"); 381 382 sim_engine_halt (sd, cpu, NULL, CPU_PC_GET (cpu), sim_stopped, SIM_SIGTRAP); 383} 384