1 1.1 christos /* Single instruction disassembler for the Visium. 2 1.1 christos 3 1.1.1.8 christos Copyright (C) 2002-2026 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos This file is part of the GNU opcodes library. 6 1.1 christos 7 1.1 christos This library is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3, or (at your option) 10 1.1 christos any later version. 11 1.1 christos 12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT 13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 1.1 christos License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program; if not, write to the Free Software 19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 1.1 christos MA 02110-1301, USA. */ 21 1.1 christos 22 1.1 christos #include "sysdep.h" 23 1.1.1.3 christos #include "disassemble.h" 24 1.1 christos #include "opcode/visium.h" 25 1.1 christos 26 1.1 christos #include <string.h> 27 1.1 christos #include <stdlib.h> 28 1.1 christos #include <stdio.h> 29 1.1 christos #include <ctype.h> 30 1.1 christos #include <setjmp.h> 31 1.1 christos 32 1.1 christos /* Maximum length of an instruction. */ 33 1.1 christos #define MAXLEN 4 34 1.1 christos 35 1.1 christos struct private 36 1.1 christos { 37 1.1 christos /* Points to first byte not fetched. */ 38 1.1 christos bfd_byte *max_fetched; 39 1.1 christos bfd_byte the_buffer[MAXLEN]; 40 1.1 christos bfd_vma insn_start; 41 1.1 christos jmp_buf bailout; 42 1.1 christos }; 43 1.1 christos 44 1.1 christos /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) 45 1.1 christos to ADDR (exclusive) are valid. Returns 1 for success, longjmps 46 1.1 christos on error. */ 47 1.1 christos #define FETCH_DATA(info, addr) \ 48 1.1 christos ((addr) <= ((struct private *)(info->private_data))->max_fetched \ 49 1.1 christos ? 1 : fetch_data ((info), (addr))) 50 1.1 christos 51 1.1 christos static int fetch_data (struct disassemble_info *info, bfd_byte * addr); 52 1.1 christos 53 1.1 christos static int 54 1.1 christos fetch_data (struct disassemble_info *info, bfd_byte *addr) 55 1.1 christos { 56 1.1 christos int status; 57 1.1 christos struct private *priv = (struct private *) info->private_data; 58 1.1 christos bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); 59 1.1 christos 60 1.1 christos status = (*info->read_memory_func) (start, 61 1.1 christos priv->max_fetched, 62 1.1 christos addr - priv->max_fetched, info); 63 1.1 christos if (status != 0) 64 1.1 christos { 65 1.1 christos (*info->memory_error_func) (status, start, info); 66 1.1 christos longjmp (priv->bailout, 1); 67 1.1 christos } 68 1.1 christos else 69 1.1 christos priv->max_fetched = addr; 70 1.1 christos return 1; 71 1.1 christos } 72 1.1 christos 73 1.1 christos static char *size_names[] = { "?", "b", "w", "?", "l", "?", "?", "?" }; 74 1.1 christos 75 1.1 christos static char *cc_names[] = 76 1.1 christos { 77 1.1 christos "fa", "eq", "cs", "os", "ns", "ne", "cc", "oc", 78 1.1 christos "nc", "ge", "gt", "hi", "le", "ls", "lt", "tr" 79 1.1 christos }; 80 1.1 christos 81 1.1 christos /* Disassemble non-storage relative instructions. */ 82 1.1 christos 83 1.1 christos static int 84 1.1 christos disassem_class0 (disassemble_info *info, unsigned int ins) 85 1.1 christos { 86 1.1 christos int opcode = (ins >> 21) & 0x000f; 87 1.1 christos 88 1.1 christos if (ins & CLASS0_UNUSED_MASK) 89 1.1 christos goto illegal_opcode; 90 1.1 christos 91 1.1 christos switch (opcode) 92 1.1 christos { 93 1.1 christos case 0: 94 1.1 christos /* BRR instruction. */ 95 1.1 christos { 96 1.1 christos unsigned cbf = (ins >> 27) & 0x000f; 97 1.1.1.4 christos int displacement = ((ins & 0xffff) ^ 0x8000) - 0x8000; 98 1.1 christos 99 1.1 christos if (ins == 0) 100 1.1 christos (*info->fprintf_func) (info->stream, "nop"); 101 1.1 christos else 102 1.1 christos (*info->fprintf_func) (info->stream, "brr %s,%+d", 103 1.1 christos cc_names[cbf], displacement); 104 1.1 christos } 105 1.1 christos break; 106 1.1 christos case 1: 107 1.1 christos /* Illegal opcode. */ 108 1.1 christos goto illegal_opcode; 109 1.1 christos break; 110 1.1 christos case 2: 111 1.1 christos /* Illegal opcode. */ 112 1.1 christos goto illegal_opcode; 113 1.1 christos break; 114 1.1 christos case 3: 115 1.1 christos /* Illegal opcode. */ 116 1.1 christos goto illegal_opcode; 117 1.1 christos break; 118 1.1 christos case 4: 119 1.1 christos /* Illegal opcode. */ 120 1.1 christos goto illegal_opcode; 121 1.1 christos break; 122 1.1 christos case 5: 123 1.1 christos /* Illegal opcode. */ 124 1.1 christos goto illegal_opcode; 125 1.1 christos break; 126 1.1 christos case 6: 127 1.1 christos /* Illegal opcode. */ 128 1.1 christos goto illegal_opcode; 129 1.1 christos break; 130 1.1 christos case 7: 131 1.1 christos /* Illegal opcode. */ 132 1.1 christos goto illegal_opcode; 133 1.1 christos break; 134 1.1 christos case 8: 135 1.1 christos /* Illegal opcode. */ 136 1.1 christos goto illegal_opcode; 137 1.1 christos break; 138 1.1 christos case 9: 139 1.1 christos /* Illegal opcode. */ 140 1.1 christos goto illegal_opcode; 141 1.1 christos break; 142 1.1 christos case 10: 143 1.1 christos /* Illegal opcode. */ 144 1.1 christos goto illegal_opcode; 145 1.1 christos break; 146 1.1 christos case 11: 147 1.1 christos /* Illegal opcode. */ 148 1.1 christos goto illegal_opcode; 149 1.1 christos break; 150 1.1 christos case 12: 151 1.1 christos /* Illegal opcode. */ 152 1.1 christos goto illegal_opcode; 153 1.1 christos break; 154 1.1 christos case 13: 155 1.1 christos /* Illegal opcode. */ 156 1.1 christos goto illegal_opcode; 157 1.1 christos break; 158 1.1 christos case 14: 159 1.1 christos /* Illegal opcode. */ 160 1.1 christos goto illegal_opcode; 161 1.1 christos break; 162 1.1 christos case 15: 163 1.1 christos /* Illegal opcode. */ 164 1.1 christos goto illegal_opcode; 165 1.1 christos break; 166 1.1 christos } 167 1.1 christos return 0; 168 1.1 christos 169 1.1.1.5 christos illegal_opcode: 170 1.1 christos return -1; 171 1.1 christos } 172 1.1 christos 173 1.1 christos /* Disassemble non-storage register class instructions. */ 174 1.1 christos 175 1.1 christos static int 176 1.1 christos disassem_class1 (disassemble_info *info, unsigned int ins) 177 1.1 christos { 178 1.1 christos int opcode = (ins >> 21) & 0xf; 179 1.1 christos int source_a = (ins >> 16) & 0x1f; 180 1.1 christos int source_b = (ins >> 4) & 0x1f; 181 1.1 christos int indx = (ins >> 10) & 0x1f; 182 1.1 christos 183 1.1 christos int size = ins & 0x7; 184 1.1 christos 185 1.1 christos if (ins & CLASS1_UNUSED_MASK) 186 1.1 christos goto illegal_opcode; 187 1.1 christos 188 1.1 christos switch (opcode) 189 1.1 christos { 190 1.1 christos case 0: 191 1.1 christos /* Stop. */ 192 1.1.1.3 christos (*info->fprintf_func) (info->stream, "stop %d,r%d", indx, source_a); 193 1.1 christos break; 194 1.1 christos case 1: 195 1.1 christos /* BMI - Block Move Indirect. */ 196 1.1 christos if (ins != BMI) 197 1.1 christos goto illegal_opcode; 198 1.1 christos 199 1.1 christos (*info->fprintf_func) (info->stream, "bmi r1,r2,r3"); 200 1.1 christos break; 201 1.1 christos case 2: 202 1.1 christos /* Illegal opcode. */ 203 1.1 christos goto illegal_opcode; 204 1.1 christos break; 205 1.1 christos case 3: 206 1.1 christos /* BMD - Block Move Direct. */ 207 1.1 christos if (ins != BMD) 208 1.1 christos goto illegal_opcode; 209 1.1 christos 210 1.1 christos (*info->fprintf_func) (info->stream, "bmd r1,r2,r3"); 211 1.1 christos break; 212 1.1 christos case 4: 213 1.1 christos /* DSI - Disable Interrupts. */ 214 1.1 christos if (ins != DSI) 215 1.1 christos goto illegal_opcode; 216 1.1 christos 217 1.1 christos (*info->fprintf_func) (info->stream, "dsi"); 218 1.1 christos break; 219 1.1 christos 220 1.1 christos case 5: 221 1.1 christos /* ENI - Enable Interrupts. */ 222 1.1 christos if (ins != ENI) 223 1.1 christos goto illegal_opcode; 224 1.1 christos 225 1.1 christos (*info->fprintf_func) (info->stream, "eni"); 226 1.1 christos break; 227 1.1 christos 228 1.1 christos case 6: 229 1.1 christos /* Illegal opcode (was EUT). */ 230 1.1 christos goto illegal_opcode; 231 1.1 christos break; 232 1.1 christos case 7: 233 1.1 christos /* RFI - Return from Interrupt. */ 234 1.1 christos if (ins != RFI) 235 1.1 christos goto illegal_opcode; 236 1.1 christos 237 1.1 christos (*info->fprintf_func) (info->stream, "rfi"); 238 1.1 christos break; 239 1.1 christos case 8: 240 1.1 christos /* Illegal opcode. */ 241 1.1 christos goto illegal_opcode; 242 1.1 christos break; 243 1.1 christos case 9: 244 1.1 christos /* Illegal opcode. */ 245 1.1 christos goto illegal_opcode; 246 1.1 christos break; 247 1.1 christos case 10: 248 1.1 christos /* Illegal opcode. */ 249 1.1 christos goto illegal_opcode; 250 1.1 christos break; 251 1.1 christos case 11: 252 1.1 christos /* Illegal opcode. */ 253 1.1 christos goto illegal_opcode; 254 1.1 christos break; 255 1.1 christos case 12: 256 1.1 christos /* Illegal opcode. */ 257 1.1 christos goto illegal_opcode; 258 1.1 christos break; 259 1.1 christos case 13: 260 1.1 christos goto illegal_opcode; 261 1.1 christos break; 262 1.1 christos case 14: 263 1.1 christos goto illegal_opcode; 264 1.1 christos break; 265 1.1 christos case 15: 266 1.1 christos if (ins & EAM_SELECT_MASK) 267 1.1 christos { 268 1.1 christos /* Extension arithmetic module write */ 269 1.1 christos int fp_ins = (ins >> 27) & 0xf; 270 1.1 christos 271 1.1 christos if (size != 4) 272 1.1 christos goto illegal_opcode; 273 1.1 christos 274 1.1 christos if (ins & FP_SELECT_MASK) 275 1.1 christos { 276 1.1 christos /* Which floating point instructions don't need a fsrcB 277 1.1 christos register. */ 278 1.1 christos const int no_fsrcb[16] = { 1, 0, 0, 0, 0, 1, 1, 1, 279 1.1 christos 1, 1, 0, 0, 1, 0, 0, 0 280 1.1 christos }; 281 1.1 christos if (no_fsrcb[fp_ins] && source_b) 282 1.1 christos goto illegal_opcode; 283 1.1 christos 284 1.1 christos /* Check that none of the floating register register numbers 285 1.1 christos is higher than 15. (If this is fload, then srcA is a 286 1.1 christos general register. */ 287 1.1 christos if (ins & ((1 << 14) | (1 << 8)) || (fp_ins && ins & (1 << 20))) 288 1.1 christos goto illegal_opcode; 289 1.1 christos 290 1.1 christos switch (fp_ins) 291 1.1 christos { 292 1.1 christos case 0: 293 1.1 christos (*info->fprintf_func) (info->stream, "fload f%d,r%d", 294 1.1 christos indx, source_a); 295 1.1 christos break; 296 1.1 christos case 1: 297 1.1 christos (*info->fprintf_func) (info->stream, "fadd f%d,f%d,f%d", 298 1.1 christos indx, source_a, source_b); 299 1.1 christos break; 300 1.1 christos case 2: 301 1.1 christos (*info->fprintf_func) (info->stream, "fsub f%d,f%d,f%d", 302 1.1 christos indx, source_a, source_b); 303 1.1 christos break; 304 1.1 christos case 3: 305 1.1 christos (*info->fprintf_func) (info->stream, "fmult f%d,f%d,f%d", 306 1.1 christos indx, source_a, source_b); 307 1.1 christos break; 308 1.1 christos case 4: 309 1.1 christos (*info->fprintf_func) (info->stream, "fdiv f%d,f%d,f%d", 310 1.1 christos indx, source_a, source_b); 311 1.1 christos break; 312 1.1 christos case 5: 313 1.1 christos (*info->fprintf_func) (info->stream, "fsqrt f%d,f%d", 314 1.1 christos indx, source_a); 315 1.1 christos break; 316 1.1 christos case 6: 317 1.1 christos (*info->fprintf_func) (info->stream, "fneg f%d,f%d", 318 1.1 christos indx, source_a); 319 1.1 christos break; 320 1.1 christos case 7: 321 1.1 christos (*info->fprintf_func) (info->stream, "fabs f%d,f%d", 322 1.1 christos indx, source_a); 323 1.1 christos break; 324 1.1 christos case 8: 325 1.1 christos (*info->fprintf_func) (info->stream, "ftoi f%d,f%d", 326 1.1 christos indx, source_a); 327 1.1 christos break; 328 1.1 christos case 9: 329 1.1 christos (*info->fprintf_func) (info->stream, "itof f%d,f%d", 330 1.1 christos indx, source_a); 331 1.1 christos break; 332 1.1 christos case 12: 333 1.1 christos (*info->fprintf_func) (info->stream, "fmove f%d,f%d", 334 1.1 christos indx, source_a); 335 1.1 christos break; 336 1.1 christos default: 337 1.1 christos (*info->fprintf_func) (info->stream, 338 1.1 christos "fpinst %d,f%d,f%d,f%d", fp_ins, 339 1.1 christos indx, source_a, source_b); 340 1.1 christos break; 341 1.1 christos } 342 1.1 christos } 343 1.1 christos else 344 1.1 christos { 345 1.1 christos /* Which EAM operations do not need a srcB register. */ 346 1.1 christos const int no_srcb[32] = 347 1.1 christos { 0, 0, 1, 1, 0, 1, 1, 1, 348 1.1 christos 0, 1, 1, 1, 0, 0, 0, 0, 349 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 350 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0 351 1.1 christos }; 352 1.1 christos 353 1.1 christos if (no_srcb[indx] && source_b) 354 1.1 christos goto illegal_opcode; 355 1.1 christos 356 1.1 christos if (fp_ins) 357 1.1 christos goto illegal_opcode; 358 1.1 christos 359 1.1 christos switch (indx) 360 1.1 christos { 361 1.1 christos case 0: 362 1.1 christos (*info->fprintf_func) (info->stream, "mults r%d,r%d", 363 1.1 christos source_a, source_b); 364 1.1 christos break; 365 1.1 christos case 1: 366 1.1 christos (*info->fprintf_func) (info->stream, "multu r%d,r%d", 367 1.1 christos source_a, source_b); 368 1.1 christos break; 369 1.1 christos case 2: 370 1.1 christos (*info->fprintf_func) (info->stream, "divs r%d", 371 1.1 christos source_a); 372 1.1 christos break; 373 1.1 christos case 3: 374 1.1 christos (*info->fprintf_func) (info->stream, "divu r%d", 375 1.1 christos source_a); 376 1.1 christos break; 377 1.1 christos case 4: 378 1.1 christos (*info->fprintf_func) (info->stream, "writemd r%d,r%d", 379 1.1 christos source_a, source_b); 380 1.1 christos break; 381 1.1 christos case 5: 382 1.1 christos (*info->fprintf_func) (info->stream, "writemdc r%d", 383 1.1 christos source_a); 384 1.1 christos break; 385 1.1 christos case 6: 386 1.1 christos (*info->fprintf_func) (info->stream, "divds r%d", 387 1.1 christos source_a); 388 1.1 christos break; 389 1.1 christos case 7: 390 1.1 christos (*info->fprintf_func) (info->stream, "divdu r%d", 391 1.1 christos source_a); 392 1.1 christos break; 393 1.1 christos case 9: 394 1.1 christos (*info->fprintf_func) (info->stream, "asrd r%d", 395 1.1 christos source_a); 396 1.1 christos break; 397 1.1 christos case 10: 398 1.1 christos (*info->fprintf_func) (info->stream, "lsrd r%d", 399 1.1 christos source_a); 400 1.1 christos break; 401 1.1 christos case 11: 402 1.1 christos (*info->fprintf_func) (info->stream, "asld r%d", 403 1.1 christos source_a); 404 1.1 christos break; 405 1.1 christos default: 406 1.1 christos (*info->fprintf_func) (info->stream, 407 1.1 christos "eamwrite %d,r%d,r%d", indx, 408 1.1 christos source_a, source_b); 409 1.1 christos break; 410 1.1 christos } 411 1.1 christos } 412 1.1 christos } 413 1.1 christos else 414 1.1 christos { 415 1.1 christos /* WRITE - write to memory. */ 416 1.1 christos (*info->fprintf_func) (info->stream, "write.%s %d(r%d),r%d", 417 1.1 christos size_names[size], indx, source_a, source_b); 418 1.1 christos } 419 1.1 christos break; 420 1.1 christos } 421 1.1 christos 422 1.1 christos return 0; 423 1.1 christos 424 1.1.1.5 christos illegal_opcode: 425 1.1 christos return -1; 426 1.1 christos } 427 1.1 christos 428 1.1 christos /* Disassemble storage immediate class instructions. */ 429 1.1 christos 430 1.1 christos static int 431 1.1 christos disassem_class2 (disassemble_info *info, unsigned int ins) 432 1.1 christos { 433 1.1 christos int opcode = (ins >> 21) & 0xf; 434 1.1 christos int source_a = (ins >> 16) & 0x1f; 435 1.1 christos unsigned immediate = ins & 0x0000ffff; 436 1.1 christos 437 1.1 christos if (ins & CC_MASK) 438 1.1 christos goto illegal_opcode; 439 1.1 christos 440 1.1 christos switch (opcode) 441 1.1 christos { 442 1.1 christos case 0: 443 1.1 christos /* ADDI instruction. */ 444 1.1 christos (*info->fprintf_func) (info->stream, "addi r%d,%d", source_a, 445 1.1 christos immediate); 446 1.1 christos break; 447 1.1 christos case 1: 448 1.1 christos /* Illegal opcode. */ 449 1.1 christos goto illegal_opcode; 450 1.1 christos break; 451 1.1 christos case 2: 452 1.1 christos /* SUBI instruction. */ 453 1.1 christos (*info->fprintf_func) (info->stream, "subi r%d,%d", source_a, 454 1.1 christos immediate); 455 1.1 christos break; 456 1.1 christos case 3: 457 1.1 christos /* Illegal opcode. */ 458 1.1 christos goto illegal_opcode; 459 1.1 christos break; 460 1.1 christos case 4: 461 1.1 christos /* MOVIL instruction. */ 462 1.1 christos (*info->fprintf_func) (info->stream, "movil r%d,0x%04X", source_a, 463 1.1 christos immediate); 464 1.1 christos break; 465 1.1 christos case 5: 466 1.1 christos /* MOVIU instruction. */ 467 1.1 christos (*info->fprintf_func) (info->stream, "moviu r%d,0x%04X", source_a, 468 1.1 christos immediate); 469 1.1 christos break; 470 1.1 christos case 6: 471 1.1 christos /* MOVIQ instruction. */ 472 1.1 christos (*info->fprintf_func) (info->stream, "moviq r%d,%u", source_a, 473 1.1 christos immediate); 474 1.1 christos break; 475 1.1 christos case 7: 476 1.1 christos /* Illegal opcode. */ 477 1.1 christos goto illegal_opcode; 478 1.1 christos break; 479 1.1 christos case 8: 480 1.1 christos /* WRTL instruction. */ 481 1.1 christos if (source_a != 0) 482 1.1 christos goto illegal_opcode; 483 1.1 christos 484 1.1 christos (*info->fprintf_func) (info->stream, "wrtl 0x%04X", immediate); 485 1.1 christos break; 486 1.1 christos case 9: 487 1.1 christos /* WRTU instruction. */ 488 1.1 christos if (source_a != 0) 489 1.1 christos goto illegal_opcode; 490 1.1 christos 491 1.1 christos (*info->fprintf_func) (info->stream, "wrtu 0x%04X", immediate); 492 1.1 christos break; 493 1.1 christos case 10: 494 1.1 christos /* Illegal opcode. */ 495 1.1 christos goto illegal_opcode; 496 1.1 christos break; 497 1.1 christos case 11: 498 1.1 christos /* Illegal opcode. */ 499 1.1 christos goto illegal_opcode; 500 1.1 christos break; 501 1.1 christos case 12: 502 1.1 christos /* Illegal opcode. */ 503 1.1 christos goto illegal_opcode; 504 1.1 christos break; 505 1.1 christos case 13: 506 1.1 christos /* Illegal opcode. */ 507 1.1 christos goto illegal_opcode; 508 1.1 christos break; 509 1.1 christos case 14: 510 1.1 christos /* Illegal opcode. */ 511 1.1 christos goto illegal_opcode; 512 1.1 christos break; 513 1.1 christos case 15: 514 1.1 christos /* Illegal opcode. */ 515 1.1 christos goto illegal_opcode; 516 1.1 christos break; 517 1.1 christos } 518 1.1 christos 519 1.1 christos return 0; 520 1.1 christos 521 1.1.1.5 christos illegal_opcode: 522 1.1 christos return -1; 523 1.1 christos } 524 1.1 christos 525 1.1 christos /* Disassemble storage register class instructions. */ 526 1.1 christos 527 1.1 christos static int 528 1.1 christos disassem_class3 (disassemble_info *info, unsigned int ins) 529 1.1 christos { 530 1.1 christos int opcode = (ins >> 21) & 0xf; 531 1.1 christos int source_b = (ins >> 4) & 0x1f; 532 1.1 christos int source_a = (ins >> 16) & 0x1f; 533 1.1 christos int size = ins & 0x7; 534 1.1 christos int dest = (ins >> 10) & 0x1f; 535 1.1 christos 536 1.1 christos /* Those instructions that don't have a srcB register. */ 537 1.1 christos const int no_srcb[16] = 538 1.1 christos { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 }; 539 1.1 christos 540 1.1 christos /* These are instructions which can take an immediate srcB value. */ 541 1.1 christos const int srcb_immed[16] = 542 1.1 christos { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 }; 543 1.1 christos 544 1.1 christos /* User opcodes should not provide a non-zero srcB register 545 1.1 christos when none is required. Only a BRA or floating point 546 1.1 christos instruction should have a non-zero condition code field. 547 1.1 christos Only a WRITE or EAMWRITE (opcode 15) should select an EAM 548 1.1 christos or floating point operation. Note that FP_SELECT_MASK is 549 1.1 christos the same bit (bit 3) as the interrupt bit which 550 1.1 christos distinguishes SYS1 from BRA and SYS2 from RFLAG. */ 551 1.1 christos if ((no_srcb[opcode] && source_b) 552 1.1 christos || (!srcb_immed[opcode] && ins & CLASS3_SOURCEB_IMMED) 553 1.1 christos || (opcode != 12 && opcode != 15 && ins & CC_MASK) 554 1.1 christos || (opcode != 15 && ins & (EAM_SELECT_MASK | FP_SELECT_MASK))) 555 1.1 christos goto illegal_opcode; 556 1.1 christos 557 1.1 christos 558 1.1 christos switch (opcode) 559 1.1 christos { 560 1.1 christos case 0: 561 1.1 christos /* ADD instruction. */ 562 1.1 christos (*info->fprintf_func) (info->stream, "add.%s r%d,r%d,r%d", 563 1.1 christos size_names[size], dest, source_a, source_b); 564 1.1 christos break; 565 1.1 christos case 1: 566 1.1 christos /* ADC instruction. */ 567 1.1 christos (*info->fprintf_func) (info->stream, "adc.%s r%d,r%d,r%d", 568 1.1 christos size_names[size], dest, source_a, source_b); 569 1.1 christos break; 570 1.1 christos case 2: 571 1.1 christos /* SUB instruction. */ 572 1.1 christos if (dest == 0) 573 1.1 christos (*info->fprintf_func) (info->stream, "cmp.%s r%d,r%d", 574 1.1 christos size_names[size], source_a, source_b); 575 1.1 christos else 576 1.1 christos (*info->fprintf_func) (info->stream, "sub.%s r%d,r%d,r%d", 577 1.1 christos size_names[size], dest, source_a, source_b); 578 1.1 christos break; 579 1.1 christos case 3: 580 1.1 christos /* SUBC instruction. */ 581 1.1 christos if (dest == 0) 582 1.1 christos (*info->fprintf_func) (info->stream, "cmpc.%s r%d,r%d", 583 1.1 christos size_names[size], source_a, source_b); 584 1.1 christos else 585 1.1 christos (*info->fprintf_func) (info->stream, "subc.%s r%d,r%d,r%d", 586 1.1 christos size_names[size], dest, source_a, source_b); 587 1.1 christos break; 588 1.1 christos case 4: 589 1.1 christos /* EXTW instruction. */ 590 1.1 christos if (size == 1) 591 1.1 christos goto illegal_opcode; 592 1.1 christos 593 1.1 christos (*info->fprintf_func) (info->stream, "extw.%s r%d,r%d", 594 1.1 christos size_names[size], dest, source_a); 595 1.1 christos break; 596 1.1 christos case 5: 597 1.1 christos /* ASR instruction. */ 598 1.1 christos if (ins & CLASS3_SOURCEB_IMMED) 599 1.1 christos (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,%d", 600 1.1 christos size_names[size], dest, source_a, source_b); 601 1.1 christos else 602 1.1 christos (*info->fprintf_func) (info->stream, "asr.%s r%d,r%d,r%d", 603 1.1 christos size_names[size], dest, source_a, source_b); 604 1.1 christos break; 605 1.1 christos case 6: 606 1.1 christos /* LSR instruction. */ 607 1.1 christos if (ins & CLASS3_SOURCEB_IMMED) 608 1.1 christos (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,%d", 609 1.1 christos size_names[size], dest, source_a, source_b); 610 1.1 christos else 611 1.1 christos (*info->fprintf_func) (info->stream, "lsr.%s r%d,r%d,r%d", 612 1.1 christos size_names[size], dest, source_a, source_b); 613 1.1 christos break; 614 1.1 christos case 7: 615 1.1 christos /* ASL instruction. */ 616 1.1 christos if (ins & CLASS3_SOURCEB_IMMED) 617 1.1 christos (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,%d", 618 1.1 christos size_names[size], dest, source_a, source_b); 619 1.1 christos else 620 1.1 christos (*info->fprintf_func) (info->stream, "asl.%s r%d,r%d,r%d", 621 1.1 christos size_names[size], dest, source_a, source_b); 622 1.1 christos break; 623 1.1 christos case 8: 624 1.1 christos /* XOR instruction. */ 625 1.1 christos (*info->fprintf_func) (info->stream, "xor.%s r%d,r%d,r%d", 626 1.1 christos size_names[size], dest, source_a, source_b); 627 1.1 christos break; 628 1.1 christos case 9: 629 1.1 christos /* OR instruction. */ 630 1.1 christos if (source_b == 0) 631 1.1 christos (*info->fprintf_func) (info->stream, "move.%s r%d,r%d", 632 1.1 christos size_names[size], dest, source_a); 633 1.1 christos else 634 1.1 christos (*info->fprintf_func) (info->stream, "or.%s r%d,r%d,r%d", 635 1.1 christos size_names[size], dest, source_a, source_b); 636 1.1 christos break; 637 1.1 christos case 10: 638 1.1 christos /* AND instruction. */ 639 1.1 christos (*info->fprintf_func) (info->stream, "and.%s r%d,r%d,r%d", 640 1.1 christos size_names[size], dest, source_a, source_b); 641 1.1 christos break; 642 1.1 christos case 11: 643 1.1 christos /* NOT instruction. */ 644 1.1 christos (*info->fprintf_func) (info->stream, "not.%s r%d,r%d", 645 1.1 christos size_names[size], dest, source_a); 646 1.1 christos break; 647 1.1 christos case 12: 648 1.1 christos /* BRA instruction. */ 649 1.1 christos { 650 1.1 christos unsigned cbf = (ins >> 27) & 0x000f; 651 1.1 christos 652 1.1 christos if (size != 4) 653 1.1 christos goto illegal_opcode; 654 1.1 christos 655 1.1 christos (*info->fprintf_func) (info->stream, "bra %s,r%d,r%d", 656 1.1 christos cc_names[cbf], source_a, dest); 657 1.1 christos } 658 1.1 christos break; 659 1.1 christos case 13: 660 1.1 christos /* RFLAG instruction. */ 661 1.1 christos if (source_a || size != 4) 662 1.1 christos goto illegal_opcode; 663 1.1 christos 664 1.1 christos (*info->fprintf_func) (info->stream, "rflag r%d", dest); 665 1.1 christos break; 666 1.1 christos case 14: 667 1.1 christos /* EXTB instruction. */ 668 1.1 christos (*info->fprintf_func) (info->stream, "extb.%s r%d,r%d", 669 1.1 christos size_names[size], dest, source_a); 670 1.1 christos break; 671 1.1 christos case 15: 672 1.1 christos if (!(ins & CLASS3_SOURCEB_IMMED)) 673 1.1 christos goto illegal_opcode; 674 1.1 christos 675 1.1 christos if (ins & EAM_SELECT_MASK) 676 1.1 christos { 677 1.1 christos /* Extension arithmetic module read. */ 678 1.1 christos int fp_ins = (ins >> 27) & 0xf; 679 1.1 christos 680 1.1 christos if (size != 4) 681 1.1 christos goto illegal_opcode; 682 1.1 christos 683 1.1 christos if (ins & FP_SELECT_MASK) 684 1.1 christos { 685 1.1 christos /* Check fsrcA <= 15 and fsrcB <= 15. */ 686 1.1 christos if (ins & ((1 << 20) | (1 << 8))) 687 1.1 christos goto illegal_opcode; 688 1.1 christos 689 1.1 christos switch (fp_ins) 690 1.1 christos { 691 1.1 christos case 0: 692 1.1 christos if (source_b) 693 1.1 christos goto illegal_opcode; 694 1.1 christos 695 1.1 christos (*info->fprintf_func) (info->stream, "fstore r%d,f%d", 696 1.1 christos dest, source_a); 697 1.1 christos break; 698 1.1 christos case 10: 699 1.1 christos (*info->fprintf_func) (info->stream, "fcmp r%d,f%d,f%d", 700 1.1 christos dest, source_a, source_b); 701 1.1 christos break; 702 1.1 christos case 11: 703 1.1 christos (*info->fprintf_func) (info->stream, "fcmpe r%d,f%d,f%d", 704 1.1 christos dest, source_a, source_b); 705 1.1 christos break; 706 1.1 christos default: 707 1.1 christos (*info->fprintf_func) (info->stream, 708 1.1 christos "fpuread %d,r%d,f%d,f%d", fp_ins, 709 1.1 christos dest, source_a, source_b); 710 1.1 christos break; 711 1.1 christos } 712 1.1 christos } 713 1.1 christos else 714 1.1 christos { 715 1.1 christos if (fp_ins || source_a) 716 1.1 christos goto illegal_opcode; 717 1.1 christos 718 1.1 christos switch (source_b) 719 1.1 christos { 720 1.1 christos case 0: 721 1.1 christos (*info->fprintf_func) (info->stream, "readmda r%d", dest); 722 1.1 christos break; 723 1.1 christos case 1: 724 1.1 christos (*info->fprintf_func) (info->stream, "readmdb r%d", dest); 725 1.1 christos break; 726 1.1 christos case 2: 727 1.1 christos (*info->fprintf_func) (info->stream, "readmdc r%d", dest); 728 1.1 christos break; 729 1.1 christos default: 730 1.1 christos (*info->fprintf_func) (info->stream, "eamread r%d,%d", 731 1.1 christos dest, source_b); 732 1.1 christos break; 733 1.1 christos } 734 1.1 christos } 735 1.1 christos } 736 1.1 christos else 737 1.1 christos { 738 1.1 christos if (ins & FP_SELECT_MASK) 739 1.1 christos goto illegal_opcode; 740 1.1 christos 741 1.1 christos /* READ instruction. */ 742 1.1 christos (*info->fprintf_func) (info->stream, "read.%s r%d,%d(r%d)", 743 1.1 christos size_names[size], dest, source_b, source_a); 744 1.1 christos } 745 1.1 christos break; 746 1.1 christos } 747 1.1 christos 748 1.1 christos return 0; 749 1.1 christos 750 1.1.1.5 christos illegal_opcode: 751 1.1 christos return -1; 752 1.1 christos 753 1.1 christos } 754 1.1 christos 755 1.1 christos /* Print the visium instruction at address addr in debugged memory, 756 1.1 christos on info->stream. Return length of the instruction, in bytes. */ 757 1.1 christos 758 1.1 christos int 759 1.1 christos print_insn_visium (bfd_vma addr, disassemble_info *info) 760 1.1 christos { 761 1.1 christos unsigned ins; 762 1.1 christos unsigned p1, p2; 763 1.1 christos int ans; 764 1.1 christos int i; 765 1.1 christos 766 1.1 christos /* Stuff copied from m68k-dis.c. */ 767 1.1 christos struct private priv; 768 1.1 christos bfd_byte *buffer = priv.the_buffer; 769 1.1.1.5 christos info->private_data = &priv; 770 1.1 christos priv.max_fetched = priv.the_buffer; 771 1.1 christos priv.insn_start = addr; 772 1.1 christos if (setjmp (priv.bailout) != 0) 773 1.1 christos { 774 1.1 christos /* Error return. */ 775 1.1 christos return -1; 776 1.1 christos } 777 1.1 christos 778 1.1 christos /* We do return this info. */ 779 1.1 christos info->insn_info_valid = 1; 780 1.1 christos 781 1.1 christos /* Assume non branch insn. */ 782 1.1 christos info->insn_type = dis_nonbranch; 783 1.1 christos 784 1.1 christos /* Assume no delay. */ 785 1.1 christos info->branch_delay_insns = 0; 786 1.1 christos 787 1.1 christos /* Assume no target known. */ 788 1.1 christos info->target = 0; 789 1.1 christos 790 1.1 christos /* Get 32-bit instruction word. */ 791 1.1 christos FETCH_DATA (info, buffer + 4); 792 1.1.1.4 christos ins = (unsigned) buffer[0] << 24; 793 1.1 christos ins |= buffer[1] << 16; 794 1.1 christos ins |= buffer[2] << 8; 795 1.1 christos ins |= buffer[3]; 796 1.1 christos 797 1.1 christos ans = 0; 798 1.1 christos 799 1.1 christos p1 = buffer[0] ^ buffer[1] ^ buffer[2] ^ buffer[3]; 800 1.1 christos p2 = 0; 801 1.1 christos for (i = 0; i < 8; i++) 802 1.1 christos { 803 1.1 christos p2 += p1 & 1; 804 1.1 christos p1 >>= 1; 805 1.1 christos } 806 1.1 christos 807 1.1 christos /* Decode the instruction. */ 808 1.1 christos if (p2 & 1) 809 1.1 christos ans = -1; 810 1.1 christos else 811 1.1 christos { 812 1.1 christos switch ((ins >> 25) & 0x3) 813 1.1 christos { 814 1.1 christos case 0: 815 1.1 christos ans = disassem_class0 (info, ins); 816 1.1 christos break; 817 1.1 christos case 1: 818 1.1 christos ans = disassem_class1 (info, ins); 819 1.1 christos break; 820 1.1 christos case 2: 821 1.1 christos ans = disassem_class2 (info, ins); 822 1.1 christos break; 823 1.1 christos case 3: 824 1.1 christos ans = disassem_class3 (info, ins); 825 1.1 christos break; 826 1.1 christos } 827 1.1 christos } 828 1.1 christos 829 1.1 christos if (ans != 0) 830 1.1 christos (*info->fprintf_func) (info->stream, "err"); 831 1.1 christos 832 1.1 christos /* Return number of bytes consumed (always 4 for the Visium). */ 833 1.1 christos return 4; 834 1.1 christos } 835