This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[patch] AVR disassembler fixes



More changes for AVR binutils, mostly disassembler fixes.
It should no longer segfault (tested on a binary file with all
64K possible opcodes), and its output can be used as valid input
for the assembler (after removing the extra lines and columns).
Also some minor cleanups and portability fixes.

Happy hacking,
Marek


gas/ChangeLog:

2000-07-29  Marek Michalkiewicz  <marekm@linux.org.pl>

	* config/tc-avr.c: Use PARAMS macro in function declarations.
	Don't declare md_pcrel_from_section (already in tc-avr.h).
	(avr_operands): Use AVR_UNDEF_P and AVR_SKIP_P macros.
	(avr_operand): Don't set (unsigned) op_mask to -1.


include/opcode/ChangeLog:

2000-07-29  Marek Michalkiewicz  <marekm@linux.org.pl>

	* avr.h (AVR_UNDEF_P, AVR_SKIP_P, AVR_DISP0_P): New macros.
	Move related opcodes closer to each other.
	Minor changes in comments, list undefined opcodes.


opcodes/ChangeLog:

2000-07-29  Marek Michalkiewicz  <marekm@linux.org.pl>

	* avr-dis.c (avr_operand): Use PARAMS macro in declaration.
	Change return type from void to int.  Check the combination
	of operands, return 1 if valid.  Fix to avoid BUF overflow.
	Report undefined combinations of operands in COMMENT.
	Report internal errors to stderr.  Output the adiw/sbiw
	constant operand in both decimal and hex.
	(print_insn_avr): Disassemble ldd/std with displacement of 0
	as ld/st.  Check avr_operand () return value, handle invalid
	combinations of operands like unknown opcodes.


diff -Nrc3p orig/src/gas/config/tc-avr.c src/gas/config/tc-avr.c
*** orig/src/gas/config/tc-avr.c	Fri Jul 28 15:29:59 2000
--- src/gas/config/tc-avr.c	Sat Jul 29 14:29:12 2000
*************** const pseudo_typeS md_pseudo_table[] =
*** 117,132 ****
  
  #define LDI_IMMEDIATE(x) (((x) & 0xf) | (((x) << 4) & 0xf00))
  
! static void show_mcu_list (FILE *stream);
! static char *skip_space (char *s);
! static char *extract_word (char *from, char *to, int limit);
! static unsigned int avr_operand (struct avr_opcodes_s *opcode,
! 				 int where, char *op, char **line);
! static unsigned int avr_operands (struct avr_opcodes_s *opcode, char **line);
! static unsigned int avr_get_constant (char *str, int max);
! static char *parse_exp (char *s, expressionS *op);
! static bfd_reloc_code_real_type avr_ldi_expression (expressionS *exp);
! long md_pcrel_from_section PARAMS ((fixS *, segT));
  
  #define EXP_MOD_NAME(i) exp_mod[i].name
  #define EXP_MOD_RELOC(i) exp_mod[i].reloc
--- 117,131 ----
  
  #define LDI_IMMEDIATE(x) (((x) & 0xf) | (((x) << 4) & 0xf00))
  
! static void show_mcu_list PARAMS ((FILE *));
! static char *skip_space PARAMS ((char *));
! static char *extract_word PARAMS ((char *, char *, int));
! static unsigned int avr_operand PARAMS ((struct avr_opcodes_s *,
! 					 int, char *, char **));
! static unsigned int avr_operands PARAMS ((struct avr_opcodes_s *, char **));
! static unsigned int avr_get_constant PARAMS ((char *, int));
! static char *parse_exp PARAMS ((char *, expressionS *));
! static bfd_reloc_code_real_type avr_ldi_expression PARAMS ((expressionS *));
  
  #define EXP_MOD_NAME(i) exp_mod[i].name
  #define EXP_MOD_RELOC(i) exp_mod[i].reloc
*************** avr_operands (opcode, line)
*** 505,532 ****
        bin |= reg1 | reg2;
      }
  
