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 6This file is part of GDB, the GNU debugger. 7 8This program is free software; you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation; either version 3 of the License, or 11(at your option) any later version. 12 13This program is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along 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 34const 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 59static 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 83const 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 96void 97cgen_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 130const char * 131cgen_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 138int 139cgen_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 155DI 156make_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 166DI 167ANDDI (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 177DI 178ORDI (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 188DI 189ADDDI (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 200DI 201MULDI (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 231DI 232SHLDI (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 242DI 243SLADI (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 253DI 254SRADI (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 265int 266GEDI (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 280int 281LEDI (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 295DI 296CONVHIDI (val) 297 HI val; 298{ 299 if (val < 0) 300 return MAKEDI (-1, val); 301 else 302 return MAKEDI (0, val); 303} 304 305DI 306CONVSIDI (val) 307 SI val; 308{ 309 if (val < 0) 310 return MAKEDI (-1, val); 311 else 312 return MAKEDI (0, val); 313} 314 315SI 316CONVDISI (val) 317 DI val; 318{ 319 return GETLODI (val); 320} 321 322#endif /* DI_FN_SUPPORT */ 323 324QI 325RORQI (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 341QI 342ROLQI (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 358HI 359RORHI (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 375HI 376ROLHI (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 392SI 393RORSI (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 409SI 410ROLSI (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 429void 430cgen_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