1 /* Support code for various pieces of CGEN simulators. 2 Copyright (C) 1996-2019 Free Software Foundation, Inc. 3 Contributed by Cygnus Support. 4 5 This file is part of GDB, the GNU debugger. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along 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 31 const 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 56 static 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 80 const 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 93 void 94 cgen_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 127 const char * 128 cgen_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 135 int 136 cgen_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 152 DI 153 make_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 163 DI 164 ANDDI (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 174 DI 175 ORDI (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 185 DI 186 ADDDI (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 197 DI 198 MULDI (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 228 DI 229 SHLDI (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 239 DI 240 SLADI (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 250 DI 251 SRADI (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 262 int 263 GEDI (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 277 int 278 LEDI (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 292 DI 293 CONVHIDI (val) 294 HI val; 295 { 296 if (val < 0) 297 return MAKEDI (-1, val); 298 else 299 return MAKEDI (0, val); 300 } 301 302 DI 303 CONVSIDI (val) 304 SI val; 305 { 306 if (val < 0) 307 return MAKEDI (-1, val); 308 else 309 return MAKEDI (0, val); 310 } 311 312 SI 313 CONVDISI (val) 314 DI val; 315 { 316 return GETLODI (val); 317 } 318 319 #endif /* DI_FN_SUPPORT */ 320 321 QI 322 RORQI (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 338 QI 339 ROLQI (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 355 HI 356 RORHI (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 372 HI 373 ROLHI (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 389 SI 390 RORSI (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 406 SI 407 ROLSI (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 426 void 427 cgen_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