!   if (!avr_opt.all_opcodes)
!     {
!       /* Detect undefined combinations (like ld r31,Z+).  */
!       if (((bin & 0xFDEF) == 0x91AD) || ((bin & 0xFDEF) == 0x91AE) ||
! 	  ((bin & 0xFDEF) == 0x91C9) || ((bin & 0xFDEF) == 0x91CA) ||
! 	  ((bin & 0xFDEF) == 0x91E1) || ((bin & 0xFDEF) == 0x91E2) ||
! 	  ((bin & 0xFFED) == 0x91E5))
! 	as_warn (_("undefined combination of operands"));
!     }
  
    if (opcode->insn_size == 2)
      {
        /* Warn if the previous opcode was cpse/sbic/sbis/sbrc/sbrs
           (AVR core bug, fixed in the newer devices).  */
  
!       if (!((avr_mcu->isa & AVR_ISA_MUL) || avr_opt.no_skip_bug))
! 	{
! 	  if ((prev & 0xFC00) == 0x1000
! 	      || (prev & 0xFD00) == 0x9900
! 	      || (prev & 0xFC08) == 0xFC00)
! 	    as_warn (_("skipping two-word instruction"));
! 	}
  
        bfd_putl32 ((bfd_vma) bin, frag);
      }
--- 504,521 ----
        bin |= reg1 | reg2;
      }
  
!   /* Detect undefined combinations (like ld r31,Z+).  */
!   if (!avr_opt.all_opcodes && AVR_UNDEF_P (bin))
!     as_warn (_("undefined combination of operands"));
  
    if (opcode->insn_size == 2)
      {
        /* Warn if the previous opcode was cpse/sbic/sbis/sbrc/sbrs
           (AVR core bug, fixed in the newer devices).  */
  
!       if (!(avr_opt.no_skip_bug || (avr_mcu->isa & AVR_ISA_MUL))
! 	  && AVR_SKIP_P (prev))
! 	as_warn (_("skipping two-word instruction"));
  
        bfd_putl32 ((bfd_vma) bin, frag);
      }
*************** avr_operand (opcode, where, op, line)
*** 560,572 ****
      case 'r':
      case 'a':
      case 'v':
-       op_mask = -1;
-       
        if (*str == 'r' || *str == 'R')
  	{
  	  char r_name[20];
  	  
  	  str = extract_word (str, r_name, sizeof (r_name));
  	  if (isdigit (r_name[1]))
  	    {
  	      if (r_name[2] == '\0')
--- 549,560 ----
      case 'r':
      case 'a':
      case 'v':
        if (*str == 'r' || *str == 'R')
  	{
  	  char r_name[20];
  	  
  	  str = extract_word (str, r_name, sizeof (r_name));
+ 	  op_mask = 0xff;
  	  if (isdigit (r_name[1]))
  	    {
  	      if (r_name[2] == '\0')
*************** avr_operand (opcode, where, op, line)
*** 606,615 ****
  	      break;
  	      
  	    case 'w':
! 	      op_mask -= 24;
! 	      if (op_mask & 1 || op_mask > 6)
  		as_bad (_("register r24, r26, r28 or r30 required"));
! 	      op_mask >>= 1;
  	      break;
  	    }
  	  break;
--- 594,602 ----
  	      break;
  	      
  	    case 'w':
! 	      if ((op_mask & 1) || op_mask < 24)
  		as_bad (_("register r24, r26, r28 or r30 required"));
! 	      op_mask = (op_mask - 24) >> 1;
  	      break;
  	    }
  	  break;
diff -Nrc3p orig/src/include/opcode/avr.h src/include/opcode/avr.h
*** orig/src/include/opcode/avr.h	Tue Jun 27 18:02:00 2000
--- src/include/opcode/avr.h	Sat Jul 29 15:40:04 2000
***************
*** 45,50 ****
--- 45,66 ----
  		       || (x) == 'a'		\
  		       || (x) == 'v')
  
+ /* Undefined combination of operands - does the register
+    operand overlap with pre-decremented or post-incremented
+    pointer register (like ld r31,Z+)?  */
+ #define AVR_UNDEF_P(x) (((x) & 0xFFED) == 0x91E5 ||		\
+   ((x) & 0xFDEF) == 0x91AD || ((x) & 0xFDEF) == 0x91AE ||	\
+   ((x) & 0xFDEF) == 0x91C9 || ((x) & 0xFDEF) == 0x91CA ||	\
+   ((x) & 0xFDEF) == 0x91E1 || ((x) & 0xFDEF) == 0x91E2)
+ 
+ /* Is this a skip instruction {cpse,sbic,sbis,sbrc,sbrs}?  */
+ #define AVR_SKIP_P(x) (((x) & 0xFC00) == 0x1000 ||		\
+   ((x) & 0xFD00) == 0x9900 || ((x) & 0xFC08) == 0xFC00)
+ 
+ /* Is this `ldd r,b+0' or `std b+0,r' (b={Y,Z}, disassembled as
+    `ld r,b' or `st b,r' respectively - next opcode entry)?  */
+ #define AVR_DISP0_P(x) (((x) & 0xFC07) == 0x8000)
+ 
  /* constraint letters
     r - any register
     d - `ldi' register (r16-r31)
***************
*** 57,72 ****
     M - immediate value from 0 to 255
     n - immediate value from 0 to 255 ( n = ~M ). Relocation impossible
     s - immediate value from 0 to 7
!    P - Port address value from 0 to 64. (in, out)
!    p - Port address value from 0 to 32. (cbi, sbi, sbic, sbis)
!    K - immediate value from 0 to 64 (used in `adiw', `sbiw')
     i - immediate value
     l - signed pc relative offset from -64 to 63
     L - signed pc relative offset from -2048 to 2047
!    h - absolut code address (call, jmp)
     S - immediate value from 0 to 7 (S = s << 4)
     ? - use this opcode entry if no parameters, else use next opcode entry
! */
  
  AVR_INSN (clc,  "",    "1001010010001000", 1, AVR_ISA_1200, 0x9488)
  AVR_INSN (clh,  "",    "1001010011011000", 1, AVR_ISA_1200, 0x94d8)
