[RFC PATCH 5/5] RISC-V: Add Zcmt table-jump linker tests

Jiawei <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
This patch adds zcmt table jump relaxation tests.

Cover opt-in behavior, profitability, RV32/RV64 table emission,
no-benefit and no-Zcmt cases, PIC/shared negative behavior,
section layout, symbol policy, addends, GC, overflow,
and the Zcd encoding conflict.

ld/ChangeLog:

	* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add Zcmt tests.
	* testsuite/ld-riscv-elf/table-jump-addend.d: New test.
	* testsuite/ld-riscv-elf/table-jump-addend.s: New test.
	* testsuite/ld-riscv-elf/table-jump-base-collision.d: New test.
	* testsuite/ld-riscv-elf/table-jump-base-collision.s: New test.
	* testsuite/ld-riscv-elf/table-jump-base-local-collision.d: New test.
	* testsuite/ld-riscv-elf/table-jump-base-local-collision.s: New test.
	* testsuite/ld-riscv-elf/table-jump-be32-bytes.d: New test.
	* testsuite/ld-riscv-elf/table-jump-be32-text.d: New test.
	* testsuite/ld-riscv-elf/table-jump-be64-bytes.d: New test.
	* testsuite/ld-riscv-elf/table-jump-be64-text.d: New test.
	* testsuite/ld-riscv-elf/table-jump-benefit.d: New test.
	* testsuite/ld-riscv-elf/table-jump-benefit.s: New test.
	* testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d: New test.
	* testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d: New test.
	* testsuite/ld-riscv-elf/table-jump-default-jvt.d: New test.
	* testsuite/ld-riscv-elf/table-jump-default-no-jvt.d: New test.
	* testsuite/ld-riscv-elf/table-jump-dump-unknown.d: New test.
	* testsuite/ld-riscv-elf/table-jump-emit-relocs.d: New test.
	* testsuite/ld-riscv-elf/table-jump-equal-benefit.d: New test.
	* testsuite/ld-riscv-elf/table-jump-equal-benefit.s: New test.
	* testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d: New test.
	* testsuite/ld-riscv-elf/table-jump-gc-comdat.d: New test.
	* testsuite/ld-riscv-elf/table-jump-gc-comdat.s: New test.
	* testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d: New test.
	* testsuite/ld-riscv-elf/table-jump-gc-dead.d: New test.
	* testsuite/ld-riscv-elf/table-jump-gc-dead.s: New test.
	* testsuite/ld-riscv-elf/table-jump-jalt.d: New test.
	* testsuite/ld-riscv-elf/table-jump-jt.d: New test.
	* testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s: New test.
	* testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d: New test.
	* testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s: New test.
	* testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d: New test.
	* testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s: New test.
	* testsuite/ld-riscv-elf/table-jump-no-benefit-section.d: New test.
	* testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d: New test.
	* testsuite/ld-riscv-elf/table-jump-no-benefit.s: New test.
	* testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d: New test.
	* testsuite/ld-riscv-elf/table-jump-no-relo-1.s: New test.
	* testsuite/ld-riscv-elf/table-jump-no-relo-2.s: New test.
	* testsuite/ld-riscv-elf/table-jump-no-relo.d: New test.
	* testsuite/ld-riscv-elf/table-jump-no-zcmt.d: New test.
	* testsuite/ld-riscv-elf/table-jump-no-zcmt.s: New test.
	* testsuite/ld-riscv-elf/table-jump-norelax.d: New test.
	* testsuite/ld-riscv-elf/table-jump-norelax.s: New test.
	* testsuite/ld-riscv-elf/table-jump-overflow.d: New test.
	* testsuite/ld-riscv-elf/table-jump-overflow.s: New test.
	* testsuite/ld-riscv-elf/table-jump-pie-relocs.d: New test.
	* testsuite/ld-riscv-elf/table-jump-pie-text.d: New test.
	* testsuite/ld-riscv-elf/table-jump-pie.d: New test.
	* testsuite/ld-riscv-elf/table-jump-pie.s: New test.
	* testsuite/ld-riscv-elf/table-jump-relax-zcmt.d: New test.
	* testsuite/ld-riscv-elf/table-jump-rv32.d: New test.
	* testsuite/ld-riscv-elf/table-jump-rv32.s: New test.
	* testsuite/ld-riscv-elf/table-jump-shared-relocs.d: New test.
	* testsuite/ld-riscv-elf/table-jump-shared-symbol.d: New test.
	* testsuite/ld-riscv-elf/table-jump-shared-text.d: New test.
	* testsuite/ld-riscv-elf/table-jump-shared.d: New test.
	* testsuite/ld-riscv-elf/table-jump-shared.s: New test.
	* testsuite/ld-riscv-elf/table-jump-strip-symbol.d: New test.
	* testsuite/ld-riscv-elf/table-jump-symbol-policy.d: New test.
	* testsuite/ld-riscv-elf/table-jump-vma-lma.d: New test.
	* testsuite/ld-riscv-elf/table-jump-vma-lma.ld: New test.
	* testsuite/ld-riscv-elf/table-jump-vma-zero.d: New test.
	* testsuite/ld-riscv-elf/table-jump-vma-zero.ld: New test.
	* testsuite/ld-riscv-elf/table-jump-vma-zero.s: New test.
	* testsuite/ld-riscv-elf/table-jump-zcd-conflict.d: New test.
	* testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d: New test.
	* testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s: New test.
	* testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d: New test.
	* testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s: New test.
	* testsuite/ld-riscv-elf/table-jump.ld: New test.
	* testsuite/ld-riscv-elf/table-jump.s: New test.
