This is the mail archive of the binutils@sourceware.cygnus.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: pa2.0 branch instructions


This patch adds the new versions of the 'b', 'bve', and 'be' instructions
including the pseudos 'call' and 'ret'.  Apparently HP as doesn't implement
call or ret, despite listing them in the pa2.0 architecture manual.

It passes make check-gas.

To create the 'X' code handling, I cloned 'W' and set format to 22.  I can't
figure out where it gets used so there's a chance that something might still
be broken with 22 bit displacement branch.

Jerry


Changelog entry:

Tue Sep 21 16:45:50 EDT 1999  Jerry Quinn <jerry.quinn.adv91@alum.dartmouth.org>

    * gas/config/tc-hppa.c (pa_ip): Add branch completers for gate, link and
      push, link, pop, and 22 bit displacement.  Add implicit argument codes.
    * opcodes/hppa-dis.c (print_insn_hppa):  Same.
    * include/opcode/hppa.h (pa_opcodes): Add new entries for 'b', 'bve',
      'be', 'call', and 'ret'.
    * gas/testsuite/gas/hppa/basic/basic.exp,branch2.s:  Add tests for new
      branch instructions


*** orig/gas/config/tc-hppa.c	Thu Sep 16 15:21:12 1999
--- gas-src/gas/config/tc-hppa.c	Tue Sep 21 16:22:07 1999
***************
*** 1807,1812 ****
--- 1807,1840 ----
  		    INSERT_FIELD_AND_CONTINUE (opcode, a, 13);
  		  }
  
+ 		/* Handle a branch gate completer.  */
+ 		case 'g':
+ 		  if (strncasecmp (s, ",gate", 5) != 0)
+ 		    break;
+ 		  s += 5;
+ 		  continue;
+ 
+ 		/* Handle a branch link and push completer.  */
+ 		case 'p':
+ 		  if (strncasecmp (s, ",l,push", 7) != 0)
+ 		    break;
+ 		  s += 7;
+ 		  continue;
+ 
+ 		/* Handle a branch link completer.  */
+ 		case 'l':
+ 		  if (strncasecmp (s, ",l", 2) != 0)
+ 		    break;
+ 		  s += 2;
+ 		  continue;
+ 
+ 		/* Handle a branch pop completer.  */
+ 		case 'P':
+ 		  if (strncasecmp (s, ",pop", 4) != 0)
+ 		    break;
+ 		  s += 4;
+ 		  continue;
+ 
  		/* Handle a local processor completer.  */
  		case 'L':
  		  if (strncasecmp (s, ",l", 2) != 0)
***************
*** 2826,2831 ****
--- 2854,2897 ----
  		  continue;
  		}
  
