Changeset 609 for branches/GNU/src/binutils/opcodes/i960-dis.c
- Timestamp:
- Aug 16, 2003, 6:59:22 PM (22 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/GNU/src/binutils/opcodes/i960-dis.c
-
Property cvs2svn:cvs-rev
changed from
1.1
to1.1.1.2
r608 r609 1 1 /* Disassemble i80960 instructions. 2 Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000 2 Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 3 3 Free Software Foundation, Inc. 4 4 … … 22 22 23 23 static const char *const reg_names[] = { 24 /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", 24 /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", 25 25 /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 26 /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 27 /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", 28 /* 32 */ "pc", "ac", "ip", "tc", "fp0", "fp1", "fp2", "fp3" 26 /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 27 /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", 28 /* 32 */ "pc", "ac", "ip", "tc", "fp0", "fp1", "fp2", "fp3" 29 29 }; 30 30 … … 32 32 static FILE *stream; /* Output goes here */ 33 33 static struct disassemble_info *info; 34 static void print_addr ();35 static void ctrl ();36 static void cobr ();37 static void reg ();38 static int mem ();39 static void ea ();40 static void dstop ();41 static void regop ();42 static void invalid ();43 static int pinsn ();44 static void put_abs ();34 static void print_addr PARAMS ((bfd_vma)); 35 static void ctrl PARAMS ((bfd_vma, unsigned long, unsigned long)); 36 static void cobr PARAMS ((bfd_vma, unsigned long, unsigned long)); 37 static void reg PARAMS ((unsigned long)); 38 static int mem PARAMS ((bfd_vma, unsigned long, unsigned long, int)); 39 static void ea PARAMS ((bfd_vma, int, const char *, const char *, int, unsigned int)); 40 static void dstop PARAMS ((int, int, int)); 41 static void regop PARAMS ((int, int, int, int)); 42 static void invalid PARAMS ((int)); 43 static int pinsn PARAMS ((bfd_vma, unsigned long, unsigned long)); 44 static void put_abs PARAMS ((unsigned long, unsigned long)); 45 45 46 46 … … 120 120 121 121 static int 122 pinsn ( memaddr, word1, word2)123 bfd_vma memaddr;124 unsigned long word1, word2;125 { 126 127 128 129 put_abs( word1, word2);130 131 /* Divide instruction set into classes based on high 4 bits of opcode*/132 switch ( (word1 >> 28) & 0xf ){ 133 case 0x0: 134 case 0x1:135 ctrl( memaddr, word1, word2 ); 136 break;137 case 0x2: 138 case 0x3:139 cobr( memaddr, word1, word2 ); 140 break;141 case 0x5: 142 case 0x6:143 case 0x7:144 reg( word1 ); 145 break;146 case 0x8: 147 case 0x9:148 case 0xa:149 case 0xb:150 case 0xc:151 instr_len = mem( memaddr, word1, word2, 0 ); 152 break;153 default: 154 /* invalid instruction, print as data word */ 155 invalid( word1 ); 156 break;157 } 158 return instr_len; 159 } 160 161 /****************************************/ 162 /* CTRL format 163 /****************************************/ 122 pinsn (memaddr, word1, word2) 123 bfd_vma memaddr; 124 unsigned long word1, word2; 125 { 126 int instr_len; 127 128 instr_len = 4; 129 put_abs (word1, word2); 130 131 /* Divide instruction set into classes based on high 4 bits of opcode. */ 132 switch ((word1 >> 28) & 0xf) 133 { 134 case 0x0: 135 case 0x1: 136 ctrl (memaddr, word1, word2); 137 break; 138 case 0x2: 139 case 0x3: 140 cobr (memaddr, word1, word2); 141 break; 142 case 0x5: 143 case 0x6: 144 case 0x7: 145 reg (word1); 146 break; 147 case 0x8: 148 case 0x9: 149 case 0xa: 150 case 0xb: 151 case 0xc: 152 instr_len = mem (memaddr, word1, word2, 0); 153 break; 154 default: 155 /* Invalid instruction, print as data word. */ 156 invalid (word1); 157 break; 158 } 159 return instr_len; 160 } 161 162 /* CTRL format.. */ 163 164 164 static void 165 ctrl( memaddr, word1, word2 ) 166 bfd_vma memaddr; 167 unsigned long word1, word2; 168 { 169 int i; 170 static const struct tabent ctrl_tab[] = { 171 { NULL, 0, }, /* 0x00 */ 172 { NULL, 0, }, /* 0x01 */ 173 { NULL, 0, }, /* 0x02 */ 174 { NULL, 0, }, /* 0x03 */ 175 { NULL, 0, }, /* 0x04 */ 176 { NULL, 0, }, /* 0x05 */ 177 { NULL, 0, }, /* 0x06 */ 178 { NULL, 0, }, /* 0x07 */ 179 { "b", 1, }, /* 0x08 */ 180 { "call", 1, }, /* 0x09 */ 181 { "ret", 0, }, /* 0x0a */ 182 { "bal", 1, }, /* 0x0b */ 183 { NULL, 0, }, /* 0x0c */ 184 { NULL, 0, }, /* 0x0d */ 185 { NULL, 0, }, /* 0x0e */ 186 { NULL, 0, }, /* 0x0f */ 187 { "bno", 1, }, /* 0x10 */ 188 { "bg", 1, }, /* 0x11 */ 189 { "be", 1, }, /* 0x12 */ 190 { "bge", 1, }, /* 0x13 */ 191 { "bl", 1, }, /* 0x14 */ 192 { "bne", 1, }, /* 0x15 */ 193 { "ble", 1, }, /* 0x16 */ 194 { "bo", 1, }, /* 0x17 */ 195 { "faultno", 0, }, /* 0x18 */ 196 { "faultg", 0, }, /* 0x19 */ 197 { "faulte", 0, }, /* 0x1a */ 198 { "faultge", 0, }, /* 0x1b */ 199 { "faultl", 0, }, /* 0x1c */ 200 { "faultne", 0, }, /* 0x1d */ 201 { "faultle", 0, }, /* 0x1e */ 202 { "faulto", 0, }, /* 0x1f */ 203 }; 204 205 i = (word1 >> 24) & 0xff; 206 if ( (ctrl_tab[i].name == NULL) || ((word1 & 1) != 0) ){ 207 invalid( word1 ); 208 return; 209 } 210 211 (*info->fprintf_func) ( stream, ctrl_tab[i].name ); 212 if ( word1 & 2 ){ /* Predicts branch not taken */ 213 (*info->fprintf_func) ( stream, ".f" ); 214 } 215 216 if ( ctrl_tab[i].numops == 1 ){ 217 /* EXTRACT DISPLACEMENT AND CONVERT TO ADDRESS */ 218 word1 &= 0x00ffffff; 219 if ( word1 & 0x00800000 ){ /* Sign bit is set */ 220 word1 |= (-1 & ~0xffffff); /* Sign extend */ 221 } 222 (*info->fprintf_func)( stream, "\t" ); 223 print_addr( word1 + memaddr ); 224 } 225 } 226 227 /****************************************/ 228 /* COBR format */ 229 /****************************************/ 165 ctrl (memaddr, word1, word2) 166 bfd_vma memaddr; 167 unsigned long word1; 168 unsigned long word2 ATTRIBUTE_UNUSED; 169 { 170 int i; 171 static const struct tabent ctrl_tab[] = { 172 { NULL, 0, }, /* 0x00 */ 173 { NULL, 0, }, /* 0x01 */ 174 { NULL, 0, }, /* 0x02 */ 175 { NULL, 0, }, /* 0x03 */ 176 { NULL, 0, }, /* 0x04 */ 177 { NULL, 0, }, /* 0x05 */ 178 { NULL, 0, }, /* 0x06 */ 179 { NULL, 0, }, /* 0x07 */ 180 { "b", 1, }, /* 0x08 */ 181 { "call", 1, }, /* 0x09 */ 182 { "ret", 0, }, /* 0x0a */ 183 { "bal", 1, }, /* 0x0b */ 184 { NULL, 0, }, /* 0x0c */ 185 { NULL, 0, }, /* 0x0d */ 186 { NULL, 0, }, /* 0x0e */ 187 { NULL, 0, }, /* 0x0f */ 188 { "bno", 1, }, /* 0x10 */ 189 { "bg", 1, }, /* 0x11 */ 190 { "be", 1, }, /* 0x12 */ 191 { "bge", 1, }, /* 0x13 */ 192 { "bl", 1, }, /* 0x14 */ 193 { "bne", 1, }, /* 0x15 */ 194 { "ble", 1, }, /* 0x16 */ 195 { "bo", 1, }, /* 0x17 */ 196 { "faultno", 0, }, /* 0x18 */ 197 { "faultg", 0, }, /* 0x19 */ 198 { "faulte", 0, }, /* 0x1a */ 199 { "faultge", 0, }, /* 0x1b */ 200 { "faultl", 0, }, /* 0x1c */ 201 { "faultne", 0, }, /* 0x1d */ 202 { "faultle", 0, }, /* 0x1e */ 203 { "faulto", 0, }, /* 0x1f */ 204 }; 205 206 i = (word1 >> 24) & 0xff; 207 if ((ctrl_tab[i].name == NULL) || ((word1 & 1) != 0)) 208 { 209 invalid (word1); 210 return; 211 } 212 213 (*info->fprintf_func) (stream, ctrl_tab[i].name); 214 if (word1 & 2) 215 /* Predicts branch not taken. */ 216 (*info->fprintf_func) (stream, ".f"); 217 218 if (ctrl_tab[i].numops == 1) 219 { 220 /* Extract displacement and convert to address. */ 221 word1 &= 0x00ffffff; 222 223 if (word1 & 0x00800000) 224 { 225 /* Sign bit is set. */ 226 word1 |= (-1 & ~0xffffff); /* Sign extend. */ 227 } 228 229 (*info->fprintf_func) (stream, "\t"); 230 print_addr (word1 + memaddr); 231 } 232 } 233 234 /* COBR format. */ 235 230 236 static void 231 cobr( memaddr, word1, word2 ) 232 bfd_vma memaddr; 233 unsigned long word1, word2; 234 { 235 int src1; 236 int src2; 237 int i; 238 239 static const struct tabent cobr_tab[] = { 240 { "testno", 1, }, /* 0x20 */ 241 { "testg", 1, }, /* 0x21 */ 242 { "teste", 1, }, /* 0x22 */ 243 { "testge", 1, }, /* 0x23 */ 244 { "testl", 1, }, /* 0x24 */ 245 { "testne", 1, }, /* 0x25 */ 246 { "testle", 1, }, /* 0x26 */ 247 { "testo", 1, }, /* 0x27 */ 248 { NULL, 0, }, /* 0x28 */ 249 { NULL, 0, }, /* 0x29 */ 250 { NULL, 0, }, /* 0x2a */ 251 { NULL, 0, }, /* 0x2b */ 252 { NULL, 0, }, /* 0x2c */ 253 { NULL, 0, }, /* 0x2d */ 254 { NULL, 0, }, /* 0x2e */ 255 { NULL, 0, }, /* 0x2f */ 256 { "bbc", 3, }, /* 0x30 */ 257 { "cmpobg", 3, }, /* 0x31 */ 258 { "cmpobe", 3, }, /* 0x32 */ 259 { "cmpobge", 3, }, /* 0x33 */ 260 { "cmpobl", 3, }, /* 0x34 */ 261 { "cmpobne", 3, }, /* 0x35 */ 262 { "cmpoble", 3, }, /* 0x36 */ 263 { "bbs", 3, }, /* 0x37 */ 264 { "cmpibno", 3, }, /* 0x38 */ 265 { "cmpibg", 3, }, /* 0x39 */ 266 { "cmpibe", 3, }, /* 0x3a */ 267 { "cmpibge", 3, }, /* 0x3b */ 268 { "cmpibl", 3, }, /* 0x3c */ 269 { "cmpibne", 3, }, /* 0x3d */ 270 { "cmpible", 3, }, /* 0x3e */ 271 { "cmpibo", 3, }, /* 0x3f */ 272 }; 273 274 i = ((word1 >> 24) & 0xff) - 0x20; 275 if ( cobr_tab[i].name == NULL ){ 276 invalid( word1 ); 277 return; 278 } 279 280 (*info->fprintf_func) ( stream, cobr_tab[i].name ); 281 if ( word1 & 2 ){ /* Predicts branch not taken */ 282 (*info->fprintf_func) ( stream, ".f" ); 283 } 284 (*info->fprintf_func)( stream, "\t" ); 285 286 src1 = (word1 >> 19) & 0x1f; 287 src2 = (word1 >> 14) & 0x1f; 288 289 if ( word1 & 0x02000 ){ /* M1 is 1 */ 290 (*info->fprintf_func)( stream, "%d", src1 ); 291 } else { /* M1 is 0 */ 292 (*info->fprintf_func)( stream, reg_names[src1] ); 293 } 294 295 if ( cobr_tab[i].numops > 1 ){ 296 if ( word1 & 1 ){ /* S2 is 1 */ 297 (*info->fprintf_func)( stream, ",sf%d,", src2 ); 298 } else { /* S1 is 0 */ 299 (*info->fprintf_func)( stream, ",%s,", reg_names[src2] ); 300 } 301 302 /* Extract displacement and convert to address 303 */ 304 word1 &= 0x00001ffc; 305 if ( word1 & 0x00001000 ){ /* Negative displacement */ 306 word1 |= (-1 & ~0x1fff); /* Sign extend */ 307 } 308 print_addr( memaddr + word1 ); 309 } 310 } 311 312 /****************************************/ 313 /* MEM format */ 314 /****************************************/ 315 static int /* returns instruction length: 4 or 8 */ 316 mem( memaddr, word1, word2, noprint ) 317 bfd_vma memaddr; 318 unsigned long word1, word2; 319 int noprint; /* If TRUE, return instruction length, but 320 * don't output any text. 321 */ 322 { 323 int i, j; 324 int len; 325 int mode; 326 int offset; 327 const char *reg1, *reg2, *reg3; 328 329 /* This lookup table is too sparse to make it worth typing in, but not 330 so large as to make a sparse array necessary. We create the table 331 at runtime. */ 332 333 /* 334 * NOTE: In this table, the meaning of 'numops' is: 335 * 1: single operand 336 * 2: 2 operands, load instruction 337 * -2: 2 operands, store instruction 338 */ 339 static struct tabent *mem_tab; 340 /* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table. */ 237 cobr (memaddr, word1, word2) 238 bfd_vma memaddr; 239 unsigned long word1; 240 unsigned long word2 ATTRIBUTE_UNUSED; 241 { 242 int src1; 243 int src2; 244 int i; 245 246 static const struct tabent cobr_tab[] = { 247 { "testno", 1, }, /* 0x20 */ 248 { "testg", 1, }, /* 0x21 */ 249 { "teste", 1, }, /* 0x22 */ 250 { "testge", 1, }, /* 0x23 */ 251 { "testl", 1, }, /* 0x24 */ 252 { "testne", 1, }, /* 0x25 */ 253 { "testle", 1, }, /* 0x26 */ 254 { "testo", 1, }, /* 0x27 */ 255 { NULL, 0, }, /* 0x28 */ 256 { NULL, 0, }, /* 0x29 */ 257 { NULL, 0, }, /* 0x2a */ 258 { NULL, 0, }, /* 0x2b */ 259 { NULL, 0, }, /* 0x2c */ 260 { NULL, 0, }, /* 0x2d */ 261 { NULL, 0, }, /* 0x2e */ 262 { NULL, 0, }, /* 0x2f */ 263 { "bbc", 3, }, /* 0x30 */ 264 { "cmpobg", 3, }, /* 0x31 */ 265 { "cmpobe", 3, }, /* 0x32 */ 266 { "cmpobge",3, }, /* 0x33 */ 267 { "cmpobl", 3, }, /* 0x34 */ 268 { "cmpobne",3, }, /* 0x35 */ 269 { "cmpoble",3, }, /* 0x36 */ 270 { "bbs", 3, }, /* 0x37 */ 271 { "cmpibno",3, }, /* 0x38 */ 272 { "cmpibg", 3, }, /* 0x39 */ 273 { "cmpibe", 3, }, /* 0x3a */ 274 { "cmpibge",3, }, /* 0x3b */ 275 { "cmpibl", 3, }, /* 0x3c */ 276 { "cmpibne",3, }, /* 0x3d */ 277 { "cmpible",3, }, /* 0x3e */ 278 { "cmpibo", 3, }, /* 0x3f */ 279 }; 280 281 i = ((word1 >> 24) & 0xff) - 0x20; 282 if (cobr_tab[i].name == NULL) 283 { 284 invalid (word1); 285 return; 286 } 287 288 (*info->fprintf_func) (stream, cobr_tab[i].name); 289 290 /* Predicts branch not taken. */ 291 if (word1 & 2) 292 (*info->fprintf_func) (stream, ".f"); 293 294 (*info->fprintf_func) (stream, "\t"); 295 296 src1 = (word1 >> 19) & 0x1f; 297 src2 = (word1 >> 14) & 0x1f; 298 299 if (word1 & 0x02000) 300 /* M1 is 1 */ 301 (*info->fprintf_func) (stream, "%d", src1); 302 else 303 (*info->fprintf_func) (stream, reg_names[src1]); 304 305 if (cobr_tab[i].numops > 1) 306 { 307 if (word1 & 1) 308 /* S2 is 1. */ 309 (*info->fprintf_func) (stream, ",sf%d,", src2); 310 else 311 /* S1 is 0. */ 312 (*info->fprintf_func) (stream, ",%s,", reg_names[src2]); 313 314 /* Extract displacement and convert to address. */ 315 word1 &= 0x00001ffc; 316 if (word1 & 0x00001000) 317 /* Negative displacement. */ 318 word1 |= (-1 & ~0x1fff); /* Sign extend. */ 319 320 print_addr (memaddr + word1); 321 } 322 } 323 324 /* MEM format. */ 325 /* Returns instruction length: 4 or 8. */ 326 327 static int 328 mem (memaddr, word1, word2, noprint) 329 bfd_vma memaddr; 330 unsigned long word1, word2; 331 int noprint; /* If TRUE, return instruction length, but 332 don't output any text. */ 333 { 334 int i, j; 335 int len; 336 int mode; 337 int offset; 338 const char *reg1, *reg2, *reg3; 339 340 /* This lookup table is too sparse to make it worth typing in, but not 341 so large as to make a sparse array necessary. We create the table 342 at runtime. */ 343 344 /* NOTE: In this table, the meaning of 'numops' is: 345 1: single operand 346 2: 2 operands, load instruction 347 -2: 2 operands, store instruction. */ 348 static struct tabent *mem_tab; 349 /* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table. */ 341 350 #define MEM_MIN 0x80 342 351 #define MEM_MAX 0xcf 343 352 #define MEM_SIZ ( * sizeof(struct tabent)) 344 353 345 static const struct sparse_tabent mem_init[] = { 346 { 0x80, "ldob", 2 }, 347 { 0x82, "stob", -2 }, 348 { 0x84, "bx", 1 }, 349 { 0x85, "balx", 2 }, 350 { 0x86, "callx", 1 }, 351 { 0x88, "ldos", 2 }, 352 { 0x8a, "stos", -2 }, 353 { 0x8c, "lda", 2 }, 354 { 0x90, "ld", 2 }, 355 { 0x92, "st", -2 }, 356 { 0x98, "ldl", 2 }, 357 { 0x9a, "stl", -2 }, 358 { 0xa0, "ldt", 2 }, 359 { 0xa2, "stt", -2 }, 360 { 0xac, "dcinva", 1 }, 361 { 0xb0, "ldq", 2 }, 362 { 0xb2, "stq", -2 }, 363 { 0xc0, "ldib", 2 }, 364 { 0xc2, "stib", -2 }, 365 { 0xc8, "ldis", 2 }, 366 { 0xca, "stis", -2 }, 367 { 0, NULL, 0 } 368 }; 369 static struct tabent mem_tab_buf[MEM_MAX - MEM_MIN + 1]; 370 371 if ( mem_tab == NULL ){ 372 mem_tab = mem_tab_buf; 373 for ( i = 0; mem_init[i].opcode != 0; i++ ){ 374 j = mem_init[i].opcode - MEM_MIN; 375 mem_tab[j].name = mem_init[i].name; 376 mem_tab[j].numops = mem_init[i].numops; 377 } 378 } 379 380 i = ((word1 >> 24) & 0xff) - MEM_MIN; 381 mode = (word1 >> 10) & 0xf; 382 383 if ( (mem_tab[i].name != NULL) /* Valid instruction */ 384 && ((mode == 5) || (mode >=12)) ){ /* With 32-bit displacement */ 385 len = 8; 386 } else { 387 len = 4; 388 } 389 390 if ( noprint ){ 391 return len; 392 } 393 394 if ( (mem_tab[i].name == NULL) || (mode == 6) ){ 395 invalid( word1 ); 396 return len; 397 } 398 399 (*info->fprintf_func)( stream, "%s\t", mem_tab[i].name ); 400 401 reg1 = reg_names[ (word1 >> 19) & 0x1f ]; /* MEMB only */ 402 reg2 = reg_names[ (word1 >> 14) & 0x1f ]; 403 reg3 = reg_names[ word1 & 0x1f ]; /* MEMB only */ 404 offset = word1 & 0xfff; /* MEMA only */ 405 406 switch ( mem_tab[i].numops ){ 407 408 case 2: /* LOAD INSTRUCTION */ 409 if ( mode & 4 ){ /* MEMB FORMAT */ 410 ea( memaddr, mode, reg2, reg3, word1, word2 ); 411 (*info->fprintf_func)( stream, ",%s", reg1 ); 412 } else { /* MEMA FORMAT */ 413 (*info->fprintf_func)( stream, "0x%x", (unsigned) offset ); 414 if (mode & 8) { 415 (*info->fprintf_func)( stream, "(%s)", reg2 ); 416 } 417 (*info->fprintf_func)( stream, ",%s", reg1 ); 418 } 419 break; 420 421 case -2: /* STORE INSTRUCTION */ 422 if ( mode & 4 ){ /* MEMB FORMAT */ 423 (*info->fprintf_func)( stream, "%s,", reg1 ); 424 ea( memaddr, mode, reg2, reg3, word1, word2 ); 425 } else { /* MEMA FORMAT */ 426 (*info->fprintf_func)( stream, "%s,0x%x", reg1, (unsigned) offset ); 427 if (mode & 8) { 428 (*info->fprintf_func)( stream, "(%s)", reg2 ); 429 } 430 } 431 break; 432 433 case 1: /* BX/CALLX INSTRUCTION */ 434 if ( mode & 4 ){ /* MEMB FORMAT */ 435 ea( memaddr, mode, reg2, reg3, word1, word2 ); 436 } else { /* MEMA FORMAT */ 437 (*info->fprintf_func)( stream, "0x%x", (unsigned) offset ); 438 if (mode & 8) { 439 (*info->fprintf_func)( stream, "(%s)", reg2 ); 440 } 441 } 442 break; 443 } 444 445 return len; 446 } 447 448 /****************************************/ 449 /* REG format */ 450 /****************************************/ 354 static const struct sparse_tabent mem_init[] = { 355 { 0x80, "ldob", 2 }, 356 { 0x82, "stob", -2 }, 357 { 0x84, "bx", 1 }, 358 { 0x85, "balx", 2 }, 359 { 0x86, "callx", 1 }, 360 { 0x88, "ldos", 2 }, 361 { 0x8a, "stos", -2 }, 362 { 0x8c, "lda", 2 }, 363 { 0x90, "ld", 2 }, 364 { 0x92, "st", -2 }, 365 { 0x98, "ldl", 2 }, 366 { 0x9a, "stl", -2 }, 367 { 0xa0, "ldt", 2 }, 368 { 0xa2, "stt", -2 }, 369 { 0xac, "dcinva", 1 }, 370 { 0xb0, "ldq", 2 }, 371 { 0xb2, "stq", -2 }, 372 { 0xc0, "ldib", 2 }, 373 { 0xc2, "stib", -2 }, 374 { 0xc8, "ldis", 2 }, 375 { 0xca, "stis", -2 }, 376 { 0, NULL, 0 } 377 }; 378 static struct tabent mem_tab_buf[MEM_MAX - MEM_MIN + 1]; 379 380 if (mem_tab == NULL) 381 { 382 mem_tab = mem_tab_buf; 383 384 for (i = 0; mem_init[i].opcode != 0; i++) 385 { 386 j = mem_init[i].opcode - MEM_MIN; 387 mem_tab[j].name = mem_init[i].name; 388 mem_tab[j].numops = mem_init[i].numops; 389 } 390 } 391 392 i = ((word1 >> 24) & 0xff) - MEM_MIN; 393 mode = (word1 >> 10) & 0xf; 394 395 if ((mem_tab[i].name != NULL) /* Valid instruction */ 396 && ((mode == 5) || (mode >= 12))) 397 /* With 32-bit displacement. */ 398 len = 8; 399 else 400 len = 4; 401 402 if (noprint) 403 return len; 404 405 if ((mem_tab[i].name == NULL) || (mode == 6)) 406 { 407 invalid (word1); 408 return len; 409 } 410 411 (*info->fprintf_func) (stream, "%s\t", mem_tab[i].name); 412 413 reg1 = reg_names[ (word1 >> 19) & 0x1f ]; /* MEMB only */ 414 reg2 = reg_names[ (word1 >> 14) & 0x1f ]; 415 reg3 = reg_names[ word1 & 0x1f ]; /* MEMB only */ 416 offset = word1 & 0xfff; /* MEMA only */ 417 418 switch (mem_tab[i].numops) 419 { 420 case 2: /* LOAD INSTRUCTION */ 421 if (mode & 4) 422 { /* MEMB FORMAT */ 423 ea (memaddr, mode, reg2, reg3, word1, word2); 424 (*info->fprintf_func) (stream, ",%s", reg1); 425 } 426 else 427 { /* MEMA FORMAT */ 428 (*info->fprintf_func) (stream, "0x%x", (unsigned) offset); 429 430 if (mode & 8) 431 (*info->fprintf_func) (stream, "(%s)", reg2); 432 433 (*info->fprintf_func)(stream, ",%s", reg1); 434 } 435 break; 436 437 case -2: /* STORE INSTRUCTION */ 438 if (mode & 4) 439 { 440 /* MEMB FORMAT */ 441 (*info->fprintf_func) (stream, "%s,", reg1); 442 ea (memaddr, mode, reg2, reg3, word1, word2); 443 } 444 else 445 { 446 /* MEMA FORMAT */ 447 (*info->fprintf_func) (stream, "%s,0x%x", reg1, (unsigned) offset); 448 449 if (mode & 8) 450 (*info->fprintf_func) (stream, "(%s)", reg2); 451 } 452 break; 453 454 case 1: /* BX/CALLX INSTRUCTION */ 455 if (mode & 4) 456 { 457 /* MEMB FORMAT */ 458 ea (memaddr, mode, reg2, reg3, word1, word2); 459 } 460 else 461 { 462 /* MEMA FORMAT */ 463 (*info->fprintf_func) (stream, "0x%x", (unsigned) offset); 464 if (mode & 8) 465 (*info->fprintf_func) (stream, "(%s)", reg2); 466 } 467 break; 468 } 469 470 return len; 471 } 472 473 /* REG format. */ 474 451 475 static void 452 reg( word1 ) 453 unsigned long word1; 454 { 455 int i, j; 456 int opcode; 457 int fp; 458 int m1, m2, m3; 459 int s1, s2; 460 int src, src2, dst; 461 char *mnemp; 462 463 /* This lookup table is too sparse to make it worth typing in, but not 464 so large as to make a sparse array necessary. We create the table 465 at runtime. */ 466 467 /* 468 * NOTE: In this table, the meaning of 'numops' is: 469 * 1: single operand, which is NOT a destination. 470 * -1: single operand, which IS a destination. 471 * 2: 2 operands, the 2nd of which is NOT a destination. 472 * -2: 2 operands, the 2nd of which IS a destination. 473 * 3: 3 operands 474 * 475 * If an opcode mnemonic begins with "F", it is a floating-point 476 * opcode (the "F" is not printed). 477 */ 478 479 static struct tabent *reg_tab; 480 static const struct sparse_tabent reg_init[] = { 476 reg (word1) 477 unsigned long word1; 478 { 479 int i, j; 480 int opcode; 481 int fp; 482 int m1, m2, m3; 483 int s1, s2; 484 int src, src2, dst; 485 char *mnemp; 486 487 /* This lookup table is too sparse to make it worth typing in, but not 488 so large as to make a sparse array necessary. We create the table 489 at runtime. */ 490 491 /* NOTE: In this table, the meaning of 'numops' is: 492 1: single operand, which is NOT a destination. 493 -1: single operand, which IS a destination. 494 2: 2 operands, the 2nd of which is NOT a destination. 495 -2: 2 operands, the 2nd of which IS a destination. 496 3: 3 operands 497 498 If an opcode mnemonic begins with "F", it is a floating-point 499 opcode (the "F" is not printed). */ 500 501 static struct tabent *reg_tab; 502 static const struct sparse_tabent reg_init[] = 503 { 481 504 #define REG_MIN 0x580 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 { 0x590,"addo", 3 },498 { 0x591,"addi", 3 },499 { 0x592,"subo", 3 },500 { 0x593,"subi", 3 },501 502 503 504 505 { 0x598,"shro", 3 },506 { 0x59a,"shrdi", 3 },507 { 0x59b,"shri", 3 },508 { 0x59c,"shlo", 3 },509 { 0x59d,"rotate", 3 },510 { 0x59e,"shli", 3 },511 { 0x5a0,"cmpo", 2 },512 { 0x5a1,"cmpi", 2 },513 { 0x5a2,"concmpo", 2 },514 { 0x5a3,"concmpi", 2 },515 { 0x5a4,"cmpinco", 3 },516 { 0x5a5,"cmpinci", 3 },517 { 0x5a6,"cmpdeco", 3 },518 { 0x5a7,"cmpdeci", 3 },519 { 0x5ac,"scanbyte", 2 },520 521 { 0x5ae,"chkbit", 2 },522 { 0x5b0,"addc", 3 },523 { 0x5b2,"subc", 3 },524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 { 0x673,"ldtime", -1 },578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 { 0x6e1,"Fmovre", -2 },617 { 0x6e2,"Fcpysre", 3 },618 { 0x6e3,"Fcpyrsre", 3 },619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 505 { 0x580, "notbit", 3 }, 506 { 0x581, "and", 3 }, 507 { 0x582, "andnot", 3 }, 508 { 0x583, "setbit", 3 }, 509 { 0x584, "notand", 3 }, 510 { 0x586, "xor", 3 }, 511 { 0x587, "or", 3 }, 512 { 0x588, "nor", 3 }, 513 { 0x589, "xnor", 3 }, 514 { 0x58a, "not", -2 }, 515 { 0x58b, "ornot", 3 }, 516 { 0x58c, "clrbit", 3 }, 517 { 0x58d, "notor", 3 }, 518 { 0x58e, "nand", 3 }, 519 { 0x58f, "alterbit", 3 }, 520 { 0x590, "addo", 3 }, 521 { 0x591, "addi", 3 }, 522 { 0x592, "subo", 3 }, 523 { 0x593, "subi", 3 }, 524 { 0x594, "cmpob", 2 }, 525 { 0x595, "cmpib", 2 }, 526 { 0x596, "cmpos", 2 }, 527 { 0x597, "cmpis", 2 }, 528 { 0x598, "shro", 3 }, 529 { 0x59a, "shrdi", 3 }, 530 { 0x59b, "shri", 3 }, 531 { 0x59c, "shlo", 3 }, 532 { 0x59d, "rotate", 3 }, 533 { 0x59e, "shli", 3 }, 534 { 0x5a0, "cmpo", 2 }, 535 { 0x5a1, "cmpi", 2 }, 536 { 0x5a2, "concmpo", 2 }, 537 { 0x5a3, "concmpi", 2 }, 538 { 0x5a4, "cmpinco", 3 }, 539 { 0x5a5, "cmpinci", 3 }, 540 { 0x5a6, "cmpdeco", 3 }, 541 { 0x5a7, "cmpdeci", 3 }, 542 { 0x5ac, "scanbyte", 2 }, 543 { 0x5ad, "bswap", -2 }, 544 { 0x5ae, "chkbit", 2 }, 545 { 0x5b0, "addc", 3 }, 546 { 0x5b2, "subc", 3 }, 547 { 0x5b4, "intdis", 0 }, 548 { 0x5b5, "inten", 0 }, 549 { 0x5cc, "mov", -2 }, 550 { 0x5d8, "eshro", 3 }, 551 { 0x5dc, "movl", -2 }, 552 { 0x5ec, "movt", -2 }, 553 { 0x5fc, "movq", -2 }, 554 { 0x600, "synmov", 2 }, 555 { 0x601, "synmovl", 2 }, 556 { 0x602, "synmovq", 2 }, 557 { 0x603, "cmpstr", 3 }, 558 { 0x604, "movqstr", 3 }, 559 { 0x605, "movstr", 3 }, 560 { 0x610, "atmod", 3 }, 561 { 0x612, "atadd", 3 }, 562 { 0x613, "inspacc", -2 }, 563 { 0x614, "ldphy", -2 }, 564 { 0x615, "synld", -2 }, 565 { 0x617, "fill", 3 }, 566 { 0x630, "sdma", 3 }, 567 { 0x631, "udma", 0 }, 568 { 0x640, "spanbit", -2 }, 569 { 0x641, "scanbit", -2 }, 570 { 0x642, "daddc", 3 }, 571 { 0x643, "dsubc", 3 }, 572 { 0x644, "dmovt", -2 }, 573 { 0x645, "modac", 3 }, 574 { 0x646, "condrec", -2 }, 575 { 0x650, "modify", 3 }, 576 { 0x651, "extract", 3 }, 577 { 0x654, "modtc", 3 }, 578 { 0x655, "modpc", 3 }, 579 { 0x656, "receive", -2 }, 580 { 0x658, "intctl", -2 }, 581 { 0x659, "sysctl", 3 }, 582 { 0x65b, "icctl", 3 }, 583 { 0x65c, "dcctl", 3 }, 584 { 0x65d, "halt", 0 }, 585 { 0x660, "calls", 1 }, 586 { 0x662, "send", 3 }, 587 { 0x663, "sendserv", 1 }, 588 { 0x664, "resumprcs", 1 }, 589 { 0x665, "schedprcs", 1 }, 590 { 0x666, "saveprcs", 0 }, 591 { 0x668, "condwait", 1 }, 592 { 0x669, "wait", 1 }, 593 { 0x66a, "signal", 1 }, 594 { 0x66b, "mark", 0 }, 595 { 0x66c, "fmark", 0 }, 596 { 0x66d, "flushreg", 0 }, 597 { 0x66f, "syncf", 0 }, 598 { 0x670, "emul", 3 }, 599 { 0x671, "ediv", 3 }, 600 { 0x673, "ldtime", -1 }, 601 { 0x674, "Fcvtir", -2 }, 602 { 0x675, "Fcvtilr", -2 }, 603 { 0x676, "Fscalerl", 3 }, 604 { 0x677, "Fscaler", 3 }, 605 { 0x680, "Fatanr", 3 }, 606 { 0x681, "Flogepr", 3 }, 607 { 0x682, "Flogr", 3 }, 608 { 0x683, "Fremr", 3 }, 609 { 0x684, "Fcmpor", 2 }, 610 { 0x685, "Fcmpr", 2 }, 611 { 0x688, "Fsqrtr", -2 }, 612 { 0x689, "Fexpr", -2 }, 613 { 0x68a, "Flogbnr", -2 }, 614 { 0x68b, "Froundr", -2 }, 615 { 0x68c, "Fsinr", -2 }, 616 { 0x68d, "Fcosr", -2 }, 617 { 0x68e, "Ftanr", -2 }, 618 { 0x68f, "Fclassr", 1 }, 619 { 0x690, "Fatanrl", 3 }, 620 { 0x691, "Flogeprl", 3 }, 621 { 0x692, "Flogrl", 3 }, 622 { 0x693, "Fremrl", 3 }, 623 { 0x694, "Fcmporl", 2 }, 624 { 0x695, "Fcmprl", 2 }, 625 { 0x698, "Fsqrtrl", -2 }, 626 { 0x699, "Fexprl", -2 }, 627 { 0x69a, "Flogbnrl", -2 }, 628 { 0x69b, "Froundrl", -2 }, 629 { 0x69c, "Fsinrl", -2 }, 630 { 0x69d, "Fcosrl", -2 }, 631 { 0x69e, "Ftanrl", -2 }, 632 { 0x69f, "Fclassrl", 1 }, 633 { 0x6c0, "Fcvtri", -2 }, 634 { 0x6c1, "Fcvtril", -2 }, 635 { 0x6c2, "Fcvtzri", -2 }, 636 { 0x6c3, "Fcvtzril", -2 }, 637 { 0x6c9, "Fmovr", -2 }, 638 { 0x6d9, "Fmovrl", -2 }, 639 { 0x6e1, "Fmovre", -2 }, 640 { 0x6e2, "Fcpysre", 3 }, 641 { 0x6e3, "Fcpyrsre", 3 }, 642 { 0x701, "mulo", 3 }, 643 { 0x708, "remo", 3 }, 644 { 0x70b, "divo", 3 }, 645 { 0x741, "muli", 3 }, 646 { 0x748, "remi", 3 }, 647 { 0x749, "modi", 3 }, 648 { 0x74b, "divi", 3 }, 649 { 0x780, "addono", 3 }, 650 { 0x781, "addino", 3 }, 651 { 0x782, "subono", 3 }, 652 { 0x783, "subino", 3 }, 653 { 0x784, "selno", 3 }, 654 { 0x78b, "Fdivr", 3 }, 655 { 0x78c, "Fmulr", 3 }, 656 { 0x78d, "Fsubr", 3 }, 657 { 0x78f, "Faddr", 3 }, 658 { 0x790, "addog", 3 }, 659 { 0x791, "addig", 3 }, 660 { 0x792, "subog", 3 }, 661 { 0x793, "subig", 3 }, 662 { 0x794, "selg", 3 }, 663 { 0x79b, "Fdivrl", 3 }, 664 { 0x79c, "Fmulrl", 3 }, 665 { 0x79d, "Fsubrl", 3 }, 666 { 0x79f, "Faddrl", 3 }, 667 { 0x7a0, "addoe", 3 }, 668 { 0x7a1, "addie", 3 }, 669 { 0x7a2, "suboe", 3 }, 670 { 0x7a3, "subie", 3 }, 671 { 0x7a4, "sele", 3 }, 672 { 0x7b0, "addoge", 3 }, 673 { 0x7b1, "addige", 3 }, 674 { 0x7b2, "suboge", 3 }, 675 { 0x7b3, "subige", 3 }, 676 { 0x7b4, "selge", 3 }, 677 { 0x7c0, "addol", 3 }, 678 { 0x7c1, "addil", 3 }, 679 { 0x7c2, "subol", 3 }, 680 { 0x7c3, "subil", 3 }, 681 { 0x7c4, "sell", 3 }, 682 { 0x7d0, "addone", 3 }, 683 { 0x7d1, "addine", 3 }, 684 { 0x7d2, "subone", 3 }, 685 { 0x7d3, "subine", 3 }, 686 { 0x7d4, "selne", 3 }, 687 { 0x7e0, "addole", 3 }, 688 { 0x7e1, "addile", 3 }, 689 { 0x7e2, "subole", 3 }, 690 { 0x7e3, "subile", 3 }, 691 { 0x7e4, "selle", 3 }, 692 { 0x7f0, "addoo", 3 }, 693 { 0x7f1, "addio", 3 }, 694 { 0x7f2, "suboo", 3 }, 695 { 0x7f3, "subio", 3 }, 696 { 0x7f4, "selo", 3 }, 674 697 #define REG_MAX 0x7f4 675 { 0, NULL, 0 } 676 }; 677 static struct tabent reg_tab_buf[REG_MAX - REG_MIN + 1]; 678 679 if ( reg_tab == NULL ){ 680 reg_tab = reg_tab_buf; 681 for ( i = 0; reg_init[i].opcode != 0; i++ ){ 682 j = reg_init[i].opcode - REG_MIN; 683 reg_tab[j].name = reg_init[i].name; 684 reg_tab[j].numops = reg_init[i].numops; 685 } 686 } 687 688 opcode = ((word1 >> 20) & 0xff0) | ((word1 >> 7) & 0xf); 689 i = opcode - REG_MIN; 690 691 if ( (opcode<REG_MIN) || (opcode>REG_MAX) || (reg_tab[i].name==NULL) ){ 692 invalid( word1 ); 693 return; 694 } 695 696 mnemp = reg_tab[i].name; 697 if ( *mnemp == 'F' ){ 698 fp = 1; 699 mnemp++; 700 } else { 701 fp = 0; 702 } 703 704 (*info->fprintf_func)( stream, mnemp ); 705 706 s1 = (word1 >> 5) & 1; 707 s2 = (word1 >> 6) & 1; 708 m1 = (word1 >> 11) & 1; 709 m2 = (word1 >> 12) & 1; 710 m3 = (word1 >> 13) & 1; 711 src = word1 & 0x1f; 712 src2 = (word1 >> 14) & 0x1f; 713 dst = (word1 >> 19) & 0x1f; 714 715 if ( reg_tab[i].numops != 0 ){ 716 (*info->fprintf_func)( stream, "\t" ); 717 718 switch ( reg_tab[i].numops ){ 719 case 1: 720 regop( m1, s1, src, fp ); 721 break; 722 case -1: 723 dstop( m3, dst, fp ); 724 break; 725 case 2: 726 regop( m1, s1, src, fp ); 727 (*info->fprintf_func)( stream, "," ); 728 regop( m2, s2, src2, fp ); 729 break; 730 case -2: 731 regop( m1, s1, src, fp ); 732 (*info->fprintf_func)( stream, "," ); 733 dstop( m3, dst, fp ); 734 break; 735 case 3: 736 regop( m1, s1, src, fp ); 737 (*info->fprintf_func)( stream, "," ); 738 regop( m2, s2, src2, fp ); 739 (*info->fprintf_func)( stream, "," ); 740 dstop( m3, dst, fp ); 741 break; 742 } 743 } 744 } 745 746 747 /* 748 * Print out effective address for memb instructions. 749 */ 698 { 0, NULL, 0 } 699 }; 700 static struct tabent reg_tab_buf[REG_MAX - REG_MIN + 1]; 701 702 if (reg_tab == NULL) 703 { 704 reg_tab = reg_tab_buf; 705 706 for (i = 0; reg_init[i].opcode != 0; i++) 707 { 708 j = reg_init[i].opcode - REG_MIN; 709 reg_tab[j].name = reg_init[i].name; 710 reg_tab[j].numops = reg_init[i].numops; 711 } 712 } 713 714 opcode = ((word1 >> 20) & 0xff0) | ((word1 >> 7) & 0xf); 715 i = opcode - REG_MIN; 716 717 if ((opcode<REG_MIN) || (opcode>REG_MAX) || (reg_tab[i].name==NULL)) 718 { 719 invalid (word1); 720 return; 721 } 722 723 mnemp = reg_tab[i].name; 724 if (*mnemp == 'F') 725 { 726 fp = 1; 727 mnemp++; 728 } 729 else 730 { 731 fp = 0; 732 } 733 734 (*info->fprintf_func) (stream, mnemp); 735 736 s1 = (word1 >> 5) & 1; 737 s2 = (word1 >> 6) & 1; 738 m1 = (word1 >> 11) & 1; 739 m2 = (word1 >> 12) & 1; 740 m3 = (word1 >> 13) & 1; 741 src = word1 & 0x1f; 742 src2 = (word1 >> 14) & 0x1f; 743 dst = (word1 >> 19) & 0x1f; 744 745 if (reg_tab[i].numops != 0) 746 { 747 (*info->fprintf_func) (stream, "\t"); 748 749 switch (reg_tab[i].numops) 750 { 751 case 1: 752 regop (m1, s1, src, fp); 753 break; 754 case -1: 755 dstop (m3, dst, fp); 756 break; 757 case 2: 758 regop (m1, s1, src, fp); 759 (*info->fprintf_func) (stream, ","); 760 regop (m2, s2, src2, fp); 761 break; 762 case -2: 763 regop (m1, s1, src, fp); 764 (*info->fprintf_func) (stream, ","); 765 dstop (m3, dst, fp); 766 break; 767 case 3: 768 regop (m1, s1, src, fp); 769 (*info->fprintf_func) (stream, ","); 770 regop (m2, s2, src2, fp); 771 (*info->fprintf_func) (stream, ","); 772 dstop (m3, dst, fp); 773 break; 774 } 775 } 776 } 777 778 /* Print out effective address for memb instructions. */ 779 750 780 static void 751 ea ( memaddr, mode, reg2, reg3, word1, word2)781 ea (memaddr, mode, reg2, reg3, word1, word2) 752 782 bfd_vma memaddr; 753 783 int mode; 754 char *reg2, *reg3; 784 const char *reg2; 785 const char *reg3; 755 786 int word1; 756 787 unsigned int word2; 757 788 { 758 int scale; 759 static const int scale_tab[] = { 1, 2, 4, 8, 16 }; 760 761 scale = (word1 >> 7) & 0x07; 762 if ( (scale > 4) || (((word1 >> 5) & 0x03) != 0) ){ 763 invalid( word1 ); 764 return; 765 } 766 scale = scale_tab[scale]; 767 768 switch (mode) { 769 case 4: /* (reg) */ 770 (*info->fprintf_func)( stream, "(%s)", reg2 ); 771 break; 772 case 5: /* displ+8(ip) */ 773 print_addr( word2+8+memaddr ); 774 break; 775 case 7: /* (reg)[index*scale] */ 776 if (scale == 1) { 777 (*info->fprintf_func)( stream, "(%s)[%s]", reg2, reg3 ); 778 } else { 779 (*info->fprintf_func)( stream, "(%s)[%s*%d]",reg2,reg3,scale); 780 } 781 break; 782 case 12: /* displacement */ 783 print_addr( (bfd_vma)word2 ); 784 break; 785 case 13: /* displ(reg) */ 786 print_addr( (bfd_vma)word2 ); 787 (*info->fprintf_func)( stream, "(%s)", reg2 ); 788 break; 789 case 14: /* displ[index*scale] */ 790 print_addr( (bfd_vma)word2 ); 791 if (scale == 1) { 792 (*info->fprintf_func)( stream, "[%s]", reg3 ); 793 } else { 794 (*info->fprintf_func)( stream, "[%s*%d]", reg3, scale ); 795 } 796 break; 797 case 15: /* displ(reg)[index*scale] */ 798 print_addr( (bfd_vma)word2 ); 799 if (scale == 1) { 800 (*info->fprintf_func)( stream, "(%s)[%s]", reg2, reg3 ); 801 } else { 802 (*info->fprintf_func)( stream, "(%s)[%s*%d]",reg2,reg3,scale ); 803 } 804 break; 805 default: 806 invalid( word1 ); 807 return; 808 } 809 } 810 811 812 /************************************************/ 813 /* Register Instruction Operand */ 814 /************************************************/ 789 int scale; 790 static const int scale_tab[] = { 1, 2, 4, 8, 16 }; 791 792 scale = (word1 >> 7) & 0x07; 793 794 if ((scale > 4) || (((word1 >> 5) & 0x03) != 0)) 795 { 796 invalid (word1); 797 return; 798 } 799 scale = scale_tab[scale]; 800 801 switch (mode) 802 { 803 case 4: /* (reg) */ 804 (*info->fprintf_func)( stream, "(%s)", reg2 ); 805 break; 806 case 5: /* displ+8(ip) */ 807 print_addr (word2 + 8 + memaddr); 808 break; 809 case 7: /* (reg)[index*scale] */ 810 if (scale == 1) 811 (*info->fprintf_func) (stream, "(%s)[%s]", reg2, reg3); 812 else 813 (*info->fprintf_func) (stream, "(%s)[%s*%d]", reg2, reg3, scale); 814 break; 815 case 12: /* displacement */ 816 print_addr ((bfd_vma) word2); 817 break; 818 case 13: /* displ(reg) */ 819 print_addr ((bfd_vma) word2); 820 (*info->fprintf_func) (stream, "(%s)", reg2); 821 break; 822 case 14: /* displ[index*scale] */ 823 print_addr ((bfd_vma) word2); 824 if (scale == 1) 825 (*info->fprintf_func) (stream, "[%s]", reg3); 826 else 827 (*info->fprintf_func) (stream, "[%s*%d]", reg3, scale); 828 break; 829 case 15: /* displ(reg)[index*scale] */ 830 print_addr ((bfd_vma) word2); 831 if (scale == 1) 832 (*info->fprintf_func) (stream, "(%s)[%s]", reg2, reg3); 833 else 834 (*info->fprintf_func) (stream, "(%s)[%s*%d]", reg2, reg3, scale); 835 break; 836 default: 837 invalid (word1); 838 return; 839 } 840 } 841 842 843 /* Register Instruction Operand. */ 844 815 845 static void 816 regop( mode, spec, reg, fp ) 817 int mode, spec, reg, fp; 818 { 819 if ( fp ){ /* FLOATING POINT INSTRUCTION */ 820 if ( mode == 1 ){ /* FP operand */ 821 switch ( reg ){ 822 case 0: (*info->fprintf_func)( stream, "fp0" ); 823 break; 824 case 1: (*info->fprintf_func)( stream, "fp1" ); 825 break; 826 case 2: (*info->fprintf_func)( stream, "fp2" ); 827 break; 828 case 3: (*info->fprintf_func)( stream, "fp3" ); 829 break; 830 case 16: (*info->fprintf_func)( stream, "0f0.0" ); 831 break; 832 case 22: (*info->fprintf_func)( stream, "0f1.0" ); 833 break; 834 default: (*info->fprintf_func)( stream, "?" ); 835 break; 836 } 837 } else { /* Non-FP register */ 838 (*info->fprintf_func)( stream, reg_names[reg] ); 839 } 840 } else { /* NOT FLOATING POINT */ 841 if ( mode == 1 ){ /* Literal */ 842 (*info->fprintf_func)( stream, "%d", reg ); 843 } else { /* Register */ 844 if ( spec == 0 ){ 845 (*info->fprintf_func)( stream, reg_names[reg] ); 846 } else { 847 (*info->fprintf_func)( stream, "sf%d", reg ); 848 } 849 } 850 } 851 } 852 853 /************************************************/ 854 /* Register Instruction Destination Operand */ 855 /************************************************/ 846 regop (mode, spec, reg, fp) 847 int mode, spec, reg, fp; 848 { 849 if (fp) 850 { 851 /* Floating point instruction. */ 852 if (mode == 1) 853 { 854 /* FP operand. */ 855 switch (reg) 856 { 857 case 0: (*info->fprintf_func) (stream, "fp0"); 858 break; 859 case 1: (*info->fprintf_func) (stream, "fp1"); 860 break; 861 case 2: (*info->fprintf_func) (stream, "fp2"); 862 break; 863 case 3: (*info->fprintf_func) (stream, "fp3"); 864 break; 865 case 16: (*info->fprintf_func) (stream, "0f0.0"); 866 break; 867 case 22: (*info->fprintf_func) (stream, "0f1.0"); 868 break; 869 default: (*info->fprintf_func) (stream, "?"); 870 break; 871 } 872 } 873 else 874 { 875 /* Non-FP register. */ 876 (*info->fprintf_func) (stream, reg_names[reg]); 877 } 878 } 879 else 880 { 881 /* Not floating point. */ 882 if (mode == 1) 883 { 884 /* Literal. */ 885 (*info->fprintf_func) (stream, "%d", reg); 886 } 887 else 888 { 889 /* Register. */ 890 if (spec == 0) 891 (*info->fprintf_func) (stream, reg_names[reg]); 892 else 893 (*info->fprintf_func) (stream, "sf%d", reg); 894 } 895 } 896 } 897 898 /* Register Instruction Destination Operand. */ 899 856 900 static void 857 dstop( mode, reg, fp ) 858 int mode, reg, fp; 859 { 860 /* 'dst' operand can't be a literal. On non-FP instructions, register 861 * mode is assumed and "m3" acts as if were "s3"; on FP-instructions, 862 * sf registers are not allowed so m3 acts normally. 863 */ 864 if ( fp ){ 865 regop( mode, 0, reg, fp ); 866 } else { 867 regop( 0, mode, reg, fp ); 868 } 869 } 870 901 dstop (mode, reg, fp) 902 int mode, reg, fp; 903 { 904 /* 'dst' operand can't be a literal. On non-FP instructions, register 905 mode is assumed and "m3" acts as if were "s3"; on FP-instructions, 906 sf registers are not allowed so m3 acts normally. */ 907 if (fp) 908 regop (mode, 0, reg, fp); 909 else 910 regop (0, mode, reg, fp); 911 } 871 912 872 913 static void 873 invalid ( word1)874 int word1;875 { 876 (*info->fprintf_func)( stream, ".word\t0x%08x", (unsigned) word1);877 } 914 invalid (word1) 915 int word1; 916 { 917 (*info->fprintf_func) (stream, ".word\t0x%08x", (unsigned) word1); 918 } 878 919 879 920 static void 880 print_addr (a)881 bfd_vma a;921 print_addr (a) 922 bfd_vma a; 882 923 { 883 924 (*info->print_address_func) (a, info); … … 885 926 886 927 static void 887 put_abs( word1, word2 ) 888 unsigned long word1, word2; 928 put_abs (word1, word2) 929 unsigned long word1 ATTRIBUTE_UNUSED; 930 unsigned long word2 ATTRIBUTE_UNUSED; 889 931 { 890 932 #ifdef IN_GDB 891 933 return; 892 934 #else 893 int len; 894 895 switch ( (word1 >> 28) & 0xf ){ 896 case 0x8: 897 case 0x9: 898 case 0xa: 899 case 0xb: 900 case 0xc: 901 /* MEM format instruction */ 902 len = mem( 0, word1, word2, 1 ); 903 break; 904 default: 905 len = 4; 906 break; 907 } 908 909 if ( len == 8 ){ 910 (*info->fprintf_func)( stream, "%08x %08x\t", word1, word2 ); 911 } else { 912 (*info->fprintf_func)( stream, "%08x \t", word1 ); 913 } 914 ; 915 935 int len; 936 937 switch ((word1 >> 28) & 0xf) 938 { 939 case 0x8: 940 case 0x9: 941 case 0xa: 942 case 0xb: 943 case 0xc: 944 /* MEM format instruction. */ 945 len = mem (0, word1, word2, 1); 946 break; 947 default: 948 len = 4; 949 break; 950 } 951 952 if (len == 8) 953 (*info->fprintf_func) (stream, "%08x %08x\t", word1, word2); 954 else 955 (*info->fprintf_func) (stream, "%08x \t", word1); 916 956 #endif 917 957 } -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.