1 /* Assemble V850 instructions. 2 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007 3 Free Software Foundation, Inc. 4 5 This file is part of the GNU opcodes library. 6 7 This library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 It is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include "sysdep.h" 23 #include "opcode/v850.h" 24 #include <stdio.h> 25 #include "opintl.h" 26 27 /* Regular opcodes. */ 28 #define OP(x) ((x & 0x3f) << 5) 29 #define OP_MASK OP (0x3f) 30 31 /* Conditional branch opcodes. */ 32 #define BOP(x) ((0x0b << 7) | (x & 0x0f)) 33 #define BOP_MASK ((0x0f << 7) | 0x0f) 34 35 /* One-word opcodes. */ 36 #define one(x) ((unsigned int) (x)) 37 38 /* Two-word opcodes. */ 39 #define two(x,y) ((unsigned int) (x) | ((unsigned int) (y) << 16)) 40 41 /* The functions used to insert and extract complicated operands. */ 42 43 /* Note: There is a conspiracy between these functions and 44 v850_insert_operand() in gas/config/tc-v850.c. Error messages 45 containing the string 'out of range' will be ignored unless a 46 specific command line option is given to GAS. */ 47 48 static const char * not_valid = N_ ("displacement value is not in range and is not aligned"); 49 static const char * out_of_range = N_ ("displacement value is out of range"); 50 static const char * not_aligned = N_ ("displacement value is not aligned"); 51 52 static const char * immediate_out_of_range = N_ ("immediate value is out of range"); 53 54 static unsigned long 55 insert_d9 (unsigned long insn, long value, const char ** errmsg) 56 { 57 if (value > 0xff || value < -0x100) 58 { 59 if ((value % 2) != 0) 60 * errmsg = _("branch value not in range and to odd offset"); 61 else 62 * errmsg = _("branch value out of range"); 63 } 64 else if ((value % 2) != 0) 65 * errmsg = _("branch to odd offset"); 66 67 return insn | ((value & 0x1f0) << 7) | ((value & 0x0e) << 3); 68 } 69 70 static unsigned long 71 extract_d9 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 72 { 73 unsigned long ret = ((insn & 0xf800) >> 7) | ((insn & 0x0070) >> 3); 74 75 if ((insn & 0x8000) != 0) 76 ret -= 0x0200; 77 78 return ret; 79 } 80 81 static unsigned long 82 insert_d22 (unsigned long insn, long value, const char ** errmsg) 83 { 84 if (value > 0x1fffff || value < -0x200000) 85 { 86 if ((value % 2) != 0) 87 * errmsg = _("branch value not in range and to an odd offset"); 88 else 89 * errmsg = _("branch value out of range"); 90 } 91 else if ((value % 2) != 0) 92 * errmsg = _("branch to odd offset"); 93 94 return insn | ((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16); 95 } 96 97 static unsigned long 98 extract_d22 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 99 { 100 signed long ret = ((insn & 0xfffe0000) >> 16) | ((insn & 0x3f) << 16); 101 102 return (unsigned long) ((ret << 10) >> 10); 103 } 104 105 static unsigned long 106 insert_d16_15 (unsigned long insn, long value, const char ** errmsg) 107 { 108 if (value > 0x7fff || value < -0x8000) 109 { 110 if ((value % 2) != 0) 111 * errmsg = _(not_valid); 112 else 113 * errmsg = _(out_of_range); 114 } 115 else if ((value % 2) != 0) 116 * errmsg = _(not_aligned); 117 118 return insn | ((value & 0xfffe) << 16); 119 } 120 121 static unsigned long 122 extract_d16_15 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 123 { 124 signed long ret = (insn & 0xfffe0000); 125 126 return ret >> 16; 127 } 128 129 static unsigned long 130 insert_d8_7 (unsigned long insn, long value, const char ** errmsg) 131 { 132 if (value > 0xff || value < 0) 133 { 134 if ((value % 2) != 0) 135 * errmsg = _(not_valid); 136 else 137 * errmsg = _(out_of_range); 138 } 139 else if ((value % 2) != 0) 140 * errmsg = _(not_aligned); 141 142 value >>= 1; 143 144 return insn | (value & 0x7f); 145 } 146 147 static unsigned long 148 extract_d8_7 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 149 { 150 unsigned long ret = (insn & 0x7f); 151 152 return ret << 1; 153 } 154 155 static unsigned long 156 insert_d8_6 (unsigned long insn, long value, const char ** errmsg) 157 { 158 if (value > 0xff || value < 0) 159 { 160 if ((value % 4) != 0) 161 *errmsg = _(not_valid); 162 else 163 * errmsg = _(out_of_range); 164 } 165 else if ((value % 4) != 0) 166 * errmsg = _(not_aligned); 167 168 value >>= 1; 169 170 return insn | (value & 0x7e); 171 } 172 173 static unsigned long 174 extract_d8_6 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 175 { 176 unsigned long ret = (insn & 0x7e); 177 178 return ret << 1; 179 } 180 181 static unsigned long 182 insert_d5_4 (unsigned long insn, long value, const char ** errmsg) 183 { 184 if (value > 0x1f || value < 0) 185 { 186 if (value & 1) 187 * errmsg = _(not_valid); 188 else 189 *errmsg = _(out_of_range); 190 } 191 else if (value & 1) 192 * errmsg = _(not_aligned); 193 194 value >>= 1; 195 196 return insn | (value & 0x0f); 197 } 198 199 static unsigned long 200 extract_d5_4 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 201 { 202 unsigned long ret = (insn & 0x0f); 203 204 return ret << 1; 205 } 206 207 static unsigned long 208 insert_d16_16 (unsigned long insn, signed long value, const char ** errmsg) 209 { 210 if (value > 0x7fff || value < -0x8000) 211 * errmsg = _(out_of_range); 212 213 return insn | ((value & 0xfffe) << 16) | ((value & 1) << 5); 214 } 215 216 static unsigned long 217 extract_d16_16 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 218 { 219 signed long ret = insn & 0xfffe0000; 220 221 ret >>= 16; 222 223 ret |= ((insn & 0x20) >> 5); 224 225 return ret; 226 } 227 228 static unsigned long 229 insert_i9 (unsigned long insn, signed long value, const char ** errmsg) 230 { 231 if (value > 0xff || value < -0x100) 232 * errmsg = _(immediate_out_of_range); 233 234 return insn | ((value & 0x1e0) << 13) | (value & 0x1f); 235 } 236 237 static unsigned long 238 extract_i9 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 239 { 240 signed long ret = insn & 0x003c0000; 241 242 ret <<= 10; 243 ret >>= 23; 244 245 ret |= (insn & 0x1f); 246 247 return ret; 248 } 249 250 static unsigned long 251 insert_u9 (unsigned long insn, long v, const char ** errmsg) 252 { 253 unsigned long value = (unsigned long) v; 254 255 if (value > 0x1ff) 256 * errmsg = _(immediate_out_of_range); 257 258 return insn | ((value & 0x1e0) << 13) | (value & 0x1f); 259 } 260 261 static unsigned long 262 extract_u9 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 263 { 264 unsigned long ret = insn & 0x003c0000; 265 266 ret >>= 13; 267 268 ret |= (insn & 0x1f); 269 270 return ret; 271 } 272 273 static unsigned long 274 insert_spe (unsigned long insn, long v, const char ** errmsg) 275 { 276 unsigned long value = (unsigned long) v; 277 278 if (value != 3) 279 * errmsg = _("invalid register for stack adjustment"); 280 281 return insn & (~ 0x180000); 282 } 283 284 static unsigned long 285 extract_spe (unsigned long insn ATTRIBUTE_UNUSED, 286 int * invalid ATTRIBUTE_UNUSED) 287 { 288 return 3; 289 } 290 291 static unsigned long 292 insert_i5div (unsigned long insn, long v, const char ** errmsg) 293 { 294 unsigned long value = (unsigned long) v; 295 296 if (value > 0x1ff) 297 { 298 if (value & 1) 299 * errmsg = _("immediate value not in range and not even"); 300 else 301 * errmsg = _(immediate_out_of_range); 302 } 303 else if (value & 1) 304 * errmsg = _("immediate value must be even"); 305 306 value = 32 - value; 307 308 return insn | ((value & 0x1e) << 17); 309 } 310 311 static unsigned long 312 extract_i5div (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) 313 { 314 unsigned long ret = insn & 0x3c0000; 315 316 ret >>= 17; 317 318 ret = 32 - ret; 319 320 return ret; 321 } 322 323 324 /* Warning: code in gas/config/tc-v850.c examines the contents of this array. 325 If you change any of the values here, be sure to look for side effects in 326 that code. */ 327 const struct v850_operand v850_operands[] = 328 { 329 #define UNUSED 0 330 { 0, 0, NULL, NULL, 0 }, 331 332 /* The R1 field in a format 1, 6, 7, or 9 insn. */ 333 #define R1 (UNUSED + 1) 334 { 5, 0, NULL, NULL, V850_OPERAND_REG }, 335 336 /* As above, but register 0 is not allowed. */ 337 #define R1_NOTR0 (R1 + 1) 338 { 5, 0, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 }, 339 340 /* The R2 field in a format 1, 2, 4, 5, 6, 7, 9 insn. */ 341 #define R2 (R1_NOTR0 + 1) 342 { 5, 11, NULL, NULL, V850_OPERAND_REG }, 343 344 /* As above, but register 0 is not allowed. */ 345 #define R2_NOTR0 (R2 + 1) 346 { 5, 11, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 }, 347 348 /* The imm5 field in a format 2 insn. */ 349 #define I5 (R2_NOTR0 + 1) 350 { 5, 0, NULL, NULL, V850_OPERAND_SIGNED }, 351 352 /* The unsigned imm5 field in a format 2 insn. */ 353 #define I5U (I5 + 1) 354 { 5, 0, NULL, NULL, 0 }, 355 356 /* The imm16 field in a format 6 insn. */ 357 #define I16 (I5U + 1) 358 { 16, 16, NULL, NULL, V850_OPERAND_SIGNED }, 359 360 /* The signed disp7 field in a format 4 insn. */ 361 #define D7 (I16 + 1) 362 { 7, 0, NULL, NULL, 0}, 363 364 /* The disp16 field in a format 6 insn. */ 365 #define D16_15 (D7 + 1) 366 { 15, 17, insert_d16_15, extract_d16_15, V850_OPERAND_SIGNED }, 367 368 /* The 3 bit immediate field in format 8 insn. */ 369 #define B3 (D16_15 + 1) 370 { 3, 11, NULL, NULL, 0 }, 371 372 /* The 4 bit condition code in a setf instruction */ 373 #define CCCC (B3 + 1) 374 { 4, 0, NULL, NULL, V850_OPERAND_CC }, 375 376 /* The unsigned DISP8 field in a format 4 insn. */ 377 #define D8_7 (CCCC + 1) 378 { 7, 0, insert_d8_7, extract_d8_7, 0 }, 379 380 /* The unsigned DISP8 field in a format 4 insn. */ 381 #define D8_6 (D8_7 + 1) 382 { 6, 1, insert_d8_6, extract_d8_6, 0 }, 383 384 /* System register operands. */ 385 #define SR1 (D8_6 + 1) 386 { 5, 0, NULL, NULL, V850_OPERAND_SRG }, 387 388 /* EP Register. */ 389 #define EP (SR1 + 1) 390 { 0, 0, NULL, NULL, V850_OPERAND_EP }, 391 392 /* The imm16 field (unsigned) in a format 6 insn. */ 393 #define I16U (EP + 1) 394 { 16, 16, NULL, NULL, 0}, 395 396 /* The R2 field as a system register. */ 397 #define SR2 (I16U + 1) 398 { 5, 11, NULL, NULL, V850_OPERAND_SRG }, 399 400 /* The disp16 field in a format 8 insn. */ 401 #define D16 (SR2 + 1) 402 { 16, 16, NULL, NULL, V850_OPERAND_SIGNED }, 403 404 /* The DISP9 field in a format 3 insn, relaxable. */ 405 #define D9_RELAX (D16 + 1) 406 { 9, 0, insert_d9, extract_d9, V850_OPERAND_RELAX | V850_OPERAND_SIGNED | V850_OPERAND_DISP }, 407 408 /* The DISP22 field in a format 4 insn, relaxable. 409 This _must_ follow D9_RELAX; the assembler assumes that the longer 410 version immediately follows the shorter version for relaxing. */ 411 #define D22 (D9_RELAX + 1) 412 { 22, 0, insert_d22, extract_d22, V850_OPERAND_SIGNED | V850_OPERAND_DISP }, 413 414 /* The signed disp4 field in a format 4 insn. */ 415 #define D4 (D22 + 1) 416 { 4, 0, NULL, NULL, 0}, 417 418 /* The unsigned disp5 field in a format 4 insn. */ 419 #define D5_4 (D4 + 1) 420 { 4, 0, insert_d5_4, extract_d5_4, 0 }, 421 422 /* The disp16 field in an format 7 unsigned byte load insn. */ 423 #define D16_16 (D5_4 + 1) 424 { -1, 0xfffe0020, insert_d16_16, extract_d16_16, 0 }, 425 426 /* Third register in conditional moves. */ 427 #define R3 (D16_16 + 1) 428 { 5, 27, NULL, NULL, V850_OPERAND_REG }, 429 430 /* Condition code in conditional moves. */ 431 #define MOVCC (R3 + 1) 432 { 4, 17, NULL, NULL, V850_OPERAND_CC }, 433 434 /* The imm9 field in a multiply word. */ 435 #define I9 (MOVCC + 1) 436 { 9, 0, insert_i9, extract_i9, V850_OPERAND_SIGNED }, 437 438 /* The unsigned imm9 field in a multiply word. */ 439 #define U9 (I9 + 1) 440 { 9, 0, insert_u9, extract_u9, 0 }, 441 442 /* A list of registers in a prepare/dispose instruction. */ 443 #define LIST12 (U9 + 1) 444 { -1, 0xffe00001, NULL, NULL, V850E_PUSH_POP }, 445 446 /* The IMM6 field in a call instruction. */ 447 #define I6 (LIST12 + 1) 448 { 6, 0, NULL, NULL, 0 }, 449 450 /* The 16 bit immediate following a 32 bit instruction. */ 451 #define IMM16 (I6 + 1) 452 { 16, 16, NULL, NULL, V850_OPERAND_SIGNED | V850E_IMMEDIATE16 }, 453 454 /* The 32 bit immediate following a 32 bit instruction. */ 455 #define IMM32 (IMM16 + 1) 456 { 0, 0, NULL, NULL, V850E_IMMEDIATE32 }, 457 458 /* The imm5 field in a push/pop instruction. */ 459 #define IMM5 (IMM32 + 1) 460 { 5, 1, NULL, NULL, 0 }, 461 462 /* Reg2 in dispose instruction. */ 463 #define R2DISPOSE (IMM5 + 1) 464 { 5, 16, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 }, 465 466 /* Stack pointer in prepare instruction. */ 467 #define SP (R2DISPOSE + 1) 468 { 2, 19, insert_spe, extract_spe, V850_OPERAND_REG }, 469 470 /* The IMM5 field in a divide N step instruction. */ 471 #define I5DIV (SP + 1) 472 { 9, 0, insert_i5div, extract_i5div, V850_OPERAND_SIGNED }, 473 474 /* The list of registers in a PUSHMH/POPMH instruction. */ 475 #define LIST18_H (I5DIV + 1) 476 { -1, 0xfff8000f, NULL, NULL, V850E_PUSH_POP }, 477 478 /* The list of registers in a PUSHML/POPML instruction. */ 479 #define LIST18_L (LIST18_H + 1) 480 /* The setting of the 4th bit is a flag to disassmble() in v850-dis.c. */ 481 { -1, 0xfff8001f, NULL, NULL, V850E_PUSH_POP }, 482 }; 483 484 485 /* Reg - Reg instruction format (Format I). */ 486 #define IF1 {R1, R2} 487 488 /* Imm - Reg instruction format (Format II). */ 489 #define IF2 {I5, R2} 490 491 /* Conditional branch instruction format (Format III). */ 492 #define IF3 {D9_RELAX} 493 494 /* 3 operand instruction (Format VI). */ 495 #define IF6 {I16, R1, R2} 496 497 /* 3 operand instruction (Format VI). */ 498 #define IF6U {I16U, R1, R2} 499 500 501 502 /* The opcode table. 503 504 The format of the opcode table is: 505 506 NAME OPCODE MASK { OPERANDS } MEMOP PROCESSOR 507 508 NAME is the name of the instruction. 509 OPCODE is the instruction opcode. 510 MASK is the opcode mask; this is used to tell the disassembler 511 which bits in the actual opcode must match OPCODE. 512 OPERANDS is the list of operands. 513 MEMOP specifies which operand (if any) is a memory operand. 514 PROCESSORS specifies which CPU(s) support the opcode. 515 516 The disassembler reads the table in order and prints the first 517 instruction which matches, so this table is sorted to put more 518 specific instructions before more general instructions. It is also 519 sorted by major opcode. 520 521 The table is also sorted by name. This is used by the assembler. 522 When parsing an instruction the assembler finds the first occurance 523 of the name of the instruciton in this table and then attempts to 524 match the instruction's arguments with description of the operands 525 associated with the entry it has just found in this table. If the 526 match fails the assembler looks at the next entry in this table. 527 If that entry has the same name as the previous entry, then it 528 tries to match the instruction against that entry and so on. This 529 is how the assembler copes with multiple, different formats of the 530 same instruction. */ 531 532 const struct v850_opcode v850_opcodes[] = 533 { 534 { "breakpoint", 0xffff, 0xffff, {UNUSED}, 0, PROCESSOR_ALL }, 535 { "dbtrap", one (0xf840), one (0xffff), {UNUSED}, 0, PROCESSOR_V850E1 }, 536 537 { "jmp", one (0x0060), one (0xffe0), {R1}, 1, PROCESSOR_ALL }, 538 539 /* Load/store instructions. */ 540 { "sld.bu", one (0x0060), one (0x07f0), {D4, EP, R2_NOTR0}, 1, PROCESSOR_V850E1 }, 541 { "sld.bu", one (0x0060), one (0x07f0), {D4, EP, R2_NOTR0}, 1, PROCESSOR_V850E }, 542 543 { "sld.hu", one (0x0070), one (0x07f0), {D5_4, EP, R2_NOTR0}, 1, PROCESSOR_V850E1 }, 544 { "sld.hu", one (0x0070), one (0x07f0), {D5_4, EP, R2_NOTR0}, 1, PROCESSOR_V850E }, 545 546 { "sld.b", one (0x0300), one (0x0780), {D7, EP, R2}, 1, PROCESSOR_V850E1 }, 547 { "sld.b", one (0x0300), one (0x0780), {D7, EP, R2}, 1, PROCESSOR_V850E }, 548 { "sld.b", one (0x0300), one (0x0780), {D7, EP, R2}, 1, PROCESSOR_V850 }, 549 550 { "sld.h", one (0x0400), one (0x0780), {D8_7, EP, R2}, 1, PROCESSOR_V850E1 }, 551 { "sld.h", one (0x0400), one (0x0780), {D8_7, EP, R2}, 1, PROCESSOR_V850E }, 552 { "sld.h", one (0x0400), one (0x0780), {D8_7, EP, R2}, 1, PROCESSOR_V850 }, 553 { "sld.w", one (0x0500), one (0x0781), {D8_6, EP, R2}, 1, PROCESSOR_ALL }, 554 { "sst.b", one (0x0380), one (0x0780), {R2, D7, EP}, 2, PROCESSOR_ALL }, 555 { "sst.h", one (0x0480), one (0x0780), {R2, D8_7, EP}, 2, PROCESSOR_ALL }, 556 { "sst.w", one (0x0501), one (0x0781), {R2, D8_6, EP}, 2, PROCESSOR_ALL }, 557 558 { "prepare", two (0x0780, 0x0003), two (0xffc0, 0x001f), {LIST12, IMM5, SP}, 0, PROCESSOR_NOT_V850 }, 559 { "prepare", two (0x0780, 0x000b), two (0xffc0, 0x001f), {LIST12, IMM5, IMM16}, 0, PROCESSOR_NOT_V850 }, 560 { "prepare", two (0x0780, 0x0013), two (0xffc0, 0x001f), {LIST12, IMM5, IMM16}, 0, PROCESSOR_NOT_V850 }, 561 { "prepare", two (0x0780, 0x001b), two (0xffc0, 0x001f), {LIST12, IMM5, IMM32}, 0, PROCESSOR_NOT_V850 }, 562 { "prepare", two (0x0780, 0x0001), two (0xffc0, 0x001f), {LIST12, IMM5}, 0, PROCESSOR_NOT_V850 }, 563 { "dispose", one (0x0640), one (0xffc0), {IMM5, LIST12, R2DISPOSE},0, PROCESSOR_NOT_V850 }, 564 { "dispose", two (0x0640, 0x0000), two (0xffc0, 0x001f), {IMM5, LIST12}, 0, PROCESSOR_NOT_V850 }, 565 566 { "ld.b", two (0x0700, 0x0000), two (0x07e0, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL }, 567 { "ld.h", two (0x0720, 0x0000), two (0x07e0, 0x0001), {D16_15, R1, R2}, 1, PROCESSOR_ALL }, 568 { "ld.w", two (0x0720, 0x0001), two (0x07e0, 0x0001), {D16_15, R1, R2}, 1, PROCESSOR_ALL }, 569 { "ld.bu", two (0x0780, 0x0001), two (0x07c0, 0x0001), {D16_16, R1, R2_NOTR0}, 1, PROCESSOR_NOT_V850 }, 570 { "ld.hu", two (0x07e0, 0x0001), two (0x07e0, 0x0001), {D16_15, R1, R2_NOTR0}, 1, PROCESSOR_NOT_V850 }, 571 { "st.b", two (0x0740, 0x0000), two (0x07e0, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL }, 572 { "st.h", two (0x0760, 0x0000), two (0x07e0, 0x0001), {R2, D16_15, R1}, 2, PROCESSOR_ALL }, 573 { "st.w", two (0x0760, 0x0001), two (0x07e0, 0x0001), {R2, D16_15, R1}, 2, PROCESSOR_ALL }, 574 575 /* Byte swap/extend instructions. */ 576 { "zxb", one (0x0080), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, 577 { "zxh", one (0x00c0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, 578 { "sxb", one (0x00a0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, 579 { "sxh", one (0x00e0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, 580 { "bsh", two (0x07e0, 0x0342), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, 581 { "bsw", two (0x07e0, 0x0340), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, 582 { "hsw", two (0x07e0, 0x0344), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, 583 584 /* Jump table instructions. */ 585 { "switch", one (0x0040), one (0xffe0), {R1}, 1, PROCESSOR_NOT_V850 }, 586 { "callt", one (0x0200), one (0xffc0), {I6}, 0, PROCESSOR_NOT_V850 }, 587 { "ctret", two (0x07e0, 0x0144), two (0xffff, 0xffff), {0}, 0, PROCESSOR_NOT_V850 }, 588 589 /* Arithmetic operation instructions. */ 590 { "setf", two (0x07e0, 0x0000), two (0x07f0, 0xffff), {CCCC, R2}, 0, PROCESSOR_ALL }, 591 { "cmov", two (0x07e0, 0x0320), two (0x07e0, 0x07e1), {MOVCC, R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, 592 { "cmov", two (0x07e0, 0x0300), two (0x07e0, 0x07e1), {MOVCC, I5, R2, R3}, 0, PROCESSOR_NOT_V850 }, 593 594 { "mul", two (0x07e0, 0x0220), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, 595 { "mul", two (0x07e0, 0x0240), two (0x07e0, 0x07c3), {I9, R2, R3}, 0, PROCESSOR_NOT_V850 }, 596 { "mulu", two (0x07e0, 0x0222), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, 597 { "mulu", two (0x07e0, 0x0242), two (0x07e0, 0x07c3), {U9, R2, R3}, 0, PROCESSOR_NOT_V850 }, 598 599 { "div", two (0x07e0, 0x02c0), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, 600 { "divu", two (0x07e0, 0x02c2), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, 601 { "divhu", two (0x07e0, 0x0282), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, 602 { "divh", two (0x07e0, 0x0280), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, 603 { "divh", OP (0x02), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 604 605 { "nop", one (0x00), one (0xffff), {0}, 0, PROCESSOR_ALL }, 606 { "mov", OP (0x10), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, 607 { "mov", one (0x0620), one (0xffe0), {IMM32, R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, 608 { "mov", OP (0x00), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 609 { "movea", OP (0x31), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 610 { "movhi", OP (0x32), OP_MASK, {I16U, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 611 { "add", OP (0x0e), OP_MASK, IF1, 0, PROCESSOR_ALL }, 612 { "add", OP (0x12), OP_MASK, IF2, 0, PROCESSOR_ALL }, 613 { "addi", OP (0x30), OP_MASK, IF6, 0, PROCESSOR_ALL }, 614 { "sub", OP (0x0d), OP_MASK, IF1, 0, PROCESSOR_ALL }, 615 { "subr", OP (0x0c), OP_MASK, IF1, 0, PROCESSOR_ALL }, 616 { "mulh", OP (0x17), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, 617 { "mulh", OP (0x07), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 618 { "mulhi", OP (0x37), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 619 { "cmp", OP (0x0f), OP_MASK, IF1, 0, PROCESSOR_ALL }, 620 { "cmp", OP (0x13), OP_MASK, IF2, 0, PROCESSOR_ALL }, 621 622 /* Saturated operation instructions. */ 623 { "satadd", OP (0x11), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, 624 { "satadd", OP (0x06), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 625 { "satsub", OP (0x05), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 626 { "satsubi", OP (0x33), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 627 { "satsubr", OP (0x04), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, 628 629 /* Logical operation instructions. */ 630 { "tst", OP (0x0b), OP_MASK, IF1, 0, PROCESSOR_ALL }, 631 { "or", OP (0x08), OP_MASK, IF1, 0, PROCESSOR_ALL }, 632 { "ori", OP (0x34), OP_MASK, IF6U, 0, PROCESSOR_ALL }, 633 { "and", OP (0x0a), OP_MASK, IF1, 0, PROCESSOR_ALL }, 634 { "andi", OP (0x36), OP_MASK, IF6U, 0, PROCESSOR_ALL }, 635 { "xor", OP (0x09), OP_MASK, IF1, 0, PROCESSOR_ALL }, 636 { "xori", OP (0x35), OP_MASK, IF6U, 0, PROCESSOR_ALL }, 637 { "not", OP (0x01), OP_MASK, IF1, 0, PROCESSOR_ALL }, 638 { "sar", OP (0x15), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, 639 { "sar", two (0x07e0, 0x00a0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, 640 { "shl", OP (0x16), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, 641 { "shl", two (0x07e0, 0x00c0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, 642 { "shr", OP (0x14), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, 643 { "shr", two (0x07e0, 0x0080), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, 644 { "sasf", two (0x07e0, 0x0200), two (0x07f0, 0xffff), {CCCC, R2}, 0, PROCESSOR_NOT_V850 }, 645 646 /* Branch instructions. */ 647 /* Signed integer. */ 648 { "bgt", BOP (0xf), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 649 { "bge", BOP (0xe), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 650 { "blt", BOP (0x6), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 651 { "ble", BOP (0x7), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 652 /* Unsigned integer. */ 653 { "bh", BOP (0xb), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 654 { "bnh", BOP (0x3), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 655 { "bl", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 656 { "bnl", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 657 /* Common. */ 658 { "be", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 659 { "bne", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 660 /* Others. */ 661 { "bv", BOP (0x0), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 662 { "bnv", BOP (0x8), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 663 { "bn", BOP (0x4), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 664 { "bp", BOP (0xc), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 665 { "bc", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 666 { "bnc", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 667 { "bz", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 668 { "bnz", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 669 { "br", BOP (0x5), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 670 { "bsa", BOP (0xd), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 671 672 /* Branch macros. 673 674 We use the short form in the opcode/mask fields. The assembler 675 will twiddle bits as necessary if the long form is needed. */ 676 677 /* Signed integer. */ 678 { "jgt", BOP (0xf), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 679 { "jge", BOP (0xe), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 680 { "jlt", BOP (0x6), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 681 { "jle", BOP (0x7), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 682 /* Unsigned integer. */ 683 { "jh", BOP (0xb), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 684 { "jnh", BOP (0x3), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 685 { "jl", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 686 { "jnl", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 687 /* Common. */ 688 { "je", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 689 { "jne", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 690 /* Others. */ 691 { "jv", BOP (0x0), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 692 { "jnv", BOP (0x8), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 693 { "jn", BOP (0x4), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 694 { "jp", BOP (0xc), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 695 { "jc", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 696 { "jnc", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 697 { "jz", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 698 { "jnz", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 699 { "jsa", BOP (0xd), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 700 { "jbr", BOP (0x5), BOP_MASK, IF3, 0, PROCESSOR_ALL }, 701 702 { "jr", one (0x0780), two (0xffc0, 0x0001), {D22}, 0, PROCESSOR_ALL }, 703 { "jarl", one (0x0780), two (0x07c0, 0x0001), {D22, R2}, 0, PROCESSOR_ALL }, 704 705 /* Bit manipulation instructions. */ 706 { "set1", two (0x07c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL }, 707 { "set1", two (0x07e0, 0x00e0), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 }, 708 { "not1", two (0x47c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL }, 709 { "not1", two (0x07e0, 0x00e2), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 }, 710 { "clr1", two (0x87c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL }, 711 { "clr1", two (0x07e0, 0x00e4), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 }, 712 { "tst1", two (0xc7c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL }, 713 { "tst1", two (0x07e0, 0x00e6), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 }, 714 715 /* Special instructions. */ 716 { "di", two (0x07e0, 0x0160), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, 717 { "ei", two (0x87e0, 0x0160), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, 718 { "halt", two (0x07e0, 0x0120), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, 719 { "reti", two (0x07e0, 0x0140), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, 720 { "trap", two (0x07e0, 0x0100), two (0xffe0, 0xffff), {I5U}, 0, PROCESSOR_ALL }, 721 { "ldsr", two (0x07e0, 0x0020), two (0x07e0, 0xffff), {R1, SR2}, 0, PROCESSOR_ALL }, 722 { "stsr", two (0x07e0, 0x0040), two (0x07e0, 0xffff), {SR1, R2}, 0, PROCESSOR_ALL }, 723 { "dbret", two (0x07e0, 0x0146), two (0xffff, 0xffff), {UNUSED}, 0, PROCESSOR_V850E1 }, 724 { 0, 0, 0, {0}, 0, 0 }, 725 726 } ; 727 728 const int v850_num_opcodes = 729 sizeof (v850_opcodes) / sizeof (v850_opcodes[0]); 730