+ 	    /* Handle a 22 bit branch displacement.  */
+ 	    case 'X':
+ 	      the_insn.field_selector = pa_chk_field_selector (&s);
+ 	      get_expression (s);
+ 	      s = expr_end;
+ 	      the_insn.pcrel = 1;
+ 	      if (!the_insn.exp.X_add_symbol
+ 		  || !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
+ 			      "L$0\001"))
+ 		{
+ 		  unsigned int w3, w2, w1, w, result;
+ 
+ 		  num = evaluate_absolute (&the_insn);
+ 		  if (num % 4)
+ 		    {
+ 		      as_bad (_("Branch to unaligned address"));
+ 		      break;
+ 		    }
+ 		  CHECK_FIELD (num, 8388607, -8388608, 0);
+ 
+ 		  if (the_insn.exp.X_add_symbol)
+ 		    num -= 8;
+ 
+ 		  sign_unext (num >> 2, 17, &result);
+ 		  dis_assemble_22 (result, &w3, &w1, &w2, &w);
+ 		  INSERT_FIELD_AND_CONTINUE (opcode,
+ 					     ((w3 << 21) | (w2 << 2) 
+ 					      | (w1 << 16) | w), 0);
+ 		}
+ 	      else
+ 		{
+ 		  the_insn.reloc = R_HPPA_PCREL_CALL;
+ 		  the_insn.format = 22;
+ 		  the_insn.arg_reloc = last_call_desc.arg_reloc;
+ 		  memset (&last_call_desc, 0, sizeof (struct call_desc));
+ 		  continue;
+ 		}
+ 
  	    /* Handle '%r1' implicit operand of addil instruction.  */
  	    case 'Z':
  	      if (*s == ',' && *(s + 1) == '%' && *(s + 3) == '1'
***************
*** 2837,2842 ****
--- 2904,2923 ----
  	      else
  	        break;
  
+ 	    /* Handle '%r2' implicit operand of b,l instruction.  */
+ 	    case '&':
+ 	      if (strncasecmp (s, "%r2", 3) != 0)
+ 		break;
+ 	      s += 3;
+ 	      continue;
+ 
+ 	    /* Handle '%sr0,%r31' implicit operand of be,l instruction.  */
+ 	    case 'Y':
+ 	      if (strncasecmp (s, "%sr0,%r31", 9) != 0)
+ 		break;
+ 	      s += 9;
+ 	      continue;
+ 
  	    /* Handle a 2 bit shift count at 25.  */
  	    case '.':
  	      num = pa_get_absolute_expression (&the_insn, &s);
***************
*** 3727,3733 ****
    char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
    struct hppa_fix_struct *hppa_fixP;
    long new_val, result = 0;
!   unsigned int w1, w2, w, resulti;
  
    hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
    /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can
--- 3808,3814 ----
    char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
    struct hppa_fix_struct *hppa_fixP;
    long new_val, result = 0;
!   unsigned int w1, w2, w3, w, resulti;
  
    hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
    /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can
***************
*** 3881,3886 ****
--- 3962,3991 ----
  	    sign_unext ((new_val - 8) >> 2, 17, &resulti);
  	    dis_assemble_17 (resulti, &w1, &w2, &w);
  	    result = ((w2 << 2) | (w1 << 16) | w);
+ 	    break;
+ 	  }
+ 
+ 	/* Handle some of the opcodes with the 'X' operand type.  */
+ 	case 22:
+ 	  {
+ 	    int distance = *valp;
+ 
+ 	    CHECK_FIELD (new_val, 8388607, -8388608, 0);
+ 
+ 	    /* If I understand right, this test isn't required because all
+ 	       22 bit targets are branch and link. */
+ 	    /*	    if (fixP->fx_r_type == R_HPPA_PCREL_CALL
+ 		&& (distance > 8388607 || distance < -8388608)
+ 		&& (bfd_get_32 (stdoutput, buf) & 0xffe00000) == 0xe8000000)
+ 		CHECK_FIELD (distance, 8388607, -8388608, 0); */
+ 
+ 	    /* Mask off 22 bits to be changed.  */
+ 	    bfd_put_32 (stdoutput,
+ 			bfd_get_32 (stdoutput, buf) & 0xfc00e002,
+ 			buf);
+ 	    sign_unext ((new_val - 8) >> 2, 22, &resulti);
+ 	    dis_assemble_22 (resulti, &w3, &w1, &w2, &w);
+ 	    result = ((w3 << 21) | (w2 << 2) | (w1 << 16) | w);
  	    break;
  	  }
  
*** orig/include/opcode/hppa.h	Thu Sep 16 15:21:25 1999
--- gas-src/include/opcode/hppa.h	Tue Sep 21 16:28:34 1999
***************
*** 70,77 ****
  
     In the args field, the following characters are unused:
  
! 	'  "#  &     -  /   34 6789:;< > @'
! 	' BC      JKLM          XY [\]  '
  	'   de gh   lm           y { } '
  
     Here are all the characters:
--- 70,77 ----
  
     In the args field, the following characters are unused:
  
! 	'  "#        -  /   34 6789:;< > @'
! 	' BC      JKLM             [\]  '
  	'   de gh   lm           y { } '
  
     Here are all the characters:
***************
*** 97,102 ****
--- 97,103 ----
     w    12 bit branch displacement
     W    17 bit branch displacement (PC relative)
     z    17 bit branch displacement (just a number, not an address)
+    X    22 bit branch displacement (PC relative)
  
  Also these:
  
***************
*** 143,149 ****
--- 144,152 ----
     Q	5 bit immediate value at 10 (a bit position specified in
  	the bb instruction. It's the same as r above, except the
          value is in a different location)
+    &	%r2 -- return address register for b,l.
     Z    %r1 -- implicit target of addil instruction.
