The MOS assembler understands and assembles all NMOS 6502 opcodes. The assembler correctly understands symbols, and it's possible to use them as branch targets, do pointer math on them, and the like. Fixups work as expected at link time.
Traditionally, the llvm-mc tool is used as a standalone assembler within the LLVM universe, but our implementation permits MOS assembly to be implemented in multiple places, such as inline within a C program:
asm volatile ("JSR\t$FFD2" : "+a"(c));
To target MOS family processors, you will need to use a triple of "mos" (try: `-triple mos` or `-mcpu mos`) as a parameter to any tool.
The assembler correctly deals with 6502 relative branches. BEQ, BCC, etc., all correctly calculate PC relative offsets in the unusual 6502 convention, in the range of [-126,+129]. Since llvm-mc is GNU assembler compatible, you can use all GNU assembler features while writing 65xx code, including macros, ifdefs, and similar.
The assembler is capable of intelligently figuring out whether symbols should refer to zero page or 16-bit locations, at compilation time.
The assembler understands that $ is a legal prefix for hexadecimal constants. Much existing 6502 assembly code depends on this older convention. See the DollarIsHexPrefix constant in MCAsmInfo.h. The lexer now queries whatever the current MCAsmInfo structure to see whether the target wants the dollar sign to be a hex prefix. So, everything that depends on the lexer (which is almost everything in LLVM) can now recognize 6502 format hexadecimal constants, if the corresponding MCAsmInfo asks for it. The modern 0x prefix works fine as well.