+2023-08-17  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+       * config/tc-bpf.c (check_immediate_overflow): New function.
+       (encode_insn): Use check_immediate_overflow.
+       (md_assemble): Do not relax instructions with
+       constant disp16 fields.
+       * doc/c-bpf.texi (BPF Instructions): Add note about how numerical
+       literal values are interpreted for instruction immediate operands.
+       * testsuite/gas/bpf/disp16-overflow.s: Adapt accordingly.
+       * testsuite/gas/bpf/jump-relax-jump.s: Likewise.
+       * testsuite/gas/bpf/jump-relax-jump.d: Likewise.
+       * testsuite/gas/bpf/jump-relax-jump-be.d: Likewise.
+       * testsuite/gas/bpf/jump-relax-ja.s: Likewise.
+       * testsuite/gas/bpf/jump-relax-ja.d: Likewise.
+       * testsuite/gas/bpf/jump-relax-ja-be.d: Likewise.
+       * testsuite/gas/bpf/disp16-overflow-relax.l: Likewise.
+       * testsuite/gas/bpf/imm32-overflow.s: Likewise.
+       * testsuite/gas/bpf/disp32-overflow.s: Likewise.
+       * testsuite/gas/bpf/disp16-overflow.l: Likewise.
+       * testsuite/gas/bpf/disp32-overflow.l: Likewise.
+       * testsuite/gas/bpf/imm32-overflow.l: Likewise.
+       * testsuite/gas/bpf/offset16-overflow.l: Likewise.
+
 2023-07-30  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
        * config/tc-bpf.h (elf_tc_final_processing): Define.
 
   return (value < -lim || value >= lim);
 }
 
+/* Return non-zero if the two's complement encoding of VALUE would
+   overflow an immediate field of width BITS bits.  */
+
+static bool
+immediate_overflow (int64_t value, unsigned bits)
+{
+  if (value < 0)
+    return signed_overflow (value, bits);
+  else
+    {
+      valueT lim;
+
+      if (bits >= sizeof (valueT) * 8)
+        return false;
+
+      lim = (valueT) 1 << bits;
+      return ((valueT) value >= lim);
+    }
+}
+
 \f
 /* Functions concerning relocs.  */
 
 #define RELAX_BRANCH_UNCOND(i) (((i) & 1) != 0)
 
 
-/* Compute the length of a branch seuqence, and adjust the stored
+/* Compute the length of a branch sequence, and adjust the stored
    length accordingly.  If FRAG is NULL, the worst-case length is
    returned.  */
 
    immediates are encoded as zeroes.  */
 
 static void
-encode_insn (struct bpf_insn *insn, char *bytes, int relaxed)
+encode_insn (struct bpf_insn *insn, char *bytes,
+             int relaxed ATTRIBUTE_UNUSED)
 {
   uint8_t src, dst;
 
     {
       int64_t imm = insn->imm32.X_add_number;
 
-      if (signed_overflow (imm, 32))
-        as_bad (_("signed immediate out of range, shall fit in 32 bits"));
+      if (immediate_overflow (imm, 32))
+        as_bad (_("immediate out of range, shall fit in 32 bits"));
       else
         encode_int32 (insn->imm32.X_add_number, bytes + 4);        
     }
     {
       int64_t disp = insn->disp32.X_add_number;
 
-      if (signed_overflow (disp, 32))
-        as_bad (_("signed pc-relative offset out of range, shall fit in 32 bits"));
+      if (immediate_overflow (disp, 32))
+        as_bad (_("pc-relative offset out of range, shall fit in 32 bits"));
       else
         encode_int32 (insn->disp32.X_add_number, bytes + 4);
     }
     {
       int64_t offset = insn->offset16.X_add_number;
 
-      if (signed_overflow (offset, 16))
-        as_bad (_("signed pc-relative offset out of range, shall fit in 16 bits"));
+      if (immediate_overflow (offset, 16))
+        as_bad (_("pc-relative offset out of range, shall fit in 16 bits"));
       else
         encode_int16 (insn->offset16.X_add_number, bytes + 2);
     }
     {
       int64_t disp = insn->disp16.X_add_number;
 
-      if (!relaxed && signed_overflow (disp, 16))
-        as_bad (_("signed pc-relative offset out of range, shall fit in 16 bits"));
+      if (immediate_overflow (disp, 16))
+        as_bad (_("pc-relative offset out of range, shall fit in 16 bits"));
       else
         encode_int16 (insn->disp16.X_add_number, bytes + 2);
     }
                       break;
                     }
                   insn.has_disp16 = 1;