--- 73,109 ----
     M - immediate value from 0 to 255
     n - immediate value from 0 to 255 ( n = ~M ). Relocation impossible
     s - immediate value from 0 to 7
!    P - Port address value from 0 to 63. (in, out)
!    p - Port address value from 0 to 31. (cbi, sbi, sbic, sbis)
!    K - immediate value from 0 to 63 (used in `adiw', `sbiw')
     i - immediate value
     l - signed pc relative offset from -64 to 63
     L - signed pc relative offset from -2048 to 2047
!    h - absolute code address (call, jmp)
     S - immediate value from 0 to 7 (S = s << 4)
     ? - use this opcode entry if no parameters, else use next opcode entry
! 
!    Order is important - some binary opcodes have more than one name,
!    the disassembler will only see the first match.
! 
!    Remaining undefined opcodes (1700 total - some of them might work
!    as normal instructions if not all of the bits are decoded):
! 
!     0x0001...0x00ff    (255) (known to be decoded as `nop' by the old core)
!    "100100xxxxxxx011"  (128) 0x9[0-3][0-9a-f][3b]
!    "100100xxxxxx1000"   (64) 0x9[0-3][0-9a-f]8
!    "1001001xxxxx01xx"  (128) 0x9[23][0-9a-f][4-7]
!    "1001010xxxxx0100"   (32) 0x9[45][0-9a-f]4
!    "1001010x001x1001"    (4) 0x9[45][23]9
!    "1001010x01xx1001"    (8) 0x9[45][4-7]9
!    "1001010x1xxx1001"   (16) 0x9[45][8-9a-f]9
!    "1001010xxxxx1011"   (32) 0x9[45][0-9a-f]b
!    "10010101001x1000"    (2) 0x95[23]8
!    "1001010101xx1000"    (4) 0x95[4-7]8
!    "1001010110x11000"    (2) 0x95[9b]8
!    "1001010111111000"    (1) 0x95f8 (`espm' removed in databook update)
!    "11111xxxxxxx1xxx" (1024) 0xf[8-9a-f][0-9a-f][8-9a-f]
!  */
  
  AVR_INSN (clc,  "",    "1001010010001000", 1, AVR_ISA_1200, 0x9488)
  AVR_INSN (clh,  "",    "1001010011011000", 1, AVR_ISA_1200, 0x94d8)
*************** AVR_INSN (cls,  "",    "1001010011001000
*** 76,98 ****
  AVR_INSN (clt,  "",    "1001010011101000", 1, AVR_ISA_1200, 0x94e8)
  AVR_INSN (clv,  "",    "1001010010111000", 1, AVR_ISA_1200, 0x94b8)
  AVR_INSN (clz,  "",    "1001010010011000", 1, AVR_ISA_1200, 0x9498)
  AVR_INSN (icall,"",    "1001010100001001", 1, AVR_ISA_2xxx, 0x9509)
  AVR_INSN (ijmp, "",    "1001010000001001", 1, AVR_ISA_2xxx, 0x9409)
  AVR_INSN (lpm,  "?",   "1001010111001000", 1, AVR_ISA_TINY1,0x95c8)
  AVR_INSN (lpm,  "r,z", "1001000ddddd010+", 1, AVR_ISA_LPMX, 0x9004)
  AVR_INSN (elpm, "?",   "1001010111011000", 1, AVR_ISA_ELPM, 0x95d8)
  AVR_INSN (elpm, "r,z", "1001000ddddd011+", 1, AVR_ISA_ELPMX,0x9006)
  AVR_INSN (nop,  "",    "0000000000000000", 1, AVR_ISA_1200, 0x0000)
  AVR_INSN (ret,  "",    "1001010100001000", 1, AVR_ISA_1200, 0x9508)
  AVR_INSN (reti, "",    "1001010100011000", 1, AVR_ISA_1200, 0x9518)
- AVR_INSN (sec,  "",    "1001010000001000", 1, AVR_ISA_1200, 0x9408)
- AVR_INSN (seh,  "",    "1001010001011000", 1, AVR_ISA_1200, 0x9458)
- AVR_INSN (sei,  "",    "1001010001111000", 1, AVR_ISA_1200, 0x9478)
- AVR_INSN (sen,  "",    "1001010000101000", 1, AVR_ISA_1200, 0x9428)
- AVR_INSN (ses,  "",    "1001010001001000", 1, AVR_ISA_1200, 0x9448)
- AVR_INSN (set,  "",    "1001010001101000", 1, AVR_ISA_1200, 0x9468)
- AVR_INSN (sev,  "",    "1001010000111000", 1, AVR_ISA_1200, 0x9438)
- AVR_INSN (sez,  "",    "1001010000011000", 1, AVR_ISA_1200, 0x9418)
  AVR_INSN (sleep,"",    "1001010110001000", 1, AVR_ISA_1200, 0x9588)
  AVR_INSN (wdr,  "",    "1001010110101000", 1, AVR_ISA_1200, 0x95a8)
  AVR_INSN (spm,  "",    "1001010111101000", 1, AVR_ISA_SPM,  0x95e8)
--- 113,143 ----
  AVR_INSN (clt,  "",    "1001010011101000", 1, AVR_ISA_1200, 0x94e8)
  AVR_INSN (clv,  "",    "1001010010111000", 1, AVR_ISA_1200, 0x94b8)
  AVR_INSN (clz,  "",    "1001010010011000", 1, AVR_ISA_1200, 0x9498)
+ 
+ AVR_INSN (sec,  "",    "1001010000001000", 1, AVR_ISA_1200, 0x9408)
+ AVR_INSN (seh,  "",    "1001010001011000", 1, AVR_ISA_1200, 0x9458)
+ AVR_INSN (sei,  "",    "1001010001111000", 1, AVR_ISA_1200, 0x9478)
+ AVR_INSN (sen,  "",    "1001010000101000", 1, AVR_ISA_1200, 0x9428)
+ AVR_INSN (ses,  "",    "1001010001001000", 1, AVR_ISA_1200, 0x9448)
+ AVR_INSN (set,  "",    "1001010001101000", 1, AVR_ISA_1200, 0x9468)
+ AVR_INSN (sev,  "",    "1001010000111000", 1, AVR_ISA_1200, 0x9438)
+ AVR_INSN (sez,  "",    "1001010000011000", 1, AVR_ISA_1200, 0x9418)
+ 
+    /* Same as {cl,se}[chinstvz] above.  */
+ AVR_INSN (bclr, "S",   "100101001SSS1000", 1, AVR_ISA_1200, 0x9488)
+ AVR_INSN (bset, "S",   "100101000SSS1000", 1, AVR_ISA_1200, 0x9408)
+ 
  AVR_INSN (icall,"",    "1001010100001001", 1, AVR_ISA_2xxx, 0x9509)
  AVR_INSN (ijmp, "",    "1001010000001001", 1, AVR_ISA_2xxx, 0x9409)
+ 
  AVR_INSN (lpm,  "?",   "1001010111001000", 1, AVR_ISA_TINY1,0x95c8)
  AVR_INSN (lpm,  "r,z", "1001000ddddd010+", 1, AVR_ISA_LPMX, 0x9004)
  AVR_INSN (elpm, "?",   "1001010111011000", 1, AVR_ISA_ELPM, 0x95d8)
  AVR_INSN (elpm, "r,z", "1001000ddddd011+", 1, AVR_ISA_ELPMX,0x9006)
+ 
  AVR_INSN (nop,  "",    "0000000000000000", 1, AVR_ISA_1200, 0x0000)
  AVR_INSN (ret,  "",    "1001010100001000", 1, AVR_ISA_1200, 0x9508)
  AVR_INSN (reti, "",    "1001010100011000", 1, AVR_ISA_1200, 0x9518)
  AVR_INSN (sleep,"",    "1001010110001000", 1, AVR_ISA_1200, 0x9588)
  AVR_INSN (wdr,  "",    "1001010110101000", 1, AVR_ISA_1200, 0x95a8)
  AVR_INSN (spm,  "",    "1001010111101000", 1, AVR_ISA_SPM,  0x95e8)
*************** AVR_INSN (or,   "r,r", "001010rdddddrrrr
*** 110,115 ****
--- 155,161 ----
  AVR_INSN (sbc,  "r,r", "000010rdddddrrrr", 1, AVR_ISA_1200, 0x0800)
  AVR_INSN (sub,  "r,r", "000110rdddddrrrr", 1, AVR_ISA_1200, 0x1800)
  
+    /* Shorthand for {eor,add,adc,and} r,r above.  */
  AVR_INSN (clr,  "r=r", "001001rdddddrrrr", 1, AVR_ISA_1200, 0x2400)
  AVR_INSN (lsl,  "r=r", "000011rdddddrrrr", 1, AVR_ISA_1200, 0x0c00)
  AVR_INSN (rol,  "r=r", "000111rdddddrrrr", 1, AVR_ISA_1200, 0x1c00)
*************** AVR_INSN (tst,  "r=r", "001000rdddddrrrr
*** 118,128 ****
  AVR_INSN (andi, "d,M", "0111KKKKddddKKKK", 1, AVR_ISA_1200, 0x7000)
    /*XXX special case*/
  AVR_INSN (cbr,  "d,n", "0111KKKKddddKKKK", 1, AVR_ISA_1200, 0x7000)
! AVR_INSN (cpi,  "d,M", "0011KKKKddddKKKK", 1, AVR_ISA_1200, 0x3000)
  AVR_INSN (ldi,  "d,M", "1110KKKKddddKKKK", 1, AVR_ISA_1200, 0xe000)
  AVR_INSN (ori,  "d,M", "0110KKKKddddKKKK", 1, AVR_ISA_1200, 0x6000)
- AVR_INSN (sbci, "d,M", "0100KKKKddddKKKK", 1, AVR_ISA_1200, 0x4000)
  AVR_INSN (sbr,  "d,M", "0110KKKKddddKKKK", 1, AVR_ISA_1200, 0x6000)
  AVR_INSN (subi, "d,M", "0101KKKKddddKKKK", 1, AVR_ISA_1200, 0x5000)
  
  AVR_INSN (sbrc, "r,s", "1111110rrrrr0sss", 1, AVR_ISA_1200, 0xfc00)
--- 164,178 ----
  AVR_INSN (andi, "d,M", "0111KKKKddddKKKK", 1, AVR_ISA_1200, 0x7000)
    /*XXX special case*/
  AVR_INSN (cbr,  "d,n", "0111KKKKddddKKKK", 1, AVR_ISA_1200, 0x7000)
! 
  AVR_INSN (ldi,  "d,M", "1110KKKKddddKKKK", 1, AVR_ISA_1200, 0xe000)
+ AVR_INSN (ser,  "d",   "11101111dddd1111", 1, AVR_ISA_1200, 0xef0f)
+ 
  AVR_INSN (ori,  "d,M", "0110KKKKddddKKKK", 1, AVR_ISA_1200, 0x6000)
  AVR_INSN (sbr,  "d,M", "0110KKKKddddKKKK", 1, AVR_ISA_1200, 0x6000)
+ 
+ AVR_INSN (cpi,  "d,M", "0011KKKKddddKKKK", 1, AVR_ISA_1200, 0x3000)
+ AVR_INSN (sbci, "d,M", "0100KKKKddddKKKK", 1, AVR_ISA_1200, 0x4000)
  AVR_INSN (subi, "d,M", "0101KKKKddddKKKK", 1, AVR_ISA_1200, 0x5000)
  
  AVR_INSN (sbrc, "r,s", "1111110rrrrr0sss", 1, AVR_ISA_1200, 0xfc00)
*************** AVR_INSN (brts, "l",   "111100lllllll110
*** 160,165 ****
--- 210,216 ----
  AVR_INSN (brvc, "l",   "111101lllllll011", 1, AVR_ISA_1200, 0xf403)
  AVR_INSN (brvs, "l",   "111100lllllll011", 1, AVR_ISA_1200, 0xf003)
  
+    /* Same as br?? above.  */
  AVR_INSN (brbc, "s,l", "111101lllllllsss", 1, AVR_ISA_1200, 0xf400)
  AVR_INSN (brbs, "s,l", "111100lllllllsss", 1, AVR_ISA_1200, 0xf000)
  
*************** AVR_INSN (neg,  "r",   "1001010rrrrr0001
*** 178,189 ****
  AVR_INSN (pop,  "r",   "1001000rrrrr1111", 1, AVR_ISA_2xxx, 0x900f)
  AVR_INSN (push, "r",   "1001001rrrrr1111", 1, AVR_ISA_2xxx, 0x920f)
  AVR_INSN (ror,  "r",   "1001010rrrrr0111", 1, AVR_ISA_1200, 0x9407)
- AVR_INSN (ser,  "d",   "11101111dddd1111", 1, AVR_ISA_1200, 0xef0f)
  AVR_INSN (swap, "r",   "1001010rrrrr0010", 1, AVR_ISA_1200, 0x9402)
  
! AVR_INSN (bclr, "S",   "100101001SSS1000", 1, AVR_ISA_1200, 0x9488)
! AVR_INSN (bset, "S",   "100101000SSS1000", 1, AVR_ISA_1200, 0x9408)
! 
  AVR_INSN (movw, "v,v", "00000001ddddrrrr", 1, AVR_ISA_MUL,  0x0100)
  AVR_INSN (muls, "d,d", "00000010ddddrrrr", 1, AVR_ISA_MUL,  0x0200)
  AVR_INSN (mulsu,"a,a", "000000110ddd0rrr", 1, AVR_ISA_MUL,  0x0300)
--- 229,237 ----
  AVR_INSN (pop,  "r",   "1001000rrrrr1111", 1, AVR_ISA_2xxx, 0x900f)
  AVR_INSN (push, "r",   "1001001rrrrr1111", 1, AVR_ISA_2xxx, 0x920f)
  AVR_INSN (ror,  "r",   "1001010rrrrr0111", 1, AVR_ISA_1200, 0x9407)
  AVR_INSN (swap, "r",   "1001010rrrrr0010", 1, AVR_ISA_1200, 0x9402)
  
!    /* Known to be decoded as `nop' by the old core.  */
  AVR_INSN (movw, "v,v", "00000001ddddrrrr", 1, AVR_ISA_MUL,  0x0100)
  AVR_INSN (muls, "d,d", "00000010ddddrrrr", 1, AVR_ISA_MUL,  0x0200)
  AVR_INSN (mulsu,"a,a", "000000110ddd0rrr", 1, AVR_ISA_MUL,  0x0300)
*************** AVR_INSN (fmulsu,"a,a","000000111ddd1rrr
*** 193,207 ****
  
  AVR_INSN (sts,  "i,r", "1001001ddddd0000", 2, AVR_ISA_2xxx, 0x9200)
  AVR_INSN (lds,  "r,i", "1001000ddddd0000", 2, AVR_ISA_2xxx, 0x9000)
  AVR_INSN (ldd,  "r,b", "10o0oo0dddddbooo", 1, AVR_ISA_2xxx, 0x8000)
- AVR_INSN (std,  "b,r", "10o0oo1rrrrrbooo", 1, AVR_ISA_2xxx, 0x8200)
-   /* ee = {X=11,Y=10,Z=00, 0) */
  AVR_INSN (ld,   "r,e", "100!000dddddee-+", 1, AVR_ISA_1200, 0x8000)
  AVR_INSN (st,   "e,r", "100!001rrrrree-+", 1, AVR_ISA_1200, 0x8200)
  
!      /* these are for devices that don't exist yet */
! /* espm (0x95f8) removed in databook update, use spm with RAMPZ:Z */
!      /* >128K program memory (PC = EIND:Z) */
  AVR_INSN (eicall, "",  "1001010100011001", 1, AVR_ISA_EIND, 0x9519)
  AVR_INSN (eijmp, "",   "1001010000011001", 1, AVR_ISA_EIND, 0x9419)
  
--- 241,256 ----
  
  AVR_INSN (sts,  "i,r", "1001001ddddd0000", 2, AVR_ISA_2xxx, 0x9200)
  AVR_INSN (lds,  "r,i", "1001000ddddd0000", 2, AVR_ISA_2xxx, 0x9000)
+ 
+    /* Special case for b+0, `e' must be next entry after `b',
+       b={Y=1,Z=0}, ee={X=11,Y=10,Z=00}, !=1 if -e or e+ or X.  */
  AVR_INSN (ldd,  "r,b", "10o0oo0dddddbooo", 1, AVR_ISA_2xxx, 0x8000)
  AVR_INSN (ld,   "r,e", "100!000dddddee-+", 1, AVR_ISA_1200, 0x8000)
+ AVR_INSN (std,  "b,r", "10o0oo1rrrrrbooo", 1, AVR_ISA_2xxx, 0x8200)
  AVR_INSN (st,   "e,r", "100!001rrrrree-+", 1, AVR_ISA_1200, 0x8200)
  
!    /* These are for devices that don't exist yet
!       (>128K program memory, PC = EIND:Z).  */
  AVR_INSN (eicall, "",  "1001010100011001", 1, AVR_ISA_EIND, 0x9519)
  AVR_INSN (eijmp, "",   "1001010000011001", 1, AVR_ISA_EIND, 0x9419)
  
diff -Nrc3p orig/src/opcodes/avr-dis.c src/opcodes/avr-dis.c
*** orig/src/opcodes/avr-dis.c	Tue Jul  4 18:33:19 2000
--- src/opcodes/avr-dis.c	Sat Jul 29 14:41:28 2000
*************** struct avr_opcodes_s avr_opcodes[] =
*** 43,54 ****
    {NULL, NULL, NULL, 0, 0, 0, 0}
  };
  
  
! static void avr_operand (unsigned int insn, unsigned int insn2,
! 			 unsigned int pc, int constraint, char *buf,
! 			 char *comment, int regs);
! 
! static void
  avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
       unsigned int insn;
       unsigned int insn2;
--- 43,52 ----
    {NULL, NULL, NULL, 0, 0, 0, 0}
  };
  
+ static int avr_operand PARAMS ((unsigned int, unsigned int,
+ 				unsigned int, int, char *, char *, int));
  
! static int
  avr_operand (insn, insn2, pc, constraint, buf, comment, regs)
       unsigned int insn;
       unsigned int insn2;
*************** avr_operand (insn, insn2, pc, constraint
*** 58,63 ****
--- 56,63 ----
       char *comment;
       int regs;
  {
+   int ok = 1;
+ 
    switch (constraint)
      {
        /* Any register operand.  */
*************** avr_operand (insn, insn2, pc, constraint
*** 96,113 ****
        break;
  
      case 'e':
!       if (insn & 0x2)
! 	*buf++ = '-';
!       switch ((insn >> 2) & 0x3)
! 	{
! 	case 0: *buf++ = 'Z'; break;
! 	case 2: *buf++ = 'Y'; break;
! 	case 3: *buf++ = 'X'; break;
! 	default: buf += sprintf (buf, _(" unknown register ")); break;
! 	}
!       if (insn & 0x1)
! 	*buf++ = '+';
!       *buf = '\0';
        break;
  
      case 'z':
--- 96,122 ----
        break;
  
      case 'e':
!       {
! 	char *xyz;
! 
! 	switch (insn & 0x100f)
! 	  {
! 	    case 0x0000: xyz = "Z";  break;
! 	    case 0x1001: xyz = "Z+"; break;
! 	    case 0x1002: xyz = "-Z"; break;
! 	    case 0x0008: xyz = "Y";  break;
! 	    case 0x1009: xyz = "Y+"; break;
! 	    case 0x100a: xyz = "-Y"; break;
! 	    case 0x100c: xyz = "X";  break;
! 	    case 0x100d: xyz = "X+"; break;
! 	    case 0x100e: xyz = "-X"; break;
! 	    default: xyz = "??"; ok = 0;
! 	  }
! 	sprintf (buf, xyz);
! 
! 	if (AVR_UNDEF_P (insn))
! 	  sprintf (comment, _("undefined"));
!       }
        break;
  
      case 'z':
*************** avr_operand (insn, insn2, pc, constraint
*** 115,125 ****
        if (insn & 0x1)
  	*buf++ = '+';
        *buf = '\0';
        break;
  
      case 'b':
        {
! 	unsigned int x = insn;
  	
  	x = (insn & 7);
  	x |= (insn >> 7) & (3 << 3);
--- 124,136 ----
        if (insn & 0x1)
  	*buf++ = '+';
        *buf = '\0';
+       if (AVR_UNDEF_P (insn))
+ 	sprintf (comment, _("undefined"));
        break;
  
      case 'b':
        {
! 	unsigned int x;
  	
  	x = (insn & 7);
  	x |= (insn >> 7) & (3 << 3);
*************** avr_operand (insn, insn2, pc, constraint
*** 165,175 ****
        break;
  
      case 'n':
!       sprintf (buf, _("Internal disassembler error"));
        break;
        
      case 'K':
!       sprintf (buf, "%d", (insn & 0xf) | ((insn >> 2) & 0x30));
        break;
        
      case 's':
--- 176,194 ----
        break;
  
      case 'n':
!       sprintf (buf, "??");
!       fprintf (stderr, _("Internal disassembler error"));
!       ok = 0;
        break;
        
      case 'K':
!       {
! 	unsigned int x;
! 
! 	x = (insn & 0xf) | ((insn >> 2) & 0x30);
! 	sprintf (buf, "0x%02x", x);
! 	sprintf (comment, "%d", x);
!       }
        break;
        
      case 's':
*************** avr_operand (insn, insn2, pc, constraint
*** 205,212 ****
        break;
        
      default:
!       sprintf (buf, _("unknown constraint `%c'"), constraint);
      }
  }
  
  static unsigned short avrdis_opcode PARAMS ((bfd_vma, disassemble_info *));
--- 224,235 ----
        break;
        
      default:
!       sprintf (buf, "??");
!       fprintf (stderr, _("unknown constraint `%c'"), constraint);
!       ok = 0;
      }
+ 
+     return ok;
  }
  
  static unsigned short avrdis_opcode PARAMS ((bfd_vma, disassemble_info *));
*************** print_insn_avr(addr, info)
*** 239,244 ****
--- 262,269 ----
    fprintf_ftype prin = info->fprintf_func;
    static int initialized;
    int cmd_len = 2;
+   int ok = 0;
+   char op1[20], op2[20], comment1[40], comment2[40];
  
    if (!initialized)
      {
*************** print_insn_avr(addr, info)
*** 271,286 ****
  	break;
      }
    
    if (opcode->name)
      {
-       char op1[20], op2[20], comment1[40], comment2[40];
        char *op = opcode->constraints;
  
-       op1[0] = 0;
-       op2[0] = 0;
-       comment1[0] = 0;
-       comment2[0] = 0;
        insn2 = 0;
  
        if (opcode->insn_size > 1)
  	{
--- 296,318 ----
  	break;
      }
    
+   /* Special case: disassemble `ldd r,b+0' as `ld r,b', and
+      `std b+0,r' as `st b,r' (next entry in the table).  */
+ 
+   if (AVR_DISP0_P (insn))
+     opcode++;
+ 
+   op1[0] = 0;
+   op2[0] = 0;
+   comment1[0] = 0;
+   comment2[0] = 0;
+ 
    if (opcode->name)
      {
        char *op = opcode->constraints;
  
        insn2 = 0;
+       ok = 1;
  
        if (opcode->insn_size > 1)
  	{
*************** print_insn_avr(addr, info)
*** 292,320 ****
  	{
  	  int regs = REGISTER_P (*op);
  
! 	  avr_operand (insn, insn2, addr, *op, op1, comment1, 0);
  
! 	  if (*(++op) == ',')
! 	    avr_operand (insn, insn2, addr, *(++op), op2,
! 			 *comment1 ? comment2 : comment1, regs);
  	}
  
!       (*prin) (stream, "    %-8s", opcode->name);
  
!       if (*op1)
! 	(*prin) (stream, "%s", op1);
  
!       if (*op2)
! 	(*prin) (stream, ", %s", op2);
  
!       if (*comment1)
! 	(*prin) (stream, "\t; %s", comment1);
  
-       if (*comment2)
- 	(*prin) (stream, " %s", comment2);
-     }
-   else
-    (*prin) (stream, ".word 0x%04x\t; ????", insn);
-   
    return cmd_len;
  }
--- 324,359 ----
  	{
  	  int regs = REGISTER_P (*op);
  
! 	  ok = avr_operand (insn, insn2, addr, *op, op1, comment1, 0);
  
! 	  if (ok && *(++op) == ',')
! 	    ok = avr_operand (insn, insn2, addr, *(++op), op2,
! 			      *comment1 ? comment2 : comment1, regs);
  	}
+     }
  
!   if (!ok)
!     {
!       /* Unknown opcode, or invalid combination of operands.  */
!       sprintf (op1, "0x%04x", insn);
!       op2[0] = 0;
!       sprintf (comment1, "????");
!       comment2[0] = 0;
!     }
  
!   (*prin) (stream, "%s", ok ? opcode->name : ".word");
  
!   if (*op1)
!     (*prin) (stream, "\t%s", op1);
  
!   if (*op2)
!     (*prin) (stream, ", %s", op2);
! 
!   if (*comment1)
!     (*prin) (stream, "\t; %s", comment1);
! 
!   if (*comment2)
!     (*prin) (stream, " %s", comment2);
  
    return cmd_len;
  }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]