diff --git a/doc/ca65.sgml b/doc/ca65.sgml
index b68acb639..37349f409 100644
--- a/doc/ca65.sgml
+++ b/doc/ca65.sgml
@@ -2758,15 +2758,19 @@ See: ,[.s.
The following reference files can be added:
-- .bin-ref:
+- ref/.bin-ref:
This is a reference for the resulting binary.
The binary as binary tested against this file.
If they are not equal, the test fails.
-- .list-ref
+- ref/.list-ref
This is a reference for the resulting listing output
This file *must* have the first line of the listing removed, as that
contains a ca65 version string, and almost always this will be changed!
+- ref/.err-ref
+ This is a reference for the resulting ca65 stdout (>) output.
+
+- ref/.err2-ref
+ This is a reference for the resulting ca65 stderr (2>) output.
+
+- ref/.ld65err-ref
+ This is a reference for the resutling ld65 stdout (>) output.
+
+- ref/.ld65err2-ref
+ This is a reference for the resulting ld65 stderr (2>) output.
+
+The following control files can be added to control the tests.
+These files are empty (contents ignored), and only the filename is used:
+
+- control/.err
+ Test is expected to produce an error.
+
+- control/.no-ld65
+ Skip the ld65 step.
+
Note that the resulting .bin file is generated twice: Once with no listing
file, and once with listing file. This way, one can find out if the listing
file generation changes anything with the resulting binary output.
-
-
-TODO:
-- add the possibility to test for specific error output that are to be
- expected
diff --git a/test/asm/listing/ref/108-long-rts.bin-ref b/test/asm/listing/ref/108-long-rts.bin-ref
new file mode 100644
index 000000000..23fa7d31a
--- /dev/null
+++ b/test/asm/listing/ref/108-long-rts.bin-ref
@@ -0,0 +1 @@
+k
\ No newline at end of file
diff --git a/test/asm/val/feature.s b/test/asm/val/feature.s
new file mode 100644
index 000000000..4428cf4c2
--- /dev/null
+++ b/test/asm/val/feature.s
@@ -0,0 +1,147 @@
+; a simple test of every .feature
+
+.export _main
+
+.segment "ZEROPAGE"
+zplabel:
+
+.segment "CODE"
+abslabel:
+
+; exit with 0
+
+_main:
+ ; if any feature needs a runtime test,
+ ; it can be added here.
+ lda #0
+ tax
+ rts
+
+
+.feature addrsize +
+.assert .addrsize(zplabel) = 1, error, ".addrsize 1 expected for ZEROPAGE"
+.assert .addrsize(abslabel) = 2, error, ".addrsize 2 expected for absolute"
+.feature addrsize -
+
+
+.feature at_in_identifiers on
+ident@with@at:
+ rts
+.feature at_in_identifiers off
+
+
+.feature bracket_as_indirect
+ lda [$82],y
+.feature bracket_as_indirect-
+
+
+.feature c_comments
+ lda zplabel /* comment */
+ /* comment */
+/* multiline
+** comment
+*/
+.feature c_comments -
+
+
+.feature dollar_in_identifiers
+ident$with$dollar:
+ rts
+.feature dollar_in_identifiers -
+
+
+.feature dollar_is_pc
+.assert $ = *, error, "dollar_is_pc failure"
+.feature dollar_is_pc -
+
+
+.feature force_range
+ lda #-1
+.feature force_range -
+
+
+.feature labels_without_colons
+labelwithoutcolon
+ jmp labelwithoutcolon
+.feature labels_without_colons -
+
+
+.feature leading_dot_in_identifiers
+.identifierwithdot:
+ rts
+.feature leading_dot_in_identifiers -
+
+
+.feature long_jsr_jmp_rts
+.p816
+ ; long addresses require alternate instruction names JSL, JML without this feature
+ jsr $123456
+ jmp $123456
+; smart + far + long_jsr_jmp_rts will promote rts to rtl
+.smart +
+.proc long_rts : far
+ rts ; should become RTL ($6B) instead of RTS ($60)
+ ; the emitted opcode is not verified by this test,
+ ; see test/asm/listing/108-long-rts
+.endproc
+.smart -
+.p02
+.feature long_jsr_jmp_rts -
+
+
+.feature loose_char_term
+.byte 'a'
+.byte "a"
+.feature loose_char_term -
+
+
+.feature loose_string_term
+.asciiz "string"
+.asciiz 'string'
+.feature loose_string_term -
+
+
+.feature missing_char_term
+ lda #'a
+.feature missing_char_term -
+
+
+.feature org_per_seg
+.segment "RODATA"
+.org $5678
+.assert * = $5678, error, "org_per_seg failed"
+.segment "CODE"
+.org $9ABC
+.assert * = $9ABC, error, "org_per_seg failed"
+.segment "RODATA"
+.assert * = $5678, error, "org_per_seg failed"
+.reloc
+.segment "CODE"
+.assert * = $9ABC, error, "org_per_seg failed"
+.reloc
+.feature org_per_seg -
+
+
+.feature pc_assignment
+* = $1234
+.assert * = $1234, error, "pc_assignment failed"
+.reloc
+.feature pc_assignment -
+
+
+.feature string_escapes
+.asciiz "quote:\""
+.feature string_escapes -
+
+
+.feature ubiquitous_idents
+.macro bit
+ brk
+.endmacro
+ bit
+.feature ubiquitous_idents -
+
+
+.feature underline_in_numbers
+.byte %10_10_10_10
+.feature underline_in_numbers -
]