1 /* Simulator for Analog Devices Blackfin processors. 2 3 Copyright (C) 2005-2024 Free Software Foundation, Inc. 4 Contributed by Analog Devices, Inc. 5 6 This file is part of simulators. 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 /* This must come before any other includes. */ 22 #include "defs.h" 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <inttypes.h> 28 29 #include "ansidecl.h" 30 #include "opcode/bfin.h" 31 #include "sim-main.h" 32 #include "arch.h" 33 #include "bfin-sim.h" 34 #include "dv-bfin_cec.h" 35 #include "dv-bfin_mmu.h" 36 37 #define HOST_LONG_WORD_SIZE (sizeof (long) * 8) 38 39 #define SIGNEXTEND(v, n) \ 40 (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n))) 41 42 static ATTRIBUTE_NORETURN void 43 illegal_instruction (SIM_CPU *cpu) 44 { 45 TRACE_INSN (cpu, "ILLEGAL INSTRUCTION"); 46 while (1) 47 cec_exception (cpu, VEC_UNDEF_I); 48 } 49 50 static ATTRIBUTE_NORETURN void 51 illegal_instruction_combination (SIM_CPU *cpu) 52 { 53 TRACE_INSN (cpu, "ILLEGAL INSTRUCTION COMBINATION"); 54 while (1) 55 cec_exception (cpu, VEC_ILGAL_I); 56 } 57 58 static ATTRIBUTE_NORETURN void 59 illegal_instruction_or_combination (SIM_CPU *cpu) 60 { 61 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 62 illegal_instruction_combination (cpu); 63 else 64 illegal_instruction (cpu); 65 } 66 67 static ATTRIBUTE_NORETURN void 68 unhandled_instruction (SIM_CPU *cpu, const char *insn) 69 { 70 SIM_DESC sd = CPU_STATE (cpu); 71 bu16 iw0, iw1; 72 bu32 iw2; 73 74 TRACE_EVENTS (cpu, "unhandled instruction"); 75 76 iw0 = IFETCH (PCREG); 77 iw1 = IFETCH (PCREG + 2); 78 iw2 = ((bu32)iw0 << 16) | iw1; 79 80 sim_io_eprintf (sd, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG, insn); 81 if ((iw0 & 0xc000) == 0xc000) 82 sim_io_eprintf (sd, "%08x", iw2); 83 else 84 sim_io_eprintf (sd, "%04x", iw0); 85 86 sim_io_eprintf (sd, ") ... aborting\n"); 87 88 illegal_instruction (cpu); 89 } 90 91 static const char * const astat_names[] = 92 { 93 [ 0] = "AZ", 94 [ 1] = "AN", 95 [ 2] = "AC0_COPY", 96 [ 3] = "V_COPY", 97 [ 4] = "ASTAT_4", 98 [ 5] = "CC", 99 [ 6] = "AQ", 100 [ 7] = "ASTAT_7", 101 [ 8] = "RND_MOD", 102 [ 9] = "ASTAT_9", 103 [10] = "ASTAT_10", 104 [11] = "ASTAT_11", 105 [12] = "AC0", 106 [13] = "AC1", 107 [14] = "ASTAT_14", 108 [15] = "ASTAT_15", 109 [16] = "AV0", 110 [17] = "AV0S", 111 [18] = "AV1", 112 [19] = "AV1S", 113 [20] = "ASTAT_20", 114 [21] = "ASTAT_21", 115 [22] = "ASTAT_22", 116 [23] = "ASTAT_23", 117 [24] = "V", 118 [25] = "VS", 119 [26] = "ASTAT_26", 120 [27] = "ASTAT_27", 121 [28] = "ASTAT_28", 122 [29] = "ASTAT_29", 123 [30] = "ASTAT_30", 124 [31] = "ASTAT_31", 125 }; 126 127 typedef enum 128 { 129 c_0, c_1, c_4, c_2, c_uimm2, c_uimm3, c_imm3, c_pcrel4, 130 c_imm4, c_uimm4s4, c_uimm4s4d, c_uimm4, c_uimm4s2, c_negimm5s4, c_imm5, 131 c_imm5d, c_uimm5, c_imm6, c_imm7, c_imm7d, c_imm8, c_uimm8, c_pcrel8, 132 c_uimm8s4, c_pcrel8s4, c_lppcrel10, c_pcrel10, c_pcrel12, c_imm16s4, 133 c_luimm16, c_imm16, c_imm16d, c_huimm16, c_rimm16, c_imm16s2, c_uimm16s4, 134 c_uimm16s4d, c_uimm16, c_pcrel24, c_uimm32, c_imm32, c_huimm32, c_huimm32e, 135 } const_forms_t; 136 137 static const struct 138 { 139 const char *name; 140 const int nbits; 141 const char reloc; 142 const char issigned; 143 const char pcrel; 144 const char scale; 145 const char offset; 146 const char negative; 147 const char positive; 148 const char decimal; 149 const char leading; 150 const char exact; 151 } constant_formats[] = 152 { 153 { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 154 { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 155 { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 156 { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 157 { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 158 { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 159 { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 160 { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0}, 161 { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 162 { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0}, 163 { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0}, 164 { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 165 { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0}, 166 { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0}, 167 { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 168 { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0}, 169 { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 170 { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 171 { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 172 { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0}, 173 { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 174 { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 175 { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0}, 176 { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 177 { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0}, 178 { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0}, 179 { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 180 { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 181 { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0}, 182 { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 183 { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 184 { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0}, 185 { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 186 { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, 187 { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0}, 188 { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0}, 189 { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0}, 190 { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 191 { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 192 { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 193 { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0}, 194 { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 195 { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 196 }; 197 198 static const char * 199 fmtconst_str (const_forms_t cf, bs32 x, bu32 pc) 200 { 201 static char buf[60]; 202 203 if (constant_formats[cf].reloc) 204 { 205 #if 0 206 bu32 ea = (((constant_formats[cf].pcrel ? SIGNEXTEND (x, constant_formats[cf].nbits) 207 : x) + constant_formats[cf].offset) << constant_formats[cf].scale); 208 if (constant_formats[cf].pcrel) 209 ea += pc; 210 if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact) 211 { 212 outf->print_address_func (ea, outf); 213 return ""; 214 } 215 else 216 #endif 217 { 218 sprintf (buf, "%#x", x); 219 return buf; 220 } 221 } 222 223 /* Negative constants have an implied sign bit. */ 224 if (constant_formats[cf].negative) 225 { 226 int nb = constant_formats[cf].nbits + 1; 227 228 x = x | (1 << constant_formats[cf].nbits); 229 x = SIGNEXTEND (x, nb); 230 } 231 else 232 x = constant_formats[cf].issigned ? SIGNEXTEND (x, constant_formats[cf].nbits) : x; 233 234 if (constant_formats[cf].offset) 235 x += constant_formats[cf].offset; 236 237 if (constant_formats[cf].scale) 238 x <<= constant_formats[cf].scale; 239 240 if (constant_formats[cf].decimal) 241 sprintf (buf, "%*i", constant_formats[cf].leading, x); 242 else 243 { 244 if (constant_formats[cf].issigned && x < 0) 245 sprintf (buf, "-0x%x", abs (x)); 246 else 247 sprintf (buf, "0x%x", x); 248 } 249 250 return buf; 251 } 252 253 static bu32 254 fmtconst_val (const_forms_t cf, bu32 x, bu32 pc) 255 { 256 if (0 && constant_formats[cf].reloc) 257 { 258 bu32 ea = (((constant_formats[cf].pcrel 259 ? (bu32)SIGNEXTEND (x, constant_formats[cf].nbits) 260 : x) + constant_formats[cf].offset) 261 << constant_formats[cf].scale); 262 if (constant_formats[cf].pcrel) 263 ea += pc; 264 265 return ea; 266 } 267 268 /* Negative constants have an implied sign bit. */ 269 if (constant_formats[cf].negative) 270 { 271 int nb = constant_formats[cf].nbits + 1; 272 x = x | (1 << constant_formats[cf].nbits); 273 x = SIGNEXTEND (x, nb); 274 } 275 else if (constant_formats[cf].issigned) 276 x = SIGNEXTEND (x, constant_formats[cf].nbits); 277 278 x += constant_formats[cf].offset; 279 x <<= constant_formats[cf].scale; 280 281 return x; 282 } 283 284 #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0) 285 #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0) 286 #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0) 287 #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc) 288 #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc) 289 #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc) 290 #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc) 291 #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc) 292 #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0) 293 #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0) 294 #define rimm16(x) fmtconst_val (c_rimm16, x, 0) 295 #define huimm16(x) fmtconst_val (c_huimm16, x, 0) 296 #define imm16(x) fmtconst_val (c_imm16, x, 0) 297 #define imm16_str(x) fmtconst_str (c_imm16, x, 0) 298 #define imm16d(x) fmtconst_val (c_imm16d, x, 0) 299 #define uimm2(x) fmtconst_val (c_uimm2, x, 0) 300 #define uimm3(x) fmtconst_val (c_uimm3, x, 0) 301 #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0) 302 #define luimm16(x) fmtconst_val (c_luimm16, x, 0) 303 #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0) 304 #define uimm4(x) fmtconst_val (c_uimm4, x, 0) 305 #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0) 306 #define uimm5(x) fmtconst_val (c_uimm5, x, 0) 307 #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0) 308 #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0) 309 #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0) 310 #define uimm8(x) fmtconst_val (c_uimm8, x, 0) 311 #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0) 312 #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0) 313 #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0) 314 #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0) 315 #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0) 316 #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0) 317 #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0) 318 #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc) 319 #define imm3(x) fmtconst_val (c_imm3, x, 0) 320 #define imm3_str(x) fmtconst_str (c_imm3, x, 0) 321 #define imm4(x) fmtconst_val (c_imm4, x, 0) 322 #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0) 323 #define imm5(x) fmtconst_val (c_imm5, x, 0) 324 #define imm5d(x) fmtconst_val (c_imm5d, x, 0) 325 #define imm6(x) fmtconst_val (c_imm6, x, 0) 326 #define imm7(x) fmtconst_val (c_imm7, x, 0) 327 #define imm7_str(x) fmtconst_str (c_imm7, x, 0) 328 #define imm7d(x) fmtconst_val (c_imm7d, x, 0) 329 #define imm8(x) fmtconst_val (c_imm8, x, 0) 330 #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc) 331 #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc) 332 #define uimm16(x) fmtconst_val (c_uimm16, x, 0) 333 #define uimm32(x) fmtconst_val (c_uimm32, x, 0) 334 #define imm32(x) fmtconst_val (c_imm32, x, 0) 335 #define huimm32(x) fmtconst_val (c_huimm32, x, 0) 336 #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0) 337 338 /* Table C-4. Core Register Encoding Map. */ 339 const char * const greg_names[] = 340 { 341 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", 342 "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP", 343 "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3", 344 "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3", 345 "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS", 346 "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", 347 "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2", 348 "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT", 349 }; 350 static const char * 351 get_allreg_name (int grp, int reg) 352 { 353 return greg_names[(grp << 3) | reg]; 354 } 355 static const char * 356 get_preg_name (int reg) 357 { 358 return get_allreg_name (1, reg); 359 } 360 361 static bool 362 reg_is_reserved (int grp, int reg) 363 { 364 return (grp == 4 && (reg == 4 || reg == 5)) || (grp == 5); 365 } 366 367 static bu32 * 368 get_allreg (SIM_CPU *cpu, int grp, int reg) 369 { 370 int fullreg = (grp << 3) | reg; 371 /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7, 372 REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP, 373 REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3, 374 REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3, 375 REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS, 376 , , , , , , , , 377 REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES, 378 REG_CYCLES2, 379 REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE, 380 REG_LASTREG */ 381 switch (fullreg >> 2) 382 { 383 case 0: case 1: return &DREG (reg); 384 case 2: case 3: return &PREG (reg); 385 case 4: return &IREG (reg & 3); 386 case 5: return &MREG (reg & 3); 387 case 6: return &BREG (reg & 3); 388 case 7: return &LREG (reg & 3); 389 default: 390 switch (fullreg) 391 { 392 case 32: return &AXREG (0); 393 case 33: return &AWREG (0); 394 case 34: return &AXREG (1); 395 case 35: return &AWREG (1); 396 case 39: return &RETSREG; 397 case 48: return &LCREG (0); 398 case 49: return <REG (0); 399 case 50: return &LBREG (0); 400 case 51: return &LCREG (1); 401 case 52: return <REG (1); 402 case 53: return &LBREG (1); 403 case 54: return &CYCLESREG; 404 case 55: return &CYCLES2REG; 405 case 56: return &USPREG; 406 case 57: return &SEQSTATREG; 407 case 58: return &SYSCFGREG; 408 case 59: return &RETIREG; 409 case 60: return &RETXREG; 410 case 61: return &RETNREG; 411 case 62: return &RETEREG; 412 case 63: return &EMUDAT_INREG; 413 } 414 illegal_instruction (cpu); 415 } 416 } 417 418 static const char * 419 amod0 (int s0, int x0) 420 { 421 static const char * const mod0[] = { 422 "", " (S)", " (CO)", " (SCO)", 423 }; 424 int i = s0 + (x0 << 1); 425 426 if (i < ARRAY_SIZE (mod0)) 427 return mod0[i]; 428 else 429 return ""; 430 } 431 432 static const char * 433 amod0amod2 (int s0, int x0, int aop0) 434 { 435 static const char * const mod02[] = { 436 "", " (S)", " (CO)", " (SCO)", 437 "", "", "", "", 438 " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)", 439 " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)", 440 }; 441 int i = s0 + (x0 << 1) + (aop0 << 2); 442 443 if (i < ARRAY_SIZE (mod02)) 444 return mod02[i]; 445 else 446 return ""; 447 } 448 449 static const char * 450 amod1 (int s0, int x0) 451 { 452 static const char * const mod1[] = { 453 " (NS)", " (S)", 454 }; 455 int i = s0 + (x0 << 1); 456 457 if (i < ARRAY_SIZE (mod1)) 458 return mod1[i]; 459 else 460 return ""; 461 } 462 463 static const char * 464 mac_optmode (int mmod, int MM) 465 { 466 static const char * const omode[] = { 467 [(M_S2RND << 1) + 0] = " (S2RND)", 468 [(M_T << 1) + 0] = " (T)", 469 [(M_W32 << 1) + 0] = " (W32)", 470 [(M_FU << 1) + 0] = " (FU)", 471 [(M_TFU << 1) + 0] = " (TFU)", 472 [(M_IS << 1) + 0] = " (IS)", 473 [(M_ISS2 << 1) + 0] = " (ISS2)", 474 [(M_IH << 1) + 0] = " (IH)", 475 [(M_IU << 1) + 0] = " (IU)", 476 [(M_S2RND << 1) + 1] = " (M, S2RND)", 477 [(M_T << 1) + 1] = " (M, T)", 478 [(M_W32 << 1) + 1] = " (M, W32)", 479 [(M_FU << 1) + 1] = " (M, FU)", 480 [(M_TFU << 1) + 1] = " (M, TFU)", 481 [(M_IS << 1) + 1] = " (M, IS)", 482 [(M_ISS2 << 1) + 1] = " (M, ISS2)", 483 [(M_IH << 1) + 1] = " (M, IH)", 484 [(M_IU << 1) + 1] = " (M, IU)", 485 }; 486 int i = MM + (mmod << 1); 487 488 if (i < ARRAY_SIZE (omode) && omode[i]) 489 return omode[i]; 490 else 491 return ""; 492 } 493 494 static const char * 495 get_store_name (SIM_CPU *cpu, bu32 *p) 496 { 497 if (p >= &DREG (0) && p <= &CYCLESREG) 498 return greg_names[p - &DREG (0)]; 499 else if (p == &AXREG (0)) 500 return greg_names[4 * 8 + 0]; 501 else if (p == &AWREG (0)) 502 return greg_names[4 * 8 + 1]; 503 else if (p == &AXREG (1)) 504 return greg_names[4 * 8 + 2]; 505 else if (p == &AWREG (1)) 506 return greg_names[4 * 8 + 3]; 507 else if (p == &ASTATREG (ac0)) 508 return "ASTAT[ac0]"; 509 else if (p == &ASTATREG (ac0_copy)) 510 return "ASTAT[ac0_copy]"; 511 else if (p == &ASTATREG (ac1)) 512 return "ASTAT[ac1]"; 513 else if (p == &ASTATREG (an)) 514 return "ASTAT[an]"; 515 else if (p == &ASTATREG (aq)) 516 return "ASTAT[aq]"; 517 else if (p == &ASTATREG (av0)) 518 return "ASTAT[av0]"; 519 else if (p == &ASTATREG (av0s)) 520 return "ASTAT[av0s]"; 521 else if (p == &ASTATREG (av1)) 522 return "ASTAT[av1]"; 523 else if (p == &ASTATREG (av1s)) 524 return "ASTAT[av1s]"; 525 else if (p == &ASTATREG (az)) 526 return "ASTAT[az]"; 527 else if (p == &ASTATREG (v)) 528 return "ASTAT[v]"; 529 else if (p == &ASTATREG (v_copy)) 530 return "ASTAT[v_copy]"; 531 else if (p == &ASTATREG (vs)) 532 return "ASTAT[vs]"; 533 else 534 { 535 /* Worry about this when we start to STORE() it. */ 536 sim_io_eprintf (CPU_STATE (cpu), "STORE(): unknown register\n"); 537 abort (); 538 } 539 } 540 541 static void 542 queue_store (SIM_CPU *cpu, bu32 *addr, bu32 val) 543 { 544 struct store *s = &BFIN_CPU_STATE.stores[BFIN_CPU_STATE.n_stores]; 545 s->addr = addr; 546 s->val = val; 547 TRACE_REGISTER (cpu, "queuing write %s = %#x", 548 get_store_name (cpu, addr), val); 549 ++BFIN_CPU_STATE.n_stores; 550 } 551 #define STORE(X, Y) \ 552 do { \ 553 if (BFIN_CPU_STATE.n_stores == 20) abort (); \ 554 queue_store (cpu, &(X), (Y)); \ 555 } while (0) 556 557 static void 558 setflags_nz (SIM_CPU *cpu, bu32 val) 559 { 560 SET_ASTATREG (az, val == 0); 561 SET_ASTATREG (an, val >> 31); 562 } 563 564 static void 565 setflags_nz_2x16 (SIM_CPU *cpu, bu32 val) 566 { 567 SET_ASTATREG (an, (bs16)val < 0 || (bs16)(val >> 16) < 0); 568 SET_ASTATREG (az, (bs16)val == 0 || (bs16)(val >> 16) == 0); 569 } 570 571 static void 572 setflags_logical (SIM_CPU *cpu, bu32 val) 573 { 574 setflags_nz (cpu, val); 575 SET_ASTATREG (ac0, 0); 576 SET_ASTATREG (v, 0); 577 } 578 579 static bu32 580 add_brev (bu32 addend1, bu32 addend2) 581 { 582 bu32 mask, b, r; 583 int i, cy; 584 585 mask = 0x80000000; 586 r = 0; 587 cy = 0; 588 589 for (i = 31; i >= 0; --i) 590 { 591 b = ((addend1 & mask) >> i) + ((addend2 & mask) >> i); 592 b += cy; 593 cy = b >> 1; 594 b &= 1; 595 r |= b << i; 596 mask >>= 1; 597 } 598 599 return r; 600 } 601 602 /* This is a bit crazy, but we want to simulate the hardware behavior exactly 603 rather than worry about the circular buffers being used correctly. Which 604 isn't to say there isn't room for improvement here, just that we want to 605 be conservative. See also dagsub(). */ 606 static bu32 607 dagadd (SIM_CPU *cpu, int dagno, bs32 M) 608 { 609 bu64 i = IREG (dagno); 610 bu64 l = LREG (dagno); 611 bu64 b = BREG (dagno); 612 bu64 m = (bu32)M; 613 614 bu64 LB, IM, IML; 615 bu32 im32, iml32, lb32, res; 616 bu64 msb, car; 617 618 /* A naïve implementation that mostly works: 619 res = i + m; 620 if (l && res >= b + l) 621 res -= l; 622 STORE (IREG (dagno), res); 623 */ 624 625 msb = (bu64)1 << 31; 626 car = (bu64)1 << 32; 627 628 IM = i + m; 629 im32 = IM; 630 LB = l + b; 631 lb32 = LB; 632 633 if (M < 0) 634 { 635 IML = i + m + l; 636 iml32 = IML; 637 if ((i & msb) || (IM & car)) 638 res = (im32 < b) ? iml32 : im32; 639 else 640 res = (im32 < b) ? im32 : iml32; 641 } 642 else 643 { 644 IML = i + m - l; 645 iml32 = IML; 646 if ((IM & car) == (LB & car)) 647 res = (im32 < lb32) ? im32 : iml32; 648 else 649 res = (im32 < lb32) ? iml32 : im32; 650 } 651 652 STORE (IREG (dagno), res); 653 return res; 654 } 655 656 /* See dagadd() notes above. */ 657 static bu32 658 dagsub (SIM_CPU *cpu, int dagno, bs32 M) 659 { 660 bu64 i = IREG (dagno); 661 bu64 l = LREG (dagno); 662 bu64 b = BREG (dagno); 663 bu64 m = (bu32)M; 664 665 bu64 mbar = (bu32)(~m + 1); 666 bu64 LB, IM, IML; 667 bu32 b32, im32, iml32, lb32, res; 668 bu64 msb, car; 669 670 /* A naïve implementation that mostly works: 671 res = i - m; 672 if (l && newi < b) 673 newi += l; 674 STORE (IREG (dagno), newi); 675 */ 676 677 msb = (bu64)1 << 31; 678 car = (bu64)1 << 32; 679 680 IM = i + mbar; 681 im32 = IM; 682 LB = l + b; 683 lb32 = LB; 684 685 if (M < 0) 686 { 687 IML = i + mbar - l; 688 iml32 = IML; 689 if (!!((i & msb) && (IM & car)) == !!(LB & car)) 690 res = (im32 < lb32) ? im32 : iml32; 691 else 692 res = (im32 < lb32) ? iml32 : im32; 693 } 694 else 695 { 696 IML = i + mbar + l; 697 iml32 = IML; 698 b32 = b; 699 if (M == 0 || IM & car) 700 res = (im32 < b32) ? iml32 : im32; 701 else 702 res = (im32 < b32) ? im32 : iml32; 703 } 704 705 STORE (IREG (dagno), res); 706 return res; 707 } 708 709 static bu40 710 ashiftrt (SIM_CPU *cpu, bu40 val, int cnt, int size) 711 { 712 int real_cnt = cnt > size ? size : cnt; 713 bu40 sgn = ~(((val & 0xFFFFFFFFFFull) >> (size - 1)) - 1); 714 int sgncnt = size - real_cnt; 715 if (sgncnt > 16) 716 sgn <<= 16, sgncnt -= 16; 717 sgn <<= sgncnt; 718 if (real_cnt > 16) 719 val >>= 16, real_cnt -= 16; 720 val >>= real_cnt; 721 val |= sgn; 722 SET_ASTATREG (an, val >> (size - 1)); 723 SET_ASTATREG (az, val == 0); 724 if (size != 40) 725 SET_ASTATREG (v, 0); 726 return val; 727 } 728 729 static bu64 730 lshiftrt (SIM_CPU *cpu, bu64 val, int cnt, int size) 731 { 732 int real_cnt = cnt > size ? size : cnt; 733 if (real_cnt > 16) 734 val >>= 16, real_cnt -= 16; 735 val >>= real_cnt; 736 switch (size) 737 { 738 case 16: 739 val &= 0xFFFF; 740 break; 741 case 32: 742 val &= 0xFFFFFFFF; 743 break; 744 case 40: 745 val &= 0xFFFFFFFFFFull; 746 break; 747 default: 748 illegal_instruction (cpu); 749 break; 750 } 751 SET_ASTATREG (an, val >> (size - 1)); 752 SET_ASTATREG (az, val == 0); 753 if (size != 40) 754 SET_ASTATREG (v, 0); 755 return val; 756 } 757 758 static bu64 759 lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate, bool overflow) 760 { 761 int v_i, real_cnt = cnt > size ? size : cnt; 762 bu64 sgn = ~((val >> (size - 1)) - 1); 763 int mask_cnt = size - 1; 764 bu64 masked, new_val = val; 765 bu64 mask = ~0; 766 767 mask <<= mask_cnt; 768 sgn <<= mask_cnt; 769 masked = val & mask; 770 771 if (real_cnt > 16) 772 new_val <<= 16, real_cnt -= 16; 773 774 new_val <<= real_cnt; 775 776 masked = new_val & mask; 777 778 /* If an operation would otherwise cause a positive value to overflow 779 and become negative, instead, saturation limits the result to the 780 maximum positive value for the size register being used. 781 782 Conversely, if an operation would otherwise cause a negative value 783 to overflow and become positive, saturation limits the result to the 784 maximum negative value for the register size. 785 786 However, it's a little more complex than looking at sign bits, we need 787 to see if we are shifting the sign information away... */ 788 if (((val << cnt) >> size) == 0 789 || (((val << cnt) >> size) == ~((bu32)~0 << cnt) 790 && ((new_val >> (size - 1)) & 0x1))) 791 v_i = 0; 792 else 793 v_i = 1; 794 795 switch (size) 796 { 797 case 16: 798 new_val &= 0xFFFF; 799 if (saturate && (v_i || ((val >> (size - 1)) != (new_val >> (size - 1))))) 800 { 801 new_val = (val >> (size - 1)) == 0 ? 0x7fff : 0x8000; 802 v_i = 1; 803 } 804 break; 805 case 32: 806 new_val &= 0xFFFFFFFF; 807 masked &= 0xFFFFFFFF; 808 sgn &= 0xFFFFFFFF; 809 if (saturate 810 && (v_i 811 || (sgn != masked) 812 || (!sgn && new_val == 0 && val != 0))) 813 { 814 new_val = sgn == 0 ? 0x7fffffff : 0x80000000; 815 v_i = 1; 816 } 817 break; 818 case 40: 819 new_val &= 0xFFFFFFFFFFull; 820 masked &= 0xFFFFFFFFFFull; 821 break; 822 default: 823 illegal_instruction (cpu); 824 break; 825 } 826 827 SET_ASTATREG (an, new_val >> (size - 1)); 828 SET_ASTATREG (az, new_val == 0); 829 if (size != 40) 830 { 831 SET_ASTATREG (v, overflow && v_i); 832 if (overflow && v_i) 833 SET_ASTATREG (vs, 1); 834 } 835 836 return new_val; 837 } 838 839 static bu32 840 algn (bu32 l, bu32 h, bu32 aln) 841 { 842 if (aln == 0) 843 return l; 844 else 845 return (l >> (8 * aln)) | (h << (32 - 8 * aln)); 846 } 847 848 static bu32 849 saturate_s16 (bu64 val, bu32 *overflow) 850 { 851 if ((bs64)val < -0x8000ll) 852 { 853 if (overflow) 854 *overflow = 1; 855 return 0x8000; 856 } 857 if ((bs64)val > 0x7fff) 858 { 859 if (overflow) 860 *overflow = 1; 861 return 0x7fff; 862 } 863 return val & 0xffff; 864 } 865 866 static bu40 867 rot40 (bu40 val, int shift, bu32 *cc) 868 { 869 const int nbits = 40; 870 bu40 ret; 871 872 shift = CLAMP (shift, -nbits, nbits); 873 if (shift == 0) 874 return val; 875 876 /* Reduce everything to rotate left. */ 877 if (shift < 0) 878 shift += nbits + 1; 879 880 ret = shift == nbits ? 0 : val << shift; 881 ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift); 882 ret |= (bu40)*cc << (shift - 1); 883 *cc = (val >> (nbits - shift)) & 1; 884 885 return ret; 886 } 887 888 static bu32 889 rot32 (bu32 val, int shift, bu32 *cc) 890 { 891 const int nbits = 32; 892 bu32 ret; 893 894 shift = CLAMP (shift, -nbits, nbits); 895 if (shift == 0) 896 return val; 897 898 /* Reduce everything to rotate left. */ 899 if (shift < 0) 900 shift += nbits + 1; 901 902 ret = shift == nbits ? 0 : val << shift; 903 ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift); 904 ret |= (bu32)*cc << (shift - 1); 905 *cc = (val >> (nbits - shift)) & 1; 906 907 return ret; 908 } 909 910 static bu32 911 add32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat) 912 { 913 int flgs = (a >> 31) & 1; 914 int flgo = (b >> 31) & 1; 915 bu32 v = a + b; 916 int flgn = (v >> 31) & 1; 917 int overflow = (flgs ^ flgn) & (flgo ^ flgn); 918 919 if (sat && overflow) 920 { 921 v = (bu32)1 << 31; 922 if (flgn) 923 v -= 1; 924 flgn = (v >> 31) & 1; 925 } 926 927 SET_ASTATREG (an, flgn); 928 if (overflow) 929 SET_ASTATREG (vs, 1); 930 SET_ASTATREG (v, overflow); 931 ASTATREG (v_internal) |= overflow; 932 SET_ASTATREG (az, v == 0); 933 if (carry) 934 SET_ASTATREG (ac0, ~a < b); 935 936 return v; 937 } 938 939 static bu32 940 sub32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat, int parallel) 941 { 942 int flgs = (a >> 31) & 1; 943 int flgo = (b >> 31) & 1; 944 bu32 v = a - b; 945 int flgn = (v >> 31) & 1; 946 int overflow = (flgs ^ flgo) & (flgn ^ flgs); 947 948 if (sat && overflow) 949 { 950 v = (bu32)1 << 31; 951 if (flgn) 952 v -= 1; 953 flgn = (v >> 31) & 1; 954 } 955 956 if (!parallel || flgn) 957 SET_ASTATREG (an, flgn); 958 if (overflow) 959 SET_ASTATREG (vs, 1); 960 if (!parallel || overflow) 961 SET_ASTATREG (v, overflow); 962 if (!parallel || overflow) 963 ASTATREG (v_internal) |= overflow; 964 if (!parallel || v == 0) 965 SET_ASTATREG (az, v == 0); 966 if (carry && (!parallel || b <= a)) 967 SET_ASTATREG (ac0, b <= a); 968 969 return v; 970 } 971 972 static bu32 973 add16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl, 974 bu32 *zero, bu32 *neg, int sat, int scale) 975 { 976 int flgs = (a >> 15) & 1; 977 int flgo = (b >> 15) & 1; 978 bs64 v = (bs16)a + (bs16)b; 979 int flgn = (v >> 15) & 1; 980 int overflow = (flgs ^ flgn) & (flgo ^ flgn); 981 982 switch (scale) 983 { 984 case 0: 985 break; 986 case 2: 987 /* (ASR) */ 988 v = (a >> 1) + (a & 0x8000) + (b >> 1) + (b & 0x8000) 989 + (((a & 1) + (b & 1)) >> 1); 990 v |= -(v & 0x8000); 991 break; 992 case 3: 993 /* (ASL) */ 994 v = (v << 1); 995 break; 996 default: 997 illegal_instruction (cpu); 998 } 999 1000 flgn = (v >> 15) & 1; 1001 overflow = (flgs ^ flgn) & (flgo ^ flgn); 1002 1003 if (v > (bs64)0xffff) 1004 overflow = 1; 1005 1006 if (sat) 1007 v = saturate_s16 (v, 0); 1008 1009 if (neg) 1010 *neg |= (v >> 15) & 1; 1011 if (overfl) 1012 *overfl |= overflow; 1013 if (zero) 1014 *zero |= (v & 0xFFFF) == 0; 1015 if (carry) 1016 *carry |= ((bu16)~a < (bu16)b); 1017 1018 return v & 0xffff; 1019 } 1020 1021 static bu32 1022 sub16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl, 1023 bu32 *zero, bu32 *neg, int sat, int scale) 1024 { 1025 int flgs = (a >> 15) & 1; 1026 int flgo = (b >> 15) & 1; 1027 bs64 v = (bs16)a - (bs16)b; 1028 int flgn = (v >> 15) & 1; 1029 int overflow = (flgs ^ flgo) & (flgn ^ flgs); 1030 1031 switch (scale) 1032 { 1033 case 0: 1034 break; 1035 case 2: 1036 /* (ASR) */ 1037 if (sat) 1038 v = ((a >> 1) + (a & 0x8000)) - ( (b >> 1) + (b & 0x8000)) 1039 + (((a & 1)-(b & 1))); 1040 else 1041 { 1042 v = ((v & 0xFFFF) >> 1); 1043 if ((!flgs & !flgo & flgn) 1044 || (flgs & !flgo & !flgn) 1045 || (flgs & flgo & flgn) 1046 || (flgs & !flgo & flgn)) 1047 v |= 0x8000; 1048 } 1049 v |= -(v & 0x8000); 1050 flgn = (v >> 15) & 1; 1051 overflow = (flgs ^ flgo) & (flgn ^ flgs); 1052 break; 1053 case 3: 1054 /* (ASL) */ 1055 v <<= 1; 1056 if (v > (bs64)0x7fff || v < (bs64)-0xffff) 1057 overflow = 1; 1058 break; 1059 default: 1060 illegal_instruction (cpu); 1061 } 1062 1063 if (sat) 1064 { 1065 v = saturate_s16 (v, 0); 1066 } 1067 if (neg) 1068 *neg |= (v >> 15) & 1; 1069 if (zero) 1070 *zero |= (v & 0xFFFF) == 0; 1071 if (overfl) 1072 *overfl |= overflow; 1073 if (carry) 1074 *carry |= (bu16)b <= (bu16)a; 1075 return v; 1076 } 1077 1078 static bu32 1079 min32 (SIM_CPU *cpu, bu32 a, bu32 b) 1080 { 1081 int val = a; 1082 if ((bs32)a > (bs32)b) 1083 val = b; 1084 setflags_nz (cpu, val); 1085 SET_ASTATREG (v, 0); 1086 return val; 1087 } 1088 1089 static bu32 1090 max32 (SIM_CPU *cpu, bu32 a, bu32 b) 1091 { 1092 int val = a; 1093 if ((bs32)a < (bs32)b) 1094 val = b; 1095 setflags_nz (cpu, val); 1096 SET_ASTATREG (v, 0); 1097 return val; 1098 } 1099 1100 static bu32 1101 min2x16 (SIM_CPU *cpu, bu32 a, bu32 b) 1102 { 1103 int val = a; 1104 if ((bs16)a > (bs16)b) 1105 val = (val & 0xFFFF0000) | (b & 0xFFFF); 1106 if ((bs16)(a >> 16) > (bs16)(b >> 16)) 1107 val = (val & 0xFFFF) | (b & 0xFFFF0000); 1108 setflags_nz_2x16 (cpu, val); 1109 SET_ASTATREG (v, 0); 1110 return val; 1111 } 1112 1113 static bu32 1114 max2x16 (SIM_CPU *cpu, bu32 a, bu32 b) 1115 { 1116 int val = a; 1117 if ((bs16)a < (bs16)b) 1118 val = (val & 0xFFFF0000) | (b & 0xFFFF); 1119 if ((bs16)(a >> 16) < (bs16)(b >> 16)) 1120 val = (val & 0xFFFF) | (b & 0xFFFF0000); 1121 setflags_nz_2x16 (cpu, val); 1122 SET_ASTATREG (v, 0); 1123 return val; 1124 } 1125 1126 static bu32 1127 add_and_shift (SIM_CPU *cpu, bu32 a, bu32 b, int shift) 1128 { 1129 int v; 1130 ASTATREG (v_internal) = 0; 1131 v = add32 (cpu, a, b, 0, 0); 1132 while (shift-- > 0) 1133 { 1134 int x = (v >> 30) & 0x3; 1135 if (x == 1 || x == 2) 1136 ASTATREG (v_internal) = 1; 1137 v <<= 1; 1138 } 1139 SET_ASTATREG (az, v == 0); 1140 SET_ASTATREG (an, v & 0x80000000); 1141 SET_ASTATREG (v, ASTATREG (v_internal)); 1142 if (ASTATREG (v)) 1143 SET_ASTATREG (vs, 1); 1144 return v; 1145 } 1146 1147 static bu32 1148 xor_reduce (bu64 acc0, bu64 acc1) 1149 { 1150 int i; 1151 bu32 v = 0; 1152 for (i = 0; i < 40; ++i) 1153 { 1154 v ^= (acc0 & acc1 & 1); 1155 acc0 >>= 1; 1156 acc1 >>= 1; 1157 } 1158 return v; 1159 } 1160 1161 /* DIVS ( Dreg, Dreg ) ; 1162 Initialize for DIVQ. Set the AQ status bit based on the signs of 1163 the 32-bit dividend and the 16-bit divisor. Left shift the dividend 1164 one bit. Copy AQ into the dividend LSB. */ 1165 static bu32 1166 divs (SIM_CPU *cpu, bu32 pquo, bu16 divisor) 1167 { 1168 bu16 r = pquo >> 16; 1169 int aq; 1170 1171 aq = (r ^ divisor) >> 15; /* Extract msb's and compute quotient bit. */ 1172 SET_ASTATREG (aq, aq); /* Update global quotient state. */ 1173 1174 pquo <<= 1; 1175 pquo |= aq; 1176 pquo = (pquo & 0x1FFFF) | (r << 17); 1177 return pquo; 1178 } 1179 1180 /* DIVQ ( Dreg, Dreg ) ; 1181 Based on AQ status bit, either add or subtract the divisor from 1182 the dividend. Then set the AQ status bit based on the MSBs of the 1183 32-bit dividend and the 16-bit divisor. Left shift the dividend one 1184 bit. Copy the logical inverse of AQ into the dividend LSB. */ 1185 static bu32 1186 divq (SIM_CPU *cpu, bu32 pquo, bu16 divisor) 1187 { 1188 unsigned short af = pquo >> 16; 1189 unsigned short r; 1190 int aq; 1191 1192 if (ASTATREG (aq)) 1193 r = divisor + af; 1194 else 1195 r = af - divisor; 1196 1197 aq = (r ^ divisor) >> 15; /* Extract msb's and compute quotient bit. */ 1198 SET_ASTATREG (aq, aq); /* Update global quotient state. */ 1199 1200 pquo <<= 1; 1201 pquo |= !aq; 1202 pquo = (pquo & 0x1FFFF) | (r << 17); 1203 return pquo; 1204 } 1205 1206 /* ONES ( Dreg ) ; 1207 Count the number of bits set to 1 in the 32bit value. */ 1208 static bu32 1209 ones (bu32 val) 1210 { 1211 bu32 i; 1212 bu32 ret; 1213 1214 ret = 0; 1215 for (i = 0; i < 32; ++i) 1216 ret += !!(val & (1 << i)); 1217 1218 return ret; 1219 } 1220 1221 static void 1222 reg_check_sup (SIM_CPU *cpu, int grp, int reg) 1223 { 1224 if (grp == 7) 1225 cec_require_supervisor (cpu); 1226 } 1227 1228 static void 1229 reg_write (SIM_CPU *cpu, int grp, int reg, bu32 value) 1230 { 1231 bu32 *whichreg; 1232 1233 /* ASTAT is special! */ 1234 if (grp == 4 && reg == 6) 1235 { 1236 SET_ASTAT (value); 1237 return; 1238 } 1239 1240 /* Check supervisor after get_allreg() so exception order is correct. */ 1241 whichreg = get_allreg (cpu, grp, reg); 1242 reg_check_sup (cpu, grp, reg); 1243 1244 if (whichreg == &CYCLES2REG) 1245 /* Writes to CYCLES2 goes to the shadow. */ 1246 whichreg = &CYCLES2SHDREG; 1247 else if (whichreg == &SEQSTATREG) 1248 /* Register is read only -- discard writes. */ 1249 return; 1250 else if (whichreg == &EMUDAT_INREG) 1251 /* Writes to EMUDAT goes to the output. */ 1252 whichreg = &EMUDAT_OUTREG; 1253 else if (whichreg == <REG (0) || whichreg == <REG (1)) 1254 /* Writes to LT clears LSB automatically. */ 1255 value &= ~0x1; 1256 else if (whichreg == &AXREG (0) || whichreg == &AXREG (1)) 1257 value &= 0xFF; 1258 1259 TRACE_REGISTER (cpu, "wrote %s = %#x", get_allreg_name (grp, reg), value); 1260 1261 *whichreg = value; 1262 } 1263 1264 static bu32 1265 reg_read (SIM_CPU *cpu, int grp, int reg) 1266 { 1267 bu32 *whichreg; 1268 bu32 value; 1269 1270 /* ASTAT is special! */ 1271 if (grp == 4 && reg == 6) 1272 return ASTAT; 1273 1274 /* Check supervisor after get_allreg() so exception order is correct. */ 1275 whichreg = get_allreg (cpu, grp, reg); 1276 reg_check_sup (cpu, grp, reg); 1277 1278 value = *whichreg; 1279 1280 if (whichreg == &CYCLESREG) 1281 /* Reads of CYCLES reloads CYCLES2 from the shadow. */ 1282 SET_CYCLES2REG (CYCLES2SHDREG); 1283 else if ((whichreg == &AXREG (1) || whichreg == &AXREG (0)) && (value & 0x80)) 1284 /* Sign extend if necessary. */ 1285 value |= 0xFFFFFF00; 1286 1287 return value; 1288 } 1289 1290 static bu64 1291 get_extended_cycles (SIM_CPU *cpu) 1292 { 1293 return ((bu64)CYCLES2SHDREG << 32) | CYCLESREG; 1294 } 1295 1296 /* We can't re-use sim_events_time() because the CYCLES registers may be 1297 written/cleared/reset/stopped/started at any time by software. */ 1298 static void 1299 cycles_inc (SIM_CPU *cpu, bu32 inc) 1300 { 1301 bu64 cycles; 1302 bu32 cycles2; 1303 1304 if (!(SYSCFGREG & SYSCFG_CCEN)) 1305 return; 1306 1307 cycles = get_extended_cycles (cpu) + inc; 1308 SET_CYCLESREG (cycles); 1309 cycles2 = cycles >> 32; 1310 if (CYCLES2SHDREG != cycles2) 1311 SET_CYCLES2SHDREG (cycles2); 1312 } 1313 1314 static bu64 1315 get_unextended_acc (SIM_CPU *cpu, int which) 1316 { 1317 return ((bu64)(AXREG (which) & 0xff) << 32) | AWREG (which); 1318 } 1319 1320 static bu64 1321 get_extended_acc (SIM_CPU *cpu, int which) 1322 { 1323 bu64 acc = AXREG (which); 1324 /* Sign extend accumulator values before adding. */ 1325 if (acc & 0x80) 1326 acc |= -0x80; 1327 else 1328 acc &= 0xFF; 1329 acc <<= 32; 1330 acc |= AWREG (which); 1331 return acc; 1332 } 1333 1334 /* Perform a multiplication of D registers SRC0 and SRC1, sign- or 1335 zero-extending the result to 64 bit. H0 and H1 determine whether the 1336 high part or the low part of the source registers is used. Store 1 in 1337 *PSAT if saturation occurs, 0 otherwise. */ 1338 static bu64 1339 decode_multfunc (SIM_CPU *cpu, int h0, int h1, int src0, int src1, int mmod, 1340 int MM, bu32 *psat) 1341 { 1342 bu32 s0 = DREG (src0), s1 = DREG (src1); 1343 bu32 sgn0, sgn1; 1344 bu32 val; 1345 bu64 val1; 1346 1347 if (h0) 1348 s0 >>= 16; 1349 1350 if (h1) 1351 s1 >>= 16; 1352 1353 s0 &= 0xffff; 1354 s1 &= 0xffff; 1355 1356 sgn0 = -(s0 & 0x8000); 1357 sgn1 = -(s1 & 0x8000); 1358 1359 if (MM) 1360 s0 |= sgn0; 1361 else 1362 switch (mmod) 1363 { 1364 case 0: 1365 case M_S2RND: 1366 case M_T: 1367 case M_IS: 1368 case M_ISS2: 1369 case M_IH: 1370 case M_W32: 1371 s0 |= sgn0; 1372 s1 |= sgn1; 1373 break; 1374 case M_FU: 1375 case M_IU: 1376 case M_TFU: 1377 break; 1378 default: 1379 illegal_instruction (cpu); 1380 } 1381 1382 val = s0 * s1; 1383 /* Perform shift correction if appropriate for the mode. */ 1384 *psat = 0; 1385 if (!MM && (mmod == 0 || mmod == M_T || mmod == M_S2RND || mmod == M_W32)) 1386 { 1387 if (val == 0x40000000) 1388 { 1389 if (mmod == M_W32) 1390 val = 0x7fffffff; 1391 else 1392 val = 0x80000000; 1393 *psat = 1; 1394 } 1395 else 1396 val <<= 1; 1397 } 1398 val1 = val; 1399 1400 /* In signed modes, sign extend. */ 1401 if (is_macmod_signed (mmod) || MM) 1402 val1 |= -(val1 & 0x80000000); 1403 1404 if (*psat) 1405 val1 &= 0xFFFFFFFFull; 1406 1407 return val1; 1408 } 1409 1410 static bu40 1411 saturate_s40_astat (bu64 val, bu32 *v) 1412 { 1413 if ((bs64)val < -((bs64)1 << 39)) 1414 { 1415 *v = 1; 1416 return -((bs64)1 << 39); 1417 } 1418 else if ((bs64)val > ((bs64)1 << 39) - 1) 1419 { 1420 *v = 1; 1421 return ((bu64)1 << 39) - 1; 1422 } 1423 *v = 0; /* No overflow. */ 1424 return val; 1425 } 1426 1427 static bu40 1428 saturate_s40 (bu64 val) 1429 { 1430 bu32 v; 1431 return saturate_s40_astat (val, &v); 1432 } 1433 1434 static bu32 1435 saturate_s32 (bu64 val, bu32 *overflow) 1436 { 1437 if ((bs64)val < -0x80000000ll) 1438 { 1439 if (overflow) 1440 *overflow = 1; 1441 return 0x80000000; 1442 } 1443 if ((bs64)val > 0x7fffffff) 1444 { 1445 if (overflow) 1446 *overflow = 1; 1447 return 0x7fffffff; 1448 } 1449 return val; 1450 } 1451 1452 static bu32 1453 saturate_u32 (bu64 val, bu32 *overflow) 1454 { 1455 if (val > 0xffffffff) 1456 { 1457 if (overflow) 1458 *overflow = 1; 1459 return 0xffffffff; 1460 } 1461 return val; 1462 } 1463 1464 static bu32 1465 saturate_u16 (bu64 val, bu32 *overflow) 1466 { 1467 if (val > 0xffff) 1468 { 1469 if (overflow) 1470 *overflow = 1; 1471 return 0xffff; 1472 } 1473 return val; 1474 } 1475 1476 static bu64 1477 rnd16 (bu64 val) 1478 { 1479 bu64 sgnbits; 1480 1481 /* FIXME: Should honour rounding mode. */ 1482 if ((val & 0xffff) > 0x8000 1483 || ((val & 0xffff) == 0x8000 && (val & 0x10000))) 1484 val += 0x8000; 1485 1486 sgnbits = val & 0xffff000000000000ull; 1487 val >>= 16; 1488 return val | sgnbits; 1489 } 1490 1491 static bu64 1492 trunc16 (bu64 val) 1493 { 1494 bu64 sgnbits = val & 0xffff000000000000ull; 1495 val >>= 16; 1496 return val | sgnbits; 1497 } 1498 1499 static int 1500 signbits (bu64 val, int size) 1501 { 1502 bu64 mask = (bu64)1 << (size - 1); 1503 bu64 bit = val & mask; 1504 int count = 0; 1505 for (;;) 1506 { 1507 mask >>= 1; 1508 bit >>= 1; 1509 if (mask == 0) 1510 break; 1511 if ((val & mask) != bit) 1512 break; 1513 count++; 1514 } 1515 if (size == 40) 1516 count -= 8; 1517 1518 return count; 1519 } 1520 1521 /* Extract a 16 or 32 bit value from a 64 bit multiplication result. 1522 These 64 bits must be sign- or zero-extended properly from the source 1523 we want to extract, either a 32 bit multiply or a 40 bit accumulator. */ 1524 1525 static bu32 1526 extract_mult (SIM_CPU *cpu, bu64 res, int mmod, int MM, 1527 int fullword, bu32 *overflow) 1528 { 1529 if (fullword) 1530 switch (mmod) 1531 { 1532 case 0: 1533 case M_IS: 1534 return saturate_s32 (res, overflow); 1535 case M_IU: 1536 if (MM) 1537 return saturate_s32 (res, overflow); 1538 return saturate_u32 (res, overflow); 1539 case M_FU: 1540 if (MM) 1541 return saturate_s32 (res, overflow); 1542 return saturate_u32 (res, overflow); 1543 case M_S2RND: 1544 case M_ISS2: 1545 return saturate_s32 (res << 1, overflow); 1546 default: 1547 illegal_instruction (cpu); 1548 } 1549 else 1550 switch (mmod) 1551 { 1552 case 0: 1553 case M_W32: 1554 case M_IH: 1555 return saturate_s16 (rnd16 (res), overflow); 1556 case M_IS: 1557 return saturate_s16 (res, overflow); 1558 case M_FU: 1559 if (MM) 1560 return saturate_s16 (rnd16 (res), overflow); 1561 return saturate_u16 (rnd16 (res), overflow); 1562 case M_IU: 1563 if (MM) 1564 return saturate_s16 (res, overflow); 1565 return saturate_u16 (res, overflow); 1566 1567 case M_T: 1568 return saturate_s16 (trunc16 (res), overflow); 1569 case M_TFU: 1570 if (MM) 1571 return saturate_s16 (trunc16 (res), overflow); 1572 return saturate_u16 (trunc16 (res), overflow); 1573 1574 case M_S2RND: 1575 return saturate_s16 (rnd16 (res << 1), overflow); 1576 case M_ISS2: 1577 return saturate_s16 (res << 1, overflow); 1578 default: 1579 illegal_instruction (cpu); 1580 } 1581 } 1582 1583 static bu32 1584 decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0, 1585 int src1, int mmod, int MM, int fullword, bu32 *overflow, 1586 bu32 *neg) 1587 { 1588 bu64 acc; 1589 bu32 sat = 0, tsat, ret; 1590 1591 /* Sign extend accumulator if necessary, otherwise unsigned. */ 1592 if (is_macmod_signed (mmod) || MM) 1593 acc = get_extended_acc (cpu, which); 1594 else 1595 acc = get_unextended_acc (cpu, which); 1596 1597 if (op != 3) 1598 { 1599 /* TODO: Figure out how the 32-bit sign is used. */ 1600 ATTRIBUTE_UNUSED bu8 sgn0 = (acc >> 31) & 1; 1601 bu8 sgn40 = (acc >> 39) & 1; 1602 bu40 nosat_acc; 1603 1604 /* This can't saturate, so we don't keep track of the sat flag. */ 1605 bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod, 1606 MM, &tsat); 1607 1608 /* Perform accumulation. */ 1609 switch (op) 1610 { 1611 case 0: 1612 acc = res; 1613 sgn0 = (acc >> 31) & 1; 1614 break; 1615 case 1: 1616 acc = acc + res; 1617 break; 1618 case 2: 1619 acc = acc - res; 1620 break; 1621 } 1622 1623 nosat_acc = acc; 1624 /* Saturate. */ 1625 switch (mmod) 1626 { 1627 case 0: 1628 case M_T: 1629 case M_IS: 1630 case M_ISS2: 1631 case M_S2RND: 1632 if ((bs64)acc < -((bs64)1 << 39)) 1633 acc = -((bu64)1 << 39), sat = 1; 1634 else if ((bs64)acc > 0x7fffffffffll) 1635 acc = 0x7fffffffffull, sat = 1; 1636 break; 1637 case M_TFU: 1638 if (MM) 1639 { 1640 if ((bs64)acc < -((bs64)1 << 39)) 1641 acc = -((bu64)1 << 39), sat = 1; 1642 if ((bs64)acc > 0x7FFFFFFFFFll) 1643 acc = 0x7FFFFFFFFFull, sat = 1; 1644 } 1645 else 1646 { 1647 if ((bs64)acc < 0) 1648 acc = 0, sat = 1; 1649 if ((bs64)acc > 0xFFFFFFFFFFull) 1650 acc = 0xFFFFFFFFFFull, sat = 1; 1651 } 1652 break; 1653 case M_IU: 1654 if (!MM && acc & 0x8000000000000000ull) 1655 acc = 0x0, sat = 1; 1656 if (!MM && acc > 0xFFFFFFFFFFull) 1657 acc = 0xFFFFFFFFFFull, sat = 1; 1658 if (MM && acc > 0xFFFFFFFFFFull) 1659 acc &= 0xFFFFFFFFFFull; 1660 if (acc & 0x8000000000ull) 1661 acc |= 0xffffff0000000000ull; 1662 break; 1663 case M_FU: 1664 if (MM) 1665 { 1666 if ((bs64)acc < -((bs64)1 << 39)) 1667 acc = -((bu64)1 << 39), sat = 1; 1668 if ((bs64)acc > 0x7FFFFFFFFFll) 1669 acc = 0x7FFFFFFFFFull, sat = 1; 1670 else if (acc & 0x8000000000ull) 1671 acc |= 0xffffff0000000000ull; 1672 } 1673 else 1674 { 1675 if ((bs64)acc < 0) 1676 acc = 0x0, sat = 1; 1677 else if ((bs64)acc > (bs64)0xFFFFFFFFFFll) 1678 acc = 0xFFFFFFFFFFull, sat = 1; 1679 } 1680 break; 1681 case M_IH: 1682 if ((bs64)acc < -0x80000000ll) 1683 acc = -0x80000000ull, sat = 1; 1684 else if ((bs64)acc > 0x7fffffffll) 1685 acc = 0x7fffffffull, sat = 1; 1686 break; 1687 case M_W32: 1688 /* check max negative value */ 1689 if (sgn40 && ((acc >> 31) != 0x1ffffffff) 1690 && ((acc >> 31) != 0x0)) 1691 acc = 0x80000000, sat = 1; 1692 if (!sat && !sgn40 && ((acc >> 31) != 0x0) 1693 && ((acc >> 31) != 0x1ffffffff)) 1694 acc = 0x7FFFFFFF, sat = 1; 1695 acc &= 0xffffffff; 1696 if (acc & 0x80000000) 1697 acc |= 0xffffffff00000000ull; 1698 if (tsat) 1699 sat = 1; 1700 break; 1701 default: 1702 illegal_instruction (cpu); 1703 } 1704 1705 if (acc & 0x8000000000ull) 1706 *neg = 1; 1707 1708 STORE (AXREG (which), (acc >> 32) & 0xff); 1709 STORE (AWREG (which), acc & 0xffffffff); 1710 STORE (ASTATREG (av[which]), sat); 1711 if (sat) 1712 STORE (ASTATREG (avs[which]), sat); 1713 1714 /* Figure out the overflow bit. */ 1715 if (sat) 1716 { 1717 if (fullword) 1718 *overflow = 1; 1719 else 1720 ret = extract_mult (cpu, nosat_acc, mmod, MM, fullword, overflow); 1721 } 1722 } 1723 1724 ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow); 1725 1726 if (!fullword) 1727 { 1728 if (ret & 0x8000) 1729 *neg = 1; 1730 } 1731 else 1732 { 1733 if (ret & 0x80000000) 1734 *neg = 1; 1735 } 1736 1737 return ret; 1738 } 1739 1740 bu32 1741 hwloop_get_next_pc (SIM_CPU *cpu, bu32 pc, bu32 insn_len) 1742 { 1743 int i; 1744 1745 if (insn_len == 0) 1746 return pc; 1747 1748 /* If our PC has reached the bottom of a hardware loop, 1749 move back up to the top of the hardware loop. */ 1750 for (i = 1; i >= 0; --i) 1751 if (LCREG (i) > 1 && pc == LBREG (i)) 1752 { 1753 BFIN_TRACE_BRANCH (cpu, pc, LTREG (i), i, "Hardware loop %i", i); 1754 return LTREG (i); 1755 } 1756 1757 return pc + insn_len; 1758 } 1759 1760 static void 1761 decode_ProgCtrl_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc) 1762 { 1763 /* ProgCtrl 1764 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 1765 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........| 1766 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 1767 int poprnd = ((iw0 >> ProgCtrl_poprnd_bits) & ProgCtrl_poprnd_mask); 1768 int prgfunc = ((iw0 >> ProgCtrl_prgfunc_bits) & ProgCtrl_prgfunc_mask); 1769 1770 TRACE_EXTRACT (cpu, "%s: poprnd:%i prgfunc:%i", __func__, poprnd, prgfunc); 1771 1772 if (prgfunc == 0 && poprnd == 0) 1773 { 1774 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_nop); 1775 TRACE_INSN (cpu, "NOP;"); 1776 } 1777 else if (prgfunc == 1 && poprnd == 0) 1778 { 1779 bu32 newpc = RETSREG; 1780 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1781 TRACE_INSN (cpu, "RTS;"); 1782 IFETCH_CHECK (newpc); 1783 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1784 illegal_instruction_combination (cpu); 1785 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "RTS"); 1786 SET_PCREG (newpc); 1787 BFIN_CPU_STATE.did_jump = true; 1788 CYCLE_DELAY = 5; 1789 } 1790 else if (prgfunc == 1 && poprnd == 1) 1791 { 1792 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1793 TRACE_INSN (cpu, "RTI;"); 1794 /* Do not do IFETCH_CHECK here -- LSB has special meaning. */ 1795 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1796 illegal_instruction_combination (cpu); 1797 cec_return (cpu, -1); 1798 CYCLE_DELAY = 5; 1799 } 1800 else if (prgfunc == 1 && poprnd == 2) 1801 { 1802 bu32 newpc = RETXREG; 1803 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1804 TRACE_INSN (cpu, "RTX;"); 1805 /* XXX: Not sure if this is what the hardware does. */ 1806 IFETCH_CHECK (newpc); 1807 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1808 illegal_instruction_combination (cpu); 1809 cec_return (cpu, IVG_EVX); 1810 CYCLE_DELAY = 5; 1811 } 1812 else if (prgfunc == 1 && poprnd == 3) 1813 { 1814 bu32 newpc = RETNREG; 1815 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1816 TRACE_INSN (cpu, "RTN;"); 1817 /* XXX: Not sure if this is what the hardware does. */ 1818 IFETCH_CHECK (newpc); 1819 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1820 illegal_instruction_combination (cpu); 1821 cec_return (cpu, IVG_NMI); 1822 CYCLE_DELAY = 5; 1823 } 1824 else if (prgfunc == 1 && poprnd == 4) 1825 { 1826 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1827 TRACE_INSN (cpu, "RTE;"); 1828 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1829 illegal_instruction_combination (cpu); 1830 cec_return (cpu, IVG_EMU); 1831 CYCLE_DELAY = 5; 1832 } 1833 else if (prgfunc == 2 && poprnd == 0) 1834 { 1835 SIM_DESC sd = CPU_STATE (cpu); 1836 sim_events *events = STATE_EVENTS (sd); 1837 1838 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync); 1839 /* XXX: in supervisor mode, utilizes wake up sources 1840 in user mode, it's a NOP ... */ 1841 TRACE_INSN (cpu, "IDLE;"); 1842 1843 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1844 illegal_instruction_combination (cpu); 1845 1846 /* Timewarp ! */ 1847 if (events->queue) 1848 CYCLE_DELAY = events->time_from_event; 1849 else 1850 abort (); /* XXX: Should this ever happen ? */ 1851 } 1852 else if (prgfunc == 2 && poprnd == 3) 1853 { 1854 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync); 1855 /* Just NOP it. */ 1856 TRACE_INSN (cpu, "CSYNC;"); 1857 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1858 illegal_instruction_combination (cpu); 1859 CYCLE_DELAY = 10; 1860 } 1861 else if (prgfunc == 2 && poprnd == 4) 1862 { 1863 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync); 1864 /* Just NOP it. */ 1865 TRACE_INSN (cpu, "SSYNC;"); 1866 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1867 illegal_instruction_combination (cpu); 1868 1869 /* Really 10+, but no model info for this. */ 1870 CYCLE_DELAY = 10; 1871 } 1872 else if (prgfunc == 2 && poprnd == 5) 1873 { 1874 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec); 1875 TRACE_INSN (cpu, "EMUEXCPT;"); 1876 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1877 illegal_instruction_combination (cpu); 1878 cec_exception (cpu, VEC_SIM_TRAP); 1879 } 1880 else if (prgfunc == 3 && poprnd < 8) 1881 { 1882 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec); 1883 TRACE_INSN (cpu, "CLI R%i;", poprnd); 1884 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1885 illegal_instruction_combination (cpu); 1886 SET_DREG (poprnd, cec_cli (cpu)); 1887 } 1888 else if (prgfunc == 4 && poprnd < 8) 1889 { 1890 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec); 1891 TRACE_INSN (cpu, "STI R%i;", poprnd); 1892 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1893 illegal_instruction_combination (cpu); 1894 cec_sti (cpu, DREG (poprnd)); 1895 CYCLE_DELAY = 3; 1896 } 1897 else if (prgfunc == 5 && poprnd < 8) 1898 { 1899 bu32 newpc = PREG (poprnd); 1900 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1901 TRACE_INSN (cpu, "JUMP (%s);", get_preg_name (poprnd)); 1902 IFETCH_CHECK (newpc); 1903 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1904 illegal_instruction_combination (cpu); 1905 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (Preg)"); 1906 SET_PCREG (newpc); 1907 BFIN_CPU_STATE.did_jump = true; 1908 PROFILE_BRANCH_TAKEN (cpu); 1909 CYCLE_DELAY = 5; 1910 } 1911 else if (prgfunc == 6 && poprnd < 8) 1912 { 1913 bu32 newpc = PREG (poprnd); 1914 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1915 TRACE_INSN (cpu, "CALL (%s);", get_preg_name (poprnd)); 1916 IFETCH_CHECK (newpc); 1917 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1918 illegal_instruction_combination (cpu); 1919 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (Preg)"); 1920 /* If we're at the end of a hardware loop, RETS is going to be 1921 the top of the loop rather than the next instruction. */ 1922 SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2)); 1923 SET_PCREG (newpc); 1924 BFIN_CPU_STATE.did_jump = true; 1925 PROFILE_BRANCH_TAKEN (cpu); 1926 CYCLE_DELAY = 5; 1927 } 1928 else if (prgfunc == 7 && poprnd < 8) 1929 { 1930 bu32 newpc = pc + PREG (poprnd); 1931 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1932 TRACE_INSN (cpu, "CALL (PC + %s);", get_preg_name (poprnd)); 1933 IFETCH_CHECK (newpc); 1934 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1935 illegal_instruction_combination (cpu); 1936 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (PC + Preg)"); 1937 SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2)); 1938 SET_PCREG (newpc); 1939 BFIN_CPU_STATE.did_jump = true; 1940 PROFILE_BRANCH_TAKEN (cpu); 1941 CYCLE_DELAY = 5; 1942 } 1943 else if (prgfunc == 8 && poprnd < 8) 1944 { 1945 bu32 newpc = pc + PREG (poprnd); 1946 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch); 1947 TRACE_INSN (cpu, "JUMP (PC + %s);", get_preg_name (poprnd)); 1948 IFETCH_CHECK (newpc); 1949 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1950 illegal_instruction_combination (cpu); 1951 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (PC + Preg)"); 1952 SET_PCREG (newpc); 1953 BFIN_CPU_STATE.did_jump = true; 1954 PROFILE_BRANCH_TAKEN (cpu); 1955 CYCLE_DELAY = 5; 1956 } 1957 else if (prgfunc == 9) 1958 { 1959 int raise = uimm4 (poprnd); 1960 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec); 1961 TRACE_INSN (cpu, "RAISE %s;", uimm4_str (raise)); 1962 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1963 illegal_instruction_combination (cpu); 1964 cec_require_supervisor (cpu); 1965 if (raise == IVG_IVHW) 1966 cec_hwerr (cpu, HWERR_RAISE_5); 1967 else 1968 cec_latch (cpu, raise); 1969 CYCLE_DELAY = 3; /* XXX: Only if IVG is unmasked. */ 1970 } 1971 else if (prgfunc == 10) 1972 { 1973 int excpt = uimm4 (poprnd); 1974 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec); 1975 TRACE_INSN (cpu, "EXCPT %s;", uimm4_str (excpt)); 1976 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1977 illegal_instruction_combination (cpu); 1978 cec_exception (cpu, excpt); 1979 CYCLE_DELAY = 3; 1980 } 1981 else if (prgfunc == 11 && poprnd < 6) 1982 { 1983 bu32 addr = PREG (poprnd); 1984 bu8 byte; 1985 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_atomic); 1986 TRACE_INSN (cpu, "TESTSET (%s);", get_preg_name (poprnd)); 1987 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 1988 illegal_instruction_combination (cpu); 1989 byte = GET_WORD (addr); 1990 SET_CCREG (byte == 0); 1991 PUT_BYTE (addr, byte | 0x80); 1992 /* Also includes memory stalls, but we don't model that. */ 1993 CYCLE_DELAY = 2; 1994 } 1995 else 1996 illegal_instruction_or_combination (cpu); 1997 } 1998 1999 static void 2000 decode_CaCTRL_0 (SIM_CPU *cpu, bu16 iw0) 2001 { 2002 /* CaCTRL 2003 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2004 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......| 2005 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2006 int a = ((iw0 >> CaCTRL_a_bits) & CaCTRL_a_mask); 2007 int op = ((iw0 >> CaCTRL_op_bits) & CaCTRL_op_mask); 2008 int reg = ((iw0 >> CaCTRL_reg_bits) & CaCTRL_reg_mask); 2009 bu32 preg = PREG (reg); 2010 const char * const sinsn[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", }; 2011 2012 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CaCTRL); 2013 TRACE_EXTRACT (cpu, "%s: a:%i op:%i reg:%i", __func__, a, op, reg); 2014 TRACE_INSN (cpu, "%s [%s%s];", sinsn[op], get_preg_name (reg), a ? "++" : ""); 2015 2016 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2017 /* None of these can be part of a parallel instruction. */ 2018 illegal_instruction_combination (cpu); 2019 2020 /* No cache simulation, so these are (mostly) all NOPs. 2021 XXX: The hardware takes care of masking to cache lines, but need 2022 to check behavior of the post increment. Should we be aligning 2023 the value to the cache line before adding the cache line size, or 2024 do we just add the cache line size ? */ 2025 if (op == 0) 2026 { /* PREFETCH */ 2027 mmu_check_cache_addr (cpu, preg, false, false); 2028 } 2029 else if (op == 1) 2030 { /* FLUSHINV */ 2031 mmu_check_cache_addr (cpu, preg, true, false); 2032 } 2033 else if (op == 2) 2034 { /* FLUSH */ 2035 mmu_check_cache_addr (cpu, preg, true, false); 2036 } 2037 else if (op == 3) 2038 { /* IFLUSH */ 2039 mmu_check_cache_addr (cpu, preg, false, true); 2040 } 2041 2042 if (a) 2043 SET_PREG (reg, preg + BFIN_L1_CACHE_BYTES); 2044 } 2045 2046 static void 2047 decode_PushPopReg_0 (SIM_CPU *cpu, bu16 iw0) 2048 { 2049 /* PushPopReg 2050 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2051 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......| 2052 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2053 int W = ((iw0 >> PushPopReg_W_bits) & PushPopReg_W_mask); 2054 int grp = ((iw0 >> PushPopReg_grp_bits) & PushPopReg_grp_mask); 2055 int reg = ((iw0 >> PushPopReg_reg_bits) & PushPopReg_reg_mask); 2056 const char *reg_name = get_allreg_name (grp, reg); 2057 bu32 value; 2058 bu32 sp = SPREG; 2059 2060 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopReg); 2061 TRACE_EXTRACT (cpu, "%s: W:%i grp:%i reg:%i", __func__, W, grp, reg); 2062 TRACE_DECODE (cpu, "%s: reg:%s", __func__, reg_name); 2063 2064 /* Can't push/pop reserved registers */ 2065 if (reg_is_reserved (grp, reg)) 2066 illegal_instruction_or_combination (cpu); 2067 2068 if (W == 0) 2069 { 2070 /* Dreg and Preg are not supported by this instruction. */ 2071 if (grp == 0 || grp == 1) 2072 illegal_instruction_or_combination (cpu); 2073 TRACE_INSN (cpu, "%s = [SP++];", reg_name); 2074 /* Can't pop USP while in userspace. */ 2075 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE 2076 || (grp == 7 && reg == 0 && cec_is_user_mode(cpu))) 2077 illegal_instruction_combination (cpu); 2078 /* XXX: The valid register check is in reg_write(), so we might 2079 incorrectly do a GET_LONG() here ... */ 2080 value = GET_LONG (sp); 2081 reg_write (cpu, grp, reg, value); 2082 if (grp == 7 && reg == 3) 2083 cec_pop_reti (cpu); 2084 2085 sp += 4; 2086 } 2087 else 2088 { 2089 TRACE_INSN (cpu, "[--SP] = %s;", reg_name); 2090 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2091 illegal_instruction_combination (cpu); 2092 2093 sp -= 4; 2094 value = reg_read (cpu, grp, reg); 2095 if (grp == 7 && reg == 3) 2096 cec_push_reti (cpu); 2097 2098 PUT_LONG (sp, value); 2099 } 2100 2101 /* Note: SP update must be delayed until after all reads/writes; see 2102 comments in decode_PushPopMultiple_0() for more info. */ 2103 SET_SPREG (sp); 2104 } 2105 2106 static void 2107 decode_PushPopMultiple_0 (SIM_CPU *cpu, bu16 iw0) 2108 { 2109 /* PushPopMultiple 2110 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2111 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........| 2112 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2113 int p = ((iw0 >> PushPopMultiple_p_bits) & PushPopMultiple_p_mask); 2114 int d = ((iw0 >> PushPopMultiple_d_bits) & PushPopMultiple_d_mask); 2115 int W = ((iw0 >> PushPopMultiple_W_bits) & PushPopMultiple_W_mask); 2116 int dr = ((iw0 >> PushPopMultiple_dr_bits) & PushPopMultiple_dr_mask); 2117 int pr = ((iw0 >> PushPopMultiple_pr_bits) & PushPopMultiple_pr_mask); 2118 int i; 2119 bu32 sp = SPREG; 2120 2121 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopMultiple); 2122 TRACE_EXTRACT (cpu, "%s: d:%i p:%i W:%i dr:%i pr:%i", 2123 __func__, d, p, W, dr, pr); 2124 2125 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2126 illegal_instruction_combination (cpu); 2127 2128 if ((d == 0 && p == 0) || (p && imm5 (pr) > 5) 2129 || (d && !p && pr) || (p && !d && dr)) 2130 illegal_instruction (cpu); 2131 2132 if (W == 1) 2133 { 2134 if (d && p) 2135 TRACE_INSN (cpu, "[--SP] = (R7:%i, P5:%i);", dr, pr); 2136 else if (d) 2137 TRACE_INSN (cpu, "[--SP] = (R7:%i);", dr); 2138 else 2139 TRACE_INSN (cpu, "[--SP] = (P5:%i);", pr); 2140 2141 if (d) 2142 for (i = dr; i < 8; i++) 2143 { 2144 sp -= 4; 2145 PUT_LONG (sp, DREG (i)); 2146 } 2147 if (p) 2148 for (i = pr; i < 6; i++) 2149 { 2150 sp -= 4; 2151 PUT_LONG (sp, PREG (i)); 2152 } 2153 2154 CYCLE_DELAY = 14; 2155 } 2156 else 2157 { 2158 if (d && p) 2159 TRACE_INSN (cpu, "(R7:%i, P5:%i) = [SP++];", dr, pr); 2160 else if (d) 2161 TRACE_INSN (cpu, "(R7:%i) = [SP++];", dr); 2162 else 2163 TRACE_INSN (cpu, "(P5:%i) = [SP++];", pr); 2164 2165 if (p) 2166 for (i = 5; i >= pr; i--) 2167 { 2168 SET_PREG (i, GET_LONG (sp)); 2169 sp += 4; 2170 } 2171 if (d) 2172 for (i = 7; i >= dr; i--) 2173 { 2174 SET_DREG (i, GET_LONG (sp)); 2175 sp += 4; 2176 } 2177 2178 CYCLE_DELAY = 11; 2179 } 2180 2181 /* Note: SP update must be delayed until after all reads/writes so that 2182 if an exception does occur, the insn may be re-executed as the 2183 SP has not yet changed. */ 2184 SET_SPREG (sp); 2185 } 2186 2187 static void 2188 decode_ccMV_0 (SIM_CPU *cpu, bu16 iw0) 2189 { 2190 /* ccMV 2191 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2192 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......| 2193 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2194 int s = ((iw0 >> CCmv_s_bits) & CCmv_s_mask); 2195 int d = ((iw0 >> CCmv_d_bits) & CCmv_d_mask); 2196 int T = ((iw0 >> CCmv_T_bits) & CCmv_T_mask); 2197 int src = ((iw0 >> CCmv_src_bits) & CCmv_src_mask); 2198 int dst = ((iw0 >> CCmv_dst_bits) & CCmv_dst_mask); 2199 int cond = T ? CCREG : ! CCREG; 2200 2201 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ccMV); 2202 TRACE_EXTRACT (cpu, "%s: T:%i d:%i s:%i dst:%i src:%i", 2203 __func__, T, d, s, dst, src); 2204 2205 TRACE_INSN (cpu, "IF %sCC %s = %s;", T ? "" : "! ", 2206 get_allreg_name (d, dst), 2207 get_allreg_name (s, src)); 2208 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2209 illegal_instruction_combination (cpu); 2210 2211 if (cond) 2212 reg_write (cpu, d, dst, reg_read (cpu, s, src)); 2213 } 2214 2215 static void 2216 decode_CCflag_0 (SIM_CPU *cpu, bu16 iw0) 2217 { 2218 /* CCflag 2219 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2220 | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........| 2221 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2222 int x = ((iw0 >> CCflag_x_bits) & CCflag_x_mask); 2223 int y = ((iw0 >> CCflag_y_bits) & CCflag_y_mask); 2224 int I = ((iw0 >> CCflag_I_bits) & CCflag_I_mask); 2225 int G = ((iw0 >> CCflag_G_bits) & CCflag_G_mask); 2226 int opc = ((iw0 >> CCflag_opc_bits) & CCflag_opc_mask); 2227 2228 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CCflag); 2229 TRACE_EXTRACT (cpu, "%s: I:%i opc:%i G:%i y:%i x:%i", 2230 __func__, I, opc, G, y, x); 2231 2232 if (opc > 4) 2233 { 2234 bs64 acc0 = get_extended_acc (cpu, 0); 2235 bs64 acc1 = get_extended_acc (cpu, 1); 2236 bs64 diff = acc0 - acc1; 2237 2238 if (x != 0 || y != 0) 2239 illegal_instruction_or_combination (cpu); 2240 2241 if (opc == 5 && I == 0 && G == 0) 2242 { 2243 TRACE_INSN (cpu, "CC = A0 == A1;"); 2244 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2245 illegal_instruction_combination (cpu); 2246 SET_CCREG (acc0 == acc1); 2247 } 2248 else if (opc == 6 && I == 0 && G == 0) 2249 { 2250 TRACE_INSN (cpu, "CC = A0 < A1"); 2251 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2252 illegal_instruction_combination (cpu); 2253 SET_CCREG (acc0 < acc1); 2254 } 2255 else if (opc == 7 && I == 0 && G == 0) 2256 { 2257 TRACE_INSN (cpu, "CC = A0 <= A1"); 2258 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2259 illegal_instruction_combination (cpu); 2260 SET_CCREG (acc0 <= acc1); 2261 } 2262 else 2263 illegal_instruction_or_combination (cpu); 2264 2265 SET_ASTATREG (az, diff == 0); 2266 SET_ASTATREG (an, diff < 0); 2267 SET_ASTATREG (ac0, (bu40)acc1 <= (bu40)acc0); 2268 } 2269 else 2270 { 2271 int issigned = opc < 3; 2272 const char *sign = issigned ? "" : " (IU)"; 2273 bu32 srcop = G ? PREG (x) : DREG (x); 2274 char s = G ? 'P' : 'R'; 2275 bu32 dstop = I ? (issigned ? imm3 (y) : uimm3 (y)) : G ? PREG (y) : DREG (y); 2276 const char *op; 2277 char d = G ? 'P' : 'R'; 2278 int flgs = srcop >> 31; 2279 int flgo = dstop >> 31; 2280 2281 bu32 result = srcop - dstop; 2282 int cc; 2283 int flgn = result >> 31; 2284 int overflow = (flgs ^ flgo) & (flgn ^ flgs); 2285 int az = result == 0; 2286 int ac0 = dstop <= srcop; 2287 int an; 2288 if (issigned) 2289 an = (flgn && !overflow) || (!flgn && overflow); 2290 else 2291 an = dstop > srcop; 2292 2293 switch (opc) 2294 { 2295 default: /* Shutup useless gcc warnings. */ 2296 case 0: /* signed */ 2297 op = "=="; 2298 cc = az; 2299 break; 2300 case 1: /* signed */ 2301 op = "<"; 2302 cc = an; 2303 break; 2304 case 2: /* signed */ 2305 op = "<="; 2306 cc = an || az; 2307 break; 2308 case 3: /* unsigned */ 2309 op = "<"; 2310 cc = !ac0; 2311 break; 2312 case 4: /* unsigned */ 2313 op = "<="; 2314 cc = !ac0 || az; 2315 break; 2316 } 2317 2318 if (I) 2319 TRACE_INSN (cpu, "CC = %c%i %s %s%s;", s, x, op, 2320 issigned ? imm3_str (y) : uimm3_str (y), sign); 2321 else 2322 { 2323 TRACE_DECODE (cpu, "%s %c%i:%x %c%i:%x", __func__, 2324 s, x, srcop, d, y, dstop); 2325 TRACE_INSN (cpu, "CC = %c%i %s %c%i%s;", s, x, op, d, y, sign); 2326 } 2327 2328 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2329 illegal_instruction_combination (cpu); 2330 2331 SET_CCREG (cc); 2332 /* Pointer compares only touch CC. */ 2333 if (!G) 2334 { 2335 SET_ASTATREG (az, az); 2336 SET_ASTATREG (an, an); 2337 SET_ASTATREG (ac0, ac0); 2338 } 2339 } 2340 } 2341 2342 static void 2343 decode_CC2dreg_0 (SIM_CPU *cpu, bu16 iw0) 2344 { 2345 /* CC2dreg 2346 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2347 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......| 2348 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2349 int op = ((iw0 >> CC2dreg_op_bits) & CC2dreg_op_mask); 2350 int reg = ((iw0 >> CC2dreg_reg_bits) & CC2dreg_reg_mask); 2351 2352 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2dreg); 2353 TRACE_EXTRACT (cpu, "%s: op:%i reg:%i", __func__, op, reg); 2354 2355 if (op == 0) 2356 { 2357 TRACE_INSN (cpu, "R%i = CC;", reg); 2358 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2359 illegal_instruction_combination (cpu); 2360 SET_DREG (reg, CCREG); 2361 } 2362 else if (op == 1) 2363 { 2364 TRACE_INSN (cpu, "CC = R%i;", reg); 2365 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2366 illegal_instruction_combination (cpu); 2367 SET_CCREG (DREG (reg) != 0); 2368 } 2369 else if (op == 3 && reg == 0) 2370 { 2371 TRACE_INSN (cpu, "CC = !CC;"); 2372 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2373 illegal_instruction_combination (cpu); 2374 SET_CCREG (!CCREG); 2375 } 2376 else 2377 illegal_instruction_or_combination (cpu); 2378 } 2379 2380 static void 2381 decode_CC2stat_0 (SIM_CPU *cpu, bu16 iw0) 2382 { 2383 /* CC2stat 2384 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2385 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............| 2386 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2387 int D = ((iw0 >> CC2stat_D_bits) & CC2stat_D_mask); 2388 int op = ((iw0 >> CC2stat_op_bits) & CC2stat_op_mask); 2389 int cbit = ((iw0 >> CC2stat_cbit_bits) & CC2stat_cbit_mask); 2390 bu32 pval; 2391 2392 const char * const op_names[] = { "", "|", "&", "^" } ; 2393 2394 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2stat); 2395 TRACE_EXTRACT (cpu, "%s: D:%i op:%i cbit:%i", __func__, D, op, cbit); 2396 2397 TRACE_INSN (cpu, "%s %s= %s;", D ? astat_names[cbit] : "CC", 2398 op_names[op], D ? "CC" : astat_names[cbit]); 2399 2400 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2401 illegal_instruction_combination (cpu); 2402 2403 /* CC = CC; is invalid. */ 2404 if (cbit == 5) 2405 illegal_instruction (cpu); 2406 2407 pval = !!(ASTAT & (1 << cbit)); 2408 if (D == 0) 2409 switch (op) 2410 { 2411 case 0: SET_CCREG (pval); break; 2412 case 1: SET_CCREG (CCREG | pval); break; 2413 case 2: SET_CCREG (CCREG & pval); break; 2414 case 3: SET_CCREG (CCREG ^ pval); break; 2415 } 2416 else 2417 { 2418 switch (op) 2419 { 2420 case 0: pval = CCREG; break; 2421 case 1: pval |= CCREG; break; 2422 case 2: pval &= CCREG; break; 2423 case 3: pval ^= CCREG; break; 2424 } 2425 TRACE_REGISTER (cpu, "wrote ASTAT[%s] = %i", astat_names[cbit], pval); 2426 SET_ASTAT ((ASTAT & ~(1 << cbit)) | (pval << cbit)); 2427 } 2428 } 2429 2430 static void 2431 decode_BRCC_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc) 2432 { 2433 /* BRCC 2434 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2435 | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................| 2436 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2437 int B = ((iw0 >> BRCC_B_bits) & BRCC_B_mask); 2438 int T = ((iw0 >> BRCC_T_bits) & BRCC_T_mask); 2439 int offset = ((iw0 >> BRCC_offset_bits) & BRCC_offset_mask); 2440 int cond = T ? CCREG : ! CCREG; 2441 int pcrel = pcrel10 (offset); 2442 2443 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_BRCC); 2444 TRACE_EXTRACT (cpu, "%s: T:%i B:%i offset:%#x", __func__, T, B, offset); 2445 TRACE_DECODE (cpu, "%s: pcrel10:%#x", __func__, pcrel); 2446 2447 TRACE_INSN (cpu, "IF %sCC JUMP %#x%s;", T ? "" : "! ", 2448 pcrel, B ? " (bp)" : ""); 2449 2450 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2451 illegal_instruction_combination (cpu); 2452 2453 if (cond) 2454 { 2455 bu32 newpc = pc + pcrel; 2456 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "Conditional JUMP"); 2457 SET_PCREG (newpc); 2458 BFIN_CPU_STATE.did_jump = true; 2459 PROFILE_BRANCH_TAKEN (cpu); 2460 CYCLE_DELAY = B ? 5 : 9; 2461 } 2462 else 2463 { 2464 PROFILE_BRANCH_UNTAKEN (cpu); 2465 CYCLE_DELAY = B ? 9 : 1; 2466 } 2467 } 2468 2469 static void 2470 decode_UJUMP_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc) 2471 { 2472 /* UJUMP 2473 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2474 | 0 | 0 | 1 | 0 |.offset........................................| 2475 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2476 int offset = ((iw0 >> UJump_offset_bits) & UJump_offset_mask); 2477 int pcrel = pcrel12 (offset); 2478 bu32 newpc = pc + pcrel; 2479 2480 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_UJUMP); 2481 TRACE_EXTRACT (cpu, "%s: offset:%#x", __func__, offset); 2482 TRACE_DECODE (cpu, "%s: pcrel12:%#x", __func__, pcrel); 2483 2484 TRACE_INSN (cpu, "JUMP.S %#x;", pcrel); 2485 2486 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2487 illegal_instruction_combination (cpu); 2488 2489 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.S"); 2490 2491 SET_PCREG (newpc); 2492 BFIN_CPU_STATE.did_jump = true; 2493 PROFILE_BRANCH_TAKEN (cpu); 2494 CYCLE_DELAY = 5; 2495 } 2496 2497 static void 2498 decode_REGMV_0 (SIM_CPU *cpu, bu16 iw0) 2499 { 2500 /* REGMV 2501 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2502 | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......| 2503 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2504 int gs = ((iw0 >> RegMv_gs_bits) & RegMv_gs_mask); 2505 int gd = ((iw0 >> RegMv_gd_bits) & RegMv_gd_mask); 2506 int src = ((iw0 >> RegMv_src_bits) & RegMv_src_mask); 2507 int dst = ((iw0 >> RegMv_dst_bits) & RegMv_dst_mask); 2508 const char *srcreg_name = get_allreg_name (gs, src); 2509 const char *dstreg_name = get_allreg_name (gd, dst); 2510 2511 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_REGMV); 2512 TRACE_EXTRACT (cpu, "%s: gd:%i gs:%i dst:%i src:%i", 2513 __func__, gd, gs, dst, src); 2514 TRACE_DECODE (cpu, "%s: dst:%s src:%s", __func__, dstreg_name, srcreg_name); 2515 2516 TRACE_INSN (cpu, "%s = %s;", dstreg_name, srcreg_name); 2517 2518 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2519 illegal_instruction_combination (cpu); 2520 2521 /* Reserved slots cannot be a src/dst. */ 2522 if (reg_is_reserved (gs, src) || reg_is_reserved (gd, dst)) 2523 goto invalid_move; 2524 2525 /* Standard register moves. */ 2526 if ((gs < 2) /* Dregs/Pregs src */ 2527 || (gd < 2) /* Dregs/Pregs dst */ 2528 || (gs == 4 && src < 4) /* Accumulators src */ 2529 || (gd == 4 && dst < 4 && (gs < 4)) /* Accumulators dst */ 2530 || (gs == 7 && src == 7 && !(gd == 4 && dst < 4)) /* EMUDAT src */ 2531 || (gd == 7 && dst == 7)) /* EMUDAT dst */ 2532 goto valid_move; 2533 2534 /* dareg = dareg (IMBL) */ 2535 if (gs < 4 && gd < 4) 2536 goto valid_move; 2537 2538 /* USP can be src to sysregs, but not dagregs. */ 2539 if ((gs == 7 && src == 0) && (gd >= 4)) 2540 goto valid_move; 2541 2542 /* USP can move between genregs (only check Accumulators). */ 2543 if (((gs == 7 && src == 0) && (gd == 4 && dst < 4)) 2544 || ((gd == 7 && dst == 0) && (gs == 4 && src < 4))) 2545 goto valid_move; 2546 2547 /* Still here ? Invalid reg pair. */ 2548 invalid_move: 2549 illegal_instruction (cpu); 2550 2551 valid_move: 2552 reg_write (cpu, gd, dst, reg_read (cpu, gs, src)); 2553 } 2554 2555 static void 2556 decode_ALU2op_0 (SIM_CPU *cpu, bu16 iw0) 2557 { 2558 /* ALU2op 2559 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2560 | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......| 2561 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2562 int src = ((iw0 >> ALU2op_src_bits) & ALU2op_src_mask); 2563 int opc = ((iw0 >> ALU2op_opc_bits) & ALU2op_opc_mask); 2564 int dst = ((iw0 >> ALU2op_dst_bits) & ALU2op_dst_mask); 2565 2566 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ALU2op); 2567 TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst); 2568 2569 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2570 illegal_instruction_combination (cpu); 2571 2572 if (opc == 0) 2573 { 2574 TRACE_INSN (cpu, "R%i >>>= R%i;", dst, src); 2575 SET_DREG (dst, ashiftrt (cpu, DREG (dst), DREG (src), 32)); 2576 } 2577 else if (opc == 1) 2578 { 2579 bu32 val; 2580 TRACE_INSN (cpu, "R%i >>= R%i;", dst, src); 2581 if (DREG (src) <= 0x1F) 2582 val = lshiftrt (cpu, DREG (dst), DREG (src), 32); 2583 else 2584 val = 0; 2585 SET_DREG (dst, val); 2586 } 2587 else if (opc == 2) 2588 { 2589 TRACE_INSN (cpu, "R%i <<= R%i;", dst, src); 2590 SET_DREG (dst, lshift (cpu, DREG (dst), DREG (src), 32, 0, 0)); 2591 } 2592 else if (opc == 3) 2593 { 2594 TRACE_INSN (cpu, "R%i *= R%i;", dst, src); 2595 SET_DREG (dst, DREG (dst) * DREG (src)); 2596 CYCLE_DELAY = 3; 2597 } 2598 else if (opc == 4) 2599 { 2600 TRACE_INSN (cpu, "R%i = (R%i + R%i) << 1;", dst, dst, src); 2601 SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 1)); 2602 } 2603 else if (opc == 5) 2604 { 2605 TRACE_INSN (cpu, "R%i = (R%i + R%i) << 2;", dst, dst, src); 2606 SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 2)); 2607 } 2608 else if (opc == 8) 2609 { 2610 TRACE_INSN (cpu, "DIVQ ( R%i, R%i );", dst, src); 2611 SET_DREG (dst, divq (cpu, DREG (dst), (bu16)DREG (src))); 2612 } 2613 else if (opc == 9) 2614 { 2615 TRACE_INSN (cpu, "DIVS ( R%i, R%i );", dst, src); 2616 SET_DREG (dst, divs (cpu, DREG (dst), (bu16)DREG (src))); 2617 } 2618 else if (opc == 10) 2619 { 2620 TRACE_INSN (cpu, "R%i = R%i.L (X);", dst, src); 2621 SET_DREG (dst, (bs32) (bs16) DREG (src)); 2622 setflags_logical (cpu, DREG (dst)); 2623 } 2624 else if (opc == 11) 2625 { 2626 TRACE_INSN (cpu, "R%i = R%i.L (Z);", dst, src); 2627 SET_DREG (dst, (bu32) (bu16) DREG (src)); 2628 setflags_logical (cpu, DREG (dst)); 2629 } 2630 else if (opc == 12) 2631 { 2632 TRACE_INSN (cpu, "R%i = R%i.B (X);", dst, src); 2633 SET_DREG (dst, (bs32) (bs8) DREG (src)); 2634 setflags_logical (cpu, DREG (dst)); 2635 } 2636 else if (opc == 13) 2637 { 2638 TRACE_INSN (cpu, "R%i = R%i.B (Z);", dst, src); 2639 SET_DREG (dst, (bu32) (bu8) DREG (src)); 2640 setflags_logical (cpu, DREG (dst)); 2641 } 2642 else if (opc == 14) 2643 { 2644 bu32 val = DREG (src); 2645 TRACE_INSN (cpu, "R%i = - R%i;", dst, src); 2646 SET_DREG (dst, -val); 2647 setflags_nz (cpu, DREG (dst)); 2648 SET_ASTATREG (v, val == 0x80000000); 2649 if (ASTATREG (v)) 2650 SET_ASTATREG (vs, 1); 2651 SET_ASTATREG (ac0, val == 0x0); 2652 /* XXX: Documentation isn't entirely clear about av0 and av1. */ 2653 } 2654 else if (opc == 15) 2655 { 2656 TRACE_INSN (cpu, "R%i = ~ R%i;", dst, src); 2657 SET_DREG (dst, ~DREG (src)); 2658 setflags_logical (cpu, DREG (dst)); 2659 } 2660 else 2661 illegal_instruction (cpu); 2662 } 2663 2664 static void 2665 decode_PTR2op_0 (SIM_CPU *cpu, bu16 iw0) 2666 { 2667 /* PTR2op 2668 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2669 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......| 2670 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2671 int src = ((iw0 >> PTR2op_src_bits) & PTR2op_dst_mask); 2672 int opc = ((iw0 >> PTR2op_opc_bits) & PTR2op_opc_mask); 2673 int dst = ((iw0 >> PTR2op_dst_bits) & PTR2op_dst_mask); 2674 const char *src_name = get_preg_name (src); 2675 const char *dst_name = get_preg_name (dst); 2676 2677 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PTR2op); 2678 TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst); 2679 2680 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2681 illegal_instruction_combination (cpu); 2682 2683 if (opc == 0) 2684 { 2685 TRACE_INSN (cpu, "%s -= %s", dst_name, src_name); 2686 SET_PREG (dst, PREG (dst) - PREG (src)); 2687 } 2688 else if (opc == 1) 2689 { 2690 TRACE_INSN (cpu, "%s = %s << 2", dst_name, src_name); 2691 SET_PREG (dst, PREG (src) << 2); 2692 } 2693 else if (opc == 3) 2694 { 2695 TRACE_INSN (cpu, "%s = %s >> 2", dst_name, src_name); 2696 SET_PREG (dst, PREG (src) >> 2); 2697 } 2698 else if (opc == 4) 2699 { 2700 TRACE_INSN (cpu, "%s = %s >> 1", dst_name, src_name); 2701 SET_PREG (dst, PREG (src) >> 1); 2702 } 2703 else if (opc == 5) 2704 { 2705 TRACE_INSN (cpu, "%s += %s (BREV)", dst_name, src_name); 2706 SET_PREG (dst, add_brev (PREG (dst), PREG (src))); 2707 } 2708 else if (opc == 6) 2709 { 2710 TRACE_INSN (cpu, "%s = (%s + %s) << 1", dst_name, dst_name, src_name); 2711 SET_PREG (dst, (PREG (dst) + PREG (src)) << 1); 2712 } 2713 else if (opc == 7) 2714 { 2715 TRACE_INSN (cpu, "%s = (%s + %s) << 2", dst_name, dst_name, src_name); 2716 SET_PREG (dst, (PREG (dst) + PREG (src)) << 2); 2717 } 2718 else 2719 illegal_instruction (cpu); 2720 } 2721 2722 static void 2723 decode_LOGI2op_0 (SIM_CPU *cpu, bu16 iw0) 2724 { 2725 /* LOGI2op 2726 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2727 | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......| 2728 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2729 int src = ((iw0 >> LOGI2op_src_bits) & LOGI2op_src_mask); 2730 int opc = ((iw0 >> LOGI2op_opc_bits) & LOGI2op_opc_mask); 2731 int dst = ((iw0 >> LOGI2op_dst_bits) & LOGI2op_dst_mask); 2732 int uimm = uimm5 (src); 2733 const char *uimm_str = uimm5_str (uimm); 2734 2735 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LOGI2op); 2736 TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst); 2737 TRACE_DECODE (cpu, "%s: uimm5:%#x", __func__, uimm); 2738 2739 if (opc == 0) 2740 { 2741 TRACE_INSN (cpu, "CC = ! BITTST (R%i, %s);", dst, uimm_str); 2742 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2743 illegal_instruction_combination (cpu); 2744 SET_CCREG ((~DREG (dst) >> uimm) & 1); 2745 } 2746 else if (opc == 1) 2747 { 2748 TRACE_INSN (cpu, "CC = BITTST (R%i, %s);", dst, uimm_str); 2749 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2750 illegal_instruction_combination (cpu); 2751 SET_CCREG ((DREG (dst) >> uimm) & 1); 2752 } 2753 else if (opc == 2) 2754 { 2755 TRACE_INSN (cpu, "BITSET (R%i, %s);", dst, uimm_str); 2756 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2757 illegal_instruction_combination (cpu); 2758 SET_DREG (dst, DREG (dst) | (1 << uimm)); 2759 setflags_logical (cpu, DREG (dst)); 2760 } 2761 else if (opc == 3) 2762 { 2763 TRACE_INSN (cpu, "BITTGL (R%i, %s);", dst, uimm_str); 2764 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2765 illegal_instruction_combination (cpu); 2766 SET_DREG (dst, DREG (dst) ^ (1 << uimm)); 2767 setflags_logical (cpu, DREG (dst)); 2768 } 2769 else if (opc == 4) 2770 { 2771 TRACE_INSN (cpu, "BITCLR (R%i, %s);", dst, uimm_str); 2772 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2773 illegal_instruction_combination (cpu); 2774 SET_DREG (dst, DREG (dst) & ~(1 << uimm)); 2775 setflags_logical (cpu, DREG (dst)); 2776 } 2777 else if (opc == 5) 2778 { 2779 TRACE_INSN (cpu, "R%i >>>= %s;", dst, uimm_str); 2780 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2781 illegal_instruction_combination (cpu); 2782 SET_DREG (dst, ashiftrt (cpu, DREG (dst), uimm, 32)); 2783 } 2784 else if (opc == 6) 2785 { 2786 TRACE_INSN (cpu, "R%i >>= %s;", dst, uimm_str); 2787 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2788 illegal_instruction_combination (cpu); 2789 SET_DREG (dst, lshiftrt (cpu, DREG (dst), uimm, 32)); 2790 } 2791 else if (opc == 7) 2792 { 2793 TRACE_INSN (cpu, "R%i <<= %s;", dst, uimm_str); 2794 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2795 illegal_instruction_combination (cpu); 2796 SET_DREG (dst, lshift (cpu, DREG (dst), uimm, 32, 0, 0)); 2797 } 2798 } 2799 2800 static void 2801 decode_COMP3op_0 (SIM_CPU *cpu, bu16 iw0) 2802 { 2803 /* COMP3op 2804 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2805 | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......| 2806 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2807 int opc = ((iw0 >> COMP3op_opc_bits) & COMP3op_opc_mask); 2808 int dst = ((iw0 >> COMP3op_dst_bits) & COMP3op_dst_mask); 2809 int src0 = ((iw0 >> COMP3op_src0_bits) & COMP3op_src0_mask); 2810 int src1 = ((iw0 >> COMP3op_src1_bits) & COMP3op_src1_mask); 2811 2812 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMP3op); 2813 TRACE_EXTRACT (cpu, "%s: opc:%i dst:%i src1:%i src0:%i", 2814 __func__, opc, dst, src1, src0); 2815 2816 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2817 illegal_instruction_combination (cpu); 2818 2819 if (opc == 0) 2820 { 2821 TRACE_INSN (cpu, "R%i = R%i + R%i;", dst, src0, src1); 2822 SET_DREG (dst, add32 (cpu, DREG (src0), DREG (src1), 1, 0)); 2823 } 2824 else if (opc == 1) 2825 { 2826 TRACE_INSN (cpu, "R%i = R%i - R%i;", dst, src0, src1); 2827 SET_DREG (dst, sub32 (cpu, DREG (src0), DREG (src1), 1, 0, 0)); 2828 } 2829 else if (opc == 2) 2830 { 2831 TRACE_INSN (cpu, "R%i = R%i & R%i;", dst, src0, src1); 2832 SET_DREG (dst, DREG (src0) & DREG (src1)); 2833 setflags_logical (cpu, DREG (dst)); 2834 } 2835 else if (opc == 3) 2836 { 2837 TRACE_INSN (cpu, "R%i = R%i | R%i;", dst, src0, src1); 2838 SET_DREG (dst, DREG (src0) | DREG (src1)); 2839 setflags_logical (cpu, DREG (dst)); 2840 } 2841 else if (opc == 4) 2842 { 2843 TRACE_INSN (cpu, "R%i = R%i ^ R%i;", dst, src0, src1); 2844 SET_DREG (dst, DREG (src0) ^ DREG (src1)); 2845 setflags_logical (cpu, DREG (dst)); 2846 } 2847 else 2848 { 2849 int shift = opc - 5; 2850 const char *dst_name = get_preg_name (dst); 2851 const char *src0_name = get_preg_name (src0); 2852 const char *src1_name = get_preg_name (src1); 2853 2854 /* If src0 == src1 this is disassembled as a shift by 1, but this 2855 distinction doesn't matter for our purposes. */ 2856 if (shift) 2857 TRACE_INSN (cpu, "%s = (%s + %s) << %#x;", 2858 dst_name, src0_name, src1_name, shift); 2859 else 2860 TRACE_INSN (cpu, "%s = %s + %s", 2861 dst_name, src0_name, src1_name); 2862 SET_PREG (dst, PREG (src0) + (PREG (src1) << shift)); 2863 } 2864 } 2865 2866 static void 2867 decode_COMPI2opD_0 (SIM_CPU *cpu, bu16 iw0) 2868 { 2869 /* COMPI2opD 2870 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2871 | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......| 2872 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2873 int op = ((iw0 >> COMPI2opD_op_bits) & COMPI2opD_op_mask); 2874 int dst = ((iw0 >> COMPI2opD_dst_bits) & COMPI2opD_dst_mask); 2875 int src = ((iw0 >> COMPI2opD_src_bits) & COMPI2opD_src_mask); 2876 int imm = imm7 (src); 2877 2878 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opD); 2879 TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst); 2880 TRACE_DECODE (cpu, "%s: imm7:%#x", __func__, imm); 2881 2882 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2883 illegal_instruction_combination (cpu); 2884 2885 if (op == 0) 2886 { 2887 TRACE_INSN (cpu, "R%i = %s (X);", dst, imm7_str (imm)); 2888 SET_DREG (dst, imm); 2889 } 2890 else if (op == 1) 2891 { 2892 TRACE_INSN (cpu, "R%i += %s;", dst, imm7_str (imm)); 2893 SET_DREG (dst, add32 (cpu, DREG (dst), imm, 1, 0)); 2894 } 2895 } 2896 2897 static void 2898 decode_COMPI2opP_0 (SIM_CPU *cpu, bu16 iw0) 2899 { 2900 /* COMPI2opP 2901 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2902 | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......| 2903 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2904 int op = ((iw0 >> COMPI2opP_op_bits) & COMPI2opP_op_mask); 2905 int src = ((iw0 >> COMPI2opP_src_bits) & COMPI2opP_src_mask); 2906 int dst = ((iw0 >> COMPI2opP_dst_bits) & COMPI2opP_dst_mask); 2907 int imm = imm7 (src); 2908 const char *dst_name = get_preg_name (dst); 2909 2910 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opP); 2911 TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst); 2912 TRACE_DECODE (cpu, "%s: imm:%#x", __func__, imm); 2913 2914 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 2915 illegal_instruction_combination (cpu); 2916 2917 if (op == 0) 2918 { 2919 TRACE_INSN (cpu, "%s = %s;", dst_name, imm7_str (imm)); 2920 SET_PREG (dst, imm); 2921 } 2922 else if (op == 1) 2923 { 2924 TRACE_INSN (cpu, "%s += %s;", dst_name, imm7_str (imm)); 2925 SET_PREG (dst, PREG (dst) + imm); 2926 } 2927 } 2928 2929 static void 2930 decode_LDSTpmod_0 (SIM_CPU *cpu, bu16 iw0) 2931 { 2932 /* LDSTpmod 2933 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 2934 | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......| 2935 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 2936 int W = ((iw0 >> LDSTpmod_W_bits) & LDSTpmod_W_mask); 2937 int aop = ((iw0 >> LDSTpmod_aop_bits) & LDSTpmod_aop_mask); 2938 int idx = ((iw0 >> LDSTpmod_idx_bits) & LDSTpmod_idx_mask); 2939 int ptr = ((iw0 >> LDSTpmod_ptr_bits) & LDSTpmod_ptr_mask); 2940 int reg = ((iw0 >> LDSTpmod_reg_bits) & LDSTpmod_reg_mask); 2941 const char *ptr_name = get_preg_name (ptr); 2942 const char *idx_name = get_preg_name (idx); 2943 bu32 addr, val; 2944 2945 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTpmod); 2946 TRACE_EXTRACT (cpu, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i", 2947 __func__, W, aop, reg, idx, ptr); 2948 2949 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2) 2950 illegal_instruction_combination (cpu); 2951 2952 if (aop == 1 && W == 0 && idx == ptr) 2953 { 2954 TRACE_INSN (cpu, "R%i.L = W[%s];", reg, ptr_name); 2955 addr = PREG (ptr); 2956 val = GET_WORD (addr); 2957 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val); 2958 } 2959 else if (aop == 2 && W == 0 && idx == ptr) 2960 { 2961 TRACE_INSN (cpu, "R%i.H = W[%s];", reg, ptr_name); 2962 addr = PREG (ptr); 2963 val = GET_WORD (addr); 2964 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16)); 2965 } 2966 else if (aop == 1 && W == 1 && idx == ptr) 2967 { 2968 TRACE_INSN (cpu, "W[%s] = R%i.L;", ptr_name, reg); 2969 addr = PREG (ptr); 2970 PUT_WORD (addr, DREG (reg)); 2971 } 2972 else if (aop == 2 && W == 1 && idx == ptr) 2973 { 2974 TRACE_INSN (cpu, "W[%s] = R%i.H;", ptr_name, reg); 2975 addr = PREG (ptr); 2976 PUT_WORD (addr, DREG (reg) >> 16); 2977 } 2978 else if (aop == 0 && W == 0) 2979 { 2980 TRACE_INSN (cpu, "R%i = [%s ++ %s];", reg, ptr_name, idx_name); 2981 addr = PREG (ptr); 2982 val = GET_LONG (addr); 2983 STORE (DREG (reg), val); 2984 if (ptr != idx) 2985 STORE (PREG (ptr), addr + PREG (idx)); 2986 } 2987 else if (aop == 1 && W == 0) 2988 { 2989 TRACE_INSN (cpu, "R%i.L = W[%s ++ %s];", reg, ptr_name, idx_name); 2990 addr = PREG (ptr); 2991 val = GET_WORD (addr); 2992 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val); 2993 if (ptr != idx) 2994 STORE (PREG (ptr), addr + PREG (idx)); 2995 } 2996 else if (aop == 2 && W == 0) 2997 { 2998 TRACE_INSN (cpu, "R%i.H = W[%s ++ %s];", reg, ptr_name, idx_name); 2999 addr = PREG (ptr); 3000 val = GET_WORD (addr); 3001 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16)); 3002 if (ptr != idx) 3003 STORE (PREG (ptr), addr + PREG (idx)); 3004 } 3005 else if (aop == 3 && W == 0) 3006 { 3007 TRACE_INSN (cpu, "R%i = W[%s ++ %s] (Z);", reg, ptr_name, idx_name); 3008 addr = PREG (ptr); 3009 val = GET_WORD (addr); 3010 STORE (DREG (reg), val); 3011 if (ptr != idx) 3012 STORE (PREG (ptr), addr + PREG (idx)); 3013 } 3014 else if (aop == 3 && W == 1) 3015 { 3016 TRACE_INSN (cpu, "R%i = W[%s ++ %s] (X);", reg, ptr_name, idx_name); 3017 addr = PREG (ptr); 3018 val = GET_WORD (addr); 3019 STORE (DREG (reg), (bs32) (bs16) val); 3020 if (ptr != idx) 3021 STORE (PREG (ptr), addr + PREG (idx)); 3022 } 3023 else if (aop == 0 && W == 1) 3024 { 3025 TRACE_INSN (cpu, "[%s ++ %s] = R%i;", ptr_name, idx_name, reg); 3026 addr = PREG (ptr); 3027 PUT_LONG (addr, DREG (reg)); 3028 if (ptr != idx) 3029 STORE (PREG (ptr), addr + PREG (idx)); 3030 } 3031 else if (aop == 1 && W == 1) 3032 { 3033 TRACE_INSN (cpu, "W[%s ++ %s] = R%i.L;", ptr_name, idx_name, reg); 3034 addr = PREG (ptr); 3035 PUT_WORD (addr, DREG (reg)); 3036 if (ptr != idx) 3037 STORE (PREG (ptr), addr + PREG (idx)); 3038 } 3039 else if (aop == 2 && W == 1) 3040 { 3041 TRACE_INSN (cpu, "W[%s ++ %s] = R%i.H;", ptr_name, idx_name, reg); 3042 addr = PREG (ptr); 3043 PUT_WORD (addr, DREG (reg) >> 16); 3044 if (ptr != idx) 3045 STORE (PREG (ptr), addr + PREG (idx)); 3046 } 3047 else 3048 illegal_instruction_or_combination (cpu); 3049 } 3050 3051 static void 3052 decode_dagMODim_0 (SIM_CPU *cpu, bu16 iw0) 3053 { 3054 /* dagMODim 3055 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3056 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....| 3057 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3058 int i = ((iw0 >> DagMODim_i_bits) & DagMODim_i_mask); 3059 int m = ((iw0 >> DagMODim_m_bits) & DagMODim_m_mask); 3060 int br = ((iw0 >> DagMODim_br_bits) & DagMODim_br_mask); 3061 int op = ((iw0 >> DagMODim_op_bits) & DagMODim_op_mask); 3062 3063 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODim); 3064 TRACE_EXTRACT (cpu, "%s: br:%i op:%i m:%i i:%i", __func__, br, op, m, i); 3065 3066 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2) 3067 illegal_instruction_combination (cpu); 3068 3069 if (op == 0 && br == 1) 3070 { 3071 TRACE_INSN (cpu, "I%i += M%i (BREV);", i, m); 3072 SET_IREG (i, add_brev (IREG (i), MREG (m))); 3073 } 3074 else if (op == 0) 3075 { 3076 TRACE_INSN (cpu, "I%i += M%i;", i, m); 3077 dagadd (cpu, i, MREG (m)); 3078 } 3079 else if (op == 1 && br == 0) 3080 { 3081 TRACE_INSN (cpu, "I%i -= M%i;", i, m); 3082 dagsub (cpu, i, MREG (m)); 3083 } 3084 else 3085 illegal_instruction_or_combination (cpu); 3086 } 3087 3088 static void 3089 decode_dagMODik_0 (SIM_CPU *cpu, bu16 iw0) 3090 { 3091 /* dagMODik 3092 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3093 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....| 3094 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3095 int i = ((iw0 >> DagMODik_i_bits) & DagMODik_i_mask); 3096 int op = ((iw0 >> DagMODik_op_bits) & DagMODik_op_mask); 3097 3098 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODik); 3099 TRACE_EXTRACT (cpu, "%s: op:%i i:%i", __func__, op, i); 3100 3101 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2) 3102 illegal_instruction_combination (cpu); 3103 3104 if (op == 0) 3105 { 3106 TRACE_INSN (cpu, "I%i += 2;", i); 3107 dagadd (cpu, i, 2); 3108 } 3109 else if (op == 1) 3110 { 3111 TRACE_INSN (cpu, "I%i -= 2;", i); 3112 dagsub (cpu, i, 2); 3113 } 3114 else if (op == 2) 3115 { 3116 TRACE_INSN (cpu, "I%i += 4;", i); 3117 dagadd (cpu, i, 4); 3118 } 3119 else if (op == 3) 3120 { 3121 TRACE_INSN (cpu, "I%i -= 4;", i); 3122 dagsub (cpu, i, 4); 3123 } 3124 else 3125 illegal_instruction_or_combination (cpu); 3126 } 3127 3128 static void 3129 decode_dspLDST_0 (SIM_CPU *cpu, bu16 iw0) 3130 { 3131 /* dspLDST 3132 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3133 | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......| 3134 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3135 int i = ((iw0 >> DspLDST_i_bits) & DspLDST_i_mask); 3136 int m = ((iw0 >> DspLDST_m_bits) & DspLDST_m_mask); 3137 int W = ((iw0 >> DspLDST_W_bits) & DspLDST_W_mask); 3138 int aop = ((iw0 >> DspLDST_aop_bits) & DspLDST_aop_mask); 3139 int reg = ((iw0 >> DspLDST_reg_bits) & DspLDST_reg_mask); 3140 bu32 addr; 3141 3142 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dspLDST); 3143 TRACE_EXTRACT (cpu, "%s: aop:%i m:%i i:%i reg:%i", __func__, aop, m, i, reg); 3144 3145 if (aop == 0 && W == 0 && m == 0) 3146 { 3147 TRACE_INSN (cpu, "R%i = [I%i++];", reg, i); 3148 addr = IREG (i); 3149 if (DIS_ALGN_EXPT & 0x1) 3150 addr &= ~3; 3151 dagadd (cpu, i, 4); 3152 STORE (DREG (reg), GET_LONG (addr)); 3153 } 3154 else if (aop == 0 && W == 0 && m == 1) 3155 { 3156 TRACE_INSN (cpu, "R%i.L = W[I%i++];", reg, i); 3157 addr = IREG (i); 3158 dagadd (cpu, i, 2); 3159 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr)); 3160 } 3161 else if (aop == 0 && W == 0 && m == 2) 3162 { 3163 TRACE_INSN (cpu, "R%i.H = W[I%i++];", reg, i); 3164 addr = IREG (i); 3165 dagadd (cpu, i, 2); 3166 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16)); 3167 } 3168 else if (aop == 1 && W == 0 && m == 0) 3169 { 3170 TRACE_INSN (cpu, "R%i = [I%i--];", reg, i); 3171 addr = IREG (i); 3172 if (DIS_ALGN_EXPT & 0x1) 3173 addr &= ~3; 3174 dagsub (cpu, i, 4); 3175 STORE (DREG (reg), GET_LONG (addr)); 3176 } 3177 else if (aop == 1 && W == 0 && m == 1) 3178 { 3179 TRACE_INSN (cpu, "R%i.L = W[I%i--];", reg, i); 3180 addr = IREG (i); 3181 dagsub (cpu, i, 2); 3182 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr)); 3183 } 3184 else if (aop == 1 && W == 0 && m == 2) 3185 { 3186 TRACE_INSN (cpu, "R%i.H = W[I%i--];", reg, i); 3187 addr = IREG (i); 3188 dagsub (cpu, i, 2); 3189 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16)); 3190 } 3191 else if (aop == 2 && W == 0 && m == 0) 3192 { 3193 TRACE_INSN (cpu, "R%i = [I%i];", reg, i); 3194 addr = IREG (i); 3195 if (DIS_ALGN_EXPT & 0x1) 3196 addr &= ~3; 3197 STORE (DREG (reg), GET_LONG (addr)); 3198 } 3199 else if (aop == 2 && W == 0 && m == 1) 3200 { 3201 TRACE_INSN (cpu, "R%i.L = W[I%i];", reg, i); 3202 addr = IREG (i); 3203 STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr)); 3204 } 3205 else if (aop == 2 && W == 0 && m == 2) 3206 { 3207 TRACE_INSN (cpu, "R%i.H = W[I%i];", reg, i); 3208 addr = IREG (i); 3209 STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16)); 3210 } 3211 else if (aop == 0 && W == 1 && m == 0) 3212 { 3213 TRACE_INSN (cpu, "[I%i++] = R%i;", i, reg); 3214 addr = IREG (i); 3215 dagadd (cpu, i, 4); 3216 PUT_LONG (addr, DREG (reg)); 3217 } 3218 else if (aop == 0 && W == 1 && m == 1) 3219 { 3220 TRACE_INSN (cpu, "W[I%i++] = R%i.L;", i, reg); 3221 addr = IREG (i); 3222 dagadd (cpu, i, 2); 3223 PUT_WORD (addr, DREG (reg)); 3224 } 3225 else if (aop == 0 && W == 1 && m == 2) 3226 { 3227 TRACE_INSN (cpu, "W[I%i++] = R%i.H;", i, reg); 3228 addr = IREG (i); 3229 dagadd (cpu, i, 2); 3230 PUT_WORD (addr, DREG (reg) >> 16); 3231 } 3232 else if (aop == 1 && W == 1 && m == 0) 3233 { 3234 TRACE_INSN (cpu, "[I%i--] = R%i;", i, reg); 3235 addr = IREG (i); 3236 dagsub (cpu, i, 4); 3237 PUT_LONG (addr, DREG (reg)); 3238 } 3239 else if (aop == 1 && W == 1 && m == 1) 3240 { 3241 TRACE_INSN (cpu, "W[I%i--] = R%i.L;", i, reg); 3242 addr = IREG (i); 3243 dagsub (cpu, i, 2); 3244 PUT_WORD (addr, DREG (reg)); 3245 } 3246 else if (aop == 1 && W == 1 && m == 2) 3247 { 3248 TRACE_INSN (cpu, "W[I%i--] = R%i.H;", i, reg); 3249 addr = IREG (i); 3250 dagsub (cpu, i, 2); 3251 PUT_WORD (addr, DREG (reg) >> 16); 3252 } 3253 else if (aop == 2 && W == 1 && m == 0) 3254 { 3255 TRACE_INSN (cpu, "[I%i] = R%i;", i, reg); 3256 addr = IREG (i); 3257 PUT_LONG (addr, DREG (reg)); 3258 } 3259 else if (aop == 2 && W == 1 && m == 1) 3260 { 3261 TRACE_INSN (cpu, "W[I%i] = R%i.L;", i, reg); 3262 addr = IREG (i); 3263 PUT_WORD (addr, DREG (reg)); 3264 } 3265 else if (aop == 2 && W == 1 && m == 2) 3266 { 3267 TRACE_INSN (cpu, "W[I%i] = R%i.H;", i, reg); 3268 addr = IREG (i); 3269 PUT_WORD (addr, DREG (reg) >> 16); 3270 } 3271 else if (aop == 3 && W == 0) 3272 { 3273 TRACE_INSN (cpu, "R%i = [I%i ++ M%i];", reg, i, m); 3274 addr = IREG (i); 3275 if (DIS_ALGN_EXPT & 0x1) 3276 addr &= ~3; 3277 dagadd (cpu, i, MREG (m)); 3278 STORE (DREG (reg), GET_LONG (addr)); 3279 } 3280 else if (aop == 3 && W == 1) 3281 { 3282 TRACE_INSN (cpu, "[I%i ++ M%i] = R%i;", i, m, reg); 3283 addr = IREG (i); 3284 dagadd (cpu, i, MREG (m)); 3285 PUT_LONG (addr, DREG (reg)); 3286 } 3287 else 3288 illegal_instruction_or_combination (cpu); 3289 } 3290 3291 static void 3292 decode_LDST_0 (SIM_CPU *cpu, bu16 iw0) 3293 { 3294 /* LDST 3295 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3296 | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......| 3297 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3298 int Z = ((iw0 >> LDST_Z_bits) & LDST_Z_mask); 3299 int W = ((iw0 >> LDST_W_bits) & LDST_W_mask); 3300 int sz = ((iw0 >> LDST_sz_bits) & LDST_sz_mask); 3301 int aop = ((iw0 >> LDST_aop_bits) & LDST_aop_mask); 3302 int reg = ((iw0 >> LDST_reg_bits) & LDST_reg_mask); 3303 int ptr = ((iw0 >> LDST_ptr_bits) & LDST_ptr_mask); 3304 const char * const posts[] = { "++", "--", "", "<INV>" }; 3305 const char *post = posts[aop]; 3306 const char *ptr_name = get_preg_name (ptr); 3307 3308 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDST); 3309 TRACE_EXTRACT (cpu, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i", 3310 __func__, sz, W, aop, Z, ptr, reg); 3311 3312 if (aop == 3 || PARALLEL_GROUP == BFIN_PARALLEL_GROUP2) 3313 illegal_instruction_or_combination (cpu); 3314 3315 if (W == 0) 3316 { 3317 if (sz == 0 && Z == 0) 3318 { 3319 TRACE_INSN (cpu, "R%i = [%s%s];", reg, ptr_name, post); 3320 SET_DREG (reg, GET_LONG (PREG (ptr))); 3321 } 3322 else if (sz == 0 && Z == 1) 3323 { 3324 TRACE_INSN (cpu, "%s = [%s%s];", get_preg_name (reg), ptr_name, post); 3325 if (aop < 2 && ptr == reg) 3326 illegal_instruction_combination (cpu); 3327 SET_PREG (reg, GET_LONG (PREG (ptr))); 3328 } 3329 else if (sz == 1 && Z == 0) 3330 { 3331 TRACE_INSN (cpu, "R%i = W[%s%s] (Z);", reg, ptr_name, post); 3332 SET_DREG (reg, GET_WORD (PREG (ptr))); 3333 } 3334 else if (sz == 1 && Z == 1) 3335 { 3336 TRACE_INSN (cpu, "R%i = W[%s%s] (X);", reg, ptr_name, post); 3337 SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr))); 3338 } 3339 else if (sz == 2 && Z == 0) 3340 { 3341 TRACE_INSN (cpu, "R%i = B[%s%s] (Z);", reg, ptr_name, post); 3342 SET_DREG (reg, GET_BYTE (PREG (ptr))); 3343 } 3344 else if (sz == 2 && Z == 1) 3345 { 3346 TRACE_INSN (cpu, "R%i = B[%s%s] (X);", reg, ptr_name, post); 3347 SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr))); 3348 } 3349 else 3350 illegal_instruction_or_combination (cpu); 3351 } 3352 else 3353 { 3354 if (sz == 0 && Z == 0) 3355 { 3356 TRACE_INSN (cpu, "[%s%s] = R%i;", ptr_name, post, reg); 3357 PUT_LONG (PREG (ptr), DREG (reg)); 3358 } 3359 else if (sz == 0 && Z == 1) 3360 { 3361 TRACE_INSN (cpu, "[%s%s] = %s;", ptr_name, post, get_preg_name (reg)); 3362 PUT_LONG (PREG (ptr), PREG (reg)); 3363 } 3364 else if (sz == 1 && Z == 0) 3365 { 3366 TRACE_INSN (cpu, "W[%s%s] = R%i;", ptr_name, post, reg); 3367 PUT_WORD (PREG (ptr), DREG (reg)); 3368 } 3369 else if (sz == 2 && Z == 0) 3370 { 3371 TRACE_INSN (cpu, "B[%s%s] = R%i;", ptr_name, post, reg); 3372 PUT_BYTE (PREG (ptr), DREG (reg)); 3373 } 3374 else 3375 illegal_instruction_or_combination (cpu); 3376 } 3377 3378 if (aop == 0) 3379 SET_PREG (ptr, PREG (ptr) + (1 << (2 - sz))); 3380 if (aop == 1) 3381 SET_PREG (ptr, PREG (ptr) - (1 << (2 - sz))); 3382 } 3383 3384 static void 3385 decode_LDSTiiFP_0 (SIM_CPU *cpu, bu16 iw0) 3386 { 3387 /* LDSTiiFP 3388 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3389 | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........| 3390 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3391 /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs, 3392 but for our usage, its functionality the same thing. */ 3393 int grp = ((iw0 >> 3) & 0x1); 3394 int reg = ((iw0 >> LDSTiiFP_reg_bits) & 0x7 /*LDSTiiFP_reg_mask*/); 3395 int offset = ((iw0 >> LDSTiiFP_offset_bits) & LDSTiiFP_offset_mask); 3396 int W = ((iw0 >> LDSTiiFP_W_bits) & LDSTiiFP_W_mask); 3397 bu32 imm = negimm5s4 (offset); 3398 bu32 ea = FPREG + imm; 3399 const char *imm_str = negimm5s4_str (offset); 3400 const char *reg_name = get_allreg_name (grp, reg); 3401 3402 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTiiFP); 3403 TRACE_EXTRACT (cpu, "%s: W:%i offset:%#x grp:%i reg:%i", __func__, 3404 W, offset, grp, reg); 3405 TRACE_DECODE (cpu, "%s: negimm5s4:%#x", __func__, imm); 3406 3407 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2) 3408 illegal_instruction_or_combination (cpu); 3409 3410 if (W == 0) 3411 { 3412 TRACE_INSN (cpu, "%s = [FP + %s];", reg_name, imm_str); 3413 reg_write (cpu, grp, reg, GET_LONG (ea)); 3414 } 3415 else 3416 { 3417 TRACE_INSN (cpu, "[FP + %s] = %s;", imm_str, reg_name); 3418 PUT_LONG (ea, reg_read (cpu, grp, reg)); 3419 } 3420 } 3421 3422 static void 3423 decode_LDSTii_0 (SIM_CPU *cpu, bu16 iw0) 3424 { 3425 /* LDSTii 3426 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3427 | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......| 3428 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3429 int reg = ((iw0 >> LDSTii_reg_bit) & LDSTii_reg_mask); 3430 int ptr = ((iw0 >> LDSTii_ptr_bit) & LDSTii_ptr_mask); 3431 int offset = ((iw0 >> LDSTii_offset_bit) & LDSTii_offset_mask); 3432 int op = ((iw0 >> LDSTii_op_bit) & LDSTii_op_mask); 3433 int W = ((iw0 >> LDSTii_W_bit) & LDSTii_W_mask); 3434 bu32 imm, ea; 3435 const char *imm_str; 3436 const char *ptr_name = get_preg_name (ptr); 3437 3438 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTii); 3439 TRACE_EXTRACT (cpu, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i", 3440 __func__, W, op, offset, ptr, reg); 3441 3442 if (op == 0 || op == 3) 3443 imm = uimm4s4 (offset), imm_str = uimm4s4_str (offset); 3444 else 3445 imm = uimm4s2 (offset), imm_str = uimm4s2_str (offset); 3446 ea = PREG (ptr) + imm; 3447 3448 TRACE_DECODE (cpu, "%s: uimm4s4/uimm4s2:%#x", __func__, imm); 3449 3450 if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2) 3451 illegal_instruction_combination (cpu); 3452 3453 if (W == 1 && op == 2) 3454 illegal_instruction (cpu); 3455 3456 if (W == 0) 3457 { 3458 if (op == 0) 3459 { 3460 TRACE_INSN (cpu, "R%i = [%s + %s];", reg, ptr_name, imm_str); 3461 SET_DREG (reg, GET_LONG (ea)); 3462 } 3463 else if (op == 1) 3464 { 3465 TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);", reg, ptr_name, imm_str); 3466 SET_DREG (reg, GET_WORD (ea)); 3467 } 3468 else if (op == 2) 3469 { 3470 TRACE_INSN (cpu, "R%i = W[%s + %s] (X);", reg, ptr_name, imm_str); 3471 SET_DREG (reg, (bs32) (bs16) GET_WORD (ea)); 3472 } 3473 else if (op == 3) 3474 { 3475 TRACE_INSN (cpu, "%s = [%s + %s];", 3476 get_preg_name (reg), ptr_name, imm_str); 3477 SET_PREG (reg, GET_LONG (ea)); 3478 } 3479 } 3480 else 3481 { 3482 if (op == 0) 3483 { 3484 TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name, imm_str, reg); 3485 PUT_LONG (ea, DREG (reg)); 3486 } 3487 else if (op == 1) 3488 { 3489 TRACE_INSN (cpu, "W[%s + %s] = R%i;", ptr_name, imm_str, reg); 3490 PUT_WORD (ea, DREG (reg)); 3491 } 3492 else if (op == 3) 3493 { 3494 TRACE_INSN (cpu, "[%s + %s] = %s;", 3495 ptr_name, imm_str, get_preg_name (reg)); 3496 PUT_LONG (ea, PREG (reg)); 3497 } 3498 } 3499 } 3500 3501 static void 3502 decode_LoopSetup_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc) 3503 { 3504 /* LoopSetup 3505 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3506 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......| 3507 |.reg...........| - | - |.eoffset...............................| 3508 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3509 int c = ((iw0 >> (LoopSetup_c_bits - 16)) & LoopSetup_c_mask); 3510 int reg = ((iw1 >> LoopSetup_reg_bits) & LoopSetup_reg_mask); 3511 int rop = ((iw0 >> (LoopSetup_rop_bits - 16)) & LoopSetup_rop_mask); 3512 int soffset = ((iw0 >> (LoopSetup_soffset_bits - 16)) & LoopSetup_soffset_mask); 3513 int eoffset = ((iw1 >> LoopSetup_eoffset_bits) & LoopSetup_eoffset_mask); 3514 int spcrel = pcrel4 (soffset); 3515 int epcrel = lppcrel10 (eoffset); 3516 3517 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LoopSetup); 3518 TRACE_EXTRACT (cpu, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i", 3519 __func__, rop, c, soffset, reg, eoffset); 3520 TRACE_DECODE (cpu, "%s: s_pcrel4:%#x e_lppcrel10:%#x", 3521 __func__, spcrel, epcrel); 3522 3523 if (reg > 7) 3524 illegal_instruction (cpu); 3525 3526 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 3527 illegal_instruction_combination (cpu); 3528 3529 if (rop == 0) 3530 { 3531 TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i;", spcrel, epcrel, c); 3532 } 3533 else if (rop == 1 && reg <= 7) 3534 { 3535 TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s;", 3536 spcrel, epcrel, c, get_preg_name (reg)); 3537 SET_LCREG (c, PREG (reg)); 3538 } 3539 else if (rop == 3 && reg <= 7) 3540 { 3541 TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s >> 1;", 3542 spcrel, epcrel, c, get_preg_name (reg)); 3543 SET_LCREG (c, PREG (reg) >> 1); 3544 } 3545 else 3546 illegal_instruction (cpu); 3547 3548 SET_LTREG (c, pc + spcrel); 3549 SET_LBREG (c, pc + epcrel); 3550 } 3551 3552 static void 3553 decode_LDIMMhalf_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) 3554 { 3555 /* LDIMMhalf 3556 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3557 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......| 3558 |.hword.........................................................| 3559 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3560 int H = ((iw0 >> (LDIMMhalf_H_bits - 16)) & LDIMMhalf_H_mask); 3561 int Z = ((iw0 >> (LDIMMhalf_Z_bits - 16)) & LDIMMhalf_Z_mask); 3562 int S = ((iw0 >> (LDIMMhalf_S_bits - 16)) & LDIMMhalf_S_mask); 3563 int reg = ((iw0 >> (LDIMMhalf_reg_bits - 16)) & LDIMMhalf_reg_mask); 3564 int grp = ((iw0 >> (LDIMMhalf_grp_bits - 16)) & LDIMMhalf_grp_mask); 3565 int hword = ((iw1 >> LDIMMhalf_hword_bits) & LDIMMhalf_hword_mask); 3566 bu32 val; 3567 const char *val_str; 3568 const char *reg_name = get_allreg_name (grp, reg); 3569 3570 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDIMMhalf); 3571 TRACE_EXTRACT (cpu, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x", 3572 __func__, Z, H, S, grp, reg, hword); 3573 3574 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 3575 illegal_instruction_combination (cpu); 3576 3577 if (S == 1) 3578 val = imm16 (hword), val_str = imm16_str (hword); 3579 else 3580 val = luimm16 (hword), val_str = luimm16_str (hword); 3581 3582 if (H == 0 && S == 1 && Z == 0) 3583 { 3584 TRACE_INSN (cpu, "%s = %s (X);", reg_name, val_str); 3585 } 3586 else if (H == 0 && S == 0 && Z == 1) 3587 { 3588 TRACE_INSN (cpu, "%s = %s (Z);", reg_name, val_str); 3589 } 3590 else if (H == 0 && S == 0 && Z == 0) 3591 { 3592 TRACE_INSN (cpu, "%s.L = %s;", reg_name, val_str); 3593 val = REG_H_L (reg_read (cpu, grp, reg), val); 3594 } 3595 else if (H == 1 && S == 0 && Z == 0) 3596 { 3597 TRACE_INSN (cpu, "%s.H = %s;", reg_name, val_str); 3598 val = REG_H_L (val << 16, reg_read (cpu, grp, reg)); 3599 } 3600 else 3601 illegal_instruction (cpu); 3602 3603 reg_write (cpu, grp, reg, val); 3604 } 3605 3606 static void 3607 decode_CALLa_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc) 3608 { 3609 /* CALLa 3610 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3611 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................| 3612 |.lsw...........................................................| 3613 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3614 int S = ((iw0 >> (CALLa_S_bits - 16)) & CALLa_S_mask); 3615 int lsw = ((iw1 >> 0) & 0xffff); 3616 int msw = ((iw0 >> 0) & 0xff); 3617 int pcrel = pcrel24 ((msw << 16) | lsw); 3618 bu32 newpc = pc + pcrel; 3619 3620 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CALLa); 3621 TRACE_EXTRACT (cpu, "%s: S:%i msw:%#x lsw:%#x", __func__, S, msw, lsw); 3622 TRACE_DECODE (cpu, "%s: pcrel24:%#x", __func__, pcrel); 3623 3624 TRACE_INSN (cpu, "%s %#x;", S ? "CALL" : "JUMP.L", pcrel); 3625 3626 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 3627 illegal_instruction_combination (cpu); 3628 3629 if (S == 1) 3630 { 3631 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL"); 3632 SET_RETSREG (hwloop_get_next_pc (cpu, pc, 4)); 3633 } 3634 else 3635 BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.L"); 3636 3637 SET_PCREG (newpc); 3638 BFIN_CPU_STATE.did_jump = true; 3639 PROFILE_BRANCH_TAKEN (cpu); 3640 CYCLE_DELAY = 5; 3641 } 3642 3643 static void 3644 decode_LDSTidxI_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) 3645 { 3646 /* LDSTidxI 3647 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3648 | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......| 3649 |.offset........................................................| 3650 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3651 int Z = ((iw0 >> (LDSTidxI_Z_bits - 16)) & LDSTidxI_Z_mask); 3652 int W = ((iw0 >> (LDSTidxI_W_bits - 16)) & LDSTidxI_W_mask); 3653 int sz = ((iw0 >> (LDSTidxI_sz_bits - 16)) & LDSTidxI_sz_mask); 3654 int reg = ((iw0 >> (LDSTidxI_reg_bits - 16)) & LDSTidxI_reg_mask); 3655 int ptr = ((iw0 >> (LDSTidxI_ptr_bits - 16)) & LDSTidxI_ptr_mask); 3656 int offset = ((iw1 >> LDSTidxI_offset_bits) & LDSTidxI_offset_mask); 3657 const char *ptr_name = get_preg_name (ptr); 3658 bu32 imm_16s4 = imm16s4 (offset); 3659 bu32 imm_16s2 = imm16s2 (offset); 3660 bu32 imm_16 = imm16 (offset); 3661 3662 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTidxI); 3663 TRACE_EXTRACT (cpu, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x", 3664 __func__, W, Z, sz, ptr, reg, offset); 3665 3666 if (sz == 3) 3667 illegal_instruction (cpu); 3668 3669 if (W == 0) 3670 { 3671 if (sz == 0 && Z == 0) 3672 { 3673 TRACE_INSN (cpu, "R%i = [%s + %s];", 3674 reg, ptr_name, imm16s4_str (offset)); 3675 SET_DREG (reg, GET_LONG (PREG (ptr) + imm_16s4)); 3676 } 3677 else if (sz == 0 && Z == 1) 3678 { 3679 TRACE_INSN (cpu, "%s = [%s + %s];", 3680 get_preg_name (reg), ptr_name, imm16s4_str (offset)); 3681 SET_PREG (reg, GET_LONG (PREG (ptr) + imm_16s4)); 3682 } 3683 else if (sz == 1 && Z == 0) 3684 { 3685 TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);", 3686 reg, ptr_name, imm16s2_str (offset)); 3687 SET_DREG (reg, GET_WORD (PREG (ptr) + imm_16s2)); 3688 } 3689 else if (sz == 1 && Z == 1) 3690 { 3691 TRACE_INSN (cpu, "R%i = W[%s + %s] (X);", 3692 reg, ptr_name, imm16s2_str (offset)); 3693 SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr) + imm_16s2)); 3694 } 3695 else if (sz == 2 && Z == 0) 3696 { 3697 TRACE_INSN (cpu, "R%i = B[%s + %s] (Z);", 3698 reg, ptr_name, imm16_str (offset)); 3699 SET_DREG (reg, GET_BYTE (PREG (ptr) + imm_16)); 3700 } 3701 else if (sz == 2 && Z == 1) 3702 { 3703 TRACE_INSN (cpu, "R%i = B[%s + %s] (X);", 3704 reg, ptr_name, imm16_str (offset)); 3705 SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr) + imm_16)); 3706 } 3707 } 3708 else 3709 { 3710 if (sz != 0 && Z != 0) 3711 illegal_instruction (cpu); 3712 3713 if (sz == 0 && Z == 0) 3714 { 3715 TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name, 3716 imm16s4_str (offset), reg); 3717 PUT_LONG (PREG (ptr) + imm_16s4, DREG (reg)); 3718 } 3719 else if (sz == 0 && Z == 1) 3720 { 3721 TRACE_INSN (cpu, "[%s + %s] = %s;", 3722 ptr_name, imm16s4_str (offset), get_preg_name (reg)); 3723 PUT_LONG (PREG (ptr) + imm_16s4, PREG (reg)); 3724 } 3725 else if (sz == 1 && Z == 0) 3726 { 3727 TRACE_INSN (cpu, "W[%s + %s] = R%i;", 3728 ptr_name, imm16s2_str (offset), reg); 3729 PUT_WORD (PREG (ptr) + imm_16s2, DREG (reg)); 3730 } 3731 else if (sz == 2 && Z == 0) 3732 { 3733 TRACE_INSN (cpu, "B[%s + %s] = R%i;", 3734 ptr_name, imm16_str (offset), reg); 3735 PUT_BYTE (PREG (ptr) + imm_16, DREG (reg)); 3736 } 3737 } 3738 } 3739 3740 static void 3741 decode_linkage_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) 3742 { 3743 /* linkage 3744 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3745 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.| 3746 |.framesize.....................................................| 3747 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3748 int R = ((iw0 >> (Linkage_R_bits - 16)) & Linkage_R_mask); 3749 int framesize = ((iw1 >> Linkage_framesize_bits) & Linkage_framesize_mask); 3750 bu32 sp; 3751 3752 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_linkage); 3753 TRACE_EXTRACT (cpu, "%s: R:%i framesize:%#x", __func__, R, framesize); 3754 3755 if (R == 0) 3756 { 3757 int size = uimm16s4 (framesize); 3758 sp = SPREG; 3759 TRACE_INSN (cpu, "LINK %s;", uimm16s4_str (framesize)); 3760 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 3761 illegal_instruction_combination (cpu); 3762 sp -= 4; 3763 PUT_LONG (sp, RETSREG); 3764 sp -= 4; 3765 PUT_LONG (sp, FPREG); 3766 SET_FPREG (sp); 3767 sp -= size; 3768 CYCLE_DELAY = 3; 3769 } 3770 else 3771 { 3772 /* Restore SP from FP. */ 3773 sp = FPREG; 3774 TRACE_INSN (cpu, "UNLINK;"); 3775 if (PARALLEL_GROUP != BFIN_PARALLEL_NONE) 3776 illegal_instruction_combination (cpu); 3777 SET_FPREG (GET_LONG (sp)); 3778 sp += 4; 3779 SET_RETSREG (GET_LONG (sp)); 3780 sp += 4; 3781 CYCLE_DELAY = 2; 3782 } 3783 3784 SET_SPREG (sp); 3785 } 3786 3787 static void 3788 decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) 3789 { 3790 /* dsp32mac 3791 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3792 | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...| 3793 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..| 3794 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3795 int op1 = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask); 3796 int w1 = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask); 3797 int P = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask); 3798 int MM = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask); 3799 int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask); 3800 int M = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask); 3801 int w0 = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask); 3802 int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask); 3803 int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask); 3804 int dst = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask); 3805 int h10 = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask); 3806 int h00 = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask); 3807 int op0 = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask); 3808 int h11 = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask); 3809 int h01 = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask); 3810 3811 bu32 res = DREG (dst); 3812 bu32 v_0 = 0, v_1 = 0, zero = 0, n_1 = 0, n_0 = 0; 3813 3814 static const char * const ops[] = { "=", "+=", "-=" }; 3815 char _buf[128], *buf = _buf; 3816 int _MM = MM; 3817 3818 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac); 3819 TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i " 3820 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i", 3821 __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10, 3822 dst, src0, src1); 3823 3824 if (w0 == 0 && w1 == 0 && op1 == 3 && op0 == 3) 3825 illegal_instruction (cpu); 3826 3827 if ((w1 || w0) && mmod == M_W32) 3828 illegal_instruction (cpu); 3829 3830 if (((1 << mmod) & (P ? 0x131b : 0x1b5f)) == 0) 3831 illegal_instruction (cpu); 3832 3833 /* First handle MAC1 side. */ 3834 if (w1 == 1 || op1 != 3) 3835 { 3836 bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0, 3837 src1, mmod, MM, P, &v_1, &n_1); 3838 3839 if (w1) 3840 buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P); 3841 3842 if (op1 == 3) 3843 { 3844 buf += sprintf (buf, " = A1"); 3845 zero = !!(res1 == 0); 3846 } 3847 else 3848 { 3849 if (w1) 3850 buf += sprintf (buf, " = ("); 3851 buf += sprintf (buf, "A1 %s R%i.%c * R%i.%c", ops[op1], 3852 src0, h01 ? 'H' : 'L', 3853 src1, h11 ? 'H' : 'L'); 3854 if (w1) 3855 buf += sprintf (buf, ")"); 3856 } 3857 3858 if (w1) 3859 { 3860 if (P) 3861 STORE (DREG (dst + 1), res1); 3862 else 3863 { 3864 if (res1 & 0xffff0000) 3865 illegal_instruction (cpu); 3866 res = REG_H_L (res1 << 16, res); 3867 } 3868 } 3869 else 3870 v_1 = 0; 3871 3872 if (w0 == 1 || op0 != 3) 3873 { 3874 if (_MM) 3875 buf += sprintf (buf, " (M)"); 3876 _MM = 0; 3877 buf += sprintf (buf, ", "); 3878 } 3879 } 3880 3881 /* Then handle MAC0 side. */ 3882 if (w0 == 1 || op0 != 3) 3883 { 3884 bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0, 3885 src1, mmod, 0, P, &v_0, &n_0); 3886 3887 if (w0) 3888 buf += sprintf (buf, P ? "R%i" : "R%i.L", dst); 3889 3890 if (op0 == 3) 3891 { 3892 buf += sprintf (buf, " = A0"); 3893 zero |= !!(res0 == 0); 3894 } 3895 else 3896 { 3897 if (w0) 3898 buf += sprintf (buf, " = ("); 3899 buf += sprintf (buf, "A0 %s R%i.%c * R%i.%c", ops[op0], 3900 src0, h00 ? 'H' : 'L', 3901 src1, h10 ? 'H' : 'L'); 3902 if (w0) 3903 buf += sprintf (buf, ")"); 3904 } 3905 3906 if (w0) 3907 { 3908 if (P) 3909 STORE (DREG (dst), res0); 3910 else 3911 { 3912 if (res0 & 0xffff0000) 3913 illegal_instruction (cpu); 3914 res = REG_H_L (res, res0); 3915 } 3916 } 3917 else 3918 v_0 = 0; 3919 } 3920 3921 TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM)); 3922 3923 if (!P && (w0 || w1)) 3924 { 3925 STORE (DREG (dst), res); 3926 SET_ASTATREG (v, v_0 | v_1); 3927 if (v_0 || v_1) 3928 SET_ASTATREG (vs, 1); 3929 } 3930 else if (P) 3931 { 3932 SET_ASTATREG (v, v_0 | v_1); 3933 if (v_0 || v_1) 3934 SET_ASTATREG (vs, 1); 3935 } 3936 3937 if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3)) 3938 { 3939 SET_ASTATREG (az, zero); 3940 if (!(w0 == 1 && op0 == 3)) 3941 n_0 = 0; 3942 if (!(w1 == 1 && op1 == 3)) 3943 n_1 = 0; 3944 SET_ASTATREG (an, n_1 | n_0); 3945 } 3946 } 3947 3948 static void 3949 decode_dsp32mult_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) 3950 { 3951 /* dsp32mult 3952 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 3953 | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...| 3954 |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..| 3955 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 3956 int op1 = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask); 3957 int w1 = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask); 3958 int P = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask); 3959 int MM = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask); 3960 int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask); 3961 int M = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask); 3962 int w0 = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask); 3963 int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask); 3964 int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask); 3965 int dst = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask); 3966 int h10 = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask); 3967 int h00 = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask); 3968 int op0 = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask); 3969 int h11 = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask); 3970 int h01 = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask); 3971 3972 bu32 res = DREG (dst); 3973 bu32 sat0 = 0, sat1 = 0, v_i0 = 0, v_i1 = 0; 3974 char _buf[128], *buf = _buf; 3975 int _MM = MM; 3976 3977 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mult); 3978 TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i " 3979 "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i", 3980 __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10, 3981 dst, src0, src1); 3982 3983 if (w1 == 0 && w0 == 0) 3984 illegal_instruction (cpu); 3985 if (((1 << mmod) & (P ? 0x313 : 0x1b57)) == 0) 3986 illegal_instruction (cpu); 3987 if (P && ((dst & 1) || (op1 != 0) || (op0 != 0) || !is_macmod_pmove (mmod))) 3988 illegal_instruction (cpu); 3989 if (!P && ((op1 != 0) || (op0 != 0) || !is_macmod_hmove (mmod))) 3990 illegal_instruction (cpu); 3991 3992 /* First handle MAC1 side. */ 3993 if (w1) 3994 { 3995 bu64 r = decode_multfunc (cpu, h01, h11, src0, src1, mmod, MM, &sat1); 3996 bu32 res1 = extract_mult (cpu, r, mmod, MM, P, &v_i1); 3997 3998 buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P); 3999 buf += sprintf (buf, " = R%i.%c * R%i.%c", 4000 src0, h01 ? 'H' : 'L', 4001 src1, h11 ? 'H' : 'L'); 4002 if (w0) 4003 { 4004 if (_MM) 4005 buf += sprintf (buf, " (M)"); 4006 _MM = 0; 4007 buf += sprintf (buf, ", "); 4008 } 4009 4010 if (P) 4011 STORE (DREG (dst + 1), res1); 4012 else 4013 { 4014 if (res1 & 0xFFFF0000) 4015 illegal_instruction (cpu); 4016 res = REG_H_L (res1 << 16, res); 4017 } 4018 } 4019 4020 /* First handle MAC0 side. */ 4021 if (w0) 4022 { 4023 bu64 r = decode_multfunc (cpu, h00, h10, src0, src1, mmod, 0, &sat0); 4024 bu32 res0 = extract_mult (cpu, r, mmod, 0, P, &v_i0); 4025 4026 buf += sprintf (buf, P ? "R%i" : "R%i.L", dst); 4027 buf += sprintf (buf, " = R%i.%c * R%i.%c", 4028 src0, h01 ? 'H' : 'L', 4029 src1, h11 ? 'H' : 'L'); 4030 4031 if (P) 4032 STORE (DREG (dst), res0); 4033 else 4034 { 4035 if (res0 & 0xFFFF0000) 4036 illegal_instruction (cpu); 4037 res = REG_H_L (res, res0); 4038 } 4039 } 4040 4041 TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM)); 4042 4043 if (!P && (w0 || w1)) 4044 STORE (DREG (dst), res); 4045 4046 if (w0 || w1) 4047 { 4048 bu32 v = sat0 | sat1 | v_i0 | v_i1; 4049 4050 STORE (ASTATREG (v), v); 4051 STORE (ASTATREG (v_copy), v); 4052 if (v) 4053 STORE (ASTATREG (vs), v); 4054 } 4055 } 4056 4057 static void 4058 decode_dsp32alu_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) 4059 { 4060 /* dsp32alu 4061 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 4062 | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............| 4063 |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......| 4064 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 4065 int s = ((iw1 >> DSP32Alu_s_bits) & DSP32Alu_s_mask); 4066 int x = ((iw1 >> DSP32Alu_x_bits) & DSP32Alu_x_mask); 4067 int aop = ((iw1 >> DSP32Alu_aop_bits) & DSP32Alu_aop_mask); 4068 int src0 = ((iw1 >> DSP32Alu_src0_bits) & DSP32Alu_src0_mask); 4069 int src1 = ((iw1 >> DSP32Alu_src1_bits) & DSP32Alu_src1_mask); 4070 int dst0 = ((iw1 >> DSP32Alu_dst0_bits) & DSP32Alu_dst0_mask); 4071 int dst1 = ((iw1 >> DSP32Alu_dst1_bits) & DSP32Alu_dst1_mask); 4072 int M = ((iw0 >> (DSP32Alu_M_bits - 16)) & DSP32Alu_M_mask); 4073 int HL = ((iw0 >> (DSP32Alu_HL_bits - 16)) & DSP32Alu_HL_mask); 4074 int aopcde = ((iw0 >> (DSP32Alu_aopcde_bits - 16)) & DSP32Alu_aopcde_mask); 4075 4076 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32alu); 4077 TRACE_EXTRACT (cpu, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i " 4078 "dst1:%i src0:%i src1:%i", 4079 __func__, M, HL, aopcde, aop, s, x, dst0, dst1, src0, src1); 4080 4081 if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 0 && HL == 0) 4082 { 4083 int a = aop >> 1; 4084 TRACE_INSN (cpu, "A%i.L = R%i.L;", a, src0); 4085 SET_AWREG (a, REG_H_L (AWREG (a), DREG (src0))); 4086 } 4087 else if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 0 && HL == 1) 4088 { 4089 int a = aop >> 1; 4090 TRACE_INSN (cpu, "A%i.H = R%i.H;", a, src0); 4091 SET_AWREG (a, REG_H_L (DREG (src0), AWREG (a))); 4092 } 4093 else if ((aop == 1 || aop == 0) && aopcde == 5 && x == 0 && s == 0) 4094 { 4095 bs32 val0 = DREG (src0); 4096 bs32 val1 = DREG (src1); 4097 bs32 res; 4098 bs32 signRes; 4099 bs32 ovX, sBit1, sBit2, sBitRes1, sBitRes2; 4100 4101 TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND12)", dst0, HL ? "L" : "H", 4102 src0, aop & 0x1 ? "-" : "+", src1); 4103 4104 /* If subtract, just invert and add one. */ 4105 if (aop & 0x1) 4106 { 4107 if (val1 == 0x80000000) 4108 val1 = 0x7FFFFFFF; 4109 else 4110 val1 = ~val1 + 1; 4111 } 4112 4113 /* Get the sign bits, since we need them later. */ 4114 sBit1 = !!(val0 & 0x80000000); 4115 sBit2 = !!(val1 & 0x80000000); 4116 4117 res = val0 + val1; 4118 4119 sBitRes1 = !!(res & 0x80000000); 4120 /* Round to the 12th bit. */ 4121 res += 0x0800; 4122 sBitRes2 = !!(res & 0x80000000); 4123 4124 signRes = res; 4125 signRes >>= 27; 4126 4127 /* Overflow if 4128 pos + pos = neg 4129 neg + neg = pos 4130 positive_res + positive_round = neg 4131 Shift and upper 4 bits where not the same. */ 4132 if ((!(sBit1 ^ sBit2) && (sBit1 ^ sBitRes1)) 4133 || (!sBit1 && !sBit2 && sBitRes2) 4134 || ((signRes != 0) && (signRes != -1))) 4135 { 4136 /* Both X1 and X2 Neg res is neg overflow. */ 4137 if (sBit1 && sBit2) 4138 res = 0x80000000; 4139 /* Both X1 and X2 Pos res is pos overflow. */ 4140 else if (!sBit1 && !sBit2) 4141 res = 0x7FFFFFFF; 4142 /* Pos+Neg or Neg+Pos take the sign of the result. */ 4143 else if (sBitRes1) 4144 res = 0x80000000; 4145 else 4146 res = 0x7FFFFFFF; 4147 4148 ovX = 1; 4149 } 4150 else 4151 { 4152 /* Shift up now after overflow detection. */ 4153 ovX = 0; 4154 res <<= 4; 4155 } 4156 4157 res >>= 16; 4158 4159 if (HL) 4160 STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0))); 4161 else 4162 STORE (DREG (dst0), REG_H_L (DREG (dst0), res)); 4163 4164 SET_ASTATREG (az, res == 0); 4165 SET_ASTATREG (an, res & 0x8000); 4166 SET_ASTATREG (v, ovX); 4167 if (ovX) 4168 SET_ASTATREG (vs, ovX); 4169 } 4170 else if ((aop == 2 || aop == 3) && aopcde == 5 && x == 1 && s == 0) 4171 { 4172 bs32 val0 = DREG (src0); 4173 bs32 val1 = DREG (src1); 4174 bs32 res; 4175 4176 TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND20)", dst0, HL ? "L" : "H", 4177 src0, aop & 0x1 ? "-" : "+", src1); 4178 4179 /* If subtract, just invert and add one. */ 4180 if (aop & 0x1) 4181 val1 = ~val1 + 1; 4182 4183 res = (val0 >> 4) + (val1 >> 4) + (((val0 & 0xf) + (val1 & 0xf)) >> 4); 4184 res += 0x8000; 4185 /* Don't sign extend during the shift. */ 4186 res = ((bu32)res >> 16); 4187 4188 /* Don't worry about overflows, since we are shifting right. */ 4189 4190 if (HL) 4191 STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0))); 4192 else 4193 STORE (DREG (dst0), REG_H_L (DREG (dst0), res)); 4194 4195 SET_ASTATREG (az, res == 0); 4196 SET_ASTATREG (an, res & 0x8000); 4197 SET_ASTATREG (v, 0); 4198 } 4199 else if ((aopcde == 2 || aopcde == 3) && x == 0) 4200 { 4201 bu32 s1, s2, val, ac0_i = 0, v_i = 0; 4202 4203 TRACE_INSN (cpu, "R%i.%c = R%i.%c %c R%i.%c%s;", 4204 dst0, HL ? 'H' : 'L', 4205 src0, aop & 2 ? 'H' : 'L', 4206 aopcde == 2 ? '+' : '-', 4207 src1, aop & 1 ? 'H' : 'L', 4208 amod1 (s, x)); 4209 4210 s1 = DREG (src0); 4211 s2 = DREG (src1); 4212 if (aop & 1) 4213 s2 >>= 16; 4214 if (aop & 2) 4215 s1 >>= 16; 4216 4217 if (aopcde == 2) 4218 val = add16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0); 4219 else 4220 val = sub16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0); 4221 4222 SET_ASTATREG (ac0, ac0_i); 4223 SET_ASTATREG (v, v_i); 4224 if (v_i) 4225 SET_ASTATREG (vs, v_i); 4226 4227 if (HL) 4228 SET_DREG_H (dst0, val << 16); 4229 else 4230 SET_DREG_L (dst0, val); 4231 4232 SET_ASTATREG (an, val & 0x8000); 4233 SET_ASTATREG (az, val == 0); 4234 } 4235 else if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 1 && HL == 0) 4236 { 4237 int a = aop >> 1; 4238 TRACE_INSN (cpu, "A%i = R%i;", a, src0); 4239 SET_AREG32 (a, DREG (src0)); 4240 } 4241 else if ((aop == 1 || aop == 3) && aopcde == 9 && x == 0 && s == 0 && HL == 0) 4242 { 4243 int a = aop >> 1; 4244 TRACE_INSN (cpu, "A%i.X = R%i.L;", a, src0); 4245 SET_AXREG (a, (bs8)DREG (src0)); 4246 } 4247 else if (aop == 3 && aopcde == 11 && x == 0 && HL == 0) 4248 { 4249 bu64 acc0 = get_extended_acc (cpu, 0); 4250 bu64 acc1 = get_extended_acc (cpu, 1); 4251 bu32 carry = (bu40)acc1 < (bu40)acc0; 4252 bu32 sat = 0; 4253 4254 TRACE_INSN (cpu, "A0 -= A1%s;", s ? " (W32)" : ""); 4255 4256 acc0 -= acc1; 4257 if ((bs64)acc0 < -0x8000000000ll) 4258 acc0 = -0x8000000000ull, sat = 1; 4259 else if ((bs64)acc0 >= 0x7fffffffffll) 4260 acc0 = 0x7fffffffffull, sat = 1; 4261 4262 if (s == 1) 4263 { 4264 /* A0 -= A1 (W32) */ 4265 if (acc0 & (bu64)0x8000000000ll) 4266 acc0 &= 0x80ffffffffll, sat = 1; 4267 else 4268 acc0 &= 0xffffffffll; 4269 } 4270 STORE (AXREG (0), (acc0 >> 32) & 0xff); 4271 STORE (AWREG (0), acc0 & 0xffffffff); 4272 STORE (ASTATREG (az), acc0 == 0); 4273 STORE (ASTATREG (an), !!(acc0 & (bu64)0x8000000000ll)); 4274 STORE (ASTATREG (ac0), carry); 4275 STORE (ASTATREG (ac0_copy), carry); 4276 STORE (ASTATREG (av0), sat); 4277 if (sat) 4278 STORE (ASTATREG (av0s), sat); 4279 } 4280 else if ((aop == 0 || aop == 1) && aopcde == 22 && x == 0) 4281 { 4282 bu32 s0, s0L, s0H, s1, s1L, s1H; 4283 bu32 tmp0, tmp1, i; 4284 const char * const opts[] = { "rndl", "rndh", "tl", "th" }; 4285 4286 TRACE_INSN (cpu, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0, 4287 src0 + 1, src0, src1 + 1, src1, opts[HL + (aop << 1)], 4288 s ? ", r" : ""); 4289 4290 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2)) 4291 illegal_instruction (cpu); 4292 4293 s0L = DREG (src0); 4294 s0H = DREG (src0 + 1); 4295 s1L = DREG (src1); 4296 s1H = DREG (src1 + 1); 4297 if (s) 4298 { 4299 s0 = algn (s0H, s0L, IREG (0) & 3); 4300 s1 = algn (s1H, s1L, IREG (0) & 3); 4301 } 4302 else 4303 { 4304 s0 = algn (s0L, s0H, IREG (0) & 3); 4305 s1 = algn (s1L, s1H, IREG (0) & 3); 4306 } 4307 4308 i = !aop * 2; 4309 tmp0 = ((((s1 >> 8) & 0xff) + ((s1 >> 0) & 0xff) + 4310 ((s0 >> 8) & 0xff) + ((s0 >> 0) & 0xff) + i) >> 2) & 0xff; 4311 tmp1 = ((((s1 >> 24) & 0xff) + ((s1 >> 16) & 0xff) + 4312 ((s0 >> 24) & 0xff) + ((s0 >> 16) & 0xff) + i) >> 2) & 0xff; 4313 STORE (DREG (dst0), (tmp1 << (16 + (HL * 8))) | (tmp0 << (HL * 8))); 4314 4315 /* Implicit DISALGNEXCPT in parallel. */ 4316 DIS_ALGN_EXPT |= 1; 4317 } 4318 else if ((aop == 0 || aop == 1) && aopcde == 8 && x == 0 && s == 0 && HL == 0) 4319 { 4320 TRACE_INSN (cpu, "A%i = 0;", aop); 4321 SET_AREG (aop, 0); 4322 } 4323 else if (aop == 2 && aopcde == 8 && x == 0 && s == 0 && HL == 0) 4324 { 4325 TRACE_INSN (cpu, "A1 = A0 = 0;"); 4326 SET_AREG (0, 0); 4327 SET_AREG (1, 0); 4328 } 4329 else if ((aop == 0 || aop == 1 || aop == 2) && s == 1 && aopcde == 8 4330 && x == 0 && HL == 0) 4331 { 4332 bs40 acc0 = get_extended_acc (cpu, 0); 4333 bs40 acc1 = get_extended_acc (cpu, 1); 4334 bu32 sat; 4335 4336 if (aop == 0 || aop == 1) 4337 TRACE_INSN (cpu, "A%i = A%i (S);", aop, aop); 4338 else 4339 TRACE_INSN (cpu, "A1 = A1 (S), A0 = A0 (S);"); 4340 4341 if (aop == 0 || aop == 2) 4342 { 4343 sat = 0; 4344 acc0 = saturate_s32 (acc0, &sat); 4345 acc0 |= -(acc0 & 0x80000000ull); 4346 SET_AXREG (0, (acc0 >> 31) & 0xFF); 4347 SET_AWREG (0, acc0 & 0xFFFFFFFF); 4348 SET_ASTATREG (av0, sat); 4349 if (sat) 4350 SET_ASTATREG (av0s, sat); 4351 } 4352 else 4353 acc0 = 1; 4354 4355 if (aop == 1 || aop == 2) 4356 { 4357 sat = 0; 4358 acc1 = saturate_s32 (acc1, &sat); 4359 acc1 |= -(acc1 & 0x80000000ull); 4360 SET_AXREG (1, (acc1 >> 31) & 0xFF); 4361 SET_AWREG (1, acc1 & 0xFFFFFFFF); 4362 SET_ASTATREG (av1, sat); 4363 if (sat) 4364 SET_ASTATREG (av1s, sat); 4365 } 4366 else 4367 acc1 = 1; 4368 4369 SET_ASTATREG (az, (acc0 == 0) || (acc1 == 0)); 4370 SET_ASTATREG (an, ((acc0 >> 31) & 1) || ((acc1 >> 31) & 1)); 4371 } 4372 else if (aop == 3 && aopcde == 8 && x == 0 && HL == 0) 4373 { 4374 TRACE_INSN (cpu, "A%i = A%i;", s, !s); 4375 SET_AXREG (s, AXREG (!s)); 4376 SET_AWREG (s, AWREG (!s)); 4377 } 4378 else if (aop == 3 && HL == 0 && aopcde == 16 && x == 0 && s == 0) 4379 { 4380 int i; 4381 bu32 az; 4382 4383 TRACE_INSN (cpu, "A1 = ABS A1 , A0 = ABS A0;"); 4384 4385 az = 0; 4386 for (i = 0; i < 2; ++i) 4387 { 4388 bu32 av; 4389 bs40 acc = get_extended_acc (cpu, i); 4390 4391 if (acc >> 39) 4392 acc = -acc; 4393 av = acc == ((bs40)1 << 39); 4394 if (av) 4395 acc = ((bs40)1 << 39) - 1; 4396 4397 SET_AREG (i, acc); 4398 SET_ASTATREG (av[i], av); 4399 if (av) 4400 SET_ASTATREG (avs[i], av); 4401 az |= (acc == 0); 4402 } 4403 SET_ASTATREG (az, az); 4404 SET_ASTATREG (an, 0); 4405 } 4406 else if (aop == 0 && aopcde == 23 && x == 0) 4407 { 4408 bu32 s0, s0L, s0H, s1, s1L, s1H; 4409 bs32 tmp0, tmp1; 4410 4411 TRACE_INSN (cpu, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0, 4412 src0 + 1, src0, src1 + 1, src1, HL ? "HI" : "LO", 4413 s ? ", R" : ""); 4414 4415 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2)) 4416 illegal_instruction (cpu); 4417 4418 s0L = DREG (src0); 4419 s0H = DREG (src0 + 1); 4420 s1L = DREG (src1); 4421 s1H = DREG (src1 + 1); 4422 if (s) 4423 { 4424 s0 = algn (s0H, s0L, IREG (0) & 3); 4425 s1 = algn (s1H, s1L, IREG (1) & 3); 4426 } 4427 else 4428 { 4429 s0 = algn (s0L, s0H, IREG (0) & 3); 4430 s1 = algn (s1L, s1H, IREG (1) & 3); 4431 } 4432 4433 tmp0 = (bs32)(bs16)(s0 >> 0) + ((s1 >> ( 0 + (8 * !HL))) & 0xff); 4434 tmp1 = (bs32)(bs16)(s0 >> 16) + ((s1 >> (16 + (8 * !HL))) & 0xff); 4435 STORE (DREG (dst0), (CLAMP (tmp0, 0, 255) << ( 0 + (8 * HL))) | 4436 (CLAMP (tmp1, 0, 255) << (16 + (8 * HL)))); 4437 4438 /* Implicit DISALGNEXCPT in parallel. */ 4439 DIS_ALGN_EXPT |= 1; 4440 } 4441 else if ((aop == 0 || aop == 1) && aopcde == 16 && x == 0 && s == 0) 4442 { 4443 bu32 av; 4444 bs40 acc; 4445 4446 TRACE_INSN (cpu, "A%i = ABS A%i;", HL, aop); 4447 4448 acc = get_extended_acc (cpu, aop); 4449 if (acc >> 39) 4450 acc = -acc; 4451 av = acc == ((bs40)1 << 39); 4452 if (av) 4453 acc = ((bs40)1 << 39) - 1; 4454 SET_AREG (HL, acc); 4455 4456 SET_ASTATREG (av[HL], av); 4457 if (av) 4458 SET_ASTATREG (avs[HL], av); 4459 SET_ASTATREG (az, acc == 0); 4460 SET_ASTATREG (an, 0); 4461 } 4462 else if (aop == 3 && aopcde == 12 && x == 0 && s == 0) 4463 { 4464 bs32 res = DREG (src0); 4465 bs32 ovX; 4466 bool sBit_a, sBit_b; 4467 4468 TRACE_INSN (cpu, "R%i.%s = R%i (RND);", dst0, HL == 0 ? "L" : "H", src0); 4469 TRACE_DECODE (cpu, "R%i.%s = R%i:%#x (RND);", dst0, 4470 HL == 0 ? "L" : "H", src0, res); 4471 4472 sBit_b = !!(res & 0x80000000); 4473 4474 res += 0x8000; 4475 sBit_a = !!(res & 0x80000000); 4476 4477 /* Overflow if the sign bit changed when we rounded. */ 4478 if ((res >> 16) && (sBit_b != sBit_a)) 4479 { 4480 ovX = 1; 4481 if (!sBit_b) 4482 res = 0x7FFF; 4483 else 4484 res = 0x8000; 4485 } 4486 else 4487 { 4488 res = res >> 16; 4489 ovX = 0; 4490 } 4491 4492 if (!HL) 4493 SET_DREG (dst0, REG_H_L (DREG (dst0), res)); 4494 else 4495 SET_DREG (dst0, REG_H_L (res << 16, DREG (dst0))); 4496 4497 SET_ASTATREG (az, res == 0); 4498 SET_ASTATREG (an, res < 0); 4499 SET_ASTATREG (v, ovX); 4500 if (ovX) 4501 SET_ASTATREG (vs, ovX); 4502 } 4503 else if (aop == 3 && HL == 0 && aopcde == 15 && x == 0 && s == 0) 4504 { 4505 bu32 hi = (-(bs16)(DREG (src0) >> 16)) << 16; 4506 bu32 lo = (-(bs16)(DREG (src0) & 0xFFFF)) & 0xFFFF; 4507 int v, ac0, ac1; 4508 4509 TRACE_INSN (cpu, "R%i = -R%i (V);", dst0, src0); 4510 4511 v = ac0 = ac1 = 0; 4512 4513 if (hi == 0x80000000) 4514 { 4515 hi = 0x7fff0000; 4516 v = 1; 4517 } 4518 else if (hi == 0) 4519 ac1 = 1; 4520 4521 if (lo == 0x8000) 4522 { 4523 lo = 0x7fff; 4524 v = 1; 4525 } 4526 else if (lo == 0) 4527 ac0 = 1; 4528 4529 SET_DREG (dst0, hi | lo); 4530 4531 SET_ASTATREG (v, v); 4532 if (v) 4533 SET_ASTATREG (vs, 1); 4534 SET_ASTATREG (ac0, ac0); 4535 SET_ASTATREG (ac1, ac1); 4536 setflags_nz_2x16 (cpu, DREG (dst0)); 4537 } 4538 else if (aop == 3 && HL == 0 && aopcde == 14 && x == 0 && s == 0) 4539 { 4540 TRACE_INSN (cpu, "A1 = - A1 , A0 = - A0;"); 4541 4542 SET_AREG (0, saturate_s40 (-get_extended_acc (cpu, 0))); 4543 SET_AREG (1, saturate_s40 (-get_extended_acc (cpu, 1))); 4544 /* XXX: what ASTAT flags need updating ? */ 4545 } 4546 else if ((aop == 0 || aop == 1) && aopcde == 14 && x == 0 && s == 0) 4547 { 4548 bs40 src_acc = get_extended_acc (cpu, aop); 4549 bu32 v = 0; 4550 4551 TRACE_INSN (cpu, "A%i = - A%i;", HL, aop); 4552 4553 SET_AREG (HL, saturate_s40_astat (-src_acc, &v)); 4554 4555 SET_ASTATREG (az, AWREG (HL) == 0 && AXREG (HL) == 0); 4556 SET_ASTATREG (an, AXREG (HL) >> 7); 4557 if (HL == 0) 4558 { 4559 SET_ASTATREG (ac0, !src_acc); 4560 SET_ASTATREG (av0, v); 4561 if (v) 4562 SET_ASTATREG (av0s, 1); 4563 } 4564 else 4565 { 4566 SET_ASTATREG (ac1, !src_acc); 4567 SET_ASTATREG (av1, v); 4568 if (v) 4569 SET_ASTATREG (av1s, 1); 4570 } 4571 } 4572 else if (aop == 0 && aopcde == 12 && x == 0 && s == 0 && HL == 0) 4573 { 4574 bs16 tmp0_hi = DREG (src0) >> 16; 4575 bs16 tmp0_lo = DREG (src0); 4576 bs16 tmp1_hi = DREG (src1) >> 16; 4577 bs16 tmp1_lo = DREG (src1); 4578 4579 TRACE_INSN (cpu, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;", 4580 dst0, dst0, src0, src1, src0, src1); 4581 4582 if ((tmp0_hi >> 15) & 1) 4583 tmp1_hi = ~tmp1_hi + 1; 4584 4585 if ((tmp0_lo >> 15) & 1) 4586 tmp1_lo = ~tmp1_lo + 1; 4587 4588 tmp1_hi = tmp1_hi + tmp1_lo; 4589 4590 STORE (DREG (dst0), REG_H_L (tmp1_hi << 16, tmp1_hi)); 4591 } 4592 else if (aopcde == 0 && HL == 0) 4593 { 4594 bu32 s0 = DREG (src0); 4595 bu32 s1 = DREG (src1); 4596 bu32 s0h = s0 >> 16; 4597 bu32 s0l = s0 & 0xFFFF; 4598 bu32 s1h = s1 >> 16; 4599 bu32 s1l = s1 & 0xFFFF; 4600 bu32 t0, t1; 4601 bu32 ac1_i = 0, ac0_i = 0, v_i = 0, z_i = 0, n_i = 0; 4602 4603 TRACE_INSN (cpu, "R%i = R%i %c|%c R%i%s;", dst0, src0, 4604 (aop & 2) ? '-' : '+', (aop & 1) ? '-' : '+', src1, 4605 amod0 (s, x)); 4606 if (aop & 2) 4607 t0 = sub16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0); 4608 else 4609 t0 = add16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0); 4610 4611 if (aop & 1) 4612 t1 = sub16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0); 4613 else 4614 t1 = add16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0); 4615 4616 SET_ASTATREG (ac1, ac1_i); 4617 SET_ASTATREG (ac0, ac0_i); 4618 SET_ASTATREG (az, z_i); 4619 SET_ASTATREG (an, n_i); 4620 SET_ASTATREG (v, v_i); 4621 if (v_i) 4622 SET_ASTATREG (vs, v_i); 4623 4624 t0 &= 0xFFFF; 4625 t1 &= 0xFFFF; 4626 if (x) 4627 SET_DREG (dst0, (t1 << 16) | t0); 4628 else 4629 SET_DREG (dst0, (t0 << 16) | t1); 4630 } 4631 else if (aop == 1 && aopcde == 12 && x == 0 && s == 0 && HL == 0) 4632 { 4633 bs32 val0 = (bs16)(AWREG (0) >> 16) + (bs16)AWREG (0); 4634 bs32 val1 = (bs16)(AWREG (1) >> 16) + (bs16)AWREG (1); 4635 4636 TRACE_INSN (cpu, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1, dst0); 4637 4638 if (dst0 == dst1) 4639 illegal_instruction_combination (cpu); 4640 4641 SET_DREG (dst0, val0); 4642 SET_DREG (dst1, val1); 4643 } 4644 else if ((aop == 0 || aop == 2 || aop == 3) && aopcde == 1) 4645 { 4646 bu32 d0, d1; 4647 bu32 x0, x1; 4648 bu16 s0L = DREG (src0); 4649 bu16 s0H = DREG (src0) >> 16; 4650 bu16 s1L = DREG (src1); 4651 bu16 s1H = DREG (src1) >> 16; 4652 bu32 v_i = 0, n_i = 0, z_i = 0; 4653 4654 TRACE_INSN (cpu, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;", 4655 dst1, src0, HL ? "+|-" : "+|+", src1, 4656 dst0, src0, HL ? "-|+" : "-|-", src1, 4657 amod0amod2 (s, x, aop)); 4658 4659 if (dst0 == dst1) 4660 illegal_instruction_combination (cpu); 4661 4662 if (HL == 0) 4663 { 4664 x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff; 4665 x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff; 4666 d1 = (x0 << 16) | x1; 4667 4668 x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff; 4669 x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff; 4670 if (x == 0) 4671 d0 = (x0 << 16) | x1; 4672 else 4673 d0 = (x1 << 16) | x0; 4674 } 4675 else 4676 { 4677 x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff; 4678 x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff; 4679 d1 = (x0 << 16) | x1; 4680 4681 x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff; 4682 x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff; 4683 if (x == 0) 4684 d0 = (x0 << 16) | x1; 4685 else 4686 d0 = (x1 << 16) | x0; 4687 } 4688 SET_ASTATREG (az, z_i); 4689 SET_ASTATREG (an, n_i); 4690 SET_ASTATREG (v, v_i); 4691 if (v_i) 4692 SET_ASTATREG (vs, v_i); 4693 4694 STORE (DREG (dst0), d0); 4695 STORE (DREG (dst1), d1); 4696 } 4697 else if ((aop == 0 || aop == 1 || aop == 2) && aopcde == 11 && x == 0) 4698 { 4699 bs40 acc0 = get_extended_acc (cpu, 0); 4700 bs40 acc1 = get_extended_acc (cpu, 1); 4701 bu32 v, dreg, sat = 0; 4702 bu32 carry = !!((bu40)~acc1 < (bu40)acc0); 4703 4704 if (aop == 0) 4705 { 4706 if (s != 0 || HL != 0) 4707 illegal_instruction (cpu); 4708 TRACE_INSN (cpu, "R%i = (A0 += A1);", dst0); 4709 } 4710 else if (aop == 1) 4711 { 4712 if (s != 0) 4713 illegal_instruction (cpu); 4714 TRACE_INSN (cpu, "R%i.%c = (A0 += A1);", dst0, HL ? 'H' : 'L'); 4715 } 4716 else 4717 { 4718 if (HL != 0) 4719 illegal_instruction (cpu); 4720 TRACE_INSN (cpu, "A0 += A1%s;", s ? " (W32)" : ""); 4721 } 4722 4723 acc0 += acc1; 4724 acc0 = saturate_s40_astat (acc0, &v); 4725 4726 if (aop == 2 && s == 1) /* A0 += A1 (W32) */ 4727 { 4728 if (acc0 & (bs40)0x8000000000ll) 4729 acc0 &= 0x80ffffffffll; 4730 else 4731 acc0 &= 0xffffffffll; 4732 } 4733 4734 STORE (AXREG (0), acc0 >> 32); 4735 STORE (AWREG (0), acc0); 4736 SET_ASTATREG (av0, v && acc1); 4737 if (v) 4738 SET_ASTATREG (av0s, v); 4739 4740 if (aop == 0 || aop == 1) 4741 { 4742 if (aop) /* Dregs_lo = A0 += A1 */ 4743 { 4744 dreg = saturate_s32 (rnd16 (acc0) << 16, &sat); 4745 if (HL) 4746 STORE (DREG (dst0), REG_H_L (dreg, DREG (dst0))); 4747 else 4748 STORE (DREG (dst0), REG_H_L (DREG (dst0), dreg >> 16)); 4749 } 4750 else /* Dregs = A0 += A1 */ 4751 { 4752 dreg = saturate_s32 (acc0, &sat); 4753 STORE (DREG (dst0), dreg); 4754 } 4755 4756 STORE (ASTATREG (az), dreg == 0); 4757 STORE (ASTATREG (an), !!(dreg & 0x80000000)); 4758 STORE (ASTATREG (ac0), carry); 4759 STORE (ASTATREG (ac0_copy), carry); 4760 STORE (ASTATREG (v), sat); 4761 STORE (ASTATREG (v_copy), sat); 4762 if (sat) 4763 STORE (ASTATREG (vs), sat); 4764 } 4765 else 4766 { 4767 STORE (ASTATREG (az), acc0 == 0); 4768 STORE (ASTATREG (an), !!(acc0 & 0x8000000000ull)); 4769 STORE (ASTATREG (ac0), carry); 4770 STORE (ASTATREG (ac0_copy), carry); 4771 } 4772 } 4773 else if ((aop == 0 || aop == 1) && aopcde == 10 && x == 0 && s == 0 && HL == 0) 4774 { 4775 TRACE_INSN (cpu, "R%i.L = A%i.X;", dst0, aop); 4776 SET_DREG_L (dst0, (bs8)AXREG (aop)); 4777 } 4778 else if (aop == 0 && aopcde == 4 && x == 0 && HL == 0) 4779 { 4780 TRACE_INSN (cpu, "R%i = R%i + R%i%s;", dst0, src0, src1, amod1 (s, x)); 4781 SET_DREG (dst0, add32 (cpu, DREG (src0), DREG (src1), 1, s)); 4782 } 4783 else if (aop == 1 && aopcde == 4 && x == 0 && HL == 0) 4784 { 4785 TRACE_INSN (cpu, "R%i = R%i - R%i%s;", dst0, src0, src1, amod1 (s, x)); 4786 SET_DREG (dst0, sub32 (cpu, DREG (src0), DREG (src1), 1, s, 0)); 4787 } 4788 else if (aop == 2 && aopcde == 4 && x == 0 && HL == 0) 4789 { 4790 TRACE_INSN (cpu, "R%i = R%i + R%i, R%i = R%i - R%i%s;", 4791 dst1, src0, src1, dst0, src0, src1, amod1 (s, x)); 4792 4793 if (dst0 == dst1) 4794 illegal_instruction_combination (cpu); 4795 4796 STORE (DREG (dst1), add32 (cpu, DREG (src0), DREG (src1), 1, s)); 4797 STORE (DREG (dst0), sub32 (cpu, DREG (src0), DREG (src1), 1, s, 1)); 4798 } 4799 else if ((aop == 0 || aop == 1) && aopcde == 17 && x == 0 && HL == 0) 4800 { 4801 bs40 acc0 = get_extended_acc (cpu, 0); 4802 bs40 acc1 = get_extended_acc (cpu, 1); 4803 bs40 val0, val1, sval0, sval1; 4804 bu32 sat, sat_i; 4805 4806 TRACE_INSN (cpu, "R%i = A%i + A%i, R%i = A%i - A%i%s", 4807 dst1, !aop, aop, dst0, !aop, aop, amod1 (s, x)); 4808 TRACE_DECODE (cpu, "R%i = A%i:%#"PRIx64" + A%i:%#"PRIx64", " 4809 "R%i = A%i:%#"PRIx64" - A%i:%#"PRIx64"%s", 4810 dst1, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0, 4811 dst0, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0, 4812 amod1 (s, x)); 4813 4814 if (dst0 == dst1) 4815 illegal_instruction_combination (cpu); 4816 4817 val1 = acc0 + acc1; 4818 if (aop) 4819 val0 = acc0 - acc1; 4820 else 4821 val0 = acc1 - acc0; 4822 4823 sval0 = saturate_s32 (val0, &sat); 4824 sat_i = sat; 4825 sval1 = saturate_s32 (val1, &sat); 4826 sat_i |= sat; 4827 if (s) 4828 { 4829 val0 = sval0; 4830 val1 = sval1; 4831 } 4832 4833 STORE (DREG (dst0), val0); 4834 STORE (DREG (dst1), val1); 4835 SET_ASTATREG (v, sat_i); 4836 if (sat_i) 4837 SET_ASTATREG (vs, sat_i); 4838 SET_ASTATREG (an, val0 & 0x80000000 || val1 & 0x80000000); 4839 SET_ASTATREG (az, val0 == 0 || val1 == 0); 4840 SET_ASTATREG (ac1, (bu40)~acc0 < (bu40)acc1); 4841 if (aop) 4842 SET_ASTATREG (ac0, !!((bu40)acc1 <= (bu40)acc0)); 4843 else 4844 SET_ASTATREG (ac0, !!((bu40)acc0 <= (bu40)acc1)); 4845 } 4846 else if (aop == 0 && aopcde == 18 && x == 0 && HL == 0) 4847 { 4848 bu40 acc0 = get_extended_acc (cpu, 0); 4849 bu40 acc1 = get_extended_acc (cpu, 1); 4850 bu32 s0L = DREG (src0); 4851 bu32 s0H = DREG (src0 + 1); 4852 bu32 s1L = DREG (src1); 4853 bu32 s1H = DREG (src1 + 1); 4854 bu32 s0, s1; 4855 bs16 tmp0, tmp1, tmp2, tmp3; 4856 4857 /* This instruction is only defined for register pairs R1:0 and R3:2. */ 4858 if (!((src0 == 0 || src0 == 2) && (src1 == 0 || src1 == 2))) 4859 illegal_instruction (cpu); 4860 4861 TRACE_INSN (cpu, "SAA (R%i:%i, R%i:%i)%s", src0 + 1, src0, 4862 src1 + 1, src1, s ? " (R)" :""); 4863 4864 /* Bit s determines the order of the two registers from a pair: 4865 if s=0 the low-order bytes come from the low reg in the pair, 4866 and if s=1 the low-order bytes come from the high reg. */ 4867 4868 if (s) 4869 { 4870 s0 = algn (s0H, s0L, IREG (0) & 3); 4871 s1 = algn (s1H, s1L, IREG (1) & 3); 4872 } 4873 else 4874 { 4875 s0 = algn (s0L, s0H, IREG (0) & 3); 4876 s1 = algn (s1L, s1H, IREG (1) & 3); 4877 } 4878 4879 /* Find the absolute difference between pairs, make it 4880 absolute, then add it to the existing accumulator half. */ 4881 /* Byte 0 */ 4882 tmp0 = ((s0 << 24) >> 24) - ((s1 << 24) >> 24); 4883 tmp1 = ((s0 << 16) >> 24) - ((s1 << 16) >> 24); 4884 tmp2 = ((s0 << 8) >> 24) - ((s1 << 8) >> 24); 4885 tmp3 = ((s0 << 0) >> 24) - ((s1 << 0) >> 24); 4886 4887 tmp0 = (tmp0 < 0) ? -tmp0 : tmp0; 4888 tmp1 = (tmp1 < 0) ? -tmp1 : tmp1; 4889 tmp2 = (tmp2 < 0) ? -tmp2 : tmp2; 4890 tmp3 = (tmp3 < 0) ? -tmp3 : tmp3; 4891 4892 s0L = saturate_u16 ((bu32)tmp0 + ((acc0 >> 0) & 0xffff), 0); 4893 s0H = saturate_u16 ((bu32)tmp1 + ((acc0 >> 16) & 0xffff), 0); 4894 s1L = saturate_u16 ((bu32)tmp2 + ((acc1 >> 0) & 0xffff), 0); 4895 s1H = saturate_u16 ((bu32)tmp3 + ((acc1 >> 16) & 0xffff), 0); 4896 4897 STORE (AWREG (0), (s0H << 16) | (s0L & 0xFFFF)); 4898 STORE (AXREG (0), 0); 4899 STORE (AWREG (1), (s1H << 16) | (s1L & 0xFFFF)); 4900 STORE (AXREG (1), 0); 4901 4902 /* Implicit DISALGNEXCPT in parallel. */ 4903 DIS_ALGN_EXPT |= 1; 4904 } 4905 else if (aop == 3 && aopcde == 18 && x == 0 && s == 0 && HL == 0) 4906 { 4907 TRACE_INSN (cpu, "DISALGNEXCPT"); 4908 DIS_ALGN_EXPT |= 1; 4909 } 4910 else if ((aop == 0 || aop == 1) && aopcde == 20 && x == 0 && HL == 0) 4911 { 4912 bu32 s0, s0L, s0H, s1, s1L, s1H; 4913 const char * const opts[] = { "", " (R)", " (T)", " (T, R)" }; 4914 4915 TRACE_INSN (cpu, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0, 4916 src0 + 1, src0, src1 + 1, src1, opts[s + (aop << 1)]); 4917 4918 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2)) 4919 illegal_instruction (cpu); 4920 4921 s0L = DREG (src0); 4922 s0H = DREG (src0 + 1); 4923 s1L = DREG (src1); 4924 s1H = DREG (src1 + 1); 4925 if (s) 4926 { 4927 s0 = algn (s0H, s0L, IREG (0) & 3); 4928 s1 = algn (s1H, s1L, IREG (1) & 3); 4929 } 4930 else 4931 { 4932 s0 = algn (s0L, s0H, IREG (0) & 3); 4933 s1 = algn (s1L, s1H, IREG (1) & 3); 4934 } 4935 4936 STORE (DREG (dst0), 4937 (((((s0 >> 0) & 0xff) + ((s1 >> 0) & 0xff) + !aop) >> 1) << 0) | 4938 (((((s0 >> 8) & 0xff) + ((s1 >> 8) & 0xff) + !aop) >> 1) << 8) | 4939 (((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff) + !aop) >> 1) << 16) | 4940 (((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff) + !aop) >> 1) << 24)); 4941 4942 /* Implicit DISALGNEXCPT in parallel. */ 4943 DIS_ALGN_EXPT |= 1; 4944 } 4945 else if (aop == 0 && aopcde == 21 && x == 0 && HL == 0) 4946 { 4947 bu32 s0, s0L, s0H, s1, s1L, s1H; 4948 4949 TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1, dst0, 4950 src0 + 1, src0, src1 + 1, src1, s ? " (R)" : ""); 4951 4952 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2)) 4953 illegal_instruction (cpu); 4954 4955 if (dst0 == dst1) 4956 illegal_instruction_combination (cpu); 4957 4958 s0L = DREG (src0); 4959 s0H = DREG (src0 + 1); 4960 s1L = DREG (src1); 4961 s1H = DREG (src1 + 1); 4962 if (s) 4963 { 4964 s0 = algn (s0H, s0L, IREG (0) & 3); 4965 s1 = algn (s1H, s1L, IREG (1) & 3); 4966 } 4967 else 4968 { 4969 s0 = algn (s0L, s0H, IREG (0) & 3); 4970 s1 = algn (s1L, s1H, IREG (1) & 3); 4971 } 4972 4973 STORE (DREG (dst0), 4974 ((((s0 >> 0) & 0xff) + ((s1 >> 0) & 0xff)) << 0) | 4975 ((((s0 >> 8) & 0xff) + ((s1 >> 8) & 0xff)) << 16)); 4976 STORE (DREG (dst1), 4977 ((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff)) << 0) | 4978 ((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff)) << 16)); 4979 4980 /* Implicit DISALGNEXCPT in parallel. */ 4981 DIS_ALGN_EXPT |= 1; 4982 } 4983 else if (aop == 1 && aopcde == 21 && x == 0 && HL == 0) 4984 { 4985 bu32 s0, s0L, s0H, s1, s1L, s1H; 4986 4987 TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1, dst0, 4988 src0 + 1, src0, src1 + 1, src1, s ? " (R)" : ""); 4989 4990 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2)) 4991 illegal_instruction (cpu); 4992 4993 if (dst0 == dst1) 4994 illegal_instruction_combination (cpu); 4995 4996 s0L = DREG (src0); 4997 s0H = DREG (src0 + 1); 4998 s1L = DREG (src1); 4999 s1H = DREG (src1 + 1); 5000 if (s) 5001 { 5002 s0 = algn (s0H, s0L, IREG (0) & 3); 5003 s1 = algn (s1H, s1L, IREG (1) & 3); 5004 } 5005 else 5006 { 5007 s0 = algn (s0L, s0H, IREG (0) & 3); 5008 s1 = algn (s1L, s1H, IREG (1) & 3); 5009 } 5010 5011 STORE (DREG (dst0), 5012 (((((s0 >> 0) & 0xff) - ((s1 >> 0) & 0xff)) << 0) & 0xffff) | 5013 (((((s0 >> 8) & 0xff) - ((s1 >> 8) & 0xff)) << 16))); 5014 STORE (DREG (dst1), 5015 (((((s0 >> 16) & 0xff) - ((s1 >> 16) & 0xff)) << 0) & 0xffff) | 5016 (((((s0 >> 24) & 0xff) - ((s1 >> 24) & 0xff)) << 16))); 5017 5018 /* Implicit DISALGNEXCPT in parallel. */ 5019 DIS_ALGN_EXPT |= 1; 5020 } 5021 else if (aop == 1 && aopcde == 7 && x == 0 && s == 0 && HL == 0) 5022 { 5023 TRACE_INSN (cpu, "R%i = MIN (R%i, R%i);", dst0, src0, src1); 5024 SET_DREG (dst0, min32 (cpu, DREG (src0), DREG (src1))); 5025 } 5026 else if (aop == 0 && aopcde == 7 && x == 0 && s == 0 && HL == 0) 5027 { 5028 TRACE_INSN (cpu, "R%i = MAX (R%i, R%i);", dst0, src0, src1); 5029 SET_DREG (dst0, max32 (cpu, DREG (src0), DREG (src1))); 5030 } 5031 else if (aop == 2 && aopcde == 7 && x == 0 && s == 0 && HL == 0) 5032 { 5033 bu32 val = DREG (src0); 5034 int v; 5035 5036 TRACE_INSN (cpu, "R%i = ABS R%i;", dst0, src0); 5037 5038 if (val >> 31) 5039 val = -val; 5040 v = (val == 0x80000000); 5041 if (v) 5042 val = 0x7fffffff; 5043 SET_DREG (dst0, val); 5044 5045 SET_ASTATREG (v, v); 5046 if (v) 5047 SET_ASTATREG (vs, 1); 5048 setflags_nz (cpu, val); 5049 } 5050 else if (aop == 3 && aopcde == 7 && x == 0 && HL == 0) 5051 { 5052 bu32 val = DREG (src0); 5053 5054 TRACE_INSN (cpu, "R%i = - R%i%s;", dst0, src0, amod1 (s, 0)); 5055 5056 if (s && val == 0x80000000) 5057 { 5058 val = 0x7fffffff; 5059 SET_ASTATREG (v, 1); 5060 SET_ASTATREG (vs, 1); 5061 } 5062 else if (val == 0x80000000) 5063 val = 0x80000000; 5064 else 5065 val = -val; 5066 SET_DREG (dst0, val); 5067 5068 SET_ASTATREG (az, val == 0); 5069 SET_ASTATREG (an, val & 0x80000000); 5070 } 5071 else if (aop == 2 && aopcde == 6 && x == 0 && s == 0 && HL == 0) 5072 { 5073 bu32 in = DREG (src0); 5074 bu32 hi = (in & 0x80000000 ? (bu32)-(bs16)(in >> 16) : in >> 16) << 16; 5075 bu32 lo = (in & 0x8000 ? (bu32)-(bs16)(in & 0xFFFF) : in) & 0xFFFF; 5076 int v; 5077 5078 TRACE_INSN (cpu, "R%i = ABS R%i (V);", dst0, src0); 5079 5080 v = 0; 5081 if (hi == 0x80000000) 5082 { 5083 hi = 0x7fff0000; 5084 v = 1; 5085 } 5086 if (lo == 0x8000) 5087 { 5088 lo = 0x7fff; 5089 v = 1; 5090 } 5091 SET_DREG (dst0, hi | lo); 5092 5093 SET_ASTATREG (v, v); 5094 if (v) 5095 SET_ASTATREG (vs, 1); 5096 setflags_nz_2x16 (cpu, DREG (dst0)); 5097 } 5098 else if (aop == 1 && aopcde == 6 && x == 0 && s == 0 && HL == 0) 5099 { 5100 TRACE_INSN (cpu, "R%i = MIN (R%i, R%i) (V);", dst0, src0, src1); 5101 SET_DREG (dst0, min2x16 (cpu, DREG (src0), DREG (src1))); 5102 } 5103 else if (aop == 0 && aopcde == 6 && x == 0 && s == 0 && HL == 0) 5104 { 5105 TRACE_INSN (cpu, "R%i = MAX (R%i, R%i) (V);", dst0, src0, src1); 5106 SET_DREG (dst0, max2x16 (cpu, DREG (src0), DREG (src1))); 5107 } 5108 else if (aop == 0 && aopcde == 24 && x == 0 && s == 0 && HL == 0) 5109 { 5110 TRACE_INSN (cpu, "R%i = BYTEPACK (R%i, R%i);", dst0, src0, src1); 5111 STORE (DREG (dst0), 5112 (((DREG (src0) >> 0) & 0xff) << 0) | 5113 (((DREG (src0) >> 16) & 0xff) << 8) | 5114 (((DREG (src1) >> 0) & 0xff) << 16) | 5115 (((DREG (src1) >> 16) & 0xff) << 24)); 5116 5117 /* Implicit DISALGNEXCPT in parallel. */ 5118 DIS_ALGN_EXPT |= 1; 5119 } 5120 else if (aop == 1 && aopcde == 24 && x == 0 && HL == 0) 5121 { 5122 int order, lo, hi; 5123 bu64 comb_src; 5124 bu8 bytea, byteb, bytec, byted; 5125 5126 TRACE_INSN (cpu, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;", 5127 dst1, dst0, src0 + 1, src0, s ? " (R)" : ""); 5128 5129 if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2)) 5130 illegal_instruction (cpu); 5131 5132 if (dst0 == dst1) 5133 illegal_instruction_combination (cpu); 5134 5135 order = IREG (0) & 0x3; 5136 if (s) 5137 hi = src0, lo = src0 + 1; 5138 else 5139 hi = src0 + 1, lo = src0; 5140 comb_src = (((bu64)DREG (hi)) << 32) | DREG (lo); 5141 bytea = (comb_src >> (0 + 8 * order)); 5142 byteb = (comb_src >> (8 + 8 * order)); 5143 bytec = (comb_src >> (16 + 8 * order)); 5144 byted = (comb_src >> (24 + 8 * order)); 5145 STORE (DREG (dst0), bytea | ((bu32)byteb << 16)); 5146 STORE (DREG (dst1), bytec | ((bu32)byted << 16)); 5147 5148 /* Implicit DISALGNEXCPT in parallel. */ 5149 DIS_ALGN_EXPT |= 1; 5150 } 5151 else if (aopcde == 13 && HL == 0 && x == 0 && s == 0) 5152 { 5153 const char *searchmodes[] = { "GT", "GE", "LT", "LE" }; 5154 bool up_hi, up_lo; 5155 bs16 a0_lo, a1_lo, src_hi, src_lo; 5156 5157 TRACE_INSN (cpu, "(R%i, R%i) = SEARCH R%i (%s);", 5158 dst1, dst0, src0, searchmodes[aop]); 5159 5160 /* XXX: The parallel version is a bit weird in its limits: 5161 5162 This instruction can be issued in parallel with the combination of one 5163 16-bit length load instruction to the P0 register and one 16-bit NOP. 5164 No other instructions can be issued in parallel with the Vector Search 5165 instruction. Note the following legal and illegal forms. 5166 (r1, r0) = search r2 (LT) || r2 = [p0++p3]; // ILLEGAL 5167 (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL 5168 (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL 5169 5170 Unfortunately, our parallel insn state doesn't (currently) track enough 5171 details to be able to check this. */ 5172 5173 if (dst0 == dst1) 5174 illegal_instruction_combination (cpu); 5175 5176 up_hi = up_lo = false; 5177 a0_lo = AWREG (0); 5178 a1_lo = AWREG (1); 5179 src_lo = DREG (src0); 5180 src_hi = DREG (src0) >> 16; 5181 5182 switch (aop) 5183 { 5184 case 0: 5185 up_hi = (src_hi > a1_lo); 5186 up_lo = (src_lo > a0_lo); 5187 break; 5188 case 1: 5189 up_hi = (src_hi >= a1_lo); 5190 up_lo = (src_lo >= a0_lo); 5191 break; 5192 case 2: 5193 up_hi = (src_hi < a1_lo); 5194 up_lo = (src_lo < a0_lo); 5195 break; 5196 case 3: 5197 up_hi = (src_hi <= a1_lo); 5198 up_lo = (src_lo <= a0_lo); 5199 break; 5200 } 5201 5202 if (up_hi) 5203 { 5204 SET_AREG (1, src_hi); 5205 SET_DREG (dst1, PREG (0)); 5206 } 5207 else 5208 SET_AREG (1, a1_lo); 5209 5210 if (up_lo) 5211 { 5212 SET_AREG (0, src_lo); 5213 SET_DREG (dst0, PREG (0)); 5214 } 5215 else 5216 SET_AREG (0, a0_lo); 5217 } 5218 else 5219 illegal_instruction (cpu); 5220 } 5221 5222 static void 5223 decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) 5224 { 5225 /* dsp32shift 5226 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 5227 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............| 5228 |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......| 5229 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 5230 int HLs = ((iw1 >> DSP32Shift_HLs_bits) & DSP32Shift_HLs_mask); 5231 int sop = ((iw1 >> DSP32Shift_sop_bits) & DSP32Shift_sop_mask); 5232 int src0 = ((iw1 >> DSP32Shift_src0_bits) & DSP32Shift_src0_mask); 5233 int src1 = ((iw1 >> DSP32Shift_src1_bits) & DSP32Shift_src1_mask); 5234 int dst0 = ((iw1 >> DSP32Shift_dst0_bits) & DSP32Shift_dst0_mask); 5235 int sopcde = ((iw0 >> (DSP32Shift_sopcde_bits - 16)) & DSP32Shift_sopcde_mask); 5236 int M = ((iw0 >> (DSP32Shift_M_bits - 16)) & DSP32Shift_M_mask); 5237 5238 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shift); 5239 TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i", 5240 __func__, M, sopcde, sop, HLs, dst0, src0, src1); 5241 5242 if ((sop == 0 || sop == 1) && sopcde == 0) 5243 { 5244 bu16 val; 5245 bs32 shft = (bs8)(DREG (src0) << 2) >> 2; 5246 5247 TRACE_INSN (cpu, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;", 5248 dst0, HLs < 2 ? 'L' : 'H', 5249 src1, HLs & 1 ? 'H' : 'L', 5250 src0, sop == 1 ? " (S)" : ""); 5251 5252 if ((HLs & 1) == 0) 5253 val = (bu16)(DREG (src1) & 0xFFFF); 5254 else 5255 val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16); 5256 5257 /* Positive shift magnitudes produce Logical Left shifts. 5258 Negative shift magnitudes produce Arithmetic Right shifts. */ 5259 if (shft <= 0) 5260 val = ashiftrt (cpu, val, -shft, 16); 5261 else 5262 { 5263 int sgn = (val >> 15) & 0x1; 5264 5265 val = lshift (cpu, val, shft, 16, sop == 1, 1); 5266 if (((val >> 15) & 0x1) != sgn) 5267 { 5268 SET_ASTATREG (v, 1); 5269 SET_ASTATREG (vs, 1); 5270 } 5271 } 5272 5273 if ((HLs & 2) == 0) 5274 STORE (DREG (dst0), REG_H_L (DREG (dst0), val)); 5275 else 5276 STORE (DREG (dst0), REG_H_L (val << 16, DREG (dst0))); 5277 } 5278 else if (sop == 2 && sopcde == 0) 5279 { 5280 bs32 shft = (bs8)(DREG (src0) << 2) >> 2; 5281 bu16 val; 5282 5283 TRACE_INSN (cpu, "R%i.%c = LSHIFT R%i.%c BY R%i.L;", 5284 dst0, HLs < 2 ? 'L' : 'H', 5285 src1, HLs & 1 ? 'H' : 'L', src0); 5286 5287 if ((HLs & 1) == 0) 5288 val = (bu16)(DREG (src1) & 0xFFFF); 5289 else 5290 val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16); 5291 5292 if (shft < 0) 5293 val = val >> (-1 * shft); 5294 else 5295 val = val << shft; 5296 5297 if ((HLs & 2) == 0) 5298 SET_DREG (dst0, REG_H_L (DREG (dst0), val)); 5299 else 5300 SET_DREG (dst0, REG_H_L (val << 16, DREG (dst0))); 5301 5302 SET_ASTATREG (az, !((val & 0xFFFF0000) == 0) || ((val & 0xFFFF) == 0)); 5303 SET_ASTATREG (an, (!!(val & 0x80000000)) ^ (!!(val & 0x8000))); 5304 SET_ASTATREG (v, 0); 5305 } 5306 else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0)) 5307 { 5308 int shift = imm6 (DREG (src0) & 0xFFFF); 5309 bu32 cc = CCREG; 5310 bu40 acc = get_unextended_acc (cpu, HLs); 5311 5312 TRACE_INSN (cpu, "A%i = ROT A%i BY R%i.L;", HLs, HLs, src0); 5313 TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc); 5314 5315 acc = rot40 (acc, shift, &cc); 5316 SET_AREG (HLs, acc); 5317 if (shift) 5318 SET_CCREG (cc); 5319 } 5320 else if (sop == 0 && sopcde == 3 && (HLs == 0 || HLs == 1)) 5321 { 5322 bs32 shft = (bs8)(DREG (src0) << 2) >> 2; 5323 bu64 acc = get_extended_acc (cpu, HLs); 5324 bu64 val; 5325 5326 HLs = !!HLs; 5327 TRACE_INSN (cpu, "A%i = ASHIFT A%i BY R%i.L;", HLs, HLs, src0); 5328 TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft); 5329 5330 if (shft <= 0) 5331 val = ashiftrt (cpu, acc, -shft, 40); 5332 else 5333 val = lshift (cpu, acc, shft, 40, 0, 0); 5334 5335 STORE (AXREG (HLs), (val >> 32) & 0xff); 5336 STORE (AWREG (HLs), (val & 0xffffffff)); 5337 STORE (ASTATREG (av[HLs]), 0); 5338 } 5339 else if (sop == 1 && sopcde == 3 && (HLs == 0 || HLs == 1)) 5340 { 5341 bs32 shft = (bs8)(DREG (src0) << 2) >> 2; 5342 bu64 acc = get_unextended_acc (cpu, HLs); 5343 bu64 val; 5344 5345 HLs = !!HLs; 5346 TRACE_INSN (cpu, "A%i = LSHIFT A%i BY R%i.L;", HLs, HLs, src0); 5347 TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft); 5348 5349 if (shft <= 0) 5350 val = lshiftrt (cpu, acc, -shft, 40); 5351 else 5352 val = lshift (cpu, acc, shft, 40, 0, 0); 5353 5354 STORE (AXREG (HLs), (val >> 32) & 0xff); 5355 STORE (AWREG (HLs), (val & 0xffffffff)); 5356 STORE (ASTATREG (av[HLs]), 0); 5357 } 5358 else if (HLs != 0) 5359 /* All the insns after this point don't use HLs. */ 5360 illegal_instruction (cpu); 5361 else if ((sop == 0 || sop == 1) && sopcde == 1 && HLs == 0) 5362 { 5363 bs32 shft = (bs8)(DREG (src0) << 2) >> 2; 5364 bu16 val0, val1; 5365 bu32 astat; 5366 5367 TRACE_INSN (cpu, "R%i = ASHIFT R%i BY R%i.L (V%s);", 5368 dst0, src1, src0, sop == 1 ? ",S" : ""); 5369 5370 val0 = (bu16)DREG (src1) & 0xFFFF; 5371 val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16); 5372 5373 if (shft <= 0) 5374 { 5375 val0 = ashiftrt (cpu, val0, -shft, 16); 5376 astat = ASTAT; 5377 val1 = ashiftrt (cpu, val1, -shft, 16); 5378 } 5379 else 5380 { 5381 int sgn0 = (val0 >> 15) & 0x1; 5382 int sgn1 = (val1 >> 15) & 0x1; 5383 5384 val0 = lshift (cpu, val0, shft, 16, sop == 1, 1); 5385 astat = ASTAT; 5386 val1 = lshift (cpu, val1, shft, 16, sop == 1, 1); 5387 5388 if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1))) 5389 { 5390 SET_ASTATREG (v, 1); 5391 SET_ASTATREG (vs, 1); 5392 } 5393 } 5394 SET_ASTAT (ASTAT | astat); 5395 STORE (DREG (dst0), (val1 << 16) | val0); 5396 } 5397 else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 2) 5398 { 5399 /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */ 5400 /* sop == 1 : opt_S */ 5401 bu32 v = DREG (src1); 5402 /* LSHIFT uses sign extended low 6 bits of dregs_lo. */ 5403 bs32 shft = (bs8)(DREG (src0) << 2) >> 2; 5404 5405 TRACE_INSN (cpu, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0, 5406 shft && sop != 2 ? 'A' : 'L', src1, src0, 5407 sop == 1 ? " (S)" : ""); 5408 5409 if (shft < 0) 5410 { 5411 if (sop == 2) 5412 STORE (DREG (dst0), lshiftrt (cpu, v, -shft, 32)); 5413 else 5414 STORE (DREG (dst0), ashiftrt (cpu, v, -shft, 32)); 5415 } 5416 else 5417 { 5418 bu32 val = lshift (cpu, v, shft, 32, sop == 1, 1); 5419 5420 STORE (DREG (dst0), val); 5421 if (((v >> 31) & 0x1) != ((val >> 31) & 0x1)) 5422 { 5423 SET_ASTATREG (v, 1); 5424 SET_ASTATREG (vs, 1); 5425 } 5426 } 5427 } 5428 else if (sop == 3 && sopcde == 2) 5429 { 5430 int shift = imm6 (DREG (src0) & 0xFFFF); 5431 bu32 src = DREG (src1); 5432 bu32 ret, cc = CCREG; 5433 5434 TRACE_INSN (cpu, "R%i = ROT R%i BY R%i.L;", dst0, src1, src0); 5435 TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i", 5436 dst0, DREG (dst0), src1, src, shift, cc); 5437 5438 ret = rot32 (src, shift, &cc); 5439 STORE (DREG (dst0), ret); 5440 if (shift) 5441 SET_CCREG (cc); 5442 } 5443 else if (sop == 2 && sopcde == 1 && HLs == 0) 5444 { 5445 bs32 shft = (bs8)(DREG (src0) << 2) >> 2; 5446 bu16 val0, val1; 5447 bu32 astat; 5448 5449 TRACE_INSN (cpu, "R%i = LSHIFT R%i BY R%i.L (V);", dst0, src1, src0); 5450 5451 val0 = (bu16)DREG (src1) & 0xFFFF; 5452 val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16); 5453 5454 if (shft <= 0) 5455 { 5456 val0 = lshiftrt (cpu, val0, -shft, 16); 5457 astat = ASTAT; 5458 val1 = lshiftrt (cpu, val1, -shft, 16); 5459 } 5460 else 5461 { 5462 val0 = lshift (cpu, val0, shft, 16, 0, 0); 5463 astat = ASTAT; 5464 val1 = lshift (cpu, val1, shft, 16, 0, 0); 5465 } 5466 SET_ASTAT (ASTAT | astat); 5467 STORE (DREG (dst0), (val1 << 16) | val0); 5468 } 5469 else if (sopcde == 4) 5470 { 5471 bu32 sv0 = DREG (src0); 5472 bu32 sv1 = DREG (src1); 5473 TRACE_INSN (cpu, "R%i = PACK (R%i.%c, R%i.%c);", dst0, 5474 src1, sop & 2 ? 'H' : 'L', 5475 src0, sop & 1 ? 'H' : 'L'); 5476 if (sop & 1) 5477 sv0 >>= 16; 5478 if (sop & 2) 5479 sv1 >>= 16; 5480 STORE (DREG (dst0), (sv1 << 16) | (sv0 & 0xFFFF)); 5481 } 5482 else if (sop == 0 && sopcde == 5) 5483 { 5484 bu32 sv1 = DREG (src1); 5485 TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i;", dst0, src1); 5486 SET_DREG_L (dst0, signbits (sv1, 32)); 5487 } 5488 else if (sop == 1 && sopcde == 5) 5489 { 5490 bu32 sv1 = DREG (src1); 5491 TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.L;", dst0, src1); 5492 SET_DREG_L (dst0, signbits (sv1, 16)); 5493 } 5494 else if (sop == 2 && sopcde == 5) 5495 { 5496 bu32 sv1 = DREG (src1); 5497 TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.H;", dst0, src1); 5498 SET_DREG_L (dst0, signbits (sv1 >> 16, 16)); 5499 } 5500 else if ((sop == 0 || sop == 1) && sopcde == 6) 5501 { 5502 bu64 acc = AXREG (sop); 5503 TRACE_INSN (cpu, "R%i.L = SIGNBITS A%i;", dst0, sop); 5504 acc <<= 32; 5505 acc |= AWREG (sop); 5506 SET_DREG_L (dst0, signbits (acc, 40) & 0xFFFF); 5507 } 5508 else if (sop == 3 && sopcde == 6) 5509 { 5510 bu32 v = ones (DREG (src1)); 5511 TRACE_INSN (cpu, "R%i.L = ONES R%i;", dst0, src1); 5512 SET_DREG_L (dst0, v); 5513 } 5514 else if (sop == 0 && sopcde == 7) 5515 { 5516 bu16 sv1 = (bu16)signbits (DREG (src1), 32); 5517 bu16 sv0 = (bu16)DREG (src0); 5518 bu16 dst_lo; 5519 5520 TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L);", dst0, src1, src0); 5521 5522 if ((sv1 & 0x1f) < (sv0 & 0x1f)) 5523 dst_lo = sv1; 5524 else 5525 dst_lo = sv0; 5526 STORE (DREG (dst0), REG_H_L (DREG (dst0), dst_lo)); 5527 } 5528 else if (sop == 1 && sopcde == 7) 5529 { 5530 /* Exponent adjust on two 16-bit inputs. Select 5531 smallest norm among 3 inputs. */ 5532 bs16 src1_hi = (DREG (src1) & 0xFFFF0000) >> 16; 5533 bs16 src1_lo = (DREG (src1) & 0xFFFF); 5534 bu16 src0_lo = (DREG (src0) & 0xFFFF); 5535 bu16 tmp_hi, tmp_lo, tmp; 5536 5537 TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0, src1, src0); 5538 5539 tmp_hi = signbits (src1_hi, 16); 5540 tmp_lo = signbits (src1_lo, 16); 5541 5542 if ((tmp_hi & 0xf) < (tmp_lo & 0xf)) 5543 if ((tmp_hi & 0xf) < (src0_lo & 0xf)) 5544 tmp = tmp_hi; 5545 else 5546 tmp = src0_lo; 5547 else 5548 if ((tmp_lo & 0xf) < (src0_lo & 0xf)) 5549 tmp = tmp_lo; 5550 else 5551 tmp = src0_lo; 5552 STORE (DREG (dst0), REG_H_L (DREG (dst0), tmp)); 5553 } 5554 else if (sop == 2 && sopcde == 7) 5555 { 5556 /* Exponent adjust on single 16-bit register. */ 5557 bu16 tmp; 5558 bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF); 5559 5560 TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0, src1, src0); 5561 5562 tmp = signbits (DREG (src1) & 0xFFFF, 16); 5563 5564 if ((tmp & 0xf) < (src0_lo & 0xf)) 5565 SET_DREG_L (dst0, tmp); 5566 else 5567 SET_DREG_L (dst0, src0_lo); 5568 } 5569 else if (sop == 3 && sopcde == 7) 5570 { 5571 bu16 tmp; 5572 bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF); 5573 5574 TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0, src1, src0); 5575 5576 tmp = signbits ((DREG (src1) & 0xFFFF0000) >> 16, 16); 5577 5578 if ((tmp & 0xf) < (src0_lo & 0xf)) 5579 SET_DREG_L (dst0, tmp); 5580 else 5581 SET_DREG_L (dst0, src0_lo); 5582 } 5583 else if (sop == 0 && sopcde == 8) 5584 { 5585 bu64 acc = get_unextended_acc (cpu, 0); 5586 bu32 s0, s1; 5587 5588 TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASR);", src0, src1); 5589 5590 if (src0 == src1) 5591 illegal_instruction_combination (cpu); 5592 5593 s0 = DREG (src0); 5594 s1 = DREG (src1); 5595 acc = (acc >> 2) | 5596 (((bu64)s0 & 1) << 38) | 5597 (((bu64)s1 & 1) << 39); 5598 STORE (DREG (src0), s0 >> 1); 5599 STORE (DREG (src1), s1 >> 1); 5600 5601 SET_AREG (0, acc); 5602 } 5603 else if (sop == 1 && sopcde == 8) 5604 { 5605 bu64 acc = get_unextended_acc (cpu, 0); 5606 bu32 s0, s1; 5607 5608 TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASL);", src0, src1); 5609 5610 if (src0 == src1) 5611 illegal_instruction_combination (cpu); 5612 5613 s0 = DREG (src0); 5614 s1 = DREG (src1); 5615 acc = (acc << 2) | 5616 ((s0 >> 31) & 1) | 5617 ((s1 >> 30) & 2); 5618 STORE (DREG (src0), s0 << 1); 5619 STORE (DREG (src1), s1 << 1); 5620 5621 SET_AREG (0, acc); 5622 } 5623 else if ((sop == 0 || sop == 1) && sopcde == 9) 5624 { 5625 bs40 acc0 = get_unextended_acc (cpu, 0); 5626 bs16 sL, sH, out; 5627 5628 TRACE_INSN (cpu, "R%i.L = VIT_MAX (R%i) (AS%c);", 5629 dst0, src1, sop & 1 ? 'R' : 'L'); 5630 5631 sL = DREG (src1); 5632 sH = DREG (src1) >> 16; 5633 5634 if (sop & 1) 5635 acc0 = (acc0 & 0xfeffffffffull) >> 1; 5636 else 5637 acc0 <<= 1; 5638 5639 if (((sH - sL) & 0x8000) == 0) 5640 { 5641 out = sH; 5642 acc0 |= (sop & 1) ? 0x80000000 : 1; 5643 } 5644 else 5645 out = sL; 5646 5647 SET_AREG (0, acc0); 5648 STORE (DREG (dst0), REG_H_L (DREG (dst0), out)); 5649 } 5650 else if ((sop == 2 || sop == 3) && sopcde == 9) 5651 { 5652 bs40 acc0 = get_extended_acc (cpu, 0); 5653 bs16 s0L, s0H, s1L, s1H, out0, out1; 5654 5655 TRACE_INSN (cpu, "R%i = VIT_MAX (R%i, R%i) (AS%c);", 5656 dst0, src1, src0, sop & 1 ? 'R' : 'L'); 5657 5658 s0L = DREG (src0); 5659 s0H = DREG (src0) >> 16; 5660 s1L = DREG (src1); 5661 s1H = DREG (src1) >> 16; 5662 5663 if (sop & 1) 5664 acc0 >>= 2; 5665 else 5666 acc0 <<= 2; 5667 5668 if (((s0H - s0L) & 0x8000) == 0) 5669 { 5670 out0 = s0H; 5671 acc0 |= (sop & 1) ? 0x40000000 : 2; 5672 } 5673 else 5674 out0 = s0L; 5675 5676 if (((s1H - s1L) & 0x8000) == 0) 5677 { 5678 out1 = s1H; 5679 acc0 |= (sop & 1) ? 0x80000000 : 1; 5680 } 5681 else 5682 out1 = s1L; 5683 5684 SET_AREG (0, acc0); 5685 STORE (DREG (dst0), REG_H_L (out1 << 16, out0)); 5686 } 5687 else if (sop == 0 && sopcde == 10) 5688 { 5689 bu32 v = DREG (src0); 5690 bu32 x = DREG (src1); 5691 bu32 mask = (1 << (v & 0x1f)) - 1; 5692 5693 TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0, src1, src0); 5694 5695 x >>= ((v >> 8) & 0x1f); 5696 x &= mask; 5697 STORE (DREG (dst0), x); 5698 setflags_logical (cpu, x); 5699 } 5700 else if (sop == 1 && sopcde == 10) 5701 { 5702 bu32 v = DREG (src0); 5703 bu32 x = DREG (src1); 5704 bu32 sgn = (1 << (v & 0x1f)) >> 1; 5705 bu32 mask = (1 << (v & 0x1f)) - 1; 5706 5707 TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0, src1, src0); 5708 5709 x >>= ((v >> 8) & 0x1f); 5710 x &= mask; 5711 if (x & sgn) 5712 x |= ~mask; 5713 STORE (DREG (dst0), x); 5714 setflags_logical (cpu, x); 5715 } 5716 else if ((sop == 2 || sop == 3) && sopcde == 10) 5717 { 5718 /* The first dregs is the "background" while the second dregs is the 5719 "foreground". The fg reg is used to overlay the bg reg and is: 5720 | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL | 5721 n = the fg bit field 5722 p = bit position in bg reg to start LSB of fg field 5723 L = number of fg bits to extract 5724 Using (X) sign-extends the fg bit field. */ 5725 bu32 fg = DREG (src0); 5726 bu32 bg = DREG (src1); 5727 bu32 len = fg & 0x1f; 5728 bu32 mask = (1 << min (16, len)) - 1; 5729 bu32 fgnd = (fg >> 16) & mask; 5730 int shft = ((fg >> 8) & 0x1f); 5731 5732 TRACE_INSN (cpu, "R%i = DEPOSIT (R%i, R%i)%s;", dst0, src1, src0, 5733 sop == 3 ? " (X)" : ""); 5734 5735 if (sop == 3) 5736 { 5737 /* Sign extend the fg bit field. */ 5738 mask = -1; 5739 fgnd = ((bs32)(bs16)(fgnd << (16 - len))) >> (16 - len); 5740 } 5741 fgnd <<= shft; 5742 mask <<= shft; 5743 bg &= ~mask; 5744 5745 bg |= fgnd; 5746 STORE (DREG (dst0), bg); 5747 setflags_logical (cpu, bg); 5748 } 5749 else if (sop == 0 && sopcde == 11) 5750 { 5751 bu64 acc0 = get_unextended_acc (cpu, 0); 5752 5753 TRACE_INSN (cpu, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0, src0); 5754 5755 acc0 <<= 1; 5756 SET_CCREG (xor_reduce (acc0, DREG (src0))); 5757 SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG)); 5758 SET_AREG (0, acc0); 5759 } 5760 else if (sop == 1 && sopcde == 11) 5761 { 5762 bu64 acc0 = get_unextended_acc (cpu, 0); 5763 5764 TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, R%i);", dst0, src0); 5765 5766 SET_CCREG (xor_reduce (acc0, DREG (src0))); 5767 SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG)); 5768 } 5769 else if (sop == 0 && sopcde == 12) 5770 { 5771 bu64 acc0 = get_unextended_acc (cpu, 0); 5772 bu64 acc1 = get_unextended_acc (cpu, 1); 5773 5774 TRACE_INSN (cpu, "A0 = BXORSHIFT (A0, A1, CC);"); 5775 5776 acc0 = (acc0 << 1) | (CCREG ^ xor_reduce (acc0, acc1)); 5777 SET_AREG (0, acc0); 5778 } 5779 else if (sop == 1 && sopcde == 12) 5780 { 5781 bu64 acc0 = get_unextended_acc (cpu, 0); 5782 bu64 acc1 = get_unextended_acc (cpu, 1); 5783 5784 TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, A1, CC);", dst0); 5785 5786 SET_CCREG (CCREG ^ xor_reduce (acc0, acc1)); 5787 acc0 = (acc0 << 1) | CCREG; 5788 SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG)); 5789 } 5790 else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 13) 5791 { 5792 int shift = (sop + 1) * 8; 5793 TRACE_INSN (cpu, "R%i = ALIGN%i (R%i, R%i);", dst0, shift, src1, src0); 5794 STORE (DREG (dst0), (DREG (src1) << (32 - shift)) | (DREG (src0) >> shift)); 5795 } 5796 else 5797 illegal_instruction (cpu); 5798 } 5799 5800 static bu64 5801 sgn_extend (bu40 org, bu40 val, int size) 5802 { 5803 bu64 ret = val; 5804 5805 if (org & (1ULL << (size - 1))) 5806 { 5807 /* We need to shift in to the MSB which is set. */ 5808 int n; 5809 5810 for (n = 40; n >= 0; n--) 5811 if (ret & (1ULL << n)) 5812 break; 5813 ret |= (-1ULL << n); 5814 } 5815 else 5816 ret &= ~(-1ULL << 39); 5817 5818 return ret; 5819 } 5820 static void 5821 decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) 5822 { 5823 /* dsp32shiftimm 5824 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 5825 | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............| 5826 |.sop...|.HLs...|.dst0......|.immag.................|.src1......| 5827 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 5828 int src1 = ((iw1 >> DSP32ShiftImm_src1_bits) & DSP32ShiftImm_src1_mask); 5829 int sop = ((iw1 >> DSP32ShiftImm_sop_bits) & DSP32ShiftImm_sop_mask); 5830 int bit8 = ((iw1 >> 8) & 0x1); 5831 int immag = ((iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask); 5832 int newimmag = (-(iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask); 5833 int dst0 = ((iw1 >> DSP32ShiftImm_dst0_bits) & DSP32ShiftImm_dst0_mask); 5834 int M = ((iw0 >> (DSP32ShiftImm_M_bits - 16)) & DSP32ShiftImm_M_mask); 5835 int sopcde = ((iw0 >> (DSP32ShiftImm_sopcde_bits - 16)) & DSP32ShiftImm_sopcde_mask); 5836 int HLs = ((iw1 >> DSP32ShiftImm_HLs_bits) & DSP32ShiftImm_HLs_mask); 5837 5838 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shiftimm); 5839 TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i", 5840 __func__, M, sopcde, sop, HLs, dst0, immag, src1); 5841 5842 if (sopcde == 0) 5843 { 5844 bu16 in = DREG (src1) >> ((HLs & 1) ? 16 : 0); 5845 bu16 result; 5846 bu32 v; 5847 5848 if (sop == 0) 5849 { 5850 TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i;", 5851 dst0, (HLs & 2) ? 'H' : 'L', 5852 src1, (HLs & 1) ? 'H' : 'L', newimmag); 5853 if (newimmag > 16) 5854 { 5855 result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0, 1); 5856 if (((result >> 15) & 0x1) != ((in >> 15) & 0x1)) 5857 { 5858 SET_ASTATREG (v, 1); 5859 SET_ASTATREG (vs, 1); 5860 } 5861 } 5862 else 5863 result = ashiftrt (cpu, in, newimmag, 16); 5864 } 5865 else if (sop == 1 && bit8 == 0) 5866 { 5867 TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i (S);", 5868 dst0, (HLs & 2) ? 'H' : 'L', 5869 src1, (HLs & 1) ? 'H' : 'L', immag); 5870 result = lshift (cpu, in, immag, 16, 1, 1); 5871 } 5872 else if (sop == 1 && bit8) 5873 { 5874 TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i (S);", 5875 dst0, (HLs & 2) ? 'H' : 'L', 5876 src1, (HLs & 1) ? 'H' : 'L', newimmag); 5877 if (newimmag > 16) 5878 { 5879 int shift = 32 - newimmag; 5880 bu16 inshift = in << shift; 5881 5882 if (((inshift & ~0xFFFF) 5883 && ((inshift & ~0xFFFF) >> 16) != ~((bu32)~0 << shift)) 5884 || (inshift & 0x8000) != (in & 0x8000)) 5885 { 5886 if (in & 0x8000) 5887 result = 0x8000; 5888 else 5889 result = 0x7fff; 5890 SET_ASTATREG (v, 1); 5891 SET_ASTATREG (vs, 1); 5892 } 5893 else 5894 { 5895 result = inshift; 5896 SET_ASTATREG (v, 0); 5897 } 5898 5899 SET_ASTATREG (az, !result); 5900 SET_ASTATREG (an, !!(result & 0x8000)); 5901 } 5902 else 5903 { 5904 result = ashiftrt (cpu, in, newimmag, 16); 5905 result = sgn_extend (in, result, 16); 5906 } 5907 } 5908 else if (sop == 2 && bit8) 5909 { 5910 TRACE_INSN (cpu, "R%i.%c = R%i.%c >> %i;", 5911 dst0, (HLs & 2) ? 'H' : 'L', 5912 src1, (HLs & 1) ? 'H' : 'L', newimmag); 5913 result = lshiftrt (cpu, in, newimmag, 16); 5914 } 5915 else if (sop == 2 && bit8 == 0) 5916 { 5917 TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i;", 5918 dst0, (HLs & 2) ? 'H' : 'L', 5919 src1, (HLs & 1) ? 'H' : 'L', immag); 5920 result = lshift (cpu, in, immag, 16, 0, 1); 5921 } 5922 else 5923 illegal_instruction (cpu); 5924 5925 v = DREG (dst0); 5926 if (HLs & 2) 5927 STORE (DREG (dst0), (v & 0xFFFF) | (result << 16)); 5928 else 5929 STORE (DREG (dst0), (v & 0xFFFF0000) | result); 5930 } 5931 else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0)) 5932 { 5933 int shift = imm6 (immag); 5934 bu32 cc = CCREG; 5935 bu40 acc = get_unextended_acc (cpu, HLs); 5936 5937 TRACE_INSN (cpu, "A%i = ROT A%i BY %i;", HLs, HLs, shift); 5938 TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc); 5939 5940 acc = rot40 (acc, shift, &cc); 5941 SET_AREG (HLs, acc); 5942 if (shift) 5943 SET_CCREG (cc); 5944 } 5945 else if (sop == 0 && sopcde == 3 && bit8 == 1 && HLs < 2) 5946 { 5947 /* Arithmetic shift, so shift in sign bit copies. */ 5948 bu64 acc, val; 5949 int shift = uimm5 (newimmag); 5950 5951 TRACE_INSN (cpu, "A%i = A%i >>> %i;", HLs, HLs, shift); 5952 5953 acc = get_extended_acc (cpu, HLs); 5954 val = acc >> shift; 5955 5956 /* Sign extend again. */ 5957 val = sgn_extend (acc, val, 40); 5958 5959 STORE (AXREG (HLs), (val >> 32) & 0xFF); 5960 STORE (AWREG (HLs), val & 0xFFFFFFFF); 5961 STORE (ASTATREG (an), !!(val & (1ULL << 39))); 5962 STORE (ASTATREG (az), !val); 5963 STORE (ASTATREG (av[HLs]), 0); 5964 } 5965 else if (((sop == 0 && sopcde == 3 && bit8 == 0) 5966 || (sop == 1 && sopcde == 3)) && HLs < 2) 5967 { 5968 bu64 acc; 5969 int shiftup = uimm5 (immag); 5970 int shiftdn = uimm5 (newimmag); 5971 5972 TRACE_INSN (cpu, "A%i = A%i %s %i;", HLs, HLs, 5973 sop == 0 ? "<<" : ">>", 5974 sop == 0 ? shiftup : shiftdn); 5975 5976 acc = AXREG (HLs); 5977 /* Logical shift, so shift in zeroes. */ 5978 acc &= 0xFF; 5979 acc <<= 32; 5980 acc |= AWREG (HLs); 5981 5982 if (sop == 0) 5983 acc <<= shiftup; 5984 else 5985 { 5986 if (shiftdn <= 32) 5987 acc >>= shiftdn; 5988 else 5989 acc <<= 32 - (shiftdn & 0x1f); 5990 } 5991 5992 SET_AREG (HLs, acc); 5993 SET_ASTATREG (av[HLs], 0); 5994 SET_ASTATREG (an, !!(acc & 0x8000000000ull)); 5995 SET_ASTATREG (az, (acc & 0xFFFFFFFFFF) == 0); 5996 } 5997 else if (HLs != 0) 5998 /* All the insns after this point don't use HLs. */ 5999 illegal_instruction (cpu); 6000 else if (sop == 1 && sopcde == 1 && bit8 == 0) 6001 { 6002 int count = imm5 (immag); 6003 bu16 val0 = DREG (src1) >> 16; 6004 bu16 val1 = DREG (src1) & 0xFFFF; 6005 bu32 astat; 6006 6007 TRACE_INSN (cpu, "R%i = R%i << %i (V,S);", dst0, src1, count); 6008 if (count >= 0) 6009 { 6010 val0 = lshift (cpu, val0, count, 16, 1, 1); 6011 astat = ASTAT; 6012 val1 = lshift (cpu, val1, count, 16, 1, 1); 6013 } 6014 else 6015 { 6016 val0 = ashiftrt (cpu, val0, -count, 16); 6017 astat = ASTAT; 6018 val1 = ashiftrt (cpu, val1, -count, 16); 6019 } 6020 SET_ASTAT (ASTAT | astat); 6021 6022 STORE (DREG (dst0), (val0 << 16) | val1); 6023 } 6024 else if (sop == 2 && sopcde == 1 && bit8 == 1) 6025 { 6026 int count = imm5 (newimmag); 6027 bu16 val0 = DREG (src1) & 0xFFFF; 6028 bu16 val1 = DREG (src1) >> 16; 6029 bu32 astat; 6030 6031 TRACE_INSN (cpu, "R%i = R%i >> %i (V);", dst0, src1, count); 6032 val0 = lshiftrt (cpu, val0, count, 16); 6033 astat = ASTAT; 6034 val1 = lshiftrt (cpu, val1, count, 16); 6035 SET_ASTAT (ASTAT | astat); 6036 6037 STORE (DREG (dst0), val0 | (val1 << 16)); 6038 } 6039 else if (sop == 2 && sopcde == 1 && bit8 == 0) 6040 { 6041 int count = imm5 (immag); 6042 bu16 val0 = DREG (src1) & 0xFFFF; 6043 bu16 val1 = DREG (src1) >> 16; 6044 bu32 astat; 6045 6046 TRACE_INSN (cpu, "R%i = R%i << %i (V);", dst0, src1, count); 6047 val0 = lshift (cpu, val0, count, 16, 0, 1); 6048 astat = ASTAT; 6049 val1 = lshift (cpu, val1, count, 16, 0, 1); 6050 SET_ASTAT (ASTAT | astat); 6051 6052 STORE (DREG (dst0), val0 | (val1 << 16)); 6053 } 6054 else if (sopcde == 1 && (sop == 0 || (sop == 1 && bit8 == 1))) 6055 { 6056 int count = uimm5 (newimmag); 6057 bu16 val0 = DREG (src1) & 0xFFFF; 6058 bu16 val1 = DREG (src1) >> 16; 6059 bu32 astat; 6060 6061 TRACE_INSN (cpu, "R%i = R%i >>> %i %s;", dst0, src1, count, 6062 sop == 0 ? "(V)" : "(V,S)"); 6063 6064 if (count > 16) 6065 { 6066 int sgn0 = (val0 >> 15) & 0x1; 6067 int sgn1 = (val1 >> 15) & 0x1; 6068 6069 val0 = lshift (cpu, val0, 16 - (count & 0xF), 16, 0, 1); 6070 astat = ASTAT; 6071 val1 = lshift (cpu, val1, 16 - (count & 0xF), 16, 0, 1); 6072 6073 if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1))) 6074 { 6075 SET_ASTATREG (v, 1); 6076 SET_ASTATREG (vs, 1); 6077 } 6078 } 6079 else 6080 { 6081 val0 = ashiftrt (cpu, val0, count, 16); 6082 astat = ASTAT; 6083 val1 = ashiftrt (cpu, val1, count, 16); 6084 } 6085 6086 SET_ASTAT (ASTAT | astat); 6087 6088 STORE (DREG (dst0), REG_H_L (val1 << 16, val0)); 6089 } 6090 else if (sop == 1 && sopcde == 2) 6091 { 6092 int count = imm6 (immag); 6093 6094 TRACE_INSN (cpu, "R%i = R%i << %i (S);", dst0, src1, count); 6095 6096 if (count < 0) 6097 STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), -count, 32)); 6098 else 6099 STORE (DREG (dst0), lshift (cpu, DREG (src1), count, 32, 1, 1)); 6100 } 6101 else if (sop == 2 && sopcde == 2) 6102 { 6103 int count = imm6 (newimmag); 6104 6105 TRACE_INSN (cpu, "R%i = R%i >> %i;", dst0, src1, count); 6106 6107 if (count < 0) 6108 STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1)); 6109 else 6110 STORE (DREG (dst0), lshiftrt (cpu, DREG (src1), count, 32)); 6111 } 6112 else if (sop == 3 && sopcde == 2) 6113 { 6114 int shift = imm6 (immag); 6115 bu32 src = DREG (src1); 6116 bu32 ret, cc = CCREG; 6117 6118 TRACE_INSN (cpu, "R%i = ROT R%i BY %i;", dst0, src1, shift); 6119 TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i", 6120 dst0, DREG (dst0), src1, src, shift, cc); 6121 6122 ret = rot32 (src, shift, &cc); 6123 STORE (DREG (dst0), ret); 6124 if (shift) 6125 SET_CCREG (cc); 6126 } 6127 else if (sop == 0 && sopcde == 2) 6128 { 6129 int count = imm6 (newimmag); 6130 6131 TRACE_INSN (cpu, "R%i = R%i >>> %i;", dst0, src1, count); 6132 6133 if (count < 0) 6134 STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1)); 6135 else 6136 STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), count, 32)); 6137 } 6138 else 6139 illegal_instruction (cpu); 6140 } 6141 6142 static void 6143 outc (SIM_CPU *cpu, char ch) 6144 { 6145 SIM_DESC sd = CPU_STATE (cpu); 6146 sim_io_printf (sd, "%c", ch); 6147 if (ch == '\n') 6148 sim_io_flush_stdout (sd); 6149 } 6150 6151 static void 6152 decode_psedoDEBUG_0 (SIM_CPU *cpu, bu16 iw0) 6153 { 6154 /* psedoDEBUG 6155 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 6156 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......| 6157 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 6158 SIM_DESC sd = CPU_STATE (cpu); 6159 int fn = ((iw0 >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask); 6160 int grp = ((iw0 >> PseudoDbg_grp_bits) & PseudoDbg_grp_mask); 6161 int reg = ((iw0 >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask); 6162 6163 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoDEBUG); 6164 TRACE_EXTRACT (cpu, "%s: fn:%i grp:%i reg:%i", __func__, fn, grp, reg); 6165 6166 if ((reg == 0 || reg == 1) && fn == 3) 6167 { 6168 TRACE_INSN (cpu, "DBG A%i;", reg); 6169 sim_io_printf (sd, "DBG : A%i = %#"PRIx64"\n", reg, 6170 get_unextended_acc (cpu, reg)); 6171 } 6172 else if (reg == 3 && fn == 3) 6173 { 6174 TRACE_INSN (cpu, "ABORT;"); 6175 cec_exception (cpu, VEC_SIM_ABORT); 6176 SET_DREG (0, 1); 6177 } 6178 else if (reg == 4 && fn == 3) 6179 { 6180 TRACE_INSN (cpu, "HLT;"); 6181 cec_exception (cpu, VEC_SIM_HLT); 6182 SET_DREG (0, 0); 6183 } 6184 else if (reg == 5 && fn == 3) 6185 unhandled_instruction (cpu, "DBGHALT"); 6186 else if (reg == 6 && fn == 3) 6187 unhandled_instruction (cpu, "DBGCMPLX (dregs)"); 6188 else if (reg == 7 && fn == 3) 6189 unhandled_instruction (cpu, "DBG"); 6190 else if (grp == 0 && fn == 2) 6191 { 6192 TRACE_INSN (cpu, "OUTC R%i;", reg); 6193 outc (cpu, DREG (reg)); 6194 } 6195 else if (fn == 0) 6196 { 6197 const char *reg_name = get_allreg_name (grp, reg); 6198 TRACE_INSN (cpu, "DBG %s;", reg_name); 6199 sim_io_printf (sd, "DBG : %s = 0x%08x\n", reg_name, 6200 reg_read (cpu, grp, reg)); 6201 } 6202 else if (fn == 1) 6203 unhandled_instruction (cpu, "PRNT allregs"); 6204 else 6205 illegal_instruction (cpu); 6206 } 6207 6208 static void 6209 decode_psedoOChar_0 (SIM_CPU *cpu, bu16 iw0) 6210 { 6211 /* psedoOChar 6212 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 6213 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................| 6214 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 6215 int ch = ((iw0 >> PseudoChr_ch_bits) & PseudoChr_ch_mask); 6216 6217 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoOChar); 6218 TRACE_EXTRACT (cpu, "%s: ch:%#x", __func__, ch); 6219 TRACE_INSN (cpu, "OUTC %#x;", ch); 6220 6221 outc (cpu, ch); 6222 } 6223 6224 static void 6225 decode_psedodbg_assert_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc) 6226 { 6227 /* psedodbg_assert 6228 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ 6229 | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...| 6230 |.expected......................................................| 6231 +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */ 6232 SIM_DESC sd = CPU_STATE (cpu); 6233 int expected = ((iw1 >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask); 6234 int dbgop = ((iw0 >> (PseudoDbg_Assert_dbgop_bits - 16)) & PseudoDbg_Assert_dbgop_mask); 6235 int grp = ((iw0 >> (PseudoDbg_Assert_grp_bits - 16)) & PseudoDbg_Assert_grp_mask); 6236 int regtest = ((iw0 >> (PseudoDbg_Assert_regtest_bits - 16)) & PseudoDbg_Assert_regtest_mask); 6237 int offset; 6238 bu16 actual; 6239 bu32 val = reg_read (cpu, grp, regtest); 6240 const char *reg_name = get_allreg_name (grp, regtest); 6241 const char *dbg_name, *dbg_appd; 6242 6243 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedodbg_assert); 6244 TRACE_EXTRACT (cpu, "%s: dbgop:%i grp:%i regtest:%i expected:%#x", 6245 __func__, dbgop, grp, regtest, expected); 6246 6247 if (dbgop == 0 || dbgop == 2) 6248 { 6249 dbg_name = dbgop == 0 ? "DBGA" : "DBGAL"; 6250 dbg_appd = dbgop == 0 ? ".L" : ""; 6251 offset = 0; 6252 } 6253 else if (dbgop == 1 || dbgop == 3) 6254 { 6255 dbg_name = dbgop == 1 ? "DBGA" : "DBGAH"; 6256 dbg_appd = dbgop == 1 ? ".H" : ""; 6257 offset = 16; 6258 } 6259 else 6260 illegal_instruction (cpu); 6261 6262 actual = val >> offset; 6263 6264 TRACE_INSN (cpu, "%s (%s%s, 0x%x);", dbg_name, reg_name, dbg_appd, expected); 6265 if (actual != expected) 6266 { 6267 sim_io_printf (sd, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n", 6268 pc, dbg_name, reg_name, dbg_appd, expected, actual); 6269 6270 /* Decode the actual ASTAT bits that are different. */ 6271 if (grp == 4 && regtest == 6) 6272 { 6273 int i; 6274 6275 sim_io_printf (sd, "Expected ASTAT:\n"); 6276 for (i = 0; i < 16; ++i) 6277 sim_io_printf (sd, " %8s%c%i%s", 6278 astat_names[i + offset], 6279 (((expected >> i) & 1) != ((actual >> i) & 1)) 6280 ? '!' : ' ', 6281 (expected >> i) & 1, 6282 i == 7 ? "\n" : ""); 6283 sim_io_printf (sd, "\n"); 6284 6285 sim_io_printf (sd, "Actual ASTAT:\n"); 6286 for (i = 0; i < 16; ++i) 6287 sim_io_printf (sd, " %8s%c%i%s", 6288 astat_names[i + offset], 6289 (((expected >> i) & 1) != ((actual >> i) & 1)) 6290 ? '!' : ' ', 6291 (actual >> i) & 1, 6292 i == 7 ? "\n" : ""); 6293 sim_io_printf (sd, "\n"); 6294 } 6295 6296 cec_exception (cpu, VEC_SIM_DBGA); 6297 SET_DREG (0, 1); 6298 } 6299 } 6300 6301 static bu32 6302 _interp_insn_bfin (SIM_CPU *cpu, bu32 pc) 6303 { 6304 bu32 insn_len; 6305 bu16 iw0, iw1; 6306 6307 BFIN_CPU_STATE.multi_pc = pc; 6308 iw0 = IFETCH (pc); 6309 if ((iw0 & 0xc000) != 0xc000) 6310 { 6311 /* 16-bit opcode. */ 6312 insn_len = 2; 6313 if (INSN_LEN == 0) 6314 INSN_LEN = insn_len; 6315 6316 TRACE_EXTRACT (cpu, "%s: iw0:%#x", __func__, iw0); 6317 if ((iw0 & 0xFF00) == 0x0000) 6318 decode_ProgCtrl_0 (cpu, iw0, pc); 6319 else if ((iw0 & 0xFFC0) == 0x0240) 6320 decode_CaCTRL_0 (cpu, iw0); 6321 else if ((iw0 & 0xFF80) == 0x0100) 6322 decode_PushPopReg_0 (cpu, iw0); 6323 else if ((iw0 & 0xFE00) == 0x0400) 6324 decode_PushPopMultiple_0 (cpu, iw0); 6325 else if ((iw0 & 0xFE00) == 0x0600) 6326 decode_ccMV_0 (cpu, iw0); 6327 else if ((iw0 & 0xF800) == 0x0800) 6328 decode_CCflag_0 (cpu, iw0); 6329 else if ((iw0 & 0xFFE0) == 0x0200) 6330 decode_CC2dreg_0 (cpu, iw0); 6331 else if ((iw0 & 0xFF00) == 0x0300) 6332 decode_CC2stat_0 (cpu, iw0); 6333 else if ((iw0 & 0xF000) == 0x1000) 6334 decode_BRCC_0 (cpu, iw0, pc); 6335 else if ((iw0 & 0xF000) == 0x2000) 6336 decode_UJUMP_0 (cpu, iw0, pc); 6337 else if ((iw0 & 0xF000) == 0x3000) 6338 decode_REGMV_0 (cpu, iw0); 6339 else if ((iw0 & 0xFC00) == 0x4000) 6340 decode_ALU2op_0 (cpu, iw0); 6341 else if ((iw0 & 0xFE00) == 0x4400) 6342 decode_PTR2op_0 (cpu, iw0); 6343 else if ((iw0 & 0xF800) == 0x4800) 6344 decode_LOGI2op_0 (cpu, iw0); 6345 else if ((iw0 & 0xF000) == 0x5000) 6346 decode_COMP3op_0 (cpu, iw0); 6347 else if ((iw0 & 0xF800) == 0x6000) 6348 decode_COMPI2opD_0 (cpu, iw0); 6349 else if ((iw0 & 0xF800) == 0x6800) 6350 decode_COMPI2opP_0 (cpu, iw0); 6351 else if ((iw0 & 0xF000) == 0x8000) 6352 decode_LDSTpmod_0 (cpu, iw0); 6353 else if ((iw0 & 0xFF60) == 0x9E60) 6354 decode_dagMODim_0 (cpu, iw0); 6355 else if ((iw0 & 0xFFF0) == 0x9F60) 6356 decode_dagMODik_0 (cpu, iw0); 6357 else if ((iw0 & 0xFC00) == 0x9C00) 6358 decode_dspLDST_0 (cpu, iw0); 6359 else if ((iw0 & 0xF000) == 0x9000) 6360 decode_LDST_0 (cpu, iw0); 6361 else if ((iw0 & 0xFC00) == 0xB800) 6362 decode_LDSTiiFP_0 (cpu, iw0); 6363 else if ((iw0 & 0xE000) == 0xA000) 6364 decode_LDSTii_0 (cpu, iw0); 6365 else 6366 { 6367 TRACE_EXTRACT (cpu, "%s: no matching 16-bit pattern", __func__); 6368 illegal_instruction_or_combination (cpu); 6369 } 6370 return insn_len; 6371 } 6372 6373 /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */ 6374 iw1 = IFETCH (pc + 2); 6375 if ((iw0 & BIT_MULTI_INS) && (iw0 & 0xe800) != 0xe800 /* not linkage */) 6376 { 6377 SIM_DESC sd = CPU_STATE (cpu); 6378 trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu), 6379 NULL, 0, "|| %#"PRIx64, sim_events_time (sd)); 6380 insn_len = 8; 6381 PARALLEL_GROUP = BFIN_PARALLEL_GROUP0; 6382 } 6383 else 6384 insn_len = 4; 6385 6386 TRACE_EXTRACT (cpu, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__, 6387 iw0, iw1, insn_len); 6388 6389 /* Only cache on first run through (in case of parallel insns). */ 6390 if (INSN_LEN == 0) 6391 INSN_LEN = insn_len; 6392 else 6393 /* Once you're past the first slot, only 16bit insns are valid. */ 6394 illegal_instruction_combination (cpu); 6395 6396 if ((iw0 & 0xf7ff) == 0xc003 && (iw1 & 0xfe00) == 0x1800) 6397 { 6398 PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac); 6399 TRACE_INSN (cpu, "MNOP;"); 6400 } 6401 else if (((iw0 & 0xFF80) == 0xE080) && ((iw1 & 0x0C00) == 0x0000)) 6402 decode_LoopSetup_0 (cpu, iw0, iw1, pc); 6403 else if (((iw0 & 0xFF00) == 0xE100) && ((iw1 & 0x0000) == 0x0000)) 6404 decode_LDIMMhalf_0 (cpu, iw0, iw1); 6405 else if (((iw0 & 0xFE00) == 0xE200) && ((iw1 & 0x0000) == 0x0000)) 6406 decode_CALLa_0 (cpu, iw0, iw1, pc); 6407 else if (((iw0 & 0xFC00) == 0xE400) && ((iw1 & 0x0000) == 0x0000)) 6408 decode_LDSTidxI_0 (cpu, iw0, iw1); 6409 else if (((iw0 & 0xFFFE) == 0xE800) && ((iw1 & 0x0000) == 0x0000)) 6410 decode_linkage_0 (cpu, iw0, iw1); 6411 else if (((iw0 & 0xF600) == 0xC000) && ((iw1 & 0x0000) == 0x0000)) 6412 decode_dsp32mac_0 (cpu, iw0, iw1); 6413 else if (((iw0 & 0xF600) == 0xC200) && ((iw1 & 0x0000) == 0x0000)) 6414 decode_dsp32mult_0 (cpu, iw0, iw1); 6415 else if (((iw0 & 0xF7C0) == 0xC400) && ((iw1 & 0x0000) == 0x0000)) 6416 decode_dsp32alu_0 (cpu, iw0, iw1); 6417 else if (((iw0 & 0xF7E0) == 0xC600) && ((iw1 & 0x01C0) == 0x0000)) 6418 decode_dsp32shift_0 (cpu, iw0, iw1); 6419 else if (((iw0 & 0xF7E0) == 0xC680) && ((iw1 & 0x0000) == 0x0000)) 6420 decode_dsp32shiftimm_0 (cpu, iw0, iw1); 6421 else if ((iw0 & 0xFF00) == 0xF800) 6422 decode_psedoDEBUG_0 (cpu, iw0), insn_len = 2; 6423 else if ((iw0 & 0xFF00) == 0xF900) 6424 decode_psedoOChar_0 (cpu, iw0), insn_len = 2; 6425 else if (((iw0 & 0xFF00) == 0xF000) && ((iw1 & 0x0000) == 0x0000)) 6426 decode_psedodbg_assert_0 (cpu, iw0, iw1, pc); 6427 else 6428 { 6429 TRACE_EXTRACT (cpu, "%s: no matching 32-bit pattern", __func__); 6430 illegal_instruction (cpu); 6431 } 6432 6433 return insn_len; 6434 } 6435 6436 bu32 6437 interp_insn_bfin (SIM_CPU *cpu, bu32 pc) 6438 { 6439 int i; 6440 bu32 insn_len; 6441 6442 BFIN_CPU_STATE.n_stores = 0; 6443 PARALLEL_GROUP = BFIN_PARALLEL_NONE; 6444 DIS_ALGN_EXPT &= ~1; 6445 CYCLE_DELAY = 1; 6446 INSN_LEN = 0; 6447 6448 insn_len = _interp_insn_bfin (cpu, pc); 6449 6450 /* Proper display of multiple issue instructions. */ 6451 if (insn_len == 8) 6452 { 6453 PARALLEL_GROUP = BFIN_PARALLEL_GROUP1; 6454 _interp_insn_bfin (cpu, pc + 4); 6455 PARALLEL_GROUP = BFIN_PARALLEL_GROUP2; 6456 _interp_insn_bfin (cpu, pc + 6); 6457 } 6458 for (i = 0; i < BFIN_CPU_STATE.n_stores; i++) 6459 { 6460 bu32 *addr = BFIN_CPU_STATE.stores[i].addr; 6461 *addr = BFIN_CPU_STATE.stores[i].val; 6462 TRACE_REGISTER (cpu, "dequeuing write %s = %#x", 6463 get_store_name (cpu, addr), *addr); 6464 } 6465 6466 cycles_inc (cpu, CYCLE_DELAY); 6467 6468 /* Set back to zero in case a pending CEC event occurs 6469 after this this insn. */ 6470 INSN_LEN = 0; 6471 6472 return insn_len; 6473 } 6474