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