Just commenting on one thing:

> It is again there for the case of an overflow which has resulted in a 
> negative zero 
> but I can't think why it is not preceded by a branch on condition for the 
> overflow 
> value in the Condition Code.

Do I interpret what you are saying as "I get the need for the ZAP, but couldn't 
they have saved the ZAP if no overflow by branching around it if no overflow?"

If so, I think the answer is because branches are expensive in the brave new 
world of caches and so forth. It's probably generally cheaper to do the zap -- 
seeing as how you already have the data in write cache -- than to screw up the 
pipeline with a branch. Just my slightly informed guess.

Charles

-----Original Message-----
From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On Behalf 
Of Bill Woodger
Sent: Saturday, February 06, 2016 5:30 PM
To: IBM-MAIN@LISTSERV.UA.EDU
Subject: COBOL Code Gened for MOVE COMP-3 S9(9) to S9(8)

Posting this to replace a post I made, by accident only in the google-something 
part of the list. Some editing, and additional examples.

MOVE PICS9-9 TO PICS9-8 
D204 3010 3028  MVC   16(5,3),40(3)   PICS9-8       PICS9-9 
940F 3010       NI    16(3),X'0F'     PICS9-8 
F844 3010 3010  ZAP   16(5,3),16(5,3) PICS9-8       PICS9-8 
                                                              
MOVE PICS9-11 TO PICS9-9 
F844 3028 3019  ZAP   40(5,3),25(5,3) PICS9-9       PICS9-11+1
                                                              
MOVE PICS9-9-2 TO PICS9-9 
D204 3028 3030  MVC   40(5,3),48(3)   PICS9-9       PICS9-9-2 
                                                              
MOVE PICS9-8-2 TO PICS9-8 
D204 3010 3020  MVC   16(5,3),32(3)   PICS9-8       PICS9-8-2 


Firstly, it is an Enterprise COBOL thing. From the "Enterprise COBOL for z/OS, 
Version 3.4, Compiler and Runtime Migration Guide" (that's the first one that 
came up, I'd suspect it is repeated in other Migration Guide):

"For example, Enterprise COBOL will not generate a negative zero result, while 
OS/VS COBOL could"

It pre-dates Enterprise COBOL, and is introduced in VS COBOL II, due to 
NUMPROC. Prior to COBOL II, all references to packed-decimal data involved 
decimal instructions. With COBOL II, plain MVC and CLC area weapons of choice, 
where possible/meaningful, over ZAP and CLC. The decimal compare, CP, treats 
postive and negative zero as equal (treats them as zero). CLC does not (as it 
doesn't know they are packed-decimal).

The "no negative zero" does not seem to be documented in anything to do with 
COBOL II that I can find, and from the standard documentation set for COBOL 
only appears in the Migration guides.

Enterprise COBOL has to ensure that a negative zero can never be a result of a 
statement. There is no action in Enterprise COBOL that can result in a negative 
zero (except see the list at the bottom).

>From the POP for any decimal instruction which can cause an overflow:

"In the absence of overflow, the sign of a zero result is made positive. If 
overflow occurs, a zero result is given the sign of the second operand but with 
the preferred sign code."

A decimal instruction can't, except for overflow, produce a negative zero.

COBOL doesn't mind overflow. It is part of the language that a larger field 
going to a smaller field is simply truncated. 

Prior to COBOL II, with decimal instructions for packed-decimal fields, where 
unproblematic overflow occured which happened to create a negative zero, it 
didn't matter since a negative zero in a decimal instruction is just zero 
anyway.

Now the actual generated code. Defining one field with 11 digits, two with nine 
and two with eight:

1.
MOVE PICS9-9 TO PICS9-8 
D204 3010 3028  MVC   16(5,3),40(3)   PICS9-8       PICS9-9 
940F 3010       NI    16(3),X'0F'     PICS9-8 
F844 3010 3010  ZAP   16(5,3),16(5,3) PICS9-8       PICS9-8 

2.                                                              
MOVE PICS9-11 TO PICS9-9 
F844 3028 3019  ZAP   40(5,3),25(5,3) PICS9-9       PICS9-11+1

3.                                                              
MOVE PICS9-9-2 TO PICS9-9 
D204 3028 3030  MVC   40(5,3),48(3)   PICS9-9       PICS9-9-2 

4.                                                              
MOVE PICS9-8-2 TO PICS9-8 
D204 3010 3020  MVC   16(5,3),32(3)   PICS9-8       PICS9-8-2 


In 2, a longer field is the source, and ZAP is used, and if the trunction of 
the longer field happened to logically yield a negative zero, the ZAP would 
present the result as a positive zero. If an MVC had been used, offset by one 
byte, a ZAP-to-itself would have been needed to ensure the positive zero if 
that had resulted in a negative zero. So cut to the chase, and just ZAP.

In 3, with two fields of the same size and an odd number of digits, an MVC is 
possible and a ZAP not needed because there can be no truncation resulting in a 
potential negative zero. There is a presumption that the source field is valid 
(not negative zero already).

4 is similar to 3, just with an even number of digits. There is the same 
presumption as in 3, and a further presumption that the leading nybble can only 
be zero.

Now number 1, the original code in the question:

The MVC does nothing with packed-decimal signs, it is just copying a lump of 
data.

The NI is indeed effecting truncation (nothing to do with compiler option TRUNC 
in Enterprise COBOL, although a compiler option of the same name, many years 
ago, was involved in that).

Source is a nine-digit-in-five-bytes. The code shown will ensure that the 
8-digit-in-five-bytes receiving field will have a zero in the high-order nybble.

What about the ZAP? It is due to the potential for a negative-zero in the data 
in the source field, which Enterprise COBOL must prevent from infecting the 
result. If the source field was -900000000, then the MVC followed by the NI 
would yield negative zero. So follow the MVC/NI with a ZAP.

You can't just ZAP then NI, because the potential -900000000 would become the 
forbidden negative zero.

The ZAP after a decimal add, subtract, multiply or divide is interesting. It is 
again there for the case of an overflow which has resulted in a negative zero 
but I can't think why it is not preceded by a branch on condition for the 
overflow value in the Condition Code.

Other points raised in the discussion:

Non-preferred signs going into ZAP (or any decimal instruction) will come out 
as preferred signs (C or D). Looking at other code generated with 
NUMPROC(NOPFD) may well show a number of ZAPs-to-itself to rectify the sign for 
comparisons, for instance.

If the source has an invalid sign (0-9) a S0C7 will ensue.

If the source has a non-preferred sign, a preferred sign, equivalent, of 
course, will be produced.

If the source is a negative zero, a positive zero will be produced, allowing a 
CLC to be used, accurately, for comparisons for equality for packed-decimal 
fields.

The code generated, in isolation at least, is not affected by compiler option 
OPT, because it is an Enterprise COBOL thing. If it were not done, you get the 
chance of a negative zero.

There is absolutely no difference in the procedure code generated by OPT(STD) 
and OPT(FULL). The only "extra" in OPT(FULL) is the identification and removal 
from the object of unreferenced storage items. If there are unused fields in 
WORKING-STORAGE or LOCAL-STORAGE, the object will be smaller.

With Enterprise COBOL V5, which has three levels of optimsation (0, 1 and 2, 
and yes, even 0 does some optimisations, clever, eh?) the FULL part of OPT up 
to V4 is replaced by a new option, STGOPT.

Given all the above, what is the potential for any field containing a negative 
zero? Date external to the program (file, DB, LINKAGE SECTION, message, 
whatever), careless use of REDEFINES, careless use of group MOVEs. So something 
to be aware of.

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN

Reply via email to