This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
Patch: pa2.0 branch instructions
- To: binutils at sourceware dot cygnus dot com
- Subject: Patch: pa2.0 branch instructions
- From: "Jerry Quinn" <jquinn at nortelnetworks dot com>
- Date: Tue, 21 Sep 1999 20:48:50 +0000
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