-                  insn.is_relaxable = 1;
+                  insn.is_relaxable = (insn.disp16.X_op != O_constant);
                   p += 4;
                 }
               else if (strncmp (p, "%d32", 4) == 0)
 
 {
   { "hix",             BFD_RELOC_SPARC_HIX22,          F_POP_V9 },
   { "lox",             BFD_RELOC_SPARC_LOX10,          F_POP_V9 },
-  { "hi",              BFD_RELOC_HI22,                 F_POP_PCREL },
+  { "hi"5,             BFD_RELOC_HI22,                 F_POP_PCREL },
   { "lo",              BFD_RELOC_LO10,                 F_POP_PCREL },
   { "pc22",            BFD_RELOC_SPARC_PC22,           F_POP_PCREL },
   { "pc10",            BFD_RELOC_SPARC_PC10,           F_POP_PCREL },
 
 Signed 64-bit immediate.
 @end table
 
+@noindent
+Note that the assembler allows to express the value for an immediate
+using any numerical literal whose two's complement encoding fits in
+the immediate field.  For example, @code{-2}, @code{0xfffffffe} and
+@code{4294967294} all denote the same encoded 32-bit immediate, whose
+value may be then interpreted by different instructions as either as a
+negative or a positive number.
+
 @subsection Arithmetic instructions
 
 The destination register in these instructions act like an
 
 .*: Assembler messages:
-.*:2: Error: signed instruction operand out of range, shall fit in 32 bits
-.*:4: Error: signed instruction operand out of range, shall fit in 32 bits
+.*:1: Error: pc-relative offset out of range, shall fit in 16 bits
+.*:2: Error: pc-relative offset out of range, shall fit in 16 bits
+.*:3: Error: pc-relative offset out of range, shall fit in 16 bits
+.*:4: Error: pc-relative offset out of range, shall fit in 16 bits
 
-        jeq %r1,%r2,2147483647
+        jeq %r1,%r2,2147483647  ; Overflows.
         jlt %r3,%r4,2147483648  ; Overflows.
-        jge %r5,10,-2147483648
+        jge %r5,10,-2147483648  ; Overflows.
         ja -2147483649          ; Overflows.
 
 .*: Assembler messages:
-.*:2: Error: signed pc-relative offset out of range, shall fit in 16 bits
-.*:4: Error: signed pc-relative offset out of range, shall fit in 16 bits
+.*:2: Error: pc-relative offset out of range, shall fit in 16 bits
+.*:4: Error: pc-relative offset out of range, shall fit in 16 bits
 
         ja 32767
-        jeq %r1,%r2,32768       ; Overflows
+        jeq %r1,%r2,65536       ; Overflows
         jlt %r3,%r4,-32768
         jge %r5,10,-32769       ; Overflows
 
 .*: Assembler messages:
-.*:2: Error: signed pc-relative offset out of range, shall fit in 32 bits
-.*:4: Error: signed pc-relative offset out of range, shall fit in 32 bits
+.*:2: Error: pc-relative offset out of range, shall fit in 32 bits
+.*:4: Error: pc-relative offset out of range, shall fit in 32 bits
 
         call -2147483648
         call -2147483649        ; This overflows.
-        call 2147483647
-        call 2147483648         ; This overflows.
+        call 4294967295
+        call 4294967296         ; This overflows.
 
 .*: Assembler messages:
-.*:2: Error: signed immediate out of range, shall fit in 32 bits
-.*:4: Error: signed immediate out of range, shall fit in 32 bits
+.*:2: Error: immediate out of range, shall fit in 32 bits
+.*:4: Error: immediate out of range, shall fit in 32 bits
 
         add %r1, 2147483647
-        or %r2, 2147483648         ; This overflows.
-        xor %r3, -2147483648
-        sub %r4, -2147483649       ; This overflows.
+        or %r2, 4294967296         ; This overflows.
+        xor %r3, 4294967295
+        sub %r4, 4294967296        ; This overflows.
 
   10:  05 00 ff fd 00 00 00 00         ja -3
   18:  05 00 00 00 00 00 00 00         ja 0
                        18: R_BPF_GNU_64_16     undefined
-  20:  06 00 00 00 ff ff 7f ff         jal -32769
-  28:  06 00 00 00 00 00 80 00         jal 32768
-  30:  06 00 00 00 00 00 80 01         jal 32769
-  38:  06 00 00 00 00 00 80 01         jal 32769
+  20:  06 00 00 00 00 00 80 01         jal 32769
+  28:  06 00 00 00 00 00 80 01         jal 32769
 
   10:  05 00 fd ff 00 00 00 00         ja -3
   18:  05 00 00 00 00 00 00 00         ja 0
                        18: R_BPF_GNU_64_16     undefined
-  20:  06 00 00 00 ff 7f ff ff         jal -32769
-  28:  06 00 00 00 00 80 00 00         jal 32768
-  30:  06 00 00 00 01 80 00 00         jal 32769
-  38:  06 00 00 00 01 80 00 00         jal 32769
+  20:  06 00 00 00 01 80 00 00         jal 32769
+  28:  06 00 00 00 01 80 00 00         jal 32769
 
         ;; The following instruction has an undefined symbol as a
         ;; target.  It is not to be relaxed.
         ja undefined + 10
-        ;; The following instructions are relaxed to JAL instructions
-        ;; so they can fit their displacements.
-        ja -32769
-        ja 32768
         ;; The following instructions refer to a defined symbol that
         ;; is not on reach.  They shall be relaxed to a JAL.
         ja tail
 
    0:  1d 12 80 00 00 00 00 00         jeq %r1,%r2,-32768
    8:  ad 12 7f ff 00 00 00 00         jlt %r1,%r2,32767
   10:  bd 12 ff fd 00 00 00 00         jle %r1,%r2,-3
-  18:  3d 12 00 01 00 00 00 00         jge %r1,%r2,1
+  18:  1d 12 00 01 00 00 00 00         jeq %r1,%r2,1
   20:  05 00 00 01 00 00 00 00         ja 1
-  28:  06 00 00 00 ff ff 7f ff         jal -32769
+  28:  06 00 00 00 00 00 80 01         jal 32769
   30:  2d 12 00 01 00 00 00 00         jgt %r1,%r2,1
   38:  05 00 00 01 00 00 00 00         ja 1
-  40:  06 00 00 00 00 00 80 00         jal 32768
-  48:  1d 12 00 01 00 00 00 00         jeq %r1,%r2,1
-  50:  05 00 00 01 00 00 00 00         ja 1
-  58:  06 00 00 00 00 00 80 01         jal 32769
-  60:  2d 12 00 01 00 00 00 00         jgt %r1,%r2,1
-  68:  05 00 00 01 00 00 00 00         ja 1
-  70:  06 00 00 00 00 00 80 01         jal 32769
+  40:  06 00 00 00 00 00 80 01         jal 32769
 
    0:  1d 21 00 80 00 00 00 00         jeq %r1,%r2,-32768
    8:  ad 21 ff 7f 00 00 00 00         jlt %r1,%r2,32767
   10:  bd 21 fd ff 00 00 00 00         jle %r1,%r2,-3
-  18:  3d 21 01 00 00 00 00 00         jge %r1,%r2,1
+  18:  1d 21 01 00 00 00 00 00         jeq %r1,%r2,1
   20:  05 00 01 00 00 00 00 00         ja 1
-  28:  06 00 00 00 ff 7f ff ff         jal -32769
+  28:  06 00 00 00 01 80 00 00         jal 32769
   30:  2d 21 01 00 00 00 00 00         jgt %r1,%r2,1
   38:  05 00 01 00 00 00 00 00         ja 1
-  40:  06 00 00 00 00 80 00 00         jal 32768
-  48:  1d 21 01 00 00 00 00 00         jeq %r1,%r2,1
-  50:  05 00 01 00 00 00 00 00         ja 1
-  58:  06 00 00 00 01 80 00 00         jal 32769
-  60:  2d 21 01 00 00 00 00 00         jgt %r1,%r2,1
-  68:  05 00 01 00 00 00 00 00         ja 1
-  70:  06 00 00 00 01 80 00 00         jal 32769
+  40:  06 00 00 00 01 80 00 00         jal 32769
 
         ;; The following instruction refers to a defined symbol that
         ;; is on reach, so it should not be relaxed.
         jle %r1, %r2, 1b
-        ;; The following instructions are relaxed to sequences
-        ;; involving unconditional jumps, so they can fi their
-        ;; displacements.
-        jge %r1, %r2, -32769
-        jgt %r1, %r2, 32768
         ;; The following instructions refer to a defined symbol that
         ;; is not on reach.  They shall be relaxed.
         jeq %r1, %r2, tail
 
 .*: Assembler messages:
-.*:2: Error: signed pc-relative offset out of range, shall fit in 16 bits
-.*:4: Error: signed pc-relative offset out of range, shall fit in 16 bits
+.*:2: Error: pc-relative offset out of range, shall fit in 16 bits
+.*:4: Error: pc-relative offset out of range, shall fit in 16 bits
 
-        ldxh %r2, [%r1 + 32767]
-        ldxw %r2, [%r1 + 32768]  ; This overflows
+        ldxh %r2, [%r1 + 65535]
+        ldxw %r2, [%r1 + 65536]  ; This overflows
         stxw [%r2 - 32768], %r1
         stxdw [%r2 - 32769], %r1  ; This overflows