+    Y    %sr0,%r31 -- implicit target of be,l instruction.
  
  Completer operands all have 'c' as the prefix:
  
***************
*** 151,156 ****
--- 154,164 ----
     cm   short load and store completer.
     cs   store bytes short completer.
  
+    cp	branch link and push completer
+    cP	branch pop completer
+    cl	branch link completer
+    cg	branch gate completer
+ 
     cw	read/write completer for PROBE
     cW	wide completer for MFCTL
     cL	local processor completer for cache control
***************
*** 245,252 ****
  
  /* pseudo-instructions */
  
- { "b",		0xe8000000, 0xffe0e000, "nW", pa10}, /* bl foo,r0 */
  { "ldi",	0x34000000, 0xffe0c000, "j,x", pa10},	/* ldo val(r0),r */
  { "comib", 	0x84000000, 0xfc000000, "?nn5,b,w", pa10}, /* comib{tf}*/
  /* This entry is for the disassembler only.  It will never be used by
     assembler.  */
--- 253,262 ----
  
  /* pseudo-instructions */
  
  { "ldi",	0x34000000, 0xffe0c000, "j,x", pa10},	/* ldo val(r0),r */
+ { "call",	0xe800f000, 0xfc1ffffd, "n(b)", pa20, FLAG_STRICT},  /* bve,l (b),r2 */
+ { "call",	0xe800a000, 0xffe0e000, "nW", pa10, FLAG_STRICT},  /* b,l foo,r2 */
+ { "ret",	0xe840d000, 0xfffffffd, "n", pa20, FLAG_STRICT},  /* bve (r2) */
  { "comib", 	0x84000000, 0xfc000000, "?nn5,b,w", pa10}, /* comib{tf}*/
  /* This entry is for the disassembler only.  It will never be used by
     assembler.  */
***************
*** 362,373 ****
--- 372,395 ----
  { "addil",	0x28000000, 0xfc000000, "k,b", pa10},
  
  /* Branching instructions. */
+ { "b",		0xe8008000, 0xfc00e000, "cpnX,&", pa20, FLAG_STRICT},
+ { "b",		0xe800a000, 0xfc00e000, "clnX,&", pa20, FLAG_STRICT},
+ { "b",		0xe8000000, 0xfc00e000, "clnW,b", pa10, FLAG_STRICT},
+ { "b",		0xe8002000, 0xfc00e000, "cgnW,b", pa10, FLAG_STRICT},
+ { "b",		0xe8000000, 0xffe0e000, "nW", pa10},  /* b,l foo,r0 */
  { "bl",		0xe8000000, 0xfc00e000, "nW,b", pa10},
  { "gate",	0xe8002000, 0xfc00e000, "nW,b", pa10},
  { "blr",	0xe8004000, 0xfc00e001, "nx,b", pa10},
  { "bv",		0xe800c000, 0xfc00fffd, "nx(b)", pa10},
  { "bv",		0xe800c000, 0xfc00fffd, "n(b)", pa10},
+ { "bve",	0xe800f001, 0xfc1ffffd, "cpn(b),&", pa20, FLAG_STRICT},
+ { "bve",	0xe800f000, 0xfc1ffffd, "cln(b),&", pa20, FLAG_STRICT},
+ { "bve",	0xe800d001, 0xfc1ffffd, "cPn(b)", pa20, FLAG_STRICT},
+ { "bve",	0xe800d000, 0xfc1ffffd, "n(b)", pa20, FLAG_STRICT},
+ { "be",		0xe4000000, 0xfc000000, "clnz(S,b),Y", pa10, FLAG_STRICT},
+ { "be",		0xe4000000, 0xfc000000, "clnz(b),Y", pa10, FLAG_STRICT},
  { "be",		0xe0000000, 0xfc000000, "nz(S,b)", pa10},
+ { "be",		0xe0000000, 0xfc000000, "nz(b)", pa10},
  { "ble",	0xe4000000, 0xfc000000, "nz(S,b)", pa10},
  { "movb",	0xc8000000, 0xfc000000, "?ynx,b,w", pa10},
  { "movib",	0xcc000000, 0xfc000000, "?yn5,b,w", pa10},
