diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c
index 8d48b128fb90..9b207c2e2389 100644
--- a/gas/config/tc-bpf.c
+++ b/gas/config/tc-bpf.c
@@ -1506,7 +1506,28 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
                 }
               else if (*(p + 1) == 'w')
                 {
-                  /* Expect zero or more spaces.  */
+                  /* Expect zero or more spaces.
+
+                     If the template text matched so far ends in a name
+                     character and the input continues with another name
+                     character, then the template only matched a prefix of a
+                     longer mnemonic written in the input, and this template
+                     does not apply.  Rejecting it here lets a subsequent
+                     template have a go at the whole mnemonic.
+
+                     Without this, `gotol +1' matches the `goto%w%d16'
+                     template, with `l +1' parsed as the branch offset
+                     expression, silently assembling to JA (opcode 0x05) plus
+                     a relocation against an undefined symbol `l' instead of
+                     to JAL (opcode 0x06).  */
+                  if (!is_whitespace (*s)
+                      && p > template
+                      && is_part_of_name (*(p - 1))
+                      && is_part_of_name (*s))
+                    {
+                      PARSE_ERROR ("expected white space, got '%s'", s);
+                      break;
+                    }
                   while (is_whitespace (*s))
                     s += 1;
                   p += 2;
diff --git a/gas/testsuite/gas/bpf/bpf.exp b/gas/testsuite/gas/bpf/bpf.exp
index f19322122527..efd1eab08f72 100644
--- a/gas/testsuite/gas/bpf/bpf.exp
+++ b/gas/testsuite/gas/bpf/bpf.exp
@@ -38,6 +38,7 @@ if {[istarget bpf*-*-*]} {
     run_dump_test jump-pseudoc
     run_dump_test jump32
     run_dump_test jump32-pseudoc
+    run_dump_test jump-gotol-signed-pseudoc
     run_dump_test atomic-v1
     run_dump_test atomic
     run_dump_test atomic-pseudoc
diff --git a/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.d b/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.d
new file mode 100644
index 000000000000..ee4146acd996
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.d
@@ -0,0 +1,15 @@
+#as: -EL -mdialect=pseudoc
+#objdump: -dr -M dec,pseudoc
+#source: jump-gotol-signed-pseudoc.s
+#name: eBPF gotol with signed offsets, pseudoc syntax
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+0+ <.text>:
+   0:	06 00 00 00 01 00 00 00 	gotol 1
+   8:	06 00 00 00 ff ff ff ff 	gotol -1
+  10:	06 00 00 00 01 00 00 00 	gotol 1
+  18:	06 00 00 00 00 00 00 00 	gotol 0
+  20:	06 00 00 00 00 00 00 00 	gotol 0
diff --git a/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.s b/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.s
new file mode 100644
index 000000000000..295afd6313d5
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jump-gotol-signed-pseudoc.s
@@ -0,0 +1,10 @@
+        # Signed branch offsets for the pseudo-C `gotol'.  PR gas/34558:
+        # these used to match the shorter `goto' template, with the
+        # trailing `l' parsed as the start of the offset expression.
+        .text
+        gotol +1
+        gotol -1
+        gotol 1
+        gotol 1f
+1:
+        gotol 0
