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