1 /* Instruction building/extraction support for xstormy16. -*- C -*- 2 3 THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator. 4 - the resultant file is machine generated, cgen-ibld.in isn't 5 6 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005, 2006, 2007, 7 2008, 2010 Free Software Foundation, Inc. 8 9 This file is part of libopcodes. 10 11 This library is free software; you can redistribute it and/or modify 12 it under the terms of the GNU General Public License as published by 13 the Free Software Foundation; either version 3, or (at your option) 14 any later version. 15 16 It is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 19 License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program; if not, write to the Free Software Foundation, Inc., 23 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 24 25 /* ??? Eventually more and more of this stuff can go to cpu-independent files. 26 Keep that in mind. */ 27 28 #include "sysdep.h" 29 #include <stdio.h> 30 #include "ansidecl.h" 31 #include "dis-asm.h" 32 #include "bfd.h" 33 #include "symcat.h" 34 #include "xstormy16-desc.h" 35 #include "xstormy16-opc.h" 36 #include "cgen/basic-modes.h" 37 #include "opintl.h" 38 #include "safe-ctype.h" 39 40 #undef min 41 #define min(a,b) ((a) < (b) ? (a) : (b)) 42 #undef max 43 #define max(a,b) ((a) > (b) ? (a) : (b)) 44 45 /* Used by the ifield rtx function. */ 46 #define FLD(f) (fields->f) 47 48 static const char * insert_normal 49 (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int, 50 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR); 51 static const char * insert_insn_normal 52 (CGEN_CPU_DESC, const CGEN_INSN *, 53 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma); 54 static int extract_normal 55 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, 56 unsigned int, unsigned int, unsigned int, unsigned int, 57 unsigned int, unsigned int, bfd_vma, long *); 58 static int extract_insn_normal 59 (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *, 60 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma); 61 #if CGEN_INT_INSN_P 62 static void put_insn_int_value 63 (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT); 64 #endif 65 #if ! CGEN_INT_INSN_P 66 static CGEN_INLINE void insert_1 67 (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *); 68 static CGEN_INLINE int fill_cache 69 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma); 70 static CGEN_INLINE long extract_1 71 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma); 72 #endif 73 74 /* Operand insertion. */ 75 76 #if ! CGEN_INT_INSN_P 77 78 /* Subroutine of insert_normal. */ 79 80 static CGEN_INLINE void 81 insert_1 (CGEN_CPU_DESC cd, 82 unsigned long value, 83 int start, 84 int length, 85 int word_length, 86 unsigned char *bufp) 87 { 88 unsigned long x,mask; 89 int shift; 90 91 x = cgen_get_insn_value (cd, bufp, word_length); 92 93 /* Written this way to avoid undefined behaviour. */ 94 mask = (((1L << (length - 1)) - 1) << 1) | 1; 95 if (CGEN_INSN_LSB0_P) 96 shift = (start + 1) - length; 97 else 98 shift = (word_length - (start + length)); 99 x = (x & ~(mask << shift)) | ((value & mask) << shift); 100 101 cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x); 102 } 103 104 #endif /* ! CGEN_INT_INSN_P */ 105 106 /* Default insertion routine. 107 108 ATTRS is a mask of the boolean attributes. 109 WORD_OFFSET is the offset in bits from the start of the insn of the value. 110 WORD_LENGTH is the length of the word in bits in which the value resides. 111 START is the starting bit number in the word, architecture origin. 112 LENGTH is the length of VALUE in bits. 113 TOTAL_LENGTH is the total length of the insn in bits. 114 115 The result is an error message or NULL if success. */ 116 117 /* ??? This duplicates functionality with bfd's howto table and 118 bfd_install_relocation. */ 119 /* ??? This doesn't handle bfd_vma's. Create another function when 120 necessary. */ 121 122 static const char * 123 insert_normal (CGEN_CPU_DESC cd, 124 long value, 125 unsigned int attrs, 126 unsigned int word_offset, 127 unsigned int start, 128 unsigned int length, 129 unsigned int word_length, 130 unsigned int total_length, 131 CGEN_INSN_BYTES_PTR buffer) 132 { 133 static char errbuf[100]; 134 /* Written this way to avoid undefined behaviour. */ 135 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1; 136 137 /* If LENGTH is zero, this operand doesn't contribute to the value. */ 138 if (length == 0) 139 return NULL; 140 141 if (word_length > 8 * sizeof (CGEN_INSN_INT)) 142 abort (); 143 144 /* For architectures with insns smaller than the base-insn-bitsize, 145 word_length may be too big. */ 146 if (cd->min_insn_bitsize < cd->base_insn_bitsize) 147 { 148 if (word_offset == 0 149 && word_length > total_length) 150 word_length = total_length; 151 } 152 153 /* Ensure VALUE will fit. */ 154 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT)) 155 { 156 long minval = - (1L << (length - 1)); 157 unsigned long maxval = mask; 158 159 if ((value > 0 && (unsigned long) value > maxval) 160 || value < minval) 161 { 162 /* xgettext:c-format */ 163 sprintf (errbuf, 164 _("operand out of range (%ld not between %ld and %lu)"), 165 value, minval, maxval); 166 return errbuf; 167 } 168 } 169 else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)) 170 { 171 unsigned long maxval = mask; 172 unsigned long val = (unsigned long) value; 173 174 /* For hosts with a word size > 32 check to see if value has been sign 175 extended beyond 32 bits. If so then ignore these higher sign bits 176 as the user is attempting to store a 32-bit signed value into an 177 unsigned 32-bit field which is allowed. */ 178 if (sizeof (unsigned long) > 4 && ((value >> 32) == -1)) 179 val &= 0xFFFFFFFF; 180 181 if (val > maxval) 182 { 183 /* xgettext:c-format */ 184 sprintf (errbuf, 185 _("operand out of range (0x%lx not between 0 and 0x%lx)"), 186 val, maxval); 187 return errbuf; 188 } 189 } 190 else 191 { 192 if (! cgen_signed_overflow_ok_p (cd)) 193 { 194 long minval = - (1L << (length - 1)); 195 long maxval = (1L << (length - 1)) - 1; 196 197 if (value < minval || value > maxval) 198 { 199 sprintf 200 /* xgettext:c-format */ 201 (errbuf, _("operand out of range (%ld not between %ld and %ld)"), 202 value, minval, maxval); 203 return errbuf; 204 } 205 } 206 } 207 208 #if CGEN_INT_INSN_P 209 210 { 211 int shift; 212 213 if (CGEN_INSN_LSB0_P) 214 shift = (word_offset + start + 1) - length; 215 else 216 shift = total_length - (word_offset + start + length); 217 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift); 218 } 219 220 #else /* ! CGEN_INT_INSN_P */ 221 222 { 223 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8; 224 225 insert_1 (cd, value, start, length, word_length, bufp); 226 } 227 228 #endif /* ! CGEN_INT_INSN_P */ 229 230 return NULL; 231 } 232 233 /* Default insn builder (insert handler). 234 The instruction is recorded in CGEN_INT_INSN_P byte order (meaning 235 that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is 236 recorded in host byte order, otherwise BUFFER is an array of bytes 237 and the value is recorded in target byte order). 238 The result is an error message or NULL if success. */ 239 240 static const char * 241 insert_insn_normal (CGEN_CPU_DESC cd, 242 const CGEN_INSN * insn, 243 CGEN_FIELDS * fields, 244 CGEN_INSN_BYTES_PTR buffer, 245 bfd_vma pc) 246 { 247 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 248 unsigned long value; 249 const CGEN_SYNTAX_CHAR_TYPE * syn; 250 251 CGEN_INIT_INSERT (cd); 252 value = CGEN_INSN_BASE_VALUE (insn); 253 254 /* If we're recording insns as numbers (rather than a string of bytes), 255 target byte order handling is deferred until later. */ 256 257 #if CGEN_INT_INSN_P 258 259 put_insn_int_value (cd, buffer, cd->base_insn_bitsize, 260 CGEN_FIELDS_BITSIZE (fields), value); 261 262 #else 263 264 cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize, 265 (unsigned) CGEN_FIELDS_BITSIZE (fields)), 266 value); 267 268 #endif /* ! CGEN_INT_INSN_P */ 269 270 /* ??? It would be better to scan the format's fields. 271 Still need to be able to insert a value based on the operand though; 272 e.g. storing a branch displacement that got resolved later. 273 Needs more thought first. */ 274 275 for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn) 276 { 277 const char *errmsg; 278 279 if (CGEN_SYNTAX_CHAR_P (* syn)) 280 continue; 281 282 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn), 283 fields, buffer, pc); 284 if (errmsg) 285 return errmsg; 286 } 287 288 return NULL; 289 } 290 291 #if CGEN_INT_INSN_P 292 /* Cover function to store an insn value into an integral insn. Must go here 293 because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */ 294 295 static void 296 put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 297 CGEN_INSN_BYTES_PTR buf, 298 int length, 299 int insn_length, 300 CGEN_INSN_INT value) 301 { 302 /* For architectures with insns smaller than the base-insn-bitsize, 303 length may be too big. */ 304 if (length > insn_length) 305 *buf = value; 306 else 307 { 308 int shift = insn_length - length; 309 /* Written this way to avoid undefined behaviour. */ 310 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1; 311 312 *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift); 313 } 314 } 315 #endif 316 317 /* Operand extraction. */ 318 319 #if ! CGEN_INT_INSN_P 320 321 /* Subroutine of extract_normal. 322 Ensure sufficient bytes are cached in EX_INFO. 323 OFFSET is the offset in bytes from the start of the insn of the value. 324 BYTES is the length of the needed value. 325 Returns 1 for success, 0 for failure. */ 326 327 static CGEN_INLINE int 328 fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 329 CGEN_EXTRACT_INFO *ex_info, 330 int offset, 331 int bytes, 332 bfd_vma pc) 333 { 334 /* It's doubtful that the middle part has already been fetched so 335 we don't optimize that case. kiss. */ 336 unsigned int mask; 337 disassemble_info *info = (disassemble_info *) ex_info->dis_info; 338 339 /* First do a quick check. */ 340 mask = (1 << bytes) - 1; 341 if (((ex_info->valid >> offset) & mask) == mask) 342 return 1; 343 344 /* Search for the first byte we need to read. */ 345 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1) 346 if (! (mask & ex_info->valid)) 347 break; 348 349 if (bytes) 350 { 351 int status; 352 353 pc += offset; 354 status = (*info->read_memory_func) 355 (pc, ex_info->insn_bytes + offset, bytes, info); 356 357 if (status != 0) 358 { 359 (*info->memory_error_func) (status, pc, info); 360 return 0; 361 } 362 363 ex_info->valid |= ((1 << bytes) - 1) << offset; 364 } 365 366 return 1; 367 } 368 369 /* Subroutine of extract_normal. */ 370 371 static CGEN_INLINE long 372 extract_1 (CGEN_CPU_DESC cd, 373 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED, 374 int start, 375 int length, 376 int word_length, 377 unsigned char *bufp, 378 bfd_vma pc ATTRIBUTE_UNUSED) 379 { 380 unsigned long x; 381 int shift; 382 383 x = cgen_get_insn_value (cd, bufp, word_length); 384 385 if (CGEN_INSN_LSB0_P) 386 shift = (start + 1) - length; 387 else 388 shift = (word_length - (start + length)); 389 return x >> shift; 390 } 391 392 #endif /* ! CGEN_INT_INSN_P */ 393 394 /* Default extraction routine. 395 396 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order, 397 or sometimes less for cases like the m32r where the base insn size is 32 398 but some insns are 16 bits. 399 ATTRS is a mask of the boolean attributes. We only need `SIGNED', 400 but for generality we take a bitmask of all of them. 401 WORD_OFFSET is the offset in bits from the start of the insn of the value. 402 WORD_LENGTH is the length of the word in bits in which the value resides. 403 START is the starting bit number in the word, architecture origin. 404 LENGTH is the length of VALUE in bits. 405 TOTAL_LENGTH is the total length of the insn in bits. 406 407 Returns 1 for success, 0 for failure. */ 408 409 /* ??? The return code isn't properly used. wip. */ 410 411 /* ??? This doesn't handle bfd_vma's. Create another function when 412 necessary. */ 413 414 static int 415 extract_normal (CGEN_CPU_DESC cd, 416 #if ! CGEN_INT_INSN_P 417 CGEN_EXTRACT_INFO *ex_info, 418 #else 419 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED, 420 #endif 421 CGEN_INSN_INT insn_value, 422 unsigned int attrs, 423 unsigned int word_offset, 424 unsigned int start, 425 unsigned int length, 426 unsigned int word_length, 427 unsigned int total_length, 428 #if ! CGEN_INT_INSN_P 429 bfd_vma pc, 430 #else 431 bfd_vma pc ATTRIBUTE_UNUSED, 432 #endif 433 long *valuep) 434 { 435 long value, mask; 436 437 /* If LENGTH is zero, this operand doesn't contribute to the value 438 so give it a standard value of zero. */ 439 if (length == 0) 440 { 441 *valuep = 0; 442 return 1; 443 } 444 445 if (word_length > 8 * sizeof (CGEN_INSN_INT)) 446 abort (); 447 448 /* For architectures with insns smaller than the insn-base-bitsize, 449 word_length may be too big. */ 450 if (cd->min_insn_bitsize < cd->base_insn_bitsize) 451 { 452 if (word_offset + word_length > total_length) 453 word_length = total_length - word_offset; 454 } 455 456 /* Does the value reside in INSN_VALUE, and at the right alignment? */ 457 458 if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length)) 459 { 460 if (CGEN_INSN_LSB0_P) 461 value = insn_value >> ((word_offset + start + 1) - length); 462 else 463 value = insn_value >> (total_length - ( word_offset + start + length)); 464 } 465 466 #if ! CGEN_INT_INSN_P 467 468 else 469 { 470 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8; 471 472 if (word_length > 8 * sizeof (CGEN_INSN_INT)) 473 abort (); 474 475 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0) 476 return 0; 477 478 value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc); 479 } 480 481 #endif /* ! CGEN_INT_INSN_P */ 482 483 /* Written this way to avoid undefined behaviour. */ 484 mask = (((1L << (length - 1)) - 1) << 1) | 1; 485 486 value &= mask; 487 /* sign extend? */ 488 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED) 489 && (value & (1L << (length - 1)))) 490 value |= ~mask; 491 492 *valuep = value; 493 494 return 1; 495 } 496 497 /* Default insn extractor. 498 499 INSN_VALUE is the first base_insn_bitsize bits, translated to host order. 500 The extracted fields are stored in FIELDS. 501 EX_INFO is used to handle reading variable length insns. 502 Return the length of the insn in bits, or 0 if no match, 503 or -1 if an error occurs fetching data (memory_error_func will have 504 been called). */ 505 506 static int 507 extract_insn_normal (CGEN_CPU_DESC cd, 508 const CGEN_INSN *insn, 509 CGEN_EXTRACT_INFO *ex_info, 510 CGEN_INSN_INT insn_value, 511 CGEN_FIELDS *fields, 512 bfd_vma pc) 513 { 514 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 515 const CGEN_SYNTAX_CHAR_TYPE *syn; 516 517 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); 518 519 CGEN_INIT_EXTRACT (cd); 520 521 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn) 522 { 523 int length; 524 525 if (CGEN_SYNTAX_CHAR_P (*syn)) 526 continue; 527 528 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn), 529 ex_info, insn_value, fields, pc); 530 if (length <= 0) 531 return length; 532 } 533 534 /* We recognized and successfully extracted this insn. */ 535 return CGEN_INSN_BITSIZE (insn); 536 } 537 538 /* Machine generated code added here. */ 539 540 const char * xstormy16_cgen_insert_operand 541 (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma); 542 543 /* Main entry point for operand insertion. 544 545 This function is basically just a big switch statement. Earlier versions 546 used tables to look up the function to use, but 547 - if the table contains both assembler and disassembler functions then 548 the disassembler contains much of the assembler and vice-versa, 549 - there's a lot of inlining possibilities as things grow, 550 - using a switch statement avoids the function call overhead. 551 552 This function could be moved into `parse_insn_normal', but keeping it 553 separate makes clear the interface between `parse_insn_normal' and each of 554 the handlers. It's also needed by GAS to insert operands that couldn't be 555 resolved during parsing. */ 556 557 const char * 558 xstormy16_cgen_insert_operand (CGEN_CPU_DESC cd, 559 int opindex, 560 CGEN_FIELDS * fields, 561 CGEN_INSN_BYTES_PTR buffer, 562 bfd_vma pc ATTRIBUTE_UNUSED) 563 { 564 const char * errmsg = NULL; 565 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields); 566 567 switch (opindex) 568 { 569 case XSTORMY16_OPERAND_RB : 570 errmsg = insert_normal (cd, fields->f_Rb, 0, 0, 17, 3, 32, total_length, buffer); 571 break; 572 case XSTORMY16_OPERAND_RBJ : 573 errmsg = insert_normal (cd, fields->f_Rbj, 0, 0, 11, 1, 32, total_length, buffer); 574 break; 575 case XSTORMY16_OPERAND_RD : 576 errmsg = insert_normal (cd, fields->f_Rd, 0, 0, 12, 4, 32, total_length, buffer); 577 break; 578 case XSTORMY16_OPERAND_RDM : 579 errmsg = insert_normal (cd, fields->f_Rdm, 0, 0, 13, 3, 32, total_length, buffer); 580 break; 581 case XSTORMY16_OPERAND_RM : 582 errmsg = insert_normal (cd, fields->f_Rm, 0, 0, 4, 3, 32, total_length, buffer); 583 break; 584 case XSTORMY16_OPERAND_RS : 585 errmsg = insert_normal (cd, fields->f_Rs, 0, 0, 8, 4, 32, total_length, buffer); 586 break; 587 case XSTORMY16_OPERAND_ABS24 : 588 { 589 { 590 FLD (f_abs24_1) = ((FLD (f_abs24)) & (255)); 591 FLD (f_abs24_2) = ((UINT) (FLD (f_abs24)) >> (8)); 592 } 593 errmsg = insert_normal (cd, fields->f_abs24_1, 0, 0, 8, 8, 32, total_length, buffer); 594 if (errmsg) 595 break; 596 errmsg = insert_normal (cd, fields->f_abs24_2, 0, 0, 16, 16, 32, total_length, buffer); 597 if (errmsg) 598 break; 599 } 600 break; 601 case XSTORMY16_OPERAND_BCOND2 : 602 errmsg = insert_normal (cd, fields->f_op2, 0, 0, 4, 4, 32, total_length, buffer); 603 break; 604 case XSTORMY16_OPERAND_BCOND5 : 605 errmsg = insert_normal (cd, fields->f_op5, 0, 0, 16, 4, 32, total_length, buffer); 606 break; 607 case XSTORMY16_OPERAND_HMEM8 : 608 { 609 long value = fields->f_hmem8; 610 value = ((value) - (32512)); 611 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer); 612 } 613 break; 614 case XSTORMY16_OPERAND_IMM12 : 615 errmsg = insert_normal (cd, fields->f_imm12, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, buffer); 616 break; 617 case XSTORMY16_OPERAND_IMM16 : 618 errmsg = insert_normal (cd, fields->f_imm16, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, buffer); 619 break; 620 case XSTORMY16_OPERAND_IMM2 : 621 errmsg = insert_normal (cd, fields->f_imm2, 0, 0, 10, 2, 32, total_length, buffer); 622 break; 623 case XSTORMY16_OPERAND_IMM3 : 624 errmsg = insert_normal (cd, fields->f_imm3, 0, 0, 4, 3, 32, total_length, buffer); 625 break; 626 case XSTORMY16_OPERAND_IMM3B : 627 errmsg = insert_normal (cd, fields->f_imm3b, 0, 0, 17, 3, 32, total_length, buffer); 628 break; 629 case XSTORMY16_OPERAND_IMM4 : 630 errmsg = insert_normal (cd, fields->f_imm4, 0, 0, 8, 4, 32, total_length, buffer); 631 break; 632 case XSTORMY16_OPERAND_IMM8 : 633 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer); 634 break; 635 case XSTORMY16_OPERAND_IMM8SMALL : 636 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer); 637 break; 638 case XSTORMY16_OPERAND_LMEM8 : 639 errmsg = insert_normal (cd, fields->f_lmem8, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer); 640 break; 641 case XSTORMY16_OPERAND_REL12 : 642 { 643 long value = fields->f_rel12; 644 value = ((value) - (((pc) + (4)))); 645 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, buffer); 646 } 647 break; 648 case XSTORMY16_OPERAND_REL12A : 649 { 650 long value = fields->f_rel12a; 651 value = ((SI) (((value) - (((pc) + (2))))) >> (1)); 652 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, buffer); 653 } 654 break; 655 case XSTORMY16_OPERAND_REL8_2 : 656 { 657 long value = fields->f_rel8_2; 658 value = ((value) - (((pc) + (2)))); 659 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer); 660 } 661 break; 662 case XSTORMY16_OPERAND_REL8_4 : 663 { 664 long value = fields->f_rel8_4; 665 value = ((value) - (((pc) + (4)))); 666 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer); 667 } 668 break; 669 case XSTORMY16_OPERAND_WS2 : 670 errmsg = insert_normal (cd, fields->f_op2m, 0, 0, 7, 1, 32, total_length, buffer); 671 break; 672 673 default : 674 /* xgettext:c-format */ 675 fprintf (stderr, _("Unrecognized field %d while building insn.\n"), 676 opindex); 677 abort (); 678 } 679 680 return errmsg; 681 } 682 683 int xstormy16_cgen_extract_operand 684 (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma); 685 686 /* Main entry point for operand extraction. 687 The result is <= 0 for error, >0 for success. 688 ??? Actual values aren't well defined right now. 689 690 This function is basically just a big switch statement. Earlier versions 691 used tables to look up the function to use, but 692 - if the table contains both assembler and disassembler functions then 693 the disassembler contains much of the assembler and vice-versa, 694 - there's a lot of inlining possibilities as things grow, 695 - using a switch statement avoids the function call overhead. 696 697 This function could be moved into `print_insn_normal', but keeping it 698 separate makes clear the interface between `print_insn_normal' and each of 699 the handlers. */ 700 701 int 702 xstormy16_cgen_extract_operand (CGEN_CPU_DESC cd, 703 int opindex, 704 CGEN_EXTRACT_INFO *ex_info, 705 CGEN_INSN_INT insn_value, 706 CGEN_FIELDS * fields, 707 bfd_vma pc) 708 { 709 /* Assume success (for those operands that are nops). */ 710 int length = 1; 711 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields); 712 713 switch (opindex) 714 { 715 case XSTORMY16_OPERAND_RB : 716 length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_Rb); 717 break; 718 case XSTORMY16_OPERAND_RBJ : 719 length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 1, 32, total_length, pc, & fields->f_Rbj); 720 break; 721 case XSTORMY16_OPERAND_RD : 722 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_Rd); 723 break; 724 case XSTORMY16_OPERAND_RDM : 725 length = extract_normal (cd, ex_info, insn_value, 0, 0, 13, 3, 32, total_length, pc, & fields->f_Rdm); 726 break; 727 case XSTORMY16_OPERAND_RM : 728 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_Rm); 729 break; 730 case XSTORMY16_OPERAND_RS : 731 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_Rs); 732 break; 733 case XSTORMY16_OPERAND_ABS24 : 734 { 735 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_abs24_1); 736 if (length <= 0) break; 737 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_abs24_2); 738 if (length <= 0) break; 739 FLD (f_abs24) = ((((FLD (f_abs24_2)) << (8))) | (FLD (f_abs24_1))); 740 } 741 break; 742 case XSTORMY16_OPERAND_BCOND2 : 743 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_op2); 744 break; 745 case XSTORMY16_OPERAND_BCOND5 : 746 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 4, 32, total_length, pc, & fields->f_op5); 747 break; 748 case XSTORMY16_OPERAND_HMEM8 : 749 { 750 long value; 751 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & value); 752 value = ((value) + (32512)); 753 fields->f_hmem8 = value; 754 } 755 break; 756 case XSTORMY16_OPERAND_IMM12 : 757 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, pc, & fields->f_imm12); 758 break; 759 case XSTORMY16_OPERAND_IMM16 : 760 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, pc, & fields->f_imm16); 761 break; 762 case XSTORMY16_OPERAND_IMM2 : 763 length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 2, 32, total_length, pc, & fields->f_imm2); 764 break; 765 case XSTORMY16_OPERAND_IMM3 : 766 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_imm3); 767 break; 768 case XSTORMY16_OPERAND_IMM3B : 769 length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_imm3b); 770 break; 771 case XSTORMY16_OPERAND_IMM4 : 772 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_imm4); 773 break; 774 case XSTORMY16_OPERAND_IMM8 : 775 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8); 776 break; 777 case XSTORMY16_OPERAND_IMM8SMALL : 778 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8); 779 break; 780 case XSTORMY16_OPERAND_LMEM8 : 781 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & fields->f_lmem8); 782 break; 783 case XSTORMY16_OPERAND_REL12 : 784 { 785 long value; 786 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, pc, & value); 787 value = ((value) + (((pc) + (4)))); 788 fields->f_rel12 = value; 789 } 790 break; 791 case XSTORMY16_OPERAND_REL12A : 792 { 793 long value; 794 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, pc, & value); 795 value = ((((value) << (1))) + (((pc) + (2)))); 796 fields->f_rel12a = value; 797 } 798 break; 799 case XSTORMY16_OPERAND_REL8_2 : 800 { 801 long value; 802 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value); 803 value = ((value) + (((pc) + (2)))); 804 fields->f_rel8_2 = value; 805 } 806 break; 807 case XSTORMY16_OPERAND_REL8_4 : 808 { 809 long value; 810 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value); 811 value = ((value) + (((pc) + (4)))); 812 fields->f_rel8_4 = value; 813 } 814 break; 815 case XSTORMY16_OPERAND_WS2 : 816 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 1, 32, total_length, pc, & fields->f_op2m); 817 break; 818 819 default : 820 /* xgettext:c-format */ 821 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"), 822 opindex); 823 abort (); 824 } 825 826 return length; 827 } 828 829 cgen_insert_fn * const xstormy16_cgen_insert_handlers[] = 830 { 831 insert_insn_normal, 832 }; 833 834 cgen_extract_fn * const xstormy16_cgen_extract_handlers[] = 835 { 836 extract_insn_normal, 837 }; 838 839 int xstormy16_cgen_get_int_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *); 840 bfd_vma xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *); 841 842 /* Getting values from cgen_fields is handled by a collection of functions. 843 They are distinguished by the type of the VALUE argument they return. 844 TODO: floating point, inlining support, remove cases where result type 845 not appropriate. */ 846 847 int 848 xstormy16_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 849 int opindex, 850 const CGEN_FIELDS * fields) 851 { 852 int value; 853 854 switch (opindex) 855 { 856 case XSTORMY16_OPERAND_RB : 857 value = fields->f_Rb; 858 break; 859 case XSTORMY16_OPERAND_RBJ : 860 value = fields->f_Rbj; 861 break; 862 case XSTORMY16_OPERAND_RD : 863 value = fields->f_Rd; 864 break; 865 case XSTORMY16_OPERAND_RDM : 866 value = fields->f_Rdm; 867 break; 868 case XSTORMY16_OPERAND_RM : 869 value = fields->f_Rm; 870 break; 871 case XSTORMY16_OPERAND_RS : 872 value = fields->f_Rs; 873 break; 874 case XSTORMY16_OPERAND_ABS24 : 875 value = fields->f_abs24; 876 break; 877 case XSTORMY16_OPERAND_BCOND2 : 878 value = fields->f_op2; 879 break; 880 case XSTORMY16_OPERAND_BCOND5 : 881 value = fields->f_op5; 882 break; 883 case XSTORMY16_OPERAND_HMEM8 : 884 value = fields->f_hmem8; 885 break; 886 case XSTORMY16_OPERAND_IMM12 : 887 value = fields->f_imm12; 888 break; 889 case XSTORMY16_OPERAND_IMM16 : 890 value = fields->f_imm16; 891 break; 892 case XSTORMY16_OPERAND_IMM2 : 893 value = fields->f_imm2; 894 break; 895 case XSTORMY16_OPERAND_IMM3 : 896 value = fields->f_imm3; 897 break; 898 case XSTORMY16_OPERAND_IMM3B : 899 value = fields->f_imm3b; 900 break; 901 case XSTORMY16_OPERAND_IMM4 : 902 value = fields->f_imm4; 903 break; 904 case XSTORMY16_OPERAND_IMM8 : 905 value = fields->f_imm8; 906 break; 907 case XSTORMY16_OPERAND_IMM8SMALL : 908 value = fields->f_imm8; 909 break; 910 case XSTORMY16_OPERAND_LMEM8 : 911 value = fields->f_lmem8; 912 break; 913 case XSTORMY16_OPERAND_REL12 : 914 value = fields->f_rel12; 915 break; 916 case XSTORMY16_OPERAND_REL12A : 917 value = fields->f_rel12a; 918 break; 919 case XSTORMY16_OPERAND_REL8_2 : 920 value = fields->f_rel8_2; 921 break; 922 case XSTORMY16_OPERAND_REL8_4 : 923 value = fields->f_rel8_4; 924 break; 925 case XSTORMY16_OPERAND_WS2 : 926 value = fields->f_op2m; 927 break; 928 929 default : 930 /* xgettext:c-format */ 931 fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"), 932 opindex); 933 abort (); 934 } 935 936 return value; 937 } 938 939 bfd_vma 940 xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 941 int opindex, 942 const CGEN_FIELDS * fields) 943 { 944 bfd_vma value; 945 946 switch (opindex) 947 { 948 case XSTORMY16_OPERAND_RB : 949 value = fields->f_Rb; 950 break; 951 case XSTORMY16_OPERAND_RBJ : 952 value = fields->f_Rbj; 953 break; 954 case XSTORMY16_OPERAND_RD : 955 value = fields->f_Rd; 956 break; 957 case XSTORMY16_OPERAND_RDM : 958 value = fields->f_Rdm; 959 break; 960 case XSTORMY16_OPERAND_RM : 961 value = fields->f_Rm; 962 break; 963 case XSTORMY16_OPERAND_RS : 964 value = fields->f_Rs; 965 break; 966 case XSTORMY16_OPERAND_ABS24 : 967 value = fields->f_abs24; 968 break; 969 case XSTORMY16_OPERAND_BCOND2 : 970 value = fields->f_op2; 971 break; 972 case XSTORMY16_OPERAND_BCOND5 : 973 value = fields->f_op5; 974 break; 975 case XSTORMY16_OPERAND_HMEM8 : 976 value = fields->f_hmem8; 977 break; 978 case XSTORMY16_OPERAND_IMM12 : 979 value = fields->f_imm12; 980 break; 981 case XSTORMY16_OPERAND_IMM16 : 982 value = fields->f_imm16; 983 break; 984 case XSTORMY16_OPERAND_IMM2 : 985 value = fields->f_imm2; 986 break; 987 case XSTORMY16_OPERAND_IMM3 : 988 value = fields->f_imm3; 989 break; 990 case XSTORMY16_OPERAND_IMM3B : 991 value = fields->f_imm3b; 992 break; 993 case XSTORMY16_OPERAND_IMM4 : 994 value = fields->f_imm4; 995 break; 996 case XSTORMY16_OPERAND_IMM8 : 997 value = fields->f_imm8; 998 break; 999 case XSTORMY16_OPERAND_IMM8SMALL : 1000 value = fields->f_imm8; 1001 break; 1002 case XSTORMY16_OPERAND_LMEM8 : 1003 value = fields->f_lmem8; 1004 break; 1005 case XSTORMY16_OPERAND_REL12 : 1006 value = fields->f_rel12; 1007 break; 1008 case XSTORMY16_OPERAND_REL12A : 1009 value = fields->f_rel12a; 1010 break; 1011 case XSTORMY16_OPERAND_REL8_2 : 1012 value = fields->f_rel8_2; 1013 break; 1014 case XSTORMY16_OPERAND_REL8_4 : 1015 value = fields->f_rel8_4; 1016 break; 1017 case XSTORMY16_OPERAND_WS2 : 1018 value = fields->f_op2m; 1019 break; 1020 1021 default : 1022 /* xgettext:c-format */ 1023 fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"), 1024 opindex); 1025 abort (); 1026 } 1027 1028 return value; 1029 } 1030 1031 void xstormy16_cgen_set_int_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, int); 1032 void xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma); 1033 1034 /* Stuffing values in cgen_fields is handled by a collection of functions. 1035 They are distinguished by the type of the VALUE argument they accept. 1036 TODO: floating point, inlining support, remove cases where argument type 1037 not appropriate. */ 1038 1039 void 1040 xstormy16_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1041 int opindex, 1042 CGEN_FIELDS * fields, 1043 int value) 1044 { 1045 switch (opindex) 1046 { 1047 case XSTORMY16_OPERAND_RB : 1048 fields->f_Rb = value; 1049 break; 1050 case XSTORMY16_OPERAND_RBJ : 1051 fields->f_Rbj = value; 1052 break; 1053 case XSTORMY16_OPERAND_RD : 1054 fields->f_Rd = value; 1055 break; 1056 case XSTORMY16_OPERAND_RDM : 1057 fields->f_Rdm = value; 1058 break; 1059 case XSTORMY16_OPERAND_RM : 1060 fields->f_Rm = value; 1061 break; 1062 case XSTORMY16_OPERAND_RS : 1063 fields->f_Rs = value; 1064 break; 1065 case XSTORMY16_OPERAND_ABS24 : 1066 fields->f_abs24 = value; 1067 break; 1068 case XSTORMY16_OPERAND_BCOND2 : 1069 fields->f_op2 = value; 1070 break; 1071 case XSTORMY16_OPERAND_BCOND5 : 1072 fields->f_op5 = value; 1073 break; 1074 case XSTORMY16_OPERAND_HMEM8 : 1075 fields->f_hmem8 = value; 1076 break; 1077 case XSTORMY16_OPERAND_IMM12 : 1078 fields->f_imm12 = value; 1079 break; 1080 case XSTORMY16_OPERAND_IMM16 : 1081 fields->f_imm16 = value; 1082 break; 1083 case XSTORMY16_OPERAND_IMM2 : 1084 fields->f_imm2 = value; 1085 break; 1086 case XSTORMY16_OPERAND_IMM3 : 1087 fields->f_imm3 = value; 1088 break; 1089 case XSTORMY16_OPERAND_IMM3B : 1090 fields->f_imm3b = value; 1091 break; 1092 case XSTORMY16_OPERAND_IMM4 : 1093 fields->f_imm4 = value; 1094 break; 1095 case XSTORMY16_OPERAND_IMM8 : 1096 fields->f_imm8 = value; 1097 break; 1098 case XSTORMY16_OPERAND_IMM8SMALL : 1099 fields->f_imm8 = value; 1100 break; 1101 case XSTORMY16_OPERAND_LMEM8 : 1102 fields->f_lmem8 = value; 1103 break; 1104 case XSTORMY16_OPERAND_REL12 : 1105 fields->f_rel12 = value; 1106 break; 1107 case XSTORMY16_OPERAND_REL12A : 1108 fields->f_rel12a = value; 1109 break; 1110 case XSTORMY16_OPERAND_REL8_2 : 1111 fields->f_rel8_2 = value; 1112 break; 1113 case XSTORMY16_OPERAND_REL8_4 : 1114 fields->f_rel8_4 = value; 1115 break; 1116 case XSTORMY16_OPERAND_WS2 : 1117 fields->f_op2m = value; 1118 break; 1119 1120 default : 1121 /* xgettext:c-format */ 1122 fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"), 1123 opindex); 1124 abort (); 1125 } 1126 } 1127 1128 void 1129 xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 1130 int opindex, 1131 CGEN_FIELDS * fields, 1132 bfd_vma value) 1133 { 1134 switch (opindex) 1135 { 1136 case XSTORMY16_OPERAND_RB : 1137 fields->f_Rb = value; 1138 break; 1139 case XSTORMY16_OPERAND_RBJ : 1140 fields->f_Rbj = value; 1141 break; 1142 case XSTORMY16_OPERAND_RD : 1143 fields->f_Rd = value; 1144 break; 1145 case XSTORMY16_OPERAND_RDM : 1146 fields->f_Rdm = value; 1147 break; 1148 case XSTORMY16_OPERAND_RM : 1149 fields->f_Rm = value; 1150 break; 1151 case XSTORMY16_OPERAND_RS : 1152 fields->f_Rs = value; 1153 break; 1154 case XSTORMY16_OPERAND_ABS24 : 1155 fields->f_abs24 = value; 1156 break; 1157 case XSTORMY16_OPERAND_BCOND2 : 1158 fields->f_op2 = value; 1159 break; 1160 case XSTORMY16_OPERAND_BCOND5 : 1161 fields->f_op5 = value; 1162 break; 1163 case XSTORMY16_OPERAND_HMEM8 : 1164 fields->f_hmem8 = value; 1165 break; 1166 case XSTORMY16_OPERAND_IMM12 : 1167 fields->f_imm12 = value; 1168 break; 1169 case XSTORMY16_OPERAND_IMM16 : 1170 fields->f_imm16 = value; 1171 break; 1172 case XSTORMY16_OPERAND_IMM2 : 1173 fields->f_imm2 = value; 1174 break; 1175 case XSTORMY16_OPERAND_IMM3 : 1176 fields->f_imm3 = value; 1177 break; 1178 case XSTORMY16_OPERAND_IMM3B : 1179 fields->f_imm3b = value; 1180 break; 1181 case XSTORMY16_OPERAND_IMM4 : 1182 fields->f_imm4 = value; 1183 break; 1184 case XSTORMY16_OPERAND_IMM8 : 1185 fields->f_imm8 = value; 1186 break; 1187 case XSTORMY16_OPERAND_IMM8SMALL : 1188 fields->f_imm8 = value; 1189 break; 1190 case XSTORMY16_OPERAND_LMEM8 : 1191 fields->f_lmem8 = value; 1192 break; 1193 case XSTORMY16_OPERAND_REL12 : 1194 fields->f_rel12 = value; 1195 break; 1196 case XSTORMY16_OPERAND_REL12A : 1197 fields->f_rel12a = value; 1198 break; 1199 case XSTORMY16_OPERAND_REL8_2 : 1200 fields->f_rel8_2 = value; 1201 break; 1202 case XSTORMY16_OPERAND_REL8_4 : 1203 fields->f_rel8_4 = value; 1204 break; 1205 case XSTORMY16_OPERAND_WS2 : 1206 fields->f_op2m = value; 1207 break; 1208 1209 default : 1210 /* xgettext:c-format */ 1211 fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"), 1212 opindex); 1213 abort (); 1214 } 1215 } 1216 1217 /* Function to call before using the instruction builder tables. */ 1218 1219 void 1220 xstormy16_cgen_init_ibld_table (CGEN_CPU_DESC cd) 1221 { 1222 cd->insert_handlers = & xstormy16_cgen_insert_handlers[0]; 1223 cd->extract_handlers = & xstormy16_cgen_extract_handlers[0]; 1224 1225 cd->insert_operand = xstormy16_cgen_insert_operand; 1226 cd->extract_operand = xstormy16_cgen_extract_operand; 1227 1228 cd->get_int_operand = xstormy16_cgen_get_int_operand; 1229 cd->set_int_operand = xstormy16_cgen_set_int_operand; 1230 cd->get_vma_operand = xstormy16_cgen_get_vma_operand; 1231 cd->set_vma_operand = xstormy16_cgen_set_vma_operand; 1232 } 1233