---
 ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp    | 50 ++++++++++++++++++
 ld/testsuite/ld-riscv-elf/table-jump-addend.d | 18 +++++++
 ld/testsuite/ld-riscv-elf/table-jump-addend.s | 21 ++++++++
 .../ld-riscv-elf/table-jump-base-collision.d  |  4 ++
 .../ld-riscv-elf/table-jump-base-collision.s  | 18 +++++++
 .../table-jump-base-local-collision.d         |  4 ++
 .../table-jump-base-local-collision.s         | 17 +++++++
 .../ld-riscv-elf/table-jump-be32-bytes.d      | 10 ++++
 .../ld-riscv-elf/table-jump-be32-text.d       | 13 +++++
 .../ld-riscv-elf/table-jump-be64-bytes.d      | 10 ++++
 .../ld-riscv-elf/table-jump-be64-text.d       | 13 +++++
 .../ld-riscv-elf/table-jump-benefit.d         | 17 +++++++
 .../ld-riscv-elf/table-jump-benefit.s         | 51 +++++++++++++++++++
 .../table-jump-default-jvt-relocs.d           |  9 ++++
 .../table-jump-default-jvt-symbol.d           | 10 ++++
 .../ld-riscv-elf/table-jump-default-jvt.d     | 12 +++++
 .../ld-riscv-elf/table-jump-default-no-jvt.d  | 15 ++++++
 .../ld-riscv-elf/table-jump-dump-unknown.d    | 25 +++++++++
 .../ld-riscv-elf/table-jump-emit-relocs.d     |  9 ++++
 .../ld-riscv-elf/table-jump-equal-benefit.d   | 18 +++++++
 .../ld-riscv-elf/table-jump-equal-benefit.s   | 19 +++++++
 .../table-jump-gc-comdat-symbol.d             |  9 ++++
 .../ld-riscv-elf/table-jump-gc-comdat.d       | 11 ++++
 .../ld-riscv-elf/table-jump-gc-comdat.s       | 18 +++++++
 .../ld-riscv-elf/table-jump-gc-dead-symbol.d  |  9 ++++
 .../ld-riscv-elf/table-jump-gc-dead.d         | 11 ++++
 .../ld-riscv-elf/table-jump-gc-dead.s         | 18 +++++++
 ld/testsuite/ld-riscv-elf/table-jump-jalt.d   | 18 +++++++
 ld/testsuite/ld-riscv-elf/table-jump-jt.d     | 23 +++++++++
 .../table-jump-multiple-local-sym-2.s         | 12 +++++
 .../table-jump-multiple-local-sym.d           | 16 ++++++
 .../table-jump-multiple-local-sym.s           | 18 +++++++
 .../table-jump-no-benefit-jvt-ref.d           |  4 ++
 .../table-jump-no-benefit-jvt-ref.s           | 16 ++++++
 .../table-jump-no-benefit-section.d           |  9 ++++
 .../table-jump-no-benefit-symbol.d            |  9 ++++
 .../ld-riscv-elf/table-jump-no-benefit.s      | 12 +++++
 .../ld-riscv-elf/table-jump-no-relax-zcmt.d   | 17 +++++++
 .../ld-riscv-elf/table-jump-no-relo-1.s       |  7 +++
 .../ld-riscv-elf/table-jump-no-relo-2.s       | 12 +++++
 .../ld-riscv-elf/table-jump-no-relo.d         | 16 ++++++
 .../ld-riscv-elf/table-jump-no-zcmt.d         | 16 ++++++
 .../ld-riscv-elf/table-jump-no-zcmt.s         | 16 ++++++
 .../ld-riscv-elf/table-jump-norelax.d         | 15 ++++++
 .../ld-riscv-elf/table-jump-norelax.s         | 17 +++++++
 .../ld-riscv-elf/table-jump-overflow.d        | 11 ++++
 .../ld-riscv-elf/table-jump-overflow.s        | 49 ++++++++++++++++++
 .../ld-riscv-elf/table-jump-pie-relocs.d      |  9 ++++
 .../ld-riscv-elf/table-jump-pie-text.d        |  9 ++++
 ld/testsuite/ld-riscv-elf/table-jump-pie.d    |  9 ++++
 ld/testsuite/ld-riscv-elf/table-jump-pie.s    | 13 +++++
 .../ld-riscv-elf/table-jump-relax-zcmt.d      | 23 +++++++++
 ld/testsuite/ld-riscv-elf/table-jump-rv32.d   | 15 ++++++
 ld/testsuite/ld-riscv-elf/table-jump-rv32.s   | 25 +++++++++
 .../ld-riscv-elf/table-jump-shared-relocs.d   |  9 ++++
 .../ld-riscv-elf/table-jump-shared-symbol.d   |  9 ++++
 .../ld-riscv-elf/table-jump-shared-text.d     |  9 ++++
 ld/testsuite/ld-riscv-elf/table-jump-shared.d | 12 +++++
 ld/testsuite/ld-riscv-elf/table-jump-shared.s | 15 ++++++
 .../ld-riscv-elf/table-jump-strip-symbol.d    |  9 ++++
 .../ld-riscv-elf/table-jump-symbol-policy.d   |  8 +++
 .../ld-riscv-elf/table-jump-vma-lma.d         | 16 ++++++
 .../ld-riscv-elf/table-jump-vma-lma.ld        | 10 ++++
 .../ld-riscv-elf/table-jump-vma-zero.d        | 15 ++++++
 .../ld-riscv-elf/table-jump-vma-zero.ld       | 13 +++++
 .../ld-riscv-elf/table-jump-vma-zero.s        | 14 +++++
 .../ld-riscv-elf/table-jump-zcd-conflict.d    |  9 ++++
 .../ld-riscv-elf/table-jump-zcmt-no-zca.d     |  9 ++++
 .../ld-riscv-elf/table-jump-zcmt-no-zca.s     | 24 +++++++++
 .../ld-riscv-elf/table-jump-zcmt-no-zicsr.d   |  9 ++++
 .../ld-riscv-elf/table-jump-zcmt-no-zicsr.s   | 24 +++++++++
 ld/testsuite/ld-riscv-elf/table-jump.ld       | 16 ++++++
 ld/testsuite/ld-riscv-elf/table-jump.s        | 46 +++++++++++++++++
 73 files changed, 1131 insertions(+)
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-addend.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-addend.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-base-collision.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-base-collision.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-be32-bytes.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-be32-text.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-be64-bytes.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-be64-text.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-benefit.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-benefit.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-default-jvt.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-default-no-jvt.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-dump-unknown.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-emit-relocs.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-dead.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-gc-dead.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-jalt.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-jt.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit-section.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-benefit.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-relo-1.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-relo-2.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-relo.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-norelax.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-norelax.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-overflow.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-overflow.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-pie-relocs.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-pie-text.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-pie.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-pie.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-relax-zcmt.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-rv32.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-rv32.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared-relocs.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared-symbol.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared-text.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-shared.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-strip-symbol.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-symbol-policy.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-lma.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-lma.ld
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-zero.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-zero.ld
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-vma-zero.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcd-conflict.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump.ld
 create mode 100644 ld/testsuite/ld-riscv-elf/table-jump.s

diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index 8e26ccff10a..32f953aba78 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -182,11 +182,60 @@ if [istarget "riscv*-*-*"] {
 	    "-march=rv64i -mabi=lp64" {weakref64.s} \
 	    {{objdump -d weakref64.d}} "weakref64"]]
 
