1/* Support code for various pieces of CGEN simulators. 2 Copyright (C) 1996-2020 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#include "config.h" 21#include "bfd.h" 22#include "sim-main.h" 23#include "dis-asm.h" 24 25#define MEMOPS_DEFINE_INLINE 26#include "cgen-mem.h" 27 28#define SEMOPS_DEFINE_INLINE 29#include "cgen-ops.h" 30 31const char * const mode_names[] = { 32 "VOID", 33 "BI", 34 "QI", 35 "HI", 36 "SI", 37 "DI", 38 "UQI", 39 "UHI", 40 "USI", 41 "UDI", 42 "SF", 43 "DF", 44 "XF", 45 "TF", 46 0, /* MODE_TARGET_MAX */ 47 "INT", 48 "UINT", 49 "PTR" 50}; 51 52/* Opcode table for virtual insns used by the simulator. */ 53 54#define V CGEN_ATTR_MASK (CGEN_INSN_VIRTUAL) 55 56static const CGEN_IBASE virtual_insn_entries[] = 57{ 58 { 59 VIRTUAL_INSN_X_INVALID, "--invalid--", NULL, 0, { V, { 0 } } 60 }, 61 { 62 VIRTUAL_INSN_X_BEFORE, "--before--", NULL, 0, { V, { 0 } } 63 }, 64 { 65 VIRTUAL_INSN_X_AFTER, "--after--", NULL, 0, { V, { 0 } } 66 }, 67 { 68 VIRTUAL_INSN_X_BEGIN, "--begin--", NULL, 0, { V, { 0 } } 69 }, 70 { 71 VIRTUAL_INSN_X_CHAIN, "--chain--", NULL, 0, { V, { 0 } } 72 }, 73 { 74 VIRTUAL_INSN_X_CTI_CHAIN, "--cti-chain--", NULL, 0, { V, { 0 } } 75 } 76}; 77 78#undef V 79 80const CGEN_INSN cgen_virtual_insn_table[] = 81{ 82 { & virtual_insn_entries[0] }, 83 { & virtual_insn_entries[1] }, 84 { & virtual_insn_entries[2] }, 85 { & virtual_insn_entries[3] }, 86 { & virtual_insn_entries[4] }, 87 { & virtual_insn_entries[5] } 88}; 89 90/* Initialize cgen things. 91 This is called after sim_post_argv_init. */ 92 93void 94cgen_init (SIM_DESC sd) 95{ 96 int i, c; 97 98 /* If no profiling or tracing has been enabled, run in fast mode. */ 99 { 100 int run_fast_p = 1; 101 102 for (c = 0; c < MAX_NR_PROCESSORS; ++c) 103 { 104 SIM_CPU *cpu = STATE_CPU (sd, c); 105 106 for (i = 0; i < MAX_PROFILE_VALUES; ++i) 107 if (CPU_PROFILE_FLAGS (cpu) [i]) 108 { 109 run_fast_p = 0; 110 break; 111 } 112 for (i = 0; i < MAX_TRACE_VALUES; ++i) 113 if (CPU_TRACE_FLAGS (cpu) [i]) 114 { 115 run_fast_p = 0; 116 break; 117 } 118 if (! run_fast_p) 119 break; 120 } 121 STATE_RUN_FAST_P (sd) = run_fast_p; 122 } 123} 124 125/* Return the name of insn number I. */ 126 127const char * 128cgen_insn_name (SIM_CPU *cpu, int i) 129{ 130 return CGEN_INSN_NAME ((* CPU_GET_IDATA (cpu)) ((cpu), (i))); 131} 132 133/* Return the maximum number of extra bytes required for a SIM_CPU struct. */ 134 135int 136cgen_cpu_max_extra_bytes (void) 137{ 138 int i; 139 int extra = 0; 140 141 for (i = 0; sim_machs[i] != 0; ++i) 142 { 143 int size = IMP_PROPS_SIM_CPU_SIZE (MACH_IMP_PROPS (sim_machs[i])); 144 if (size > extra) 145 extra = size; 146 } 147 return extra; 148} 149 150#ifdef DI_FN_SUPPORT 151 152DI 153make_struct_di (hi, lo) 154 SI hi, lo; 155{ 156 DI result; 157 158 result.hi = hi; 159 result.lo = lo; 160 return result; 161} 162 163DI 164ANDDI (a, b) 165 DI a, b; 166{ 167 SI ahi = GETHIDI (a); 168 SI alo = GETLODI (a); 169 SI bhi = GETHIDI (b); 170 SI blo = GETLODI (b); 171 return MAKEDI (ahi & bhi, alo & blo); 172} 173 174DI 175ORDI (a, b) 176 DI a, b; 177{ 178 SI ahi = GETHIDI (a); 179 SI alo = GETLODI (a); 180 SI bhi = GETHIDI (b); 181 SI blo = GETLODI (b); 182 return MAKEDI (ahi | bhi, alo | blo); 183} 184 185DI 186ADDDI (a, b) 187 DI a, b; 188{ 189 USI ahi = GETHIDI (a); 190 USI alo = GETLODI (a); 191 USI bhi = GETHIDI (b); 192 USI blo = GETLODI (b); 193 USI x = alo + blo; 194 return MAKEDI (ahi + bhi + (x < alo), x); 195} 196 197DI 198MULDI (a, b) 199 DI a, b; 200{ 201 USI ahi = GETHIDI (a); 202 USI alo = GETLODI (a); 203 USI bhi = GETHIDI (b); 204 USI blo = GETLODI (b); 205 USI rhi,rlo; 206 USI x0, x1, x2, x3; 207 208 x0 = alo * blo; 209 x1 = alo * bhi; 210 x2 = ahi * blo; 211 x3 = ahi * bhi; 212 213#define SI_TYPE_SIZE 32 214#define BITS4 (SI_TYPE_SIZE / 4) 215#define ll_B (1L << (SI_TYPE_SIZE / 2)) 216#define ll_lowpart(t) ((USI) (t) % ll_B) 217#define ll_highpart(t) ((USI) (t) / ll_B) 218 x1 += ll_highpart (x0); /* this can't give carry */ 219 x1 += x2; /* but this indeed can */ 220 if (x1 < x2) /* did we get it? */ 221 x3 += ll_B; /* yes, add it in the proper pos. */ 222 223 rhi = x3 + ll_highpart (x1); 224 rlo = ll_lowpart (x1) * ll_B + ll_lowpart (x0); 225 return MAKEDI (rhi + (alo * bhi) + (ahi * blo), rlo); 226} 227 228DI 229SHLDI (val, shift) 230 DI val; 231 SI shift; 232{ 233 USI hi = GETHIDI (val); 234 USI lo = GETLODI (val); 235 /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 236 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); 237} 238 239DI 240SLADI (val, shift) 241 DI val; 242 SI shift; 243{ 244 SI hi = GETHIDI (val); 245 USI lo = GETLODI (val); 246 /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 247 return MAKEDI ((hi << shift) | (lo >> (32 - shift)), lo << shift); 248} 249 250DI 251SRADI (val, shift) 252 DI val; 253 SI shift; 254{ 255 SI hi = GETHIDI (val); 256 USI lo = GETLODI (val); 257 /* We use SRASI because the result is implementation defined if hi < 0. */ 258 /* FIXME: Need to worry about shift < 0 || shift >= 32. */ 259 return MAKEDI (SRASI (hi, shift), (hi << (32 - shift)) | (lo >> shift)); 260} 261 262int 263GEDI (a, b) 264 DI a, b; 265{ 266 SI ahi = GETHIDI (a); 267 USI alo = GETLODI (a); 268 SI bhi = GETHIDI (b); 269 USI blo = GETLODI (b); 270 if (ahi > bhi) 271 return 1; 272 if (ahi == bhi) 273 return alo >= blo; 274 return 0; 275} 276 277int 278LEDI (a, b) 279 DI a, b; 280{ 281 SI ahi = GETHIDI (a); 282 USI alo = GETLODI (a); 283 SI bhi = GETHIDI (b); 284 USI blo = GETLODI (b); 285 if (ahi < bhi) 286 return 1; 287 if (ahi == bhi) 288 return alo <= blo; 289 return 0; 290} 291 292DI 293CONVHIDI (val) 294 HI val; 295{ 296 if (val < 0) 297 return MAKEDI (-1, val); 298 else 299 return MAKEDI (0, val); 300} 301 302DI 303CONVSIDI (val) 304 SI val; 305{ 306 if (val < 0) 307 return MAKEDI (-1, val); 308 else 309 return MAKEDI (0, val); 310} 311 312SI 313CONVDISI (val) 314 DI val; 315{ 316 return GETLODI (val); 317} 318 319#endif /* DI_FN_SUPPORT */ 320 321QI 322RORQI (val, shift) 323 QI val; 324 int shift; 325{ 326 if (shift != 0) 327 { 328 int remain = 8 - shift; 329 int mask = (1 << shift) - 1; 330 QI result = (val & mask) << remain; 331 mask = (1 << remain) - 1; 332 result |= (val >> shift) & mask; 333 return result; 334 } 335 return val; 336} 337 338QI 339ROLQI (val, shift) 340 QI val; 341 int shift; 342{ 343 if (shift != 0) 344 { 345 int remain = 8 - shift; 346 int mask = (1 << remain) - 1; 347 QI result = (val & mask) << shift; 348 mask = (1 << shift) - 1; 349 result |= (val >> remain) & mask; 350 return result; 351 } 352 return val; 353} 354 355HI 356RORHI (val, shift) 357 HI val; 358 int shift; 359{ 360 if (shift != 0) 361 { 362 int remain = 16 - shift; 363 int mask = (1 << shift) - 1; 364 HI result = (val & mask) << remain; 365 mask = (1 << remain) - 1; 366 result |= (val >> shift) & mask; 367 return result; 368 } 369 return val; 370} 371 372HI 373ROLHI (val, shift) 374 HI val; 375 int shift; 376{ 377 if (shift != 0) 378 { 379 int remain = 16 - shift; 380 int mask = (1 << remain) - 1; 381 HI result = (val & mask) << shift; 382 mask = (1 << shift) - 1; 383 result |= (val >> remain) & mask; 384 return result; 385 } 386 return val; 387} 388 389SI 390RORSI (val, shift) 391 SI val; 392 int shift; 393{ 394 if (shift != 0) 395 { 396 int remain = 32 - shift; 397 int mask = (1 << shift) - 1; 398 SI result = (val & mask) << remain; 399 mask = (1 << remain) - 1; 400 result |= (val >> shift) & mask; 401 return result; 402 } 403 return val; 404} 405 406SI 407ROLSI (val, shift) 408 SI val; 409 int shift; 410{ 411 if (shift != 0) 412 { 413 int remain = 32 - shift; 414 int mask = (1 << remain) - 1; 415 SI result = (val & mask) << shift; 416 mask = (1 << shift) - 1; 417 result |= (val >> remain) & mask; 418 return result; 419 } 420 421 return val; 422} 423 424/* Emit an error message from CGEN RTL. */ 425 426void 427cgen_rtx_error (SIM_CPU *cpu, const char * msg) 428{ 429 SIM_DESC sd = CPU_STATE (cpu); 430 431 sim_io_printf (sd, msg); 432 sim_io_printf (sd, "\n"); 433 434 sim_engine_halt (sd, cpu, NULL, CPU_PC_GET (cpu), sim_stopped, SIM_SIGTRAP); 435} 436