*** orig/opcodes/hppa-dis.c     Thu Sep 16 15:21:34 1999
--- gas-src/opcodes/hppa-dis.c  Tue Sep 21 16:52:13 1999
***************
*** 317,322 ****
--- 317,336 ----
                        (word & 0x1) << 16, 17) << 2;
  }
  
+ /* extract a 22 bit constant from branch instructions, returning the
+    24 bit signed value. */
+ 
+ static int
+ extract_22 (word)
+      unsigned word;
+ {
+   return sign_extend (GET_FIELD (word, 19, 28) |
+                       GET_FIELD (word, 29, 29) << 10 |
+                       GET_FIELD (word, 11, 15) << 11 |
+                     GET_FIELD (word, 6, 10) << 16 |
+                       (word & 0x1) << 21, 17) << 2;
+ }
+ 
  /* Print one instruction.  */
  int
  print_insn_hppa (memaddr, info)
***************
*** 485,490 ****
--- 499,514 ----
                      (*info->fprintf_func) (info->stream, "%s ",
                                             short_bytes_compl_names[GET_COMPL (insn)]);
                      break;
+                   case 'g':
+                     (*info->fprintf_func) (info->stream, ",gate");
+                     break;
+                   case 'p':
+                     (*info->fprintf_func) (info->stream, ",l,push");
+                     break;
+                   case 'P':
+                     (*info->fprintf_func) (info->stream, ",pop");
+                     break;
+                   case 'l':
                    case 'L':
                      (*info->fprintf_func) (info->stream, ",l");
                      break;
***************
*** 757,762 ****
--- 781,792 ----
                                                + extract_17 (insn)),
                                               info);
                  break;
+               case 'X':
+                 /* 22 bit PC-relative branch.  */
+                 (*info->print_address_func) ((memaddr + 8 
+                                               + extract_22 (insn)),
+                                              info);
+                 break;
                case 'z':
                  /* 17 bit displacement.  This is an offset from a register
                     so it gets disasssembled as just a number, not any sort
***************
*** 767,772 ****
--- 797,812 ----
                case 'Z':
                  /* addil %r1 implicit output.  */
                  (*info->fprintf_func) (info->stream, "%%r1");
+                 break;
+                 
+               case '&':
+                 /* b,l %r2 implicit output.  */
+                 (*info->fprintf_func) (info->stream, "%%r2");
+                 break;
+                 
+               case 'Y':
+                 /* be,l %sr0,%r31 implicit output.  */
+                 (*info->fprintf_func) (info->stream, "%%sr0,%%r31");
                  break;
                  
                case '.':
*** orig/bfd/libhppa.h	Mon Sep 20 15:55:50 1999
--- gas-src/bfd/libhppa.h	Tue Sep 21 16:09:43 1999
***************
*** 606,611 ****
--- 606,619 ----
        fmt = 14;
        break;
      case BL:
+       {
+ 	unsigned char ext = (insn & 0xe000) >> 13;
+ 	if (ext == 4 || ext == 5)
+ 	  fmt = 22;
+ 	else
+ 	  fmt = 17;
+ 	break;
+       }
      case BE:
      case BLE:
        fmt = 17;
diff -c orig/gas/testsuite/gas/hppa/basic/basic.exp gas-src/gas/testsuite/gas/hppa/basic/basic.exp
*** orig/gas/testsuite/gas/hppa/basic/basic.exp	Fri Sep 17 14:41:32 1999
--- gas-src/gas/testsuite/gas/hppa/basic/basic.exp	Fri Sep 17 15:19:59 1999
***************
*** 391,396 ****
--- 391,422 ----
  	    -re "^ +\[0-9\]+ 0038 E8004F9D\[^\n\]*\n"	{ set x [expr $x+1] }
  	    -re "^ +\[0-9\]+ 003c E8004001\[^\n\]*\n"	{ set x [expr $x+1] }
  	    -re "^ +\[0-9\]+ 0040 E8044001\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0044 EBFF9FF5\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0048 EBFF9FEF\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 004c EBFFBFE5\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0050 EBFFBFDF\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0054 EA7F1FD5\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0058 EA7F1FCF\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 005c EA7F3FC5\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0060 EA7F3FBF\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0064 EBFFBFB5\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0068 EBFFBFAF\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 006c E8A0F000\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0070 E8A0F002\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0074 E840D000\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0078 E840D002\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 007c E8A0D000\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0080 E8A0D002\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0084 E8A0D001\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0088 E8A0D003\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 008c E8A0F000\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0090 E8A0F002\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0094 E8A0F001\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 0098 E8A0F003\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 009c E4A0446C\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 00a0 E4A0046C\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 00a4 E4A0446E\[^\n\]*\n"	{ set x [expr $x+1] }
