cr16-dis.c revision 214634
125537Sdfr/* Disassembler code for CR16. 225537Sdfr Copyright 2007 Free Software Foundation, Inc. 325537Sdfr Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com). 425537Sdfr 525537Sdfr This file is part of GAS, GDB and the GNU binutils. 625537Sdfr 725537Sdfr This program is free software; you can redistribute it and/or modify it under 825537Sdfr the terms of the GNU General Public License as published by the Free 925537Sdfr Software Foundation; either version 2, or (at your option) 1025537Sdfr any later version. 1125537Sdfr 1225537Sdfr This program is distributed in the hope that it will be useful, but WITHOUT 1325537Sdfr ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1425537Sdfr FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1525537Sdfr more details. 1625537Sdfr 1725537Sdfr You should have received a copy of the GNU General Public License 1825537Sdfr along with this program; if not, write to the Free Software Foundation, 1925537Sdfr Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2025537Sdfr 2125537Sdfr#include "dis-asm.h" 2225537Sdfr#include "sysdep.h" 2325537Sdfr#include "opcode/cr16.h" 2425537Sdfr#include "libiberty.h" 2525537Sdfr 2643084Speter/* String to print when opcode was not matched. */ 2725537Sdfr#define ILLEGAL "illegal" 2825537Sdfr /* Escape to 16-bit immediate. */ 2940159Speter#define ESCAPE_16_BIT 0xB 3040159Speter 3125537Sdfr/* Extract 'n_bits' from 'a' starting from offset 'offs'. */ 3225537Sdfr#define EXTRACT(a, offs, n_bits) \ 3325537Sdfr (n_bits == 32 ? (((a) >> (offs)) & 0xffffffffL) \ 3425537Sdfr : (((a) >> (offs)) & ((1 << (n_bits)) -1))) 3525537Sdfr 3625537Sdfr/* Set Bit Mask - a mask to set all bits starting from offset 'offs'. */ 3725537Sdfr#define SBM(offs) ((((1 << (32 - offs)) -1) << (offs))) 3825537Sdfr 3925537Sdfrtypedef unsigned long dwordU; 4040159Spetertypedef unsigned short wordU; 4125537Sdfr 4225537Sdfrtypedef struct 4331675Sdyson{ 4440159Speter dwordU val; 4540159Speter int nbits; 4640159Speter} parameter; 4740159Speter 4840159Speter/* Structure to map valid 'cinv' instruction options. */ 4925537Sdfr 5040961Spetertypedef struct 5140961Speter { 5240961Speter /* Cinv printed string. */ 5340961Speter char *istr; 5432153Sbde /* Value corresponding to the string. */ 5531324Sbde char *ostr; 5640906Speter } 5731324Sbdecinv_entry; 5825537Sdfr 5925537Sdfr/* CR16 'cinv' options mapping. */ 6025537Sdfrconst cinv_entry cr16_cinvs[] = 6125537Sdfr{ 6225537Sdfr {"cinv[i]", "cinv [i]"}, 6325537Sdfr {"cinv[i,u]", "cinv [i,u]"}, 6425537Sdfr {"cinv[d]", "cinv [d]"}, 6525537Sdfr {"cinv[d,u]", "cinv [d,u]"}, 6625537Sdfr {"cinv[d,i]", "cinv [d,i]"}, 6725537Sdfr {"cinv[d,i,u]", "cinv [d,i,u]"} 6825537Sdfr}; 6925537Sdfr 7025537Sdfr/* Number of valid 'cinv' instruction options. */ 7140159Speterstatic int NUMCINVS = ARRAY_SIZE (cr16_cinvs); 7225537Sdfr 7325537Sdfr/* Enum to distinguish different registers argument types. */ 7425537Sdfrtypedef enum REG_ARG_TYPE 7525537Sdfr { 7625537Sdfr /* General purpose register (r<N>). */ 7725537Sdfr REG_ARG = 0, 7825537Sdfr /*Processor register */ 7925537Sdfr P_ARG, 8025537Sdfr } 8125537SdfrREG_ARG_TYPE; 8240395Speter 8325537Sdfr/* Current opcode table entry we're disassembling. */ 8425537Sdfrconst inst *instruction; 8525537Sdfr/* Current instruction we're disassembling. */ 8625537Sdfrins currInsn; 8725537Sdfr/* The current instruction is read into 3 consecutive words. */ 8825537SdfrwordU words[3]; 8925537Sdfr/* Contains all words in appropriate order. */ 9025537SdfrULONGLONG allWords; 9125537Sdfr/* Holds the current processed argument number. */ 9225537Sdfrint processing_argument_number; 9325537Sdfr/* Nonzero means a IMM4 instruction. */ 9425537Sdfrint imm4flag; 9525537Sdfr/* Nonzero means the instruction's original size is 9625537Sdfr incremented (escape sequence is used). */ 9725537Sdfrint size_changed; 9825537Sdfr 9940159Speter 10025537Sdfr/* Print the constant expression length. */ 10125537Sdfr 10225537Sdfrstatic char * 10325537Sdfrprint_exp_len (int size) 10425537Sdfr{ 10525537Sdfr switch (size) 10640159Speter { 10740159Speter case 4: 10825537Sdfr case 5: 10925537Sdfr case 6: 11025537Sdfr case 8: 11140159Speter case 14: 11240159Speter case 16: 11340159Speter return ":s"; 11440159Speter case 20: 11540159Speter case 24: 11640159Speter case 32: 11740159Speter return ":m"; 11840159Speter case 48: 11925537Sdfr return ":l"; 12025537Sdfr default: 12125537Sdfr return ""; 12225537Sdfr } 12325537Sdfr} 12425537Sdfr 12525537Sdfr 12641055Speter/* Retrieve the number of operands for the current assembled instruction. */ 12741055Speter 12841055Speterstatic int 12941055Speterget_number_of_operands (void) 13041055Speter{ 13125537Sdfr int i; 13225537Sdfr 13325537Sdfr for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++) 13425537Sdfr ; 13525537Sdfr 13625537Sdfr return i; 13725537Sdfr} 13825537Sdfr 13925537Sdfr/* Return the bit size for a given operand. */ 14025537Sdfr 14125537Sdfrstatic int 14225537Sdfrgetbits (operand_type op) 14341055Speter{ 14441055Speter if (op < MAX_OPRD) 14525537Sdfr return cr16_optab[op].bit_size; 14625537Sdfr 14741055Speter return 0; 14825537Sdfr} 14925537Sdfr 15041055Speter/* Return the argument type of a given operand. */ 15125537Sdfr 15225537Sdfrstatic argtype 15325537Sdfrgetargtype (operand_type op) 15431675Sdyson{ 15525537Sdfr if (op < MAX_OPRD) 15631675Sdyson return cr16_optab[op].arg_type; 15731675Sdyson 15831675Sdyson return nullargs; 15931675Sdyson} 16031675Sdyson 16131675Sdyson/* Given a 'CC' instruction constant operand, return its corresponding 16231675Sdyson string. This routine is used when disassembling the 'CC' instruction. */ 16331675Sdyson 16431675Sdysonstatic char * 16531675Sdysongetccstring (unsigned cc) 16625537Sdfr{ 16730994Sphk return (char *) cr16_b_cond_tab[cc]; 16830994Sphk} 16925537Sdfr 17025537Sdfr 17125537Sdfr/* Given a 'cinv' instruction constant operand, return its corresponding 17241055Speter string. This routine is used when disassembling the 'cinv' instruction. */ 17325537Sdfr 17425537Sdfrstatic char * 17525537Sdfrgetcinvstring (char *str) 17625537Sdfr{ 17741055Speter const cinv_entry *cinv; 17841055Speter 17941055Speter for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++) 18041055Speter if (strcmp (cinv->istr, str) == 0) 18141055Speter return cinv->ostr; 18241055Speter 18341055Speter return ILLEGAL; 18441055Speter} 18541055Speter 18641055Speter/* Given the trap index in dispatch table, return its name. 18741055Speter This routine is used when disassembling the 'excp' instruction. */ 18841055Speter 18941055Speterstatic char * 19041055Spetergettrapstring (unsigned int index) 19141055Speter{ 19241055Speter const trap_entry *trap; 19341055Speter 19441055Speter for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++) 19541055Speter if (trap->entry == index) 19641055Speter return trap->name; 19741055Speter 19841055Speter return ILLEGAL; 19941055Speter} 20041055Speter 20141055Speter/* Given a register enum value, retrieve its name. */ 20241055Speter 20341055Speterstatic char * 20441055Spetergetregname (reg r) 20541055Speter{ 20641055Speter const reg_entry *reg = cr16_regtab + r; 20741055Speter 20841055Speter if (reg->type != CR16_R_REGTYPE) 20941055Speter return ILLEGAL; 21041055Speter 21141055Speter return reg->name; 21241055Speter} 21341055Speter 21441055Speter/* Given a register pair enum value, retrieve its name. */ 21541055Speter 21641055Speterstatic char * 21741055Spetergetregpname (reg r) 21841055Speter{ 21941055Speter const reg_entry *reg = cr16_regptab + r; 22041055Speter 22141055Speter if (reg->type != CR16_RP_REGTYPE) 22241055Speter return ILLEGAL; 22341055Speter 22441055Speter return reg->name; 22541055Speter} 22641055Speter 22741055Speter/* Given a index register pair enum value, retrieve its name. */ 22841055Speter 22941055Speterstatic char * 23041055Spetergetidxregpname (reg r) 23141055Speter{ 23241055Speter const reg_entry *reg; 23341055Speter 23441055Speter switch (r) 23525537Sdfr { 23625537Sdfr case 0: r = 0; break; 23725537Sdfr case 1: r = 2; break; 23825537Sdfr case 2: r = 4; break; 23925537Sdfr case 3: r = 6; break; 24042755Speter case 4: r = 8; break; 24140861Speter case 5: r = 10; break; 24225537Sdfr case 6: r = 3; break; 24325537Sdfr case 7: r = 5; break; 24425537Sdfr default: 24525537Sdfr break; 24625537Sdfr } 24725537Sdfr 24825537Sdfr reg = cr16_regptab + r; 24925537Sdfr 25025537Sdfr if (reg->type != CR16_RP_REGTYPE) 25140861Speter return ILLEGAL; 25240861Speter 25340861Speter return reg->name; 25440861Speter} 25540861Speter 25640861Speter/* Getting a processor register name. */ 25725537Sdfr 25842755Speterstatic char * 25925537Sdfrgetprocregname (int index) 26025537Sdfr{ 26125537Sdfr const reg_entry *r; 26242755Speter 26342755Speter for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++) 26442755Speter if (r->image == index) 26542755Speter return r->name; 26642755Speter 26742755Speter return "ILLEGAL REGISTER"; 26842755Speter} 26942755Speter 27042755Speter/* Getting a processor register name - 32 bit size. */ 27142755Speter 27225537Sdfrstatic char * 27325537Sdfrgetprocpregname (int index) 27425537Sdfr{ 27525537Sdfr const reg_entry *r; 27640861Speter 27725537Sdfr for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++) 27825537Sdfr if (r->image == index) 27925537Sdfr return r->name; 28042755Speter 28142755Speter return "ILLEGAL REGISTER"; 28242755Speter} 28342755Speter 28442755Speter/* START and END are relating 'allWords' struct, which is 48 bits size. 28542755Speter 28642755Speter START|--------|END 28742755Speter +---------+---------+---------+---------+ 28825537Sdfr | | V | A | L | 28925537Sdfr +---------+---------+---------+---------+ 29040861Speter 0 16 32 48 29140861Speter words [0] [1] [2] */ 29225537Sdfr 29325537Sdfrstatic parameter 29425537Sdfrmakelongparameter (ULONGLONG val, int start, int end) 29525537Sdfr{ 29625537Sdfr parameter p; 29725537Sdfr 29825537Sdfr p.val = (dwordU) EXTRACT (val, 48 - end, end - start); 29940861Speter p.nbits = end - start; 30025537Sdfr return p; 30140861Speter} 30240861Speter 30340861Speter/* Build a mask of the instruction's 'constant' opcode, 30440861Speter based on the instruction's printing flags. */ 30540861Speter 30625537Sdfrstatic unsigned long 30740861Speterbuild_mask (void) 30840861Speter{ 30940861Speter unsigned long mask = SBM (instruction->match_bits); 31025537Sdfr return mask; 31125537Sdfr} 31240861Speter 31325537Sdfr/* Search for a matching opcode. Return 1 for success, 0 for failure. */ 31425537Sdfr 31540861Speterstatic int 31640861Spetermatch_opcode (void) 31740861Speter{ 31825537Sdfr unsigned long mask; 31925537Sdfr /* The instruction 'constant' opcode doewsn't exceed 32 bits. */ 32025537Sdfr unsigned long doubleWord = words[1] + (words[0] << 16); 32125537Sdfr 32225537Sdfr /* Start searching from end of instruction table. */ 32325537Sdfr instruction = &cr16_instruction[NUMOPCODES - 2]; 32425537Sdfr 32525537Sdfr /* Loop over instruction table until a full match is found. */ 32625537Sdfr while (instruction >= cr16_instruction) 32725537Sdfr { 32825537Sdfr mask = build_mask (); 32925537Sdfr if ((doubleWord & mask) == BIN (instruction->match, 33025537Sdfr instruction->match_bits)) 33125537Sdfr return 1; 33225537Sdfr else 33325537Sdfr instruction--; 33425537Sdfr } 33525537Sdfr return 0; 33640159Speter} 33725537Sdfr 33825537Sdfr/* Set the proper parameter value for different type of arguments. */ 33925537Sdfr 34040159Speterstatic void 34125537Sdfrmake_argument (argument * a, int start_bits) 34240159Speter{ 34340159Speter int inst_bit_size; 34440159Speter parameter p; 34540159Speter 34640159Speter if ((instruction->size == 3) && a->size >= 16) 34740159Speter inst_bit_size = 48; 34825537Sdfr else 34925537Sdfr inst_bit_size = 32; 35025537Sdfr 35125537Sdfr switch (a->type) 35225537Sdfr { 35325537Sdfr case arg_r: 35440395Speter p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), 35525537Sdfr inst_bit_size - start_bits); 35625537Sdfr a->r = p.val; 35725537Sdfr break; 35825537Sdfr 35925537Sdfr case arg_rp: 36025537Sdfr p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), 36125537Sdfr inst_bit_size - start_bits); 36225537Sdfr a->rp = p.val; 36325537Sdfr break; 36425537Sdfr 36525537Sdfr case arg_pr: 36625537Sdfr p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), 36725537Sdfr inst_bit_size - start_bits); 36825537Sdfr a->pr = p.val; 36925537Sdfr break; 37025537Sdfr 37125537Sdfr case arg_prp: 37225537Sdfr p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), 37325537Sdfr inst_bit_size - start_bits); 37425537Sdfr a->prp = p.val; 37525537Sdfr break; 37625537Sdfr 37725537Sdfr case arg_ic: 37825537Sdfr p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), 37925537Sdfr inst_bit_size - start_bits); 38025537Sdfr a->constant = p.val; 38125537Sdfr break; 38225537Sdfr 38340159Speter case arg_cc: 38425537Sdfr p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size), 38525537Sdfr inst_bit_size - start_bits); 38625537Sdfr 38725537Sdfr a->cc = p.val; 38825537Sdfr break; 38925537Sdfr 39025537Sdfr case arg_idxr: 39125537Sdfr if ((IS_INSN_MNEMONIC ("cbitb")) 39225537Sdfr || (IS_INSN_MNEMONIC ("sbitb")) 39325537Sdfr || (IS_INSN_MNEMONIC ("tbitb"))) 39425537Sdfr p = makelongparameter (allWords, 8, 9); 39525537Sdfr else 39625537Sdfr p = makelongparameter (allWords, 9, 10); 39725537Sdfr a->i_r = p.val; 39825537Sdfr p = makelongparameter (allWords, inst_bit_size - a->size, inst_bit_size); 39925537Sdfr a->constant = p.val; 40025537Sdfr break; 40125537Sdfr 40225537Sdfr case arg_idxrp: 40325537Sdfr p = makelongparameter (allWords, start_bits + 12, start_bits + 13); 40425537Sdfr a->i_r = p.val; 40525537Sdfr p = makelongparameter (allWords, start_bits + 13, start_bits + 16); 40625537Sdfr a->rp = p.val; 40725537Sdfr if (inst_bit_size > 32) 40825537Sdfr { 40925537Sdfr p = makelongparameter (allWords, inst_bit_size - start_bits - 12, 41025537Sdfr inst_bit_size); 41125537Sdfr a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000)); 41225537Sdfr } 41341055Speter else if (instruction->size == 2) 41441055Speter { 41525537Sdfr p = makelongparameter (allWords, inst_bit_size - 22, inst_bit_size); 41625537Sdfr a->constant = (p.val & 0xf) | (((p.val >>20) & 0x3) << 4) 41740159Speter | ((p.val >>14 & 0x3) << 6) | (((p.val >>7) & 0x1f) <<7); 41825537Sdfr } 41925537Sdfr else if (instruction->size == 1 && a->size == 0) 42025537Sdfr a->constant = 0; 42125537Sdfr 42225537Sdfr break; 42325537Sdfr 42425537Sdfr case arg_rbase: 42525537Sdfr p = makelongparameter (allWords, inst_bit_size, inst_bit_size); 42625537Sdfr a->constant = p.val; 42725537Sdfr p = makelongparameter (allWords, inst_bit_size - (start_bits + 4), 42825537Sdfr inst_bit_size - start_bits); 42925537Sdfr a->r = p.val; 43025537Sdfr break; 43125537Sdfr 43225537Sdfr case arg_cr: 43325537Sdfr p = makelongparameter (allWords, start_bits + 12, start_bits + 16); 43425537Sdfr a->r = p.val; 43525537Sdfr p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size); 43625537Sdfr a->constant = p.val; 43725537Sdfr break; 43825537Sdfr 43925537Sdfr case arg_crp: 44025537Sdfr if (instruction->size == 1) 44125537Sdfr p = makelongparameter (allWords, 12, 16); 44225537Sdfr else 44325537Sdfr p = makelongparameter (allWords, start_bits + 12, start_bits + 16); 44440395Speter a->rp = p.val; 44525537Sdfr 44625537Sdfr if (inst_bit_size > 32) 44725537Sdfr { 44825537Sdfr p = makelongparameter (allWords, inst_bit_size - start_bits - 12, 44925537Sdfr inst_bit_size); 45025537Sdfr a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000)); 45125537Sdfr } 45225537Sdfr else if (instruction->size == 2) 45325537Sdfr { 45425537Sdfr p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size); 45525537Sdfr a->constant = p.val; 45625537Sdfr } 45725537Sdfr else if (instruction->size == 1 && a->size != 0) 45825537Sdfr { 45925537Sdfr p = makelongparameter (allWords, 4, 8); 46038275Sdfr if (IS_INSN_MNEMONIC ("loadw") 46138275Sdfr || IS_INSN_MNEMONIC ("loadd") 46242849Speter || IS_INSN_MNEMONIC ("storw") 46325537Sdfr || IS_INSN_MNEMONIC ("stord")) 46425537Sdfr a->constant = (p.val * 2); 46525537Sdfr else 46625537Sdfr a->constant = p.val; 46740159Speter } 46825537Sdfr else /* below case for 0x0(reg pair) */ 46925537Sdfr a->constant = 0; 47038275Sdfr 47138275Sdfr break; 47238275Sdfr 47325537Sdfr case arg_c: 47425537Sdfr 47525537Sdfr if ((IS_INSN_TYPE (BRANCH_INS)) 47625537Sdfr || (IS_INSN_MNEMONIC ("bal")) 47738275Sdfr || (IS_INSN_TYPE (CSTBIT_INS)) 47840159Speter || (IS_INSN_TYPE (LD_STOR_INS))) 47940159Speter { 48038275Sdfr switch (a->size) 48140159Speter { 48238275Sdfr case 8 : 48325537Sdfr p = makelongparameter (allWords, 0, start_bits); 48442849Speter a->constant = ((((p.val&0xf00)>>4)) | (p.val&0xf)); 48525537Sdfr break; 48625537Sdfr 48740159Speter case 24: 48840159Speter if (instruction->size == 3) 48925537Sdfr { 49040159Speter p = makelongparameter (allWords, 16, inst_bit_size); 49125537Sdfr a->constant = ((((p.val>>16)&0xf) << 20) 49225537Sdfr | (((p.val>>24)&0xf) << 16) 49342849Speter | (p.val & 0xffff)); 49442849Speter } 49542849Speter else if (instruction->size == 2) 49642849Speter { 49742849Speter p = makelongparameter (allWords, 8, inst_bit_size); 49842849Speter a->constant = p.val; 49942849Speter } 50042849Speter break; 50142849Speter 50242849Speter default: 50342849Speter p = makelongparameter (allWords, inst_bit_size - (start_bits + 50442849Speter a->size), inst_bit_size - start_bits); 50542849Speter a->constant = p.val; 50642849Speter break; 50742849Speter } 50842849Speter } 50942849Speter else 51042849Speter { 51142849Speter p = makelongparameter (allWords, inst_bit_size - 51225537Sdfr (start_bits + a->size), 51325537Sdfr inst_bit_size - start_bits); 51425537Sdfr a->constant = p.val; 51525537Sdfr } 51625537Sdfr break; 51725537Sdfr 51825537Sdfr default: 51925537Sdfr break; 52025537Sdfr } 52125537Sdfr} 52240159Speter 52340159Speter/* Print a single argument. */ 52425537Sdfr 52540159Speterstatic void 52625537Sdfrprint_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info) 52725537Sdfr{ 52825537Sdfr LONGLONG longdisp, mask; 52925537Sdfr int sign_flag = 0; 53025537Sdfr int relative = 0; 53125537Sdfr bfd_vma number; 53225537Sdfr PTR stream = info->stream; 53325537Sdfr fprintf_ftype func = info->fprintf_func; 53425537Sdfr 53540159Speter switch (a->type) 53640159Speter { 53725537Sdfr case arg_r: 53840159Speter func (stream, "%s", getregname (a->r)); 53940395Speter break; 54025537Sdfr 54125537Sdfr case arg_rp: 54225537Sdfr func (stream, "%s", getregpname (a->rp)); 54325537Sdfr break; 54425537Sdfr 54525537Sdfr case arg_pr: 54625537Sdfr func (stream, "%s", getprocregname (a->pr)); 54740159Speter break; 54825537Sdfr 54925537Sdfr case arg_prp: 55025537Sdfr func (stream, "%s", getprocpregname (a->prp)); 55140159Speter break; 55225537Sdfr 55325537Sdfr case arg_cc: 55425537Sdfr func (stream, "%s", getccstring (a->cc)); 55540159Speter func (stream, "%s", "\t"); 55625537Sdfr break; 55740159Speter 55840159Speter case arg_ic: 55940159Speter if (IS_INSN_MNEMONIC ("excp")) 56040159Speter { 56140159Speter func (stream, "%s", gettrapstring (a->constant)); 56240159Speter break; 56340159Speter } 56440159Speter else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS)) 56540159Speter && ((instruction->size == 1) && (a->constant == 9))) 56640159Speter func (stream, "$%d", -1); 56740159Speter else if (INST_HAS_REG_LIST) 56840159Speter func (stream, "$0x%lx", a->constant +1); 56940159Speter else if (IS_INSN_TYPE (SHIFT_INS)) 57040159Speter { 57140159Speter longdisp = a->constant; 57240159Speter mask = ((LONGLONG)1 << a->size) - 1; 57340159Speter if (longdisp & ((LONGLONG)1 << (a->size -1))) 57440159Speter { 57540159Speter sign_flag = 1; 57640159Speter longdisp = ~(longdisp) + 1; 57740159Speter } 57840159Speter a->constant = (unsigned long int) (longdisp & mask); 57940159Speter func (stream, "$%d", ((int)(sign_flag ? -a->constant : 58040159Speter a->constant))); 58140159Speter } 58240159Speter else 58340159Speter func (stream, "$0x%lx", a->constant); 58440159Speter switch (a->size) 58540159Speter { 58640159Speter case 4 : case 5 : case 6 : case 8 : 58740159Speter func (stream, "%s", ":s"); break; 58840159Speter case 16 : case 20 : func (stream, "%s", ":m"); break; 58940159Speter case 24 : case 32 : func (stream, "%s", ":l"); break; 59040159Speter default: break; 59140159Speter } 59240159Speter break; 59340159Speter 59440159Speter case arg_idxr: 59540159Speter if (a->i_r == 0) func (stream, "[r12]"); 59640159Speter if (a->i_r == 1) func (stream, "[r13]"); 59740159Speter func (stream, "0x%lx", a->constant); 59840159Speter func (stream, "%s", print_exp_len (instruction->size * 16)); 59940159Speter break; 60040159Speter 60140159Speter case arg_idxrp: 60240159Speter if (a->i_r == 0) func (stream, "[r12]"); 60340159Speter if (a->i_r == 1) func (stream, "[r13]"); 60440159Speter func (stream, "0x%lx", a->constant); 60540159Speter func (stream, "%s", print_exp_len (instruction->size * 16)); 60640159Speter func (stream, "%s", getidxregpname (a->rp)); 60740159Speter break; 60840159Speter 60940159Speter case arg_rbase: 61040159Speter func (stream, "(%s)", getregname (a->r)); 61140159Speter break; 61240159Speter 61340159Speter case arg_cr: 61440159Speter func (stream, "0x%lx", a->constant); 61540159Speter func (stream, "%s", print_exp_len (instruction->size * 16)); 61640159Speter func (stream, "(%s)", getregname (a->r)); 61740159Speter break; 61840159Speter 61940159Speter case arg_crp: 62040159Speter func (stream, "0x%lx", a->constant); 62140159Speter func (stream, "%s", print_exp_len (instruction->size * 16)); 62240159Speter func (stream, "%s", getregpname (a->rp)); 62340159Speter break; 62425537Sdfr 62525537Sdfr case arg_c: 62625537Sdfr /*Removed the *2 part as because implicit zeros are no more required. 62725537Sdfr Have to fix this as this needs a bit of extension in terms of branch 62830994Sphk instructions. */ 62925537Sdfr if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal")) 63042316Smsmith { 63125537Sdfr relative = 1; 63225537Sdfr longdisp = a->constant; 63325537Sdfr /* REVISIT: To sync with WinIDEA and CR16 4.1tools, the below 63430994Sphk line commented */ 63525537Sdfr /* longdisp <<= 1; */ 63625537Sdfr mask = ((LONGLONG)1 << a->size) - 1; 63725537Sdfr switch (a->size) 63825537Sdfr { 63925537Sdfr case 8 : 64025537Sdfr { 64125537Sdfr longdisp <<= 1; 64225537Sdfr if (longdisp & ((LONGLONG)1 << a->size)) 64325537Sdfr { 64425537Sdfr sign_flag = 1; 64525537Sdfr longdisp = ~(longdisp) + 1; 64642316Smsmith } 64742316Smsmith break; 64842316Smsmith } 64942316Smsmith case 16 : 65042316Smsmith case 24 : 65142316Smsmith { 65242316Smsmith if (longdisp & 1) 65342316Smsmith { 65442316Smsmith sign_flag = 1; 65540859Speter longdisp = ~(longdisp) + 1; 65625537Sdfr } 65725537Sdfr break; 65825537Sdfr } 65930994Sphk default: 66040159Speter func (stream, "Wrong offset used in branch/bal instruction"); 66125537Sdfr break; 66225537Sdfr } 66325537Sdfr a->constant = (unsigned long int) (longdisp & mask); 66425537Sdfr } 66525537Sdfr /* For branch Neq instruction it is 2*offset + 2. */ 66625537Sdfr else if (IS_INSN_TYPE (BRANCH_NEQ_INS)) 66725537Sdfr a->constant = 2 * a->constant + 2; 66830994Sphk 66925537Sdfr if ((!IS_INSN_TYPE (CSTBIT_INS)) && (!IS_INSN_TYPE (LD_STOR_INS))) 67025537Sdfr (sign_flag) ? func (stream, "%s", "*-"): func (stream, "%s","*+"); 67125537Sdfr 67225537Sdfr func (stream, "%s", "0x"); 67325537Sdfr number = ((relative ? memaddr : 0) + 67425537Sdfr (sign_flag ? ((- a->constant) & 0xffffffe) : a->constant)); 67525537Sdfr 67625537Sdfr (*info->print_address_func) ((number & ((1 << 24) - 1)), info); 67725537Sdfr 67825537Sdfr func (stream, "%s", print_exp_len (instruction->size * 16)); 67925537Sdfr break; 68025537Sdfr 68125537Sdfr default: 68225537Sdfr break; 68343084Speter } 68425537Sdfr} 68525537Sdfr 68625537Sdfr/* Print all the arguments of CURRINSN instruction. */ 68743084Speter 68842837Speterstatic void 68942837Speterprint_arguments (ins *currInsn, bfd_vma memaddr, struct disassemble_info *info) 69043084Speter{ 69125537Sdfr int i; 69225537Sdfr 69325537Sdfr /* For "pop/push/popret RA instruction only. */ 69425537Sdfr if ((IS_INSN_MNEMONIC ("pop") 69525537Sdfr || (IS_INSN_MNEMONIC ("popret") 69625537Sdfr || (IS_INSN_MNEMONIC ("push")))) 69725537Sdfr && currInsn->nargs == 1) 69825537Sdfr { 69930994Sphk info->fprintf_func (info->stream, "RA"); 70025537Sdfr return; 70142316Smsmith } 70225537Sdfr 70325537Sdfr for (i = 0; i < currInsn->nargs; i++) 70425537Sdfr { 70530994Sphk processing_argument_number = i; 70625537Sdfr 70725537Sdfr /* For "bal (ra), disp17" instruction only. */ 70825537Sdfr if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2) 70925537Sdfr { 71025537Sdfr info->fprintf_func (info->stream, "(ra),"); 71142316Smsmith continue; 71242316Smsmith } 71342316Smsmith 71442316Smsmith if ((INST_HAS_REG_LIST) && (i == 2)) 71542316Smsmith info->fprintf_func (info->stream, "RA"); 71625537Sdfr else 71730994Sphk print_arg (&currInsn->arg[i], memaddr, info); 71825537Sdfr 71925537Sdfr if ((i != currInsn->nargs - 1) && (!IS_INSN_MNEMONIC ("b"))) 72040159Speter info->fprintf_func (info->stream, ","); 72125537Sdfr } 72225537Sdfr} 72325537Sdfr 72425537Sdfr/* Build the instruction's arguments. */ 72525537Sdfr 72625537Sdfrstatic void 72725537Sdfrmake_instruction (void) 72830994Sphk{ 72925537Sdfr int i; 73025537Sdfr unsigned int shift; 73125537Sdfr 73225537Sdfr for (i = 0; i < currInsn.nargs; i++) 73325537Sdfr { 73425537Sdfr argument a; 73530994Sphk 73625537Sdfr memset (&a, 0, sizeof (a)); 73730994Sphk a.type = getargtype (instruction->operands[i].op_type); 73825537Sdfr a.size = getbits (instruction->operands[i].op_type); 73925537Sdfr shift = instruction->operands[i].shift; 74040159Speter 74125537Sdfr make_argument (&a, shift); 74225537Sdfr currInsn.arg[i] = a; 74325537Sdfr } 74430994Sphk 74525537Sdfr /* Calculate instruction size (in bytes). */ 74630994Sphk currInsn.size = instruction->size + (size_changed ? 1 : 0); 74725537Sdfr /* Now in bits. */ 74825537Sdfr currInsn.size *= 2; 74925537Sdfr} 75025537Sdfr 75125537Sdfr/* Retrieve a single word from a given memory address. */ 75225537Sdfr 75325537Sdfrstatic wordU 75430994Sphkget_word_at_PC (bfd_vma memaddr, struct disassemble_info *info) 75525537Sdfr{ 75625537Sdfr bfd_byte buffer[4]; 75725537Sdfr int status; 75825537Sdfr wordU insn = 0; 75925537Sdfr 76025537Sdfr status = info->read_memory_func (memaddr, buffer, 2, info); 76125537Sdfr 76225537Sdfr if (status == 0) 76325537Sdfr insn = (wordU) bfd_getl16 (buffer); 76425537Sdfr 76525537Sdfr return insn; 76625537Sdfr} 76725537Sdfr 76825537Sdfr/* Retrieve multiple words (3) from a given memory address. */ 76925537Sdfr 77025537Sdfrstatic void 77125537Sdfrget_words_at_PC (bfd_vma memaddr, struct disassemble_info *info) 77225537Sdfr{ 77325537Sdfr int i; 77425537Sdfr bfd_vma mem; 77525537Sdfr 77625537Sdfr for (i = 0, mem = memaddr; i < 3; i++, mem += 2) 77725537Sdfr words[i] = get_word_at_PC (mem, info); 77825537Sdfr 77925537Sdfr allWords = 78025537Sdfr ((ULONGLONG) words[0] << 32) + ((unsigned long) words[1] << 16) + words[2]; 78125537Sdfr} 78225537Sdfr 78325537Sdfr/* Prints the instruction by calling print_arguments after proper matching. */ 78425537Sdfr 78525537Sdfrint 78625537Sdfrprint_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info) 78725537Sdfr{ 78825537Sdfr int is_decoded; /* Nonzero means instruction has a match. */ 78925537Sdfr 79025537Sdfr /* Initialize global variables. */ 79125537Sdfr imm4flag = 0; 79225537Sdfr size_changed = 0; 79325537Sdfr 79430994Sphk /* Retrieve the encoding from current memory location. */ 79525537Sdfr get_words_at_PC (memaddr, info); 79625537Sdfr /* Find a matching opcode in table. */ 79725537Sdfr is_decoded = match_opcode (); 79825537Sdfr /* If found, print the instruction's mnemonic and arguments. */ 79925537Sdfr if (is_decoded > 0 && (words[0] << 16 || words[1]) != 0) 80025537Sdfr { 80130994Sphk if (strneq (instruction->mnemonic, "cinv", 4)) 80225537Sdfr info->fprintf_func (info->stream,"%s", getcinvstring ((char *)instruction->mnemonic)); 80325537Sdfr else 80425537Sdfr info->fprintf_func (info->stream, "%s", instruction->mnemonic); 80525537Sdfr 80625537Sdfr if (((currInsn.nargs = get_number_of_operands ()) != 0) 80725537Sdfr && ! (IS_INSN_MNEMONIC ("b"))) 80825537Sdfr info->fprintf_func (info->stream, "\t"); 80930994Sphk make_instruction (); 81025537Sdfr /* For push/pop/pushrtn with RA instructions. */ 81130994Sphk if ((INST_HAS_REG_LIST) && ((words[0] >> 7) & 0x1)) 81225537Sdfr currInsn.nargs +=1; 81325537Sdfr print_arguments (&currInsn, memaddr, info); 81425537Sdfr return currInsn.size; 81525537Sdfr } 81625537Sdfr 81740159Speter /* No match found. */ 81841090Speter info->fprintf_func (info->stream,"%s ",ILLEGAL); 81941090Speter return 2; 82041090Speter} 82141090Speter