+    # Zcmt (jump table) tests.
+    run_dump_test "table-jump-jalt"
+    run_dump_test "table-jump-jt"
+    run_dump_test "table-jump-dump-unknown"
+    run_dump_test "table-jump-no-relo"
+    run_dump_test "table-jump-relax-zcmt"
+    run_dump_test "table-jump-no-relax-zcmt"
+    run_dump_test "table-jump-multiple-local-sym"
+    run_dump_test "table-jump-benefit"
+    run_dump_test "table-jump-addend"
+    run_dump_test "table-jump-norelax"
+    run_dump_test "table-jump-no-zcmt"
+    run_dump_test "table-jump-zcmt-no-zca"
+    run_dump_test "table-jump-zcmt-no-zicsr"
+    run_dump_test "table-jump-zcd-conflict"
+    run_dump_test "table-jump-overflow"
+    run_dump_test "table-jump-equal-benefit"
+    run_dump_test "table-jump-rv32"
+    run_dump_test "table-jump-vma-zero"
+    run_dump_test "table-jump-emit-relocs"
+    run_dump_test "table-jump-be64-bytes"
+    run_dump_test "table-jump-be64-text"
+    run_dump_test "table-jump-be32-bytes"
+    run_dump_test "table-jump-be32-text"
+    run_dump_test "table-jump-no-benefit-symbol"
+    run_dump_test "table-jump-no-benefit-section"
+    run_dump_test "table-jump-no-benefit-jvt-ref"
+    run_dump_test "table-jump-default-no-jvt"
+    run_dump_test "table-jump-default-jvt"
+    run_dump_test "table-jump-default-jvt-symbol"
+    run_dump_test "table-jump-default-jvt-relocs"
+    run_dump_test "table-jump-base-collision"
+    run_dump_test "table-jump-base-local-collision"
+    run_dump_test "table-jump-symbol-policy"
+    run_dump_test "table-jump-strip-symbol"
+    run_dump_test "table-jump-gc-dead"
+    run_dump_test "table-jump-gc-dead-symbol"
+    run_dump_test "table-jump-gc-comdat"
+    run_dump_test "table-jump-gc-comdat-symbol"
+    run_dump_test "table-jump-vma-lma"
+
     # The following tests require shared library support.
     if ![check_shared_lib_support] {
 	return
     }
 
+    run_dump_test "table-jump-pie"
+    run_dump_test "table-jump-pie-text"
+    run_dump_test "table-jump-pie-relocs"
+    run_dump_test "table-jump-shared"
+    run_dump_test "table-jump-shared-text"
+    run_dump_test "table-jump-shared-symbol"
+    run_dump_test "table-jump-shared-relocs"
+
     run_dump_test "relro-relax-lui"
     run_dump_test "relro-relax-pcrel"
     run_dump_test "variant_cc-now"
@@ -342,4 +391,5 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "tls"
     run_dump_test "tlsbin"
     run_dump_test "absolute-no-relative"
