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