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