+
 }
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-addend.d b/ld/testsuite/ld-riscv-elf/table-jump-addend.d
new file mode 100644
index 00000000000..11cc2b9fdfe
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-addend.d
@@ -0,0 +1,18 @@
+#source: table-jump-addend.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <__jvt_base\$>:
+[ 	]+...
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[32\]:[ 	]+target
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[33\]:[ 	]+target_4
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[34\]:[ 	]+target_8
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <target>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+33 # [0-9a-f]+ <target_4>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+34 # [0-9a-f]+ <target_8>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-addend.s b/ld/testsuite/ld-riscv-elf/table-jump-addend.s
new file mode 100644
index 00000000000..823e0710e08
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-addend.s
@@ -0,0 +1,21 @@
+	.section .text
+
+	.globl _start
+	.type _start, %function
+_start:
+	.rept 50
+	call target
+	call target + 4
+	call target + 8
+	.endr
+
+	.globl target
+	.type target, %function
+target:
+	.word 0x00000013
+	.globl target_4
+target_4:
+	.word 0x00000013
+	.globl target_8
+target_8:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-base-collision.d b/ld/testsuite/ld-riscv-elf/table-jump-base-collision.d
new file mode 100644
index 00000000000..5cdfe8a8e77
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-base-collision.d
@@ -0,0 +1,4 @@
+#source: table-jump-base-collision.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#error: .*__jvt_base\$ is reserved for Zcmt table-jump relaxation
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-base-collision.s b/ld/testsuite/ld-riscv-elf/table-jump-base-collision.s
new file mode 100644
index 00000000000..182150f86a5
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-base-collision.s
@@ -0,0 +1,18 @@
+	.section .text
+
+	.globl _start
+	.type _start, %function
+_start:
+	.rept 5
+	tail target
+	.endr
+	ret
+	.space 4096
+
+	.globl __jvt_base$
+__jvt_base$:
+	.word 0
+
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.d b/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.d
new file mode 100644
index 00000000000..2708f2e86d1
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.d
@@ -0,0 +1,4 @@
+#source: table-jump-base-local-collision.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#error: .*__jvt_base\$ is reserved for Zcmt table-jump relaxation
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.s b/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.s
new file mode 100644
index 00000000000..f7206d15b49
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-base-local-collision.s
@@ -0,0 +1,17 @@
+	.section .text
+
+	.globl _start
+	.type _start, %function
+_start:
+	.rept 5
+	tail target
+	.endr
+	ret
+	.space 4096
+
+__jvt_base$:
+	.word 0
+
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-be32-bytes.d b/ld/testsuite/ld-riscv-elf/table-jump-be32-bytes.d
new file mode 100644
index 00000000000..49dc3451e16
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-be32-bytes.d
@@ -0,0 +1,10 @@
+#source: table-jump-rv32.s
+#as: -march=rv32ic_zcmt -mbig-endian
+#ld: -melf32briscv -Ttable-jump.ld --relax-zcmt
+#objdump: -s -j .riscv.jvt
+
+#...
+.*:     file format elf32-bigriscv
+#...
+Contents of section .riscv.jvt:
+[ 	]+0+[0-9a-f]*[ 	]+0000400e[ 	]+0000400c.*
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-be32-text.d b/ld/testsuite/ld-riscv-elf/table-jump-be32-text.d
new file mode 100644
index 00000000000..a7a00bf3e39
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-be32-text.d
@@ -0,0 +1,13 @@
+#source: table-jump-rv32.s
+#as: -march=rv32ic_zcmt -mbig-endian
+#ld: -melf32briscv -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+
+#...
+.*:     file format elf32-bigriscv
+#...
+Disassembly of section .text:
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1 # [0-9a-f]+ <foo_global>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-be64-bytes.d b/ld/testsuite/ld-riscv-elf/table-jump-be64-bytes.d
new file mode 100644
index 00000000000..7dbc2d1a30e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-be64-bytes.d
@@ -0,0 +1,10 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT=1 -mbig-endian
+#ld: -melf64briscv -Ttable-jump.ld --relax-zcmt
+#objdump: -s -j .riscv.jvt
+
+#...
+.*:     file format elf64-bigriscv
+#...
+Contents of section .riscv.jvt:
+[ 	]+0+[0-9a-f]*[ 	]+00000000[ 	]+00004016[ 	]+00000000[ 	]+00004014.*
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-be64-text.d b/ld/testsuite/ld-riscv-elf/table-jump-be64-text.d
new file mode 100644
index 00000000000..7477201f199
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-be64-text.d
@@ -0,0 +1,13 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT=1 -mbig-endian
+#ld: -melf64briscv -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+
+#...
+.*:     file format elf64-bigriscv
+#...
+Disassembly of section .text:
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1 # [0-9a-f]+ <foo_global>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-benefit.d b/ld/testsuite/ld-riscv-elf/table-jump-benefit.d
new file mode 100644
index 00000000000..2fe5c787605
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-benefit.d
@@ -0,0 +1,17 @@
+#source: table-jump-benefit.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <__jvt_base\$>:
+[ 	]+...
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[32\]:[ 	]+func_d
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[33\]:[ 	]+func_c
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[34\]:[ 	]+func_b
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[35\]:[ 	]+func_a
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <func_d>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-benefit.s b/ld/testsuite/ld-riscv-elf/table-jump-benefit.s
new file mode 100644
index 00000000000..0450fef000f
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-benefit.s
@@ -0,0 +1,51 @@
+	.section .text
+
+	.globl _start
+	.type	_start, %function
+_start:
+	# Test benefit ranking: higher frequency functions should
+	# be prioritized for JVT entry allocation.
+	# Use reverse alphabetical order to verify sorting by benefit,
+	# not by name.
+
+	# func_d called 80 times - highest benefit
+	.rept 80
+	call func_d
+	.endr
+
+	# func_c called 50 times - medium benefit
+	.rept 50
+	call func_c
+	.endr
+
+	# func_b called 20 times - lower benefit
+	.rept 20
+	call func_b
+	.endr
+
+	# func_a called 5 times - lowest benefit
+	.rept 5
+	call func_a
+	.endr
+
+	ret
+
+	.globl func_a
+	.type	func_a, %function
+func_a:
+	ret
+
+	.globl func_b
+	.type	func_b, %function
+func_b:
+	ret
+
+	.globl func_c
+	.type	func_c, %function
+func_c:
+	ret
+
+	.globl func_d
+	.type	func_d, %function
+func_d:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d
new file mode 100644
index 00000000000..9b3079f24b3
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-relocs.d
@@ -0,0 +1,9 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1
+#ld: --relax-zcmt
+#readelf: -rW
+
+#failif
+#...
+.*R_RISCV_TABLE_JUMP.*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d
new file mode 100644
index 00000000000..5dd5e43c680
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt-symbol.d
@@ -0,0 +1,10 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1
+#ld: --relax-zcmt
+#readelf: -SWs
+
+#...
+.*\.riscv\.jvt[ 	]+PROGBITS[ 	]+[0-9a-f]+[ 	]+[0-9a-f]+[ 	]+[0-9a-f]+.*
+#...
+[ 	]+[0-9]+:[ 	]+0+[0-9a-f]+[ 	]+0[ 	]+NOTYPE[ 	]+LOCAL[ 	]+DEFAULT[ 	]+[0-9]+[ 	]+__jvt_base\$
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-default-jvt.d b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt.d
new file mode 100644
index 00000000000..96c9efaa29d
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-default-jvt.d
@@ -0,0 +1,12 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1
+#ld: --relax-zcmt
+#objdump: -d
+
+#...
+Disassembly of section .text:
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_global>
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <foo_global>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-default-no-jvt.d b/ld/testsuite/ld-riscv-elf/table-jump-default-no-jvt.d
new file mode 100644
index 00000000000..1ebad80ec12
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-default-no-jvt.d
@@ -0,0 +1,15 @@
+#source: table-jump-no-benefit.s
+#as: -march=rv64ic_zcmt
+#ld: --relax-zcmt
+#objdump: -d
+
+#...
+Disassembly of section .text:
+#...
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <target>
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <target>
+#...
+0+[0-9a-f]+ <target>:
+.*:[ 	]+[0-9a-f]+[ 	]+ret
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-dump-unknown.d b/ld/testsuite/ld-riscv-elf/table-jump-dump-unknown.d
new file mode 100644
index 00000000000..53e9097603c
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-dump-unknown.d
@@ -0,0 +1,25 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT=1
+#ld: -Ttable-jump.ld --strip-all --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <.riscv.jvt>:
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jt\[0\]:[ 	]+<unknown>
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jt\[1\]:[ 	]+<unknown>
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <.text>:
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+ret
+.*:[ 	]+[0-9a-f]+[ 	]+ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-emit-relocs.d b/ld/testsuite/ld-riscv-elf/table-jump-emit-relocs.d
new file mode 100644
index 00000000000..32c69c727ae
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-emit-relocs.d
@@ -0,0 +1,9 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1
+#ld: -Ttable-jump.ld --emit-relocs --relax-zcmt
+#readelf: -rW
+
+#failif
+#...
+.*R_RISCV_(TABLE_JUMP|DELETE|DELETE_AND_RELAX).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.d b/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.d
new file mode 100644
index 00000000000..6f4ed2e2682
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.d
@@ -0,0 +1,18 @@
+#source: table-jump-equal-benefit.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <__jvt_base\$>:
+[ 	]+...
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[32\]:[ 	]+func_b
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[33\]:[ 	]+func_a
+#...
+Disassembly of section .text:
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <func_b>
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+33 # [0-9a-f]+ <func_a>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.s b/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.s
new file mode 100644
index 00000000000..13dc4200569
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-equal-benefit.s
@@ -0,0 +1,19 @@
+	.section .text
+
+	.globl _start
+	.type _start, %function
+_start:
+	.rept 70
+	call func_b
+	call func_a
+	.endr
+
+	.globl func_a
+	.type func_a, %function
+func_a:
+	ret
+
+	.globl func_b
+	.type func_b, %function
+func_b:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d
new file mode 100644
index 00000000000..0b8ebee90bc
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat-symbol.d
@@ -0,0 +1,9 @@
+#source: table-jump-gc-comdat.s
+#as: -march=rv64ic_zcmt
+#ld: --gc-sections --relax-zcmt -e _start
+#readelf: -SWs
+
+#failif
+#...
+.*(__jvt_base\$|\.riscv\.jvt).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.d b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.d
new file mode 100644
index 00000000000..6a5e01c8ae9
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.d
@@ -0,0 +1,11 @@
+#source: table-jump-gc-comdat.s
+#as: -march=rv64ic_zcmt
+#ld: --gc-sections --relax-zcmt -e _start
+#objdump: -d
+
+#...
+Disassembly of section .text:
+#...
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+ret
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.s b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.s
new file mode 100644
index 00000000000..591d7c47e29
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-comdat.s
@@ -0,0 +1,18 @@
+	.section .text.live, "ax"
+
+	.globl _start
+	.type _start, %function
+_start:
+	ret
+
+	.section .text.dead_group, "axG", @progbits, dead_group, comdat
+	.type dead_group_start, %function
+dead_group_start:
+	.rept 70
+	call dead_group_target
+	.endr
+	ret
+
+	.type dead_group_target, %function
+dead_group_target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d
new file mode 100644
index 00000000000..b8a14241f12
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead-symbol.d
@@ -0,0 +1,9 @@
+#source: table-jump-gc-dead.s
+#as: -march=rv64ic_zcmt
+#ld: --gc-sections --relax-zcmt -e _start
+#readelf: -SWs
+
+#failif
+#...
+.*(__jvt_base\$|\.riscv\.jvt).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.d b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.d
new file mode 100644
index 00000000000..1c95f06c7e0
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.d
@@ -0,0 +1,11 @@
+#source: table-jump-gc-dead.s
+#as: -march=rv64ic_zcmt
+#ld: --gc-sections --relax-zcmt -e _start
+#objdump: -d
+
+#...
+Disassembly of section .text:
+#...
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+ret
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.s b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.s
new file mode 100644
index 00000000000..0030a207897
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-gc-dead.s
@@ -0,0 +1,18 @@
+	.section .text.live, "ax"
+
+	.globl _start
+	.type _start, %function
+_start:
+	ret
+
+	.section .text.dead, "ax"
+	.type dead_start, %function
+dead_start:
+	.rept 70
+	call dead_target
+	.endr
+	ret
+
+	.type dead_target, %function
+dead_target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-jalt.d b/ld/testsuite/ld-riscv-elf/table-jump-jalt.d
new file mode 100644
index 00000000000..098e65fc403
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-jalt.d
@@ -0,0 +1,18 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <__jvt_base\$>:
+[ 	]+...
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[32\]:[ 	]+foo_global
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[33\]:[ 	]+foo_local
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+33 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+33 # [0-9a-f]+ <foo_local>
+#...
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-jt.d b/ld/testsuite/ld-riscv-elf/table-jump-jt.d
new file mode 100644
index 00000000000..0b0250ee104
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-jt.d
@@ -0,0 +1,23 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT=1
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <__jvt_base\$>:
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jt\[0\]:[ 	]+foo_local
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jt\[1\]:[ 	]+foo_global
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1 # [0-9a-f]+ <foo_global>
+#...
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s
new file mode 100644
index 00000000000..bf106b88f2d
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym-2.s
@@ -0,0 +1,12 @@
+    .section .text
+    .type   bar, %function
+bar:
+    .rept 70
+    call foo_local
+    call foo_global
+    .endr
+    ret
+
+    .type   foo_local, %function
+foo_local:
+    ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d
new file mode 100644
index 00000000000..07dbd3978be
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.d
@@ -0,0 +1,16 @@
+#source: table-jump-multiple-local-sym.s
+#source: table-jump-multiple-local-sym-2.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <__jvt_base\$>:
+[ 	]+...
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[32\]:[ 	]+foo_global
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[33\]:[ 	]+foo_local
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[34\]:[ 	]+foo_local
+
+Disassembly of section .text:
+#...
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s
new file mode 100644
index 00000000000..ccc2525e2f7
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-multiple-local-sym.s
@@ -0,0 +1,18 @@
+    .section .text
+
+    .globl _start
+    .type   _start, %function
+_start:
+    .rept 70
+    call foo_global
+    call foo_local
+    .endr
+
+    .globl  foo_global
+    .type   foo_global, %function
+foo_global:
+    ret
+
+    .type   foo_local, %function
+foo_local:
+    ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d
new file mode 100644
index 00000000000..3b392efa45c
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.d
@@ -0,0 +1,4 @@
+#source: table-jump-no-benefit-jvt-ref.s
+#as: -march=rv64ic_zcmt
+#ld: --relax-zcmt
+#error: .*undefined reference to `__jvt_base\$'
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s
new file mode 100644
index 00000000000..3665215f92d
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-jvt-ref.s
@@ -0,0 +1,16 @@
+	.section .text
+
+	.globl _start
+	.type _start, %function
+_start:
+	.option push
+	.option norelax
+	la a0, __jvt_base$
+	.option pop
+	tail target
+	tail target
+	.space 4096
+
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-section.d b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-section.d
new file mode 100644
index 00000000000..74363ad11c6
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-section.d
@@ -0,0 +1,9 @@
+#source: table-jump-no-benefit.s
+#as: -march=rv64ic_zcmt
+#ld: --relax-zcmt
+#readelf: -SW
+
+#failif
+#...
+.*\.riscv\.jvt.*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d
new file mode 100644
index 00000000000..6d5eb9a35b0
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit-symbol.d
@@ -0,0 +1,9 @@
+#source: table-jump-no-benefit.s
+#as: -march=rv64ic_zcmt
+#ld: --relax-zcmt
+#readelf: -sW
+
+#failif
+#...
+.*__jvt_base\$.*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-benefit.s b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit.s
new file mode 100644
index 00000000000..2292cc43b3e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-benefit.s
@@ -0,0 +1,12 @@
+	.section .text
+
+	.globl _start
+	.type _start, %function
+_start:
+	tail target
+	tail target
+	.space 4096
+
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d b/ld/testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d
new file mode 100644
index 00000000000..a551a05c97e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-relax-zcmt.d
@@ -0,0 +1,17 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1
+#ld: -Ttable-jump.ld --no-relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <foo_global>
+#...
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-relo-1.s b/ld/testsuite/ld-riscv-elf/table-jump-no-relo-1.s
new file mode 100644
index 00000000000..d3e9b7ce4dd
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-relo-1.s
@@ -0,0 +1,7 @@
+    .section .text
+
+    .globl _start
+    .type	_start, %function
+_start:
+L0: j L0
+    ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-relo-2.s b/ld/testsuite/ld-riscv-elf/table-jump-no-relo-2.s
new file mode 100644
index 00000000000..f68cdaf423b
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-relo-2.s
@@ -0,0 +1,12 @@
+    .section .text
+
+    .globl foo
+    .type  foo, %function
+foo:
+    call bar
+
+
+    .globl bar
+    .type  bar, %function
+bar:
+    ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-relo.d b/ld/testsuite/ld-riscv-elf/table-jump-no-relo.d
new file mode 100644
index 00000000000..9ff45cb2616
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-relo.d
@@ -0,0 +1,16 @@
+#source: table-jump-no-relo-1.s
+#source: table-jump-no-relo-2.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <_start>
+.*:[ 	]+[0-9a-f]+[ 	]+ret
+
+0+[0-9a-f]+ <foo>:
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <bar>
+
+0+[0-9a-f]+ <bar>:
+.*:[ 	]+[0-9a-f]+[ 	]+ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.d b/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.d
new file mode 100644
index 00000000000..5b23e81e2c8
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.d
@@ -0,0 +1,16 @@
+#source: table-jump-no-zcmt.s
+#as: -march=rv64ic
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+# All calls should remain as jal (not converted to cm.jalt)
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <foo>
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <foo>
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <foo>
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <foo>
+#...
+0+[0-9a-f]+ <foo>:
+.*:[ 	]+[0-9a-f]+[ 	]+ret
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.s b/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.s
new file mode 100644
index 00000000000..3e483757ba5
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-no-zcmt.s
@@ -0,0 +1,16 @@
+	.section .text
+
+	.globl _start
+	.type	_start, %function
+_start:
+	# This file is assembled without Zcmt extension.
+	# The linker should NOT generate JVT section
+	.rept 50
+	call foo
+	.endr
+	ret
+
+	.globl foo
+	.type	foo, %function
+foo:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-norelax.d b/ld/testsuite/ld-riscv-elf/table-jump-norelax.d
new file mode 100644
index 00000000000..8621ad8550b
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-norelax.d
@@ -0,0 +1,15 @@
+#source: table-jump-norelax.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+auipc[ 	]+ra,0x1
+.*:[ 	]+[0-9a-f]+[ 	]+jalr[ 	]+[0-9]+\(ra\) # [0-9a-f]+ <target>
+.*:[ 	]+[0-9a-f]+[ 	]+auipc[ 	]+t[0-9],0x1
+.*:[ 	]+[0-9a-f]+[ 	]+jr[ 	]+[0-9]+\(t[0-9]\) # [0-9a-f]+ <target>
+.*:[ 	]+[0-9a-f]+[ 	]+j[ 	]+[0-9a-f]+ <target>
+#...
+0+[0-9a-f]+ <target>:
+.*:[ 	]+[0-9a-f]+[ 	]+ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-norelax.s b/ld/testsuite/ld-riscv-elf/table-jump-norelax.s
new file mode 100644
index 00000000000..0880f79a5c5
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-norelax.s
@@ -0,0 +1,17 @@
+	.section .text
+
+	.globl _start
+	.type _start, %function
+_start:
+	.option push
+	.option norelax
+	call target
+	tail target
+	jal x0, target
+	.option pop
+
+	.space 4096
+
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-overflow.d b/ld/testsuite/ld-riscv-elf/table-jump-overflow.d
new file mode 100644
index 00000000000..4b5e36005a9
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-overflow.d
@@ -0,0 +1,11 @@
+#source: table-jump-overflow.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <func_top>
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <func_overflow>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-overflow.s b/ld/testsuite/ld-riscv-elf/table-jump-overflow.s
new file mode 100644
index 00000000000..5aae80f24c6
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-overflow.s
@@ -0,0 +1,49 @@
+	.altmacro
+	.section .text
+
+	# Test JVT overflow: cm.jalt has 224 entries (index 32-255)
+	# func_top: called 10x (highest benefit), guaranteed jvt.jalt[32]
+	# func_0 to func_222: called 2x each, fill remaining 223 JVT slots
+	# func_overflow: called 1x (lowest benefit), overflows, remains jal
+
+	.macro call2 n
+	call func_\n
+	call func_\n
+	.endm
+
+	.macro defn n
+	.type func_\n, %function
+func_\n:	ret
+	.endm
+
+	.globl _start
+	.type	_start, %function
+_start:
+	# func_top: highest benefit, guaranteed first JVT entry
+	.rept 10
+	call func_top
+	.endr
+
+	# 223 functions with 2 calls each (fill remaining JVT entries)
+	.set i, 0
+	.rept 223
+	call2 %i
+	.set i, i+1
+	.endr
+
+	# func_overflow: lowest benefit, will not fit in JVT
+	call func_overflow
+	ret
+
+	# Define functions
+	.type func_top, %function
+func_top:	ret
+
+	.set i, 0
+	.rept 223
+	defn %i
+	.set i, i+1
+	.endr
+
+	.type func_overflow, %function
+func_overflow:	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-pie-relocs.d b/ld/testsuite/ld-riscv-elf/table-jump-pie-relocs.d
new file mode 100644
index 00000000000..407acf5fcc6
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-pie-relocs.d
@@ -0,0 +1,9 @@
+#source: table-jump-pie.s
+#as: -march=rv64ic_zcmt -fpic
+#ld: -pie --relax-zcmt
+#readelf: -rW
+
+#failif
+#...
+.*R_RISCV_(TABLE_JUMP|DELETE|DELETE_AND_RELAX).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-pie-text.d b/ld/testsuite/ld-riscv-elf/table-jump-pie-text.d
new file mode 100644
index 00000000000..8cb52d4a5df
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-pie-text.d
@@ -0,0 +1,9 @@
+#source: table-jump-pie.s
+#as: -march=rv64ic_zcmt -fpic
+#ld: -pie --relax-zcmt
+#objdump: -d
+
+#failif
+#...
+.*cm\.j(al)?t.*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-pie.d b/ld/testsuite/ld-riscv-elf/table-jump-pie.d
new file mode 100644
index 00000000000..d8a8a6a532d
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-pie.d
@@ -0,0 +1,9 @@
+#source: table-jump-pie.s
+#as: -march=rv64ic_zcmt -fpic
+#ld: -pie --relax-zcmt
+#readelf: -SWs
+
+#failif
+#...
+.*(__jvt_base\$|\.riscv\.jvt).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-pie.s b/ld/testsuite/ld-riscv-elf/table-jump-pie.s
new file mode 100644
index 00000000000..3d5fe7759bd
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-pie.s
@@ -0,0 +1,13 @@
+	.section .text
+
+	.globl _start
+	.type _start, %function
+_start:
+	.rept 70
+	call target
+	.endr
+	ret
+
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-relax-zcmt.d b/ld/testsuite/ld-riscv-elf/table-jump-relax-zcmt.d
new file mode 100644
index 00000000000..1adb1b289ce
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-relax-zcmt.d
@@ -0,0 +1,23 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JT_JALT=1
+#ld: -Ttable-jump.ld --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <__jvt_base\$>:
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jt\[0\]:[ 	]+foo_global
+[ 	]+...
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jalt\[32\]:[ 	]+foo_global
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # [0-9a-f]+ <foo_global>
+#...
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-rv32.d b/ld/testsuite/ld-riscv-elf/table-jump-rv32.d
new file mode 100644
index 00000000000..ef6bbcdd526
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-rv32.d
@@ -0,0 +1,15 @@
+#source: table-jump-rv32.s
+#as: -march=rv32ic_zcmt
+#ld: -Ttable-jump.ld --relax-zcmt -melf32lriscv
+#objdump: -d
+#...
+Disassembly of section .riscv.jvt:
+0+[0-9a-f]+ <__jvt_base\$>:
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jt\[0\]:[ 	]+foo_local
+.*:[ 	]+[0-9a-f]+[ 	]+jvt.jt\[1\]:[ 	]+foo_global
+#...
+Disassembly of section .text:
+0+[0-9a-f]+ <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # [0-9a-f]+ <foo_local>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+1 # [0-9a-f]+ <foo_global>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-rv32.s b/ld/testsuite/ld-riscv-elf/table-jump-rv32.s
new file mode 100644
index 00000000000..274c3b03f8b
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-rv32.s
@@ -0,0 +1,25 @@
+	.section .text
+
+	# Test RV32 ZCMT relaxation for cm.jt
+	# jal x0 (no link) -> cm.jt (index 0-31)
+	# JVT entry cost: 4 bytes (RV32), benefit = 2 per call
+	# Threshold: 3*2=6 > 4 (just profitable)
+
+	.globl _start
+	.type	_start, %function
+_start:
+	.rept 3
+	tail foo_local
+	tail foo_global
+	.endr
+
+	.space 4096
+
+	.globl  foo_global
+	.type	foo_global, %function
+foo_global:
+	ret
+
+	.type	foo_local, %function
+foo_local:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared-relocs.d b/ld/testsuite/ld-riscv-elf/table-jump-shared-relocs.d
new file mode 100644
index 00000000000..1c879fff883
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-shared-relocs.d
@@ -0,0 +1,9 @@
+#source: table-jump-shared.s
+#as: -march=rv64ic_zcmt -fpic
+#ld: -shared --relax-zcmt
+#readelf: -rW
+
+#failif
+#...
+.*R_RISCV_(TABLE_JUMP|DELETE|DELETE_AND_RELAX).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-shared-symbol.d
new file mode 100644
index 00000000000..a82763c2f8c
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-shared-symbol.d
@@ -0,0 +1,9 @@
+#source: table-jump-shared.s
+#as: -march=rv64ic_zcmt -fpic
+#ld: -shared --relax-zcmt
+#readelf: -SWs
+
+#failif
+#...
+.*(__jvt_base\$|\.riscv\.jvt).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared-text.d b/ld/testsuite/ld-riscv-elf/table-jump-shared-text.d
new file mode 100644
index 00000000000..262d4c59643
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-shared-text.d
@@ -0,0 +1,9 @@
+#source: table-jump-shared.s
+#as: -march=rv64ic_zcmt -fpic
+#ld: -shared --relax-zcmt
+#objdump: -d
+
+#failif
+#...
+.*cm\.j(al)?t.*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared.d b/ld/testsuite/ld-riscv-elf/table-jump-shared.d
new file mode 100644
index 00000000000..1fec141e6b6
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-shared.d
@@ -0,0 +1,12 @@
+#source: table-jump-shared.s
+#as: -march=rv64ic_zcmt -fpic
+#ld: -shared --relax-zcmt
+#objdump: -d
+#...
+Disassembly of section .text:
+#...
+0+[0-9a-f]+ <foo>:
+#  Calls should NOT be cm.jalt in shared library (should be jal to PLT)
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <bar@plt>
+.*:[ 	]+[0-9a-f]+[ 	]+jal[ 	]+[0-9a-f]+ <bar@plt>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-shared.s b/ld/testsuite/ld-riscv-elf/table-jump-shared.s
new file mode 100644
index 00000000000..0bd853d1ae6
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-shared.s
@@ -0,0 +1,15 @@
+	.section .text
+
+	.globl foo
+	.type	foo, %function
+foo:
+	# Shared library: JVT relaxation should be disabled
+	.rept 50
+	call bar
+	.endr
+	ret
+
+	.globl bar
+	.type	bar, %function
+bar:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-strip-symbol.d b/ld/testsuite/ld-riscv-elf/table-jump-strip-symbol.d
new file mode 100644
index 00000000000..39b1d99e93e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-strip-symbol.d
@@ -0,0 +1,9 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1
+#ld: -Ttable-jump.ld --strip-all --relax-zcmt
+#readelf: -sW
+
+#failif
+#...
+.*__jvt_base\$.*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-symbol-policy.d b/ld/testsuite/ld-riscv-elf/table-jump-symbol-policy.d
new file mode 100644
index 00000000000..acd152a93be
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-symbol-policy.d
@@ -0,0 +1,8 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1
+#ld: -Ttable-jump.ld --relax-zcmt
+#readelf: -sW
+
+#...
+[ 	]+[0-9]+:[ 	]+0+[0-9a-f]+[ 	]+0[ 	]+NOTYPE[ 	]+LOCAL[ 	]+DEFAULT[ 	]+[0-9]+[ 	]+__jvt_base\$
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.d b/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.d
new file mode 100644
index 00000000000..222d546df8b
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.d
@@ -0,0 +1,16 @@
+#source: table-jump.s
+#as: -march=rv64ic_zcmt --defsym TEST_CM_JALT=1
+#ld: -Ttable-jump-vma-lma.ld --relax-zcmt
+#objdump: -d
+
+#...
+Disassembly of section .riscv.jvt:
+#...
+.*:[ 	]+0000000000003118[ 	]+jvt.jalt\[32\]:[ 	]+foo_global
+.*:[ 	]+000000000000311a[ 	]+jvt.jalt\[33\]:[ 	]+foo_local
+#...
+Disassembly of section .text:
+#...
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+32 # 3118 <foo_global>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jalt[ 	]+33 # 311a <foo_local>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.ld b/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.ld
new file mode 100644
index 00000000000..a8202afb381
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-lma.ld
@@ -0,0 +1,10 @@
+ENTRY(_start)
+SECTIONS
+{
+	.riscv.jvt 0x1000 : AT(0x8000) {
+		*(.riscv.jvt)
+	}
+	.text 0x3000 : AT(0x9000) {
+		*(.text)
+	}
+}
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.d b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.d
new file mode 100644
index 00000000000..c93a1c6c4f2
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.d
@@ -0,0 +1,15 @@
+#source: table-jump-vma-zero.s
+#as: -march=rv64ic_zcmt
+#ld: -Ttable-jump-vma-zero.ld --relax-zcmt
+#objdump: -d -s -j .riscv.jvt -j .text
+
+#...
+Contents of section .riscv.jvt:
+[ 	]+1000[ 	]+00000000[ 	]+00000000.*
+#...
+Disassembly of section .text:
+#...
+0+3000 <_start>:
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # 0 <target>
+.*:[ 	]+[0-9a-f]+[ 	]+cm.jt[ 	]+0 # 0 <target>
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.ld b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.ld
new file mode 100644
index 00000000000..6db8ac52006
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.ld
@@ -0,0 +1,13 @@
+ENTRY(_start)
+SECTIONS
+{
+	.text.target 0x0 : {
+		*(.text.target)
+	}
+	.riscv.jvt 0x1000 : {
+		*(.riscv.jvt)
+	}
+	.text 0x3000 : {
+		*(.text.start)
+	}
+}
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.s b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.s
new file mode 100644
index 00000000000..742a0ee23fe
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-vma-zero.s
@@ -0,0 +1,14 @@
+	.section .text.start, "ax"
+
+	.globl _start
+	.type _start, %function
+_start:
+	.rept 5
+	tail target
+	.endr
+	ret
+
+	.section .text.target, "ax"
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcd-conflict.d b/ld/testsuite/ld-riscv-elf/table-jump-zcd-conflict.d
new file mode 100644
index 00000000000..ed70f3fd94e
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-zcd-conflict.d
@@ -0,0 +1,9 @@
+#source: table-jump.s
+#as: -march=rv64imafd_zicsr_zifencei_zca_zcd_zcmt --defsym TEST_CM_JT_JALT=1
+#ld: -Ttable-jump.ld --relax-zcmt
+#readelf: -SWs
+
+#failif
+#...
+.*(__jvt_base\$|\.riscv\.jvt).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d
new file mode 100644
index 00000000000..9554df1aa91
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.d
@@ -0,0 +1,9 @@
+#source: table-jump-zcmt-no-zca.s
+#as: -march=rv64i -mno-arch-attr
+#ld: --relax-zcmt
+#readelf: -SWs
+
+#failif
+#...
+.*(__jvt_base\$|\.riscv\.jvt).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s
new file mode 100644
index 00000000000..91aa8f07ed3
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zca.s
@@ -0,0 +1,24 @@
+	.section .riscv.attributes,"",@0x70000003
+	.byte 0x41
+0:
+	.4byte 1f-0b
+	.asciz "riscv"
+2:
+	.byte 1
+	.4byte 1f-2b
+	.byte 5
+	.asciz "rv64i2p1_zicsr2p0_zcmt1p0"
+1:
+
+	.section .text
+	.globl _start
+	.type _start, %function
+_start:
+	.rept 70
+	call target
+	.endr
+	ret
+
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d
new file mode 100644
index 00000000000..981e5933097
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.d
@@ -0,0 +1,9 @@
+#source: table-jump-zcmt-no-zicsr.s
+#as: -march=rv64i -mno-arch-attr
+#ld: --relax-zcmt
+#readelf: -SWs
+
+#failif
+#...
+.*(__jvt_base\$|\.riscv\.jvt).*
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s
new file mode 100644
index 00000000000..768a6fb32fa
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump-zcmt-no-zicsr.s
@@ -0,0 +1,24 @@
+	.section .riscv.attributes,"",@0x70000003
+	.byte 0x41
+0:
+	.4byte 1f-0b
+	.asciz "riscv"
+2:
+	.byte 1
+	.4byte 1f-2b
+	.byte 5
+	.asciz "rv64i2p1_zca1p0_zcmt1p0"
+1:
+
+	.section .text
+	.globl _start
+	.type _start, %function
+_start:
+	.rept 70
+	call target
+	.endr
+	ret
+
+	.type target, %function
+target:
+	ret
diff --git a/ld/testsuite/ld-riscv-elf/table-jump.ld b/ld/testsuite/ld-riscv-elf/table-jump.ld
new file mode 100644
index 00000000000..ab84fdcb772
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump.ld
@@ -0,0 +1,16 @@
+ENTRY(_start)
+SECTIONS
+{
+	.got  0x1000 : {
+		*(.got)
+	}
+	.riscv.jvt : {
+		*(.riscv.jvt)
+	}
+	.data 0x2000: {
+		*(.data)
+	}
+	.text 0x3000 : {
+		*(.text)
+	}
+}
diff --git a/ld/testsuite/ld-riscv-elf/table-jump.s b/ld/testsuite/ld-riscv-elf/table-jump.s
new file mode 100644
index 00000000000..75574a69223
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/table-jump.s
@@ -0,0 +1,46 @@
+    .section .text
+
+    .globl _start
+	.type	_start, %function
+_start:
+.ifdef TEST_CM_JT
+    .rept 5
+    tail foo_local
+    tail foo_global
+    .endr
+.endif
+
+.ifdef TEST_CM_JALT
+    .rept 70
+    call foo_global
+    call foo_local
+    .endr
+.endif
+
+.ifdef TEST_CM_JT_JALT
+    .rept 5
+    tail foo_global
+    .endr
+    .rept 140
+    call foo_global
+    .endr
+.endif
+
+	# Keep paired JAL candidates out of C.J range.  Zcmt profiling runs
+	# after ordinary shortening, so near paired JALs should become C.J
+	# and no longer be Zcmt candidates.
+.ifdef TEST_CM_JT
+    .space 4096
+.endif
+.ifdef TEST_CM_JT_JALT
+    .space 4096
+.endif
+
+    .globl  foo_global
+	.type	foo_global, %function
+foo_global:
+    ret
+
+	.type	foo_local, %function
+foo_local:
+    ret
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.