ARM Flag Manipulation

Operation Mode-agnostic, ARMv2+ 26-bit mode only, ARMv2+ Mode-agnostic, ARMv3+
Assign all flags
; Precondition: user-mode, or known PSR;
; also PSR non-zero - can precede with
; TEQ R0, R0 if not
TEQ PC, PC
TEQNEP PC, #0x??00000?
MSR CPSR_f, #0x?0000000  ; no-op on ARMv2
; Precondition: Rd available
MOV Rd, PC
BICS Rd, Rd, #0xF0000000 ; (set C)
TEQ PC, PC
TEQNEP Rd, #0x?0000000
MSR CPSR_f, #0x?0000000  ; no-op on ARMv2
; Rn=NZCVxxxx...x, Rt available
MOV Rt, Rn LSL #3
CMN Rt, #0x80000000      ; assign V
MOVS Rt, Rn ASR #30      ; assign C
TEQ Rt, #1               ; assign N, Z
; Note that it's not possible to set both N and Z without
; directly writing the PSR, so N set will force Z clear
; Rn=NZCVxxxx...x, Ru=1<<31, Rv=1
CMN Ru, Rn LSL #3       ; assign V
TEQ Rv, Rn ASR #30      ; assign C, N, Z
; Rn=(V⊕N)NZ̅Cxxxx...x, Rt (or Rd) available
ADDS Rt, Rd, Rd         ; assign V
MOVS Rt, Rt ASR #30     ; assign C, N, Z
; Rn=N(V⊕N)Z̅Z̅0000...000C
CMN Rn, Rn              ; assign V
TST Rn, Rn RRX          ; assign C, N, Z
; Rn=1V̅Z̅CN010...0
CMN Rn, Rn              ; assign V
TST Rn, Rn LSL #4       ; assign C, N, Z
; Rn=N(V⊕N)Z̅Cxxxx...xx01
CMN Rn, Rn              ; assign V
TST Rn, Rn ASR #29      ; assign C, N, Z
; Rn=1V̅1xxxxx...xCN0Z̅
CMN Rn, Rn              ; assign V
TST Rn, Rn LSL #29      ; assign C, N, Z
; Precondition: user-mode, or known PSR
TEQP PC, #0x??00000?
; Precondition: Rd=0x0C000003 or Rd=~0xF0000000
AND Rd, Rd, PC
TEQP Rd, #0x?0000000
; Precondition: Rd available
MOV Rd, PC
BIC Rd, Rd, #0xF0000000
TEQP Rd, #0x?0000000
MSR CPSR_f, #0x?0000000
Extract all flags
MOV Rd, PC
MRS Rd, CPSR             ; no-op on ARMv2
AND Rd, Rd, #0xF0000000  ; if want
MOV Rd, #0
ORRVS Rd, Rd, #0x10000000
ORRCS Rd, Rd, #0x20000000
ORREQ Rd, Rd, #0x40000000
ORRMI Rd, Rd, #0x80000000
SBC Rd, Rd, Rd
EORVS Rd, Rd, #0x10000000
EOREQ Rd, Rd, #0x40000000
EORMI Rd, Rd, #0x80000000
; Result: encodes flags non-trivially
; Precondition: Ru=0
ADC Rd, Ru, #0
ORRVS Rd, Rd, #0x80000000
ORREQ Rd, Rd, #2
ORRMI Rd, Rd, #4
; Result: flags rotated left 3
MOV Rd, PC
AND Rd, Rd, #0xF0000000  ; if want
EOR Rd, PC, PC           ; or RSB
; Note: includes mode+interrupt flags
MOV Rd, PC LSR 28
; Result: flags rotated left 4
MRS Rd, CPSR
AND Rd, Rd, #0xF0000000  ; if want
Assign V/C/N
CMN Rn, Rn
; Result: N=Rn30, Z=[Rn=0 or 1<<31], C=Rn31, V=Rn31Rn30
RSBS Rn, Rn, Rn LSL #1
; Result: N=Rn31, Z=[Rn=0], C=Rn31, V=Rn31Rn30
Assign V
CMN Rn, #0x80000000
; Result: N=Rn31, Z=[Rn=1<<31], C=Rn31, V=Rn31
CMP Rn, #0x80000000
; Result: N=Rn31, Z=[Rn=1<<31], C=Rn31, V=Rn31
Set V
; Precondition: Rn31=0
CMP Rn, #0x80000000
; Result: NzcV
; Precondition: Rn31=1
CMN Rn, #0x80000000
; Result: n, Z=[Rn=1<<31], CV
CMP Rn, #0x80000000
CMNVC Rn, #0x80000000
; Result: N=Rn31, Z=[Rn=1<<31], C=Rn31, V
CMP PC, #0x80000000
MSR CPSR_f, #0x90000000  ; no-op on ARMv2
; Result: NzcV
CMP PC, #0x80000000
; Result: NzcV
; Precondition: Rd=0x10000000
TEQVCP Rd, PC
; Result: V
; Precondition: Rd available
MOV Rd, PC
TEQVCP Rd, #0x10000000
; Result: V
; Precondition: Rd available
MOV Rd, PC
ORRS PC, Rd, #0x10000000
; Result: V
; Precondition: Rd available
MRS Rd, CPSR
ORR Rd, Rd, #0x10000000
MSR CPSR_f, Rd
; Result: V
Clear V
CMN Rn, #0
; Result: N=Rn31, Z=[Rn=0], cv
CMP Rn, #0
; Result: N=Rn31, Z=[Rn=0], Cv
CMP Rn, Rn
; Result: nZCv
; Precondition: Rd=0x10000000
TEQVSP Rd, PC
; Result: v
; Precondition: Rn=0xEC000003 or Rn=~0x10000000
TSTP Rn, PC
; Result: v
; Precondition: Rd available
MOV Rd, PC
TSTP Rd, #0xEC000003
; Result: v
; Precondition: Rd available
MOV Rd, PC
BICS PC, Rd, #0x10000000
; Result: v
; Precondition: Rd available
MRS Rd, CPSR
BIC Rd, Rd, #0x10000000
MSR CPSR_f, Rd
; Result: v
Assign C
Set C
TST Rn, #0x80000000
; Result: N=Rn31, Z=Rn31, C
TEQ Rn, #0x80000000
; Result: N=Rn31, Z=Rn31, C
CMP Rn, Rn
; Result: nZCv
CMP Rn, #0
; Result: N=Rn31, Z=[Rn=0], Cv
Clear C
TST Rn, #0, 2
; Result: nZc
TEQ Rn, #0, 2
; Result: N=Rn31, Z=Rn31, c
CMN Rn, #0
; Result: N=Rn31, Z=[Rn=0], cv
Assign Z
Set Z
Clear Z
Assign N
Set N
Clear N