+ 	    -re "^ +\[0-9\]+ 00a8 E4A0046E\[^\n\]*\n"	{ set x [expr $x+1] }
  	    -re "\[^\n\]*\n"				{ }
  	    timeout				{ perror "timeout\n"; break }
  	    eof					{ break }
***************
*** 402,408 ****
      gas_finish
  
      # Did we find what we were looking for?  If not, flunk it.
!     if [expr $x==17] then { pass $testname } else { fail $testname }
  }
  
  proc do_add {} {
--- 428,434 ----
      gas_finish
  
      # Did we find what we were looking for?  If not, flunk it.
!     if [expr $x==43] then { pass $testname } else { fail $testname }
  }
  
  proc do_add {} {
diff -c orig/gas/testsuite/gas/hppa/basic/branch2.s gas-src/gas/testsuite/gas/hppa/basic/branch2.s
*** orig/gas/testsuite/gas/hppa/basic/branch2.s	Fri Sep 17 14:41:32 1999
--- gas-src/gas/testsuite/gas/hppa/basic/branch2.s	Fri Sep 17 17:04:03 1999
***************
*** 9,15 ****
  ; immediate fields.  We should also check the assorted field
  ; selectors to make sure they're handled correctly.
  
! bb_tests:	
  	bb,< %r4,%sar,bb_tests
  	bb,>= %r4,%sar,bb_tests
  	bb,<,n %r4,%cr11,bb_tests
--- 9,15 ----
  ; immediate fields.  We should also check the assorted field
  ; selectors to make sure they're handled correctly.
  
! bb_tests	
  	bb,< %r4,%sar,bb_tests
  	bb,>= %r4,%sar,bb_tests
  	bb,<,n %r4,%cr11,bb_tests
***************
*** 23,32 ****
  	bb,*<,n %r4,5,bb_tests
  	bb,*>=,n %r4,5,bb_tests
  	
! branch_stack:	
  	clrbts
  	popbts 1
  	popbts 499
  	pushnom
  	pushbts %r4
  
--- 23,70 ----
  	bb,*<,n %r4,5,bb_tests
  	bb,*>=,n %r4,5,bb_tests
  	
! branch_stack	
  	clrbts
  	popbts 1
  	popbts 499
  	pushnom
  	pushbts %r4
  
+ branch_tests	
+ 	b,l,push branch_tests,%r2
+ 	b,l,push,n branch_tests,%r2
+ 	b,l branch_tests,%r2
+ 	b,l,n branch_tests,%r2
+ 	b,l branch_tests,%r19
+ 	b,l,n branch_tests,%r19
+ 	b,gate branch_tests,%r19
+ 	b,gate,n branch_tests,%r19
+ 
+ ; The commented insns are used to get HP assembler to generate test reference
+ ; opcodes.  The HP assembler doesn't support these pseudos despite listing
+ ; them in the architecture manual
+ 	call branch_tests
+ 	call,n branch_tests
+ ;	b,l branch_tests,%r2
+ ;	b,l,n branch_tests,%r2
+ 	call (%r5)
+ 	call,n (%r5)
+ 	ret
+ 	ret,n
+ ;	bve,l (%r5),%r2
+ ;	bve,l,n (%r5),%r2
+ ;	bve (%r2)
+ ;	bve,n (%r2)
+ 		
+ 	bve (%r5)
+ 	bve,n (%r5)
+ 	bve,pop (%r5)
+ 	bve,pop,n (%r5)
+ 	bve,l (%r5),%r2
+ 	bve,l,n (%r5),%r2
+ 	bve,l,push (%r5),%r2
+ 	bve,l,push,n (%r5),%r2
+ 	be,l 0x1234(%sr1,%r5),%sr0,%r31
+ 	be,l 0x1234(%r5),%sr0,%r31
+ 	be,l,n 0x1234(%sr1,%r5),%sr0,%r31
+ 	be,l,n 0x1234(%r5),%sr0,%r31


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