S0C6: Specification exception
An S0C6 abend means an instruction broke one of the processor's operand rules. Typical examples are a branch to an odd address, an odd register where an even-odd register pair is required, or an operand that isn't on the boundary the instruction demands.
Other names for this code
Also written as 0C6, SOC6, abend 0C6, system abend 0C6, S0C6-6, specification exception.
What it means
Each instruction has rules about its operands beyond simply naming valid storage. When an instruction breaks one of them, the processor raises a specification exception, program interruption code 6, and z/OS ends the task with system completion code 0C6 and reason code 6.
The rules that matter most in practice are these.
- Instructions start on an even address. A branch to an odd address raises the exception as soon as the processor tries to fetch from it.
- Some instructions work on an even-odd pair of registers and must name the even one. Divide (D, DR), multiply (M, MR), MVCL and CLCL are examples.
- A few instructions need their storage operand on a fixed boundary. COMPARE AND SWAP needs a fullword boundary, and some of its larger relatives need a doubleword or quadword.
- For packed decimal multiply (MP) and divide (DP), the second operand may be at most 8 bytes long and must be shorter than the first.
Compilers follow these rules, so an S0C6 in a COBOL or PL/I program almost always means the program branched to a bad address. In assembler, any of the rules can be the cause.
Common causes
- A branch to an odd address, because a return address, entry address or procedure pointer was overwritten or never set.
- The caller and the called program disagree about the parameter list, so a data value ends up used as a branch address.
- In assembler, an odd register named where an even-odd pair is required, for example in D, M, MVCL or CLCL.
- In assembler, a COMPARE AND SWAP or similar operand that isn't on its required boundary.
- In assembler, an MP or DP whose second operand is longer than 8 bytes or not shorter than the first operand.
How to find the problem
- Find CEE3206S (Language Environment) or the IEA995I symptom dump in the job log. Note the PSW address, the ILC and the load module offset.
- Look at the instruction address in the PSW. If it is odd, the program branched to an odd address, so look for where that address came from. Registers 14 and 15 and the save area chain usually show the last call.
- If the address is even, match the offset to the listing and check the failing instruction's register numbers, operand alignment and packed operand lengths against the rules above.
- For a bad branch in a compiled program, compare the caller's CALL USING list with the called program's parameter list, field by field.
How to fix it
- Set procedure pointers and entry addresses before branching through them, and keep save areas and return addresses intact.
- Make caller and called program parameter lists match, and recompile both after a copybook change.
- In assembler, use the even register of the pair, align operands that need it with DS 0F, DS 0D or the right boundary, and keep MP and DP operand lengths within the rules.
- If the failing code belongs to IBM or a vendor, search for a fix and report the problem with the dump.
What it looks like
IEA995I SYMPTOM DUMP OUTPUT SYSTEM COMPLETION CODE=0C6 REASON CODE=00000006 IEF450I ORDENTRY STEP020 - ABEND=S0C6 U0000 REASON=00000006
IBM documentation
IBM z/OS: 0Cx program interruptions. Use the documentation for your installed release.
Related codes
Questions
Can an unaligned COBOL binary field cause S0C6?
No. The ordinary load and store instructions work on unaligned data, so a COMP field without SYNCHRONIZED is fine. Alignment-related S0C6 comes from the few instructions that demand it, which compilers handle correctly.
Why does the PSW show an odd address?
Because the program branched to it. Instructions must start on an even address, so the processor raised the exception when it tried to fetch from there. Find where the branch address came from.
How does S0C6 show up in CICS?
As the transaction abend ASRA. The transaction dump shows the program check with interrupt code 6.