1 /* Support code for various pieces of CGEN simulators. 2 Copyright (C) 1996-2024 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 /* 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 35 const 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 60 static 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 84 const 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 96 const char * 97 cgen_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 104 int 105 cgen_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 123 DI 124 ANDDI (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 134 DI 135 ORDI (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 145 DI 146 ADDDI (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 157 DI 158 MULDI (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 188 DI 189 SHLDI (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 199 DI 200 SLADI (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 210 DI 211 SRADI (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 222 int 223 GEDI (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 237 int 238 LEDI (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 252 DI 253 CONVHIDI (val) 254 HI val; 255 { 256 if (val < 0) 257 return MAKEDI (-1, val); 258 else 259 return MAKEDI (0, val); 260 } 261 262 DI 263 CONVSIDI (val) 264 SI val; 265 { 266 if (val < 0) 267 return MAKEDI (-1, val); 268 else 269 return MAKEDI (0, val); 270 } 271 272 SI 273 CONVDISI (val) 274 DI val; 275 { 276 return GETLODI (val); 277 } 278 279 #endif /* DI_FN_SUPPORT */ 280 281 QI 282 RORQI (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 296 QI 297 ROLQI (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 311 HI 312 RORHI (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 326 HI 327 ROLHI (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 341 SI 342 RORSI (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 356 SI 357 ROLSI (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 374 void 375 cgen_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