|
View previous topic :: View next topic
|
| Author |
Message |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
This topic has received some coverage in this forum before, but, from some recent questions (why did this not S0C7?) and idiotic code which "works" I think it is worth looking at.
Why? Because anyone with an ounce of programming-self-respect "feels" for the system when bad data gets into it.
Compiler option NUMPROC with NOPFD makes me sick to my stomach, at least initially.
First of all, what is PFD/NOPFD? PFD means "preferred", and NOPFD means "non-preferred" - however, don't take that as indicating the use of one over the other. What is "preferred", or not, is the sign symbol.
Ignoring "sign is seperate", IBM zoned and packed decimals have a "preferred" sign of C (positive), D (negative) or F (unsigned, assumed positive). "Non-preferred" opens up the possibility of other sign values, in fact A, B, C, D, E and F. Why? TBD.
Now, if you had a whole load of different sign values for your program to cater with, things would get more complicated. So, what NOPFD does is to "fix" the sign for you, so it can then only be a C, D or F when it is actually used for anything (IF, MOVE, calculation, any sort of reference) in your program. It doesn't "fix" the sign in the DATA DIVISION location, but in the progam's temporary storage area. Meaning that it does this each time any zoned (PIC (S)9(n) USAGE DISPLAY) or packed (COMP-3) field is referenced.
The way PFD (preferred sign) behaves is to assume that the DATA DIVISION fields all have a correct sign (C or D in PIC S9(n) and F in PIC 9(n)) with respect to the PICTURE.
Two main problems arise:
| Code: |
01 W-VALUE-IN-PICX PIC XXX.
01 W-VALUE-IN-PIC9 REDEFINES W-VALUE-IN-PICX PIC S999.
01 W-TEST-FOR-S0C7 COMP-3 PIC S999.
|
The zoned-decimal looks like this - ZNZNSN
The packed-decimal looks like this - NNNS
Z = Zone = Value Irrelevant
S = Sign (C, D, F valid or A, B, C, D, E, F valid)
N = Number (0-9 valid)
At the moment, restricting the discussion to zoned-decimals, it goes like this.
With NUMPROC(NOPFD)
Valid for Sign = Any single-byte binary value where high-order nibble is numeric. 160 distinct values.
Valid for Zone = Any single-byte binary value where low-order nibble is numeric. 160 distinct values.
Any receiving field, result of a MOVE, calculation, will have a "preferred sign" C, D or F. An unsigned source to a signed receiving field, will have a C.
NUMPROC(PFD)
Valid for Sign = Any single-byte binary value where high-order nibble is numeric and low-order nibble is C, D or F. 30 distinct values.
Valid for Zone = Any single-byte binary value where low-order nibble is numeric. 160 distinct values.
Any receving field will have its sign propagated from the source field (except in the case of an unsigned source to a signed receiving field, which will have a C).
What does all this mean?
Firstly, fewer S0C7s with NOPFD. Not good.
Secondly, potential errorenous processing with PFD if a signed field has an F for a sign, ie it contains an unsigned value. Not good.
For example, a zoned-decimal containing spaces, or low-values, will be treated as zero with NOPFD. When processed to a packed-decimal receiving field it will look like a completely valid field. With PFD it will S0C7.
For example, for PFD, a signed packed-decimal with an F sign will not compare correctly to another equal-length packed-decimal if a Compare Packed is not generated (ie if Compare Logical Characters is generated by the compiler). With NOPFD the comparison will always be "correct".
So, what do you do? If all your signs conform to the PICTURE, then PFD will always work, produce less code, and optimise better.
If all your signs do not conform to the PICTURE, NOPFD will "fix them" in receiving fields and all processing will be consistent - but a lot more "invalid" data could be made "valid". NOPFD will produce more code, for every reference to zoned- and packed-decimal fields in your program, and will not optimise as well.
So, it seems a bit sloppy. I prefer the sound of PFD so far.
For intial testing, I would use PFD for definite. More likely to get S0C7s. Beyond initial testing, I'd stick to whatever was set in production.
At the end of the day, with proper validation of all data entering the system, they should be equivalent. So, again, I'd go for PFD.
What I'd think long and hard about would be changing the value in production. Could be a nightmare waiting to happen.
Oh, and if you are calling FORTRAN or PL/I from your Cobol program, IBM says you should use NOPFD. I wonder what they get up to? Even there, I'd prefer to handle the individual fields going to those programs, and still use PFD.
Any comments, questions, thoughts, suggestions, attempts to sway me, are welcome. |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
The "sign-fixing" of NUMPROC(NOPFD) is interesting, and not as bad as I was thinking it might be.
For example, here is an IF comparing two PIC S9(4) zoned decimals:
| Code: |
000052 IF
00035E F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
000364 F223 D0F8 A040 PACK 248(3,13),64(4,10) TS2=8 W-DISPNUM-SIZE4-ST
00036A F922 D0F0 D0F8 CP 240(3,13),248(3,13) TS2=0 TS2=8
000370 4770 B15A BC 7,346(0,11) GN=5(000386)
|
Pretty straightforward. Pack 'em into temporary storage, packed compare, branch on condition. Although the PACK leaves the signs alone, the CP "knows" about non-preferred signs. So here, no "sign-fixing" at all.
Here is a MOVE involving the same two fields.
| Code: |
000053 MOVE
000374 F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
00037A F822 D0F0 D0F0 ZAP 240(3,13),240(3,13) TS2=0 TS2=0
000380 F332 A040 D0F0 UNPK 64(4,10),240(3,13) W-DISPNUM-SIZE4-ST TS2=0
|
Now it gets more interesting. Pack the field with the potential non-preferred sign into Temporary Storage. Then ZAP (Zero and Add Packed) it to itself! What does that do? Well, the "ADD" part is what is crucial here, because, from the POP:
| Quote: |
The preferred sign codes are 1100 for plus and 1101 for minus. These are the sign codes generated for the results of the decimal-arithmetic instructions and the CONVERT TO DECIMAL instruction.
Alternate sign codes are also recognized as valid in the sign position: 1010, 1110, and 1111 are alternate codes for plus, and 1011 is an alternate code for minus. Alternate sign codes are accepted for any decimal source operand, but are not generated in the completed result of a decimal-arithmetic instruction or CONVERT TO DECIMAL. This is true even when an operand remains otherwise unchanged, such as when adding zero to a number. An alternate sign code is, however, left unchanged by MOVE NUMERICS, MOVE WITH OFFSET, MOVE ZONES, PACK, and UNPACK.
|
(my emphasis added).
So the ZAP is how NOPFD does the "sign-fixing" in this case (two signed four byte, zoned decimals, in a MOVE).
Having ZAP'd it, unpack it in to the receiving field.
For PFD, by comparison:
| Code: |
000052 IF
00035E D503 A000 A040 CLC 0(4,10),64(10) W-DISPNUM-SIZE4-S W-DISPNUM-SIZE4-ST
000364 4770 B142 BC 7,322(0,11) GN=5(00036E)
|
Now, this is doing a logical compare. If one of the signs is actually non-preferred, then the compare is not going to work properly. More on that later.
| Code: |
000053 MOVE
000368 D203 A040 A000 MVC 64(4,10),0(10) W-DISPNUM-SIZE4-ST W-DISPNUM-SIZE4-S
|
And the move, just picks up four bytes and drops 'em down again in the right place.
So far, this is un-optimised code.
So, NOPFD again
| Code: |
000052 IF
000256 F223 D100 A000 PACK 256(3,13),0(4,10) OPT=0 W-DISPNUM-SIZE4-S
00025C F223 D0F8 A030 PACK 248(3,13),48(4,10) TS2=8 W-DISPNUM-SIZE4-ST
000262 F922 D100 D0F8 CP 256(3,13),248(3,13) OPT=0 TS2=8
000268 4770 B060 BC 7,96(0,11) GN=5(000278)
|
Code is the same for the IF, except for use of OPT storage for one field.
| Code: |
00026C F822 D100 D100 ZAP 256(3,13),256(3,13) OPT=0 OPT=0
000272 F332 A030 D100 UNPK 48(4,10),256(3,13) W-DISPNUM-SIZE4-ST OPT=0
|
For the MOVE, one instruction is saved, because it's value has already been packed from the IF immediately before it. Still doing the ZAP to itself.
| Code: |
000052 IF
000256 D503 A000 A030 CLC 0(4,10),48(10) W-DISPNUM-SIZE4-S W-DISPNUM-SIZE4-ST
00025C 4770 B04E BC 7,78(0,11) GN=5(000266)
000053 MOVE
000260 D203 A030 A000 MVC 48(4,10),0(10) W-DISPNUM-SIZE4-ST W-DISPNUM-SIZE4-S
|
For PFD, the IF and the MOVE remain the same, even when OPT'd. |
|
| Back to top |
|
 |
Akatsukami
Global Moderator

Joined: 03 Oct 2009 Posts: 1787 Location: Bloomington, IL
|
|
|
|
| Bill Woodger wrote: |
| Ignoring "sign is seperate", IBM zoned and packed decimals have a "preferred" sign of C (positive), D (negative) or F (unsigned, assumed positive). "Non-preferred" opens up the possibility of other sign values, in fact A, B, C, D, E and F. Why? TBD. |
It may be worth noting that an overpunched positive sign (punch in zone 12) is interpreted as {-I (EBCDIC C0-C9) and an overpunched negative sign (punch in zone 11) is interpreted as }-R (EBCDIC D0-D9), which is probably why C, D, and F are "preferred".
Overpunching goes back to 1928, IIRC; the association between overpunched digits and alphas is no later than the introduction of the 360 in 1964, and probably older. Unless IBM recorded the reasons (or lack thereof), anyone who could tell us the "whys" has probably long since shuffled off this mortal coil. |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
Thanks Mr Akatsukami. Understood. Any ideas why the potential to encounter non-preferred signs exists in Cobol to the extent that IBM added the NUMPROC compiler option? VS Cobol had no special processing for them. I guess if they had appeared, they would have failed NUMERIC tests, but otherwise would have got along reasonably well. I have never seen one. I just assumed it was something "assembler guys" used to do, but we didn't need to. Now, there it is. Is it because of the Cobol 85 standard? Is it because of the Web stuff now available? Some managerial nonsense, having found it on some "to do" list from 1964?
Other than deliberately making one, has anyone ever seen a "non-preferred" sign? If they are not scattered all over DASD, why do we have a "new" compiler option for them? |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
The next example is four byte zoned signed to four byte zoned unsigned.
With NOPFD, for the IF
| Code: |
000059 IF
000386 F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
00038C F223 D0F8 A048 PACK 248(3,13),72(4,10) TS2=8 W-DISPNUM-SIZE4-UT
000392 960F D0FA OI 250(13),X'0F' TS2=10
000396 F922 D0F0 D0F8 CP 240(3,13),248(3,13) TS2=0 TS2=8
00039C 4770 B17E BC 7,382(0,11) GN=6(0003AA)
|
Again, Pack, Pack. Then ensure that the unsigned field is unsigned. Compare packed.
For the MOVE
| Code: |
000060 MOVE
0003A0 D203 A048 A000 MVC 72(4,10),0(10) W-DISPNUM-SIZE4-UT W-DISPNUM-SIZE4-S
0003A6 96F0 A04B OI 75(10),X'F0' W-DISPNUM-SIZE4-UT+3
|
This time an MVC is used, and the sign is "fixed" for the destination. Can we deduce, from this and the signed-to-signed example previously, that the method for the MOVE is dependent on how the sign is "fixed"? PACK-ZAP-UNPACK for the signed field, because the ZAP is doing the fixing, MVC for the unsigned field because the OI will do the fixing.
With PFD for the IF
| Code: |
000059 IF
00036E F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
000374 F223 D0F8 A048 PACK 248(3,13),72(4,10) TS2=8 W-DISPNUM-SIZE4-UT
00037A F922 D0F0 D0F8 CP 240(3,13),248(3,13) TS2=0 TS2=8
000380 4770 B162 BC 7,354(0,11) GN=6(00038E)
|
Which is the same as for NOPFD except for the assumption that the unsigned field has an F sign, rather than forcing it (in NOPFD) for the compare. CLC cannot be used, as the signs should be different.
For the MOVE
| Code: |
000060 MOVE
000384 D203 A048 A000 MVC 72(4,10),0(10) W-DISPNUM-SIZE4-UT W-DISPNUM-SIZE4-S
00038A 96F0 A04B OI 75(10),X'F0' W-DISPNUM-SIZE4-UT+3
|
Exactly the same as for NOPFD. This time sign is "fixed" to unsiged, because that is the sort of field it is.
OPT, NOPFD
| Code: |
000059 IF
000278 F223 D100 A000 PACK 256(3,13),0(4,10) OPT=0 W-DISPNUM-SIZE4-S
00027E F223 D0F8 A038 PACK 248(3,13),56(4,10) TS2=8 W-DISPNUM-SIZE4-UT
000284 960F D0FA OI 250(13),X'0F' TS2=10
000288 F922 D100 D0F8 CP 256(3,13),248(3,13) OPT=0 TS2=8
00028E 4770 B084 BC 7,132(0,11) GN=6(00029C)
|
Again, like the example previously posted, other than using OPT storage to save the value for later (elsewhere in the program this time) the IF is the same as the unoptimised one.
| Code: |
000060 MOVE
000292 D203 A038 A000 MVC 56(4,10),0(10) W-DISPNUM-SIZE4-UT W-DISPNUM-SIZE4-S
000298 96F0 A03B OI 59(10),X'F0' W-DISPNUM-SIZE4-UT+3
|
Same instructions as the non-optimised.
OPT, PFD
| Code: |
000059 IF
000266 F223 D100 A000 PACK 256(3,13),0(4,10) OPT=0 W-DISPNUM-SIZE4-S
00026C F223 D0F8 A038 PACK 248(3,13),56(4,10) TS2=8 W-DISPNUM-SIZE4-UT
000272 F922 D100 D0F8 CP 256(3,13),248(3,13) OPT=0 TS2=8
000278 4770 B06E BC 7,110(0,11) GN=6(000286)
|
| Code: |
000060 MOVE
00027C D203 A038 A000 MVC 56(4,10),0(10) W-DISPNUM-SIZE4-UT W-DISPNUM-SIZE4-S
000282 96F0 A03B OI 59(10),X'F0' W-DISPNUM-SIZE4-UT+3
|
Both sets of code mirror the non-optimised PFD, except for the preparatory storage for use later.
When comparing the same length signed zoned to unsigned zoned, the code generated of NOPFD and PFD is very similar (one extra OI for NOPFD) and is only open to any optimisation at all where a non-receiving field is used more than once. |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
| Bill Woodger wrote: |
[...]
Other than deliberately making one, has anyone ever seen a "non-preferred" sign? If they are not scattered all over DASD, why do we have a "new" compiler option for them? |
I may have been looking at this the wrong way. What NUMPROC(PFD) does is change the way the Cobol compiler generates code for decimals in some common instances. For instance, using CLC instead of CP, MVC instead of ZAP. Goes much faster, well, faster, but your data has to conform to the "preferred" signs. A CP can compare sign F to sign C and find them equal (if the amounts are equal, of course). A CLC cannot.
So maybe NUMPROC(PFD) is NUMPROC(GO-FASTER) and NUMPROC(NOPFD) is NUMPROC(SLOW-DOWN-THE-SIGNS-MIGHT-BE-ODD).
So it is not really all the other odd signs getting in the way, it is when you get an F in a signed field. Not difficult to do (if you want to do that), but when it happens in error it is difficult to get through testing. Well, it should be. |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
The next example is four byte zoned signed to seven byte zoned unsigned.
With NOPFD, for the IF
| Code: |
000066 IF
0003AA F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
0003B0 F236 D0F8 A050 PACK 248(4,13),80(7,10) TS2=8 W-DISPNUM-SIZE7-ST
0003B6 F923 D0F0 D0F8 CP 240(3,13),248(4,13) TS2=0 TS2=8
0003BC 4770 B1A6 BC 7,422(0,11) GN=7(0003D2)
|
Again, a straight PACK, PACK, Compare Packed. Just to emphasise, as is indicated in the manual, NOPFD does not always generate "sign fixing" code. Here it does not. It doesn't need to, because the CP can understand all the possibile signs and do a correct comparison.
| Code: |
000067 MOVE
0003C0 F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
0003C6 F822 D0F0 D0F0 ZAP 240(3,13),240(3,13) TS2=0 TS2=0
0003CC F362 A050 D0F0 UNPK 80(7,10),240(3,13) W-DISPNUM-SIZE7-ST TS2=0
|
Here, for the MOVE, we need the "sign fixing", to ensure that the receivng field has a "preferred sign".
For PFD, same source code:
| Code: |
000066 IF
00038E F233 D0F0 A000 PACK 240(4,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
000394 F236 D0F8 A050 PACK 248(4,13),80(7,10) TS2=8 W-DISPNUM-SIZE7-ST
00039A D503 D0F0 D0F8 CLC 240(4,13),248(13) TS2=0 TS2=8
0003A0 4770 B184 BC 7,388(0,11) GN=7(0003B0)
|
Here, an interesting development. Packing both fields to four-bytes and then a logical compare. Why not pad with three leading zeros the four-byte zoned field in temporary storage and then a CLC? I don't know.
| Code: |
000067 MOVE
00029C D202 A040 C004 MVC 64(3,10),4(12) W-DISPNUM-SIZE7-ST SYSLIT AT +4
0002A2 D203 A043 A000 MVC 67(4,10),0(10) W-DISPNUM-SIZE7-ST+3 W-DISPNUM-SIZE4-S
|
Although, curiously, the padding of three leading zeros is how the compiler achieves the MOVE.
OPT, NOPFD
| Code: |
000066 IF
00029C F236 D0F8 A040 PACK 248(4,13),64(7,10) TS2=8 W-DISPNUM-SIZE7-ST
0002A2 F923 D100 D0F8 CP 256(3,13),248(4,13) OPT=0 TS2=8
0002A8 4770 B0A0 BC 7,160(0,11) GN=7(0002B8)
|
Here, the four-byte signed, zoned, field has already been allocated space in the Optimisation area, ie in OPT=0 there is a packed representation of the field, three bytes long. So, then compare packed. Wait, though, although it doesn't matter, what is the sign-type of OPT=0. Let's look back at the last post with code in. OK, so it is still potentially non-preferred.
| Code: |
000067 MOVE
0002AC F822 D100 D100 ZAP 256(3,13),256(3,13) OPT=0 OPT=0
0002B2 F362 A040 D100 UNPK 64(7,10),256(3,13) W-DISPNUM-SIZE7-ST OPT=0
|
Now, we ZAP the OPT=0, and unpack it to the receiving field. Both OPT=0 and the receiving field are now preferred signs. The optimiser has removed two pack instructions in total, by using the OPT=0 field established earlier.
OPT, PFD
| Code: |
000066 IF
000286 F233 D108 A000 PACK 264(4,13),0(4,10) OPT=8 W-DISPNUM-SIZE4-S
00028C F236 D0F8 A040 PACK 248(4,13),64(7,10) TS2=8 W-DISPNUM-SIZE7-ST
000292 D503 D108 D0F8 CLC 264(4,13),248(13) OPT=8 TS2=8
000298 4770 B090 BC 7,144(0,11) GN=7(0002A8)
|
Sticking with the theme, pack both fields to four bytes, and do a logical compare. Note that W-DISPNUM-SIZE4-S is now in two OPT locations, firstly as three bytes packed, secondly as four bytes packed.
| Code: |
000067 MOVE
00029C D202 A040 C004 MVC 64(3,10),4(12) W-DISPNUM-SIZE7-ST SYSLIT AT +4
0002A2 D203 A043 A000 MVC 67(4,10),0(10) W-DISPNUM-SIZE7-ST+3 W-DISPNUM-SIZE4-S
|
Identical to the un-optimised MOVE. Three zeros padded on the front, then an MVC.
When comparing two signed zoned fields, the code for NOPFD differs substantially from PFD. NOPFD sticks to decimal instructions, PFD uses CLC and a couple of MVC's. |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
Next up, four bytes zoned signed to seven bytes zoned unsigned. I wonder if we can predict the code yet?
For NOPFD, Pack (3 bytes), Pack (four bytes), OI, CP. MVC LIT, MVC, OI.
For PFD, Pack (four bytes), Pack (four bytes), CP. MVC LIT, MVC, OI.
And for the optimised?
NOPFD
| Code: |
000073 IF
0002B8 F223 D100 A000 PACK 256(3,13),0(4,10) OPT=0 W-DISPNUM-SIZE4-S
0002BE F236 D0F8 A048 PACK 248(4,13),72(7,10) TS2=8 W-DISPNUM-SIZE7-UT
0002C4 960F D0FB OI 251(13),X'0F' TS2=11
0002C8 F923 D100 D0F8 CP 256(3,13),248(4,13) OPT=0 TS2=8
0002CE 4770 B0CA BC 7,202(0,11) GN=8(0002E2)
|
Hang about. Why is that setting OPT=0 again? Well, I missed it earlier, but what is happening is that every time the compiler generates the ZAP-to-itself as part of the MOVE, to get the "preferred sign", then it has to reset OPT=0 (in this case). The result being that for NOPFD the OPT fields for packed data have less of a life-span. The compiler knows the value has changed, if it has carried out "sign fixing", so cannot use it again without re-setting it first. Yet, if it did use it again without resetting, it would make no difference at all to the results of anything. The CP does not mind about the signs as long as they are valid. The receiving field always contains a preferred sign. The manual hints at problems like this when discussing performance.
There is nothing remarkable about the MOVE, as it is the same as the two above.
For OPT, PFD one instruction is saved through the use of the 3-byte packed OPT=0, otherwise the code is the same as for NOOPT, PFD. |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
Having looked at a 4-byte signed zoned decimal being compare 4- and 7-byte signed and unsiged zoned decimals, let's have a look at comparing it to a packed decimal.
NOPFD, IF
| Code: |
000080 IF
0003FC F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
000402 F822 D0F0 D0F0 ZAP 240(3,13),240(3,13) TS2=0 TS2=0
000408 F922 A060 D0F0 CP 96(3,10),240(3,13) W-COMP3PD-SIZE4-ST TS2=0
00040E 4770 B1F2 BC 7,498(0,11) GN=9(00041E)
|
There is nothing unusual here, except, why is it doing the ZAP? OK, it does the ZAP to get a preferred sign, but why does it want a preferred sign, the CP can handle non-preferred as well. In none of the code generated for the zoned fields, which were all packed before doing a CP, did the ZAP-to-itself get done.
| Code: |
000412 F223 A060 A000 PACK 96(3,10),0(4,10) W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S
000418 F822 A060 A060 ZAP 96(3,10),96(3,10) W-COMP3PD-SIZE4-ST W-COMP3PD-SIZE4-ST
|
Pack into the receiver, then ZAP the receiver to itself. Expected.
With PFD, IF
| Code: |
000080 IF
0003D6 F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
0003DC D502 A060 D0F0 CLC 96(3,10),240(13) W-COMP3PD-SIZE4-ST TS2=0
0003E2 4770 B1C0 BC 7,448(0,11) GN=9(0003EC)
|
Just a PACK and CLC.
| Code: |
000081 MOVE
0003E6 F223 A060 A000 PACK 96(3,10),0(4,10) W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S
|
And just a PACK into the receiving field.
For OPT, NOPFD
| Code: |
000080 IF
0002E2 D202 D108 D100 MVC 264(3,13),256(13) OPT=8 OPT=0
0002E8 F822 D100 D100 ZAP 256(3,13),256(3,13) OPT=0 OPT=0
0002EE F922 A050 D100 CP 80(3,10),256(3,13) W-COMP3PD-SIZE4-ST OPT=0
0002F4 4770 B0EC BC 7,236(0,11) GN=9(000304)
|
This time, the code makes use of OPT=8 to generate a new OPT=0 with an MVC, then continues as usual.
| Code: |
000081 MOVE
0002F8 F223 A050 A000 PACK 80(3,10),0(4,10) W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S
0002FE F822 A050 A050 ZAP 80(3,10),80(3,10) W-COMP3PD-SIZE4-ST W-COMP3PD-SIZE4-ST
|
For the MOVE, just pack into the receiver and ZAP-to-itself.
For OPT, PFD
| Code: |
000080 IF
0002C8 D502 A050 D100 CLC 80(3,10),256(13) W-COMP3PD-SIZE4-ST OPT=0
0002CE 4770 B0C0 BC 7,192(0,11) GN=9(0002D8)
|
Using OPT=0 which has preserved the 3-byte packed value of the 4-byte zoned, just a logical compare.
| Code: |
000081 MOVE
0002D2 F223 A050 A000 PACK 80(3,10),0(4,10) W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S
|
And then just a PACK to the receiver.
Overall, to this packed field, the only unexpected this is the ZAP-in-place for the IF with NOPFD, both NOOPT and OPT. Still can't think why it does it. |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
Now 4-byte signed zoned to 3-byte unsigned packed.
With NOPFD, IF
| Code: |
000087 IF
00041E F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
000424 F822 D0F0 D0F0 ZAP 240(3,13),240(3,13) TS2=0 TS2=0
00042A D202 D0F8 A068 MVC 248(3,13),104(10) TS2=8 W-COMP3PD-SIZE4-UT
000430 960F D0FA OI 250(13),X'0F' TS2=10
000434 F922 D0F8 D0F0 CP 248(3,13),240(3,13) TS2=8 TS2=0
00043A 4770 B21C BC 7,540(0,11) GN=10(000448)
|
Pack it, ZAP-in-place (again curious), MVC and OI for the unsigned packed, then compare packed.
| Code: |
000088 MOVE
00043E F223 A068 A000 PACK 104(3,10),0(4,10) W-COMP3PD-SIZE4-UT W-DISPNUM-SIZE4-S
000444 960F A06A OI 106(10),X'0F' W-COMP3PD-SIZE4-UT+2
|
Just a Pack, and the OI to keep the receiver unsigned.
With PFD, IF
| Code: |
000087 IF
0003EC F223 D0F0 A000 PACK 240(3,13),0(4,10) TS2=0 W-DISPNUM-SIZE4-S
0003F2 F922 A068 D0F0 CP 104(3,10),240(3,13) W-COMP3PD-SIZE4-UT TS2=0
0003F8 4770 B1DA BC 7,474(0,11) GN=10(000406)
|
Here the Pack, and, as the already packed field is unsigned, a Compare Packed, not a Compare Logical.
| Code: |
000088 MOVE
0003FC F223 A068 A000 PACK 104(3,10),0(4,10) W-COMP3PD-SIZE4-UT W-DISPNUM-SIZE4-S
000402 960F A06A OI 106(10),X'0F' W-COMP3PD-SIZE4-UT+2
|
Pack, and OI, to ensure an unsigned receiver.
OPT, NOPFD
| Code: |
000087 IF
000304 D202 D0F8 A058 MVC 248(3,13),88(10) TS2=8 W-COMP3PD-SIZE4-UT
00030A 960F D0FA OI 250(13),X'0F' TS2=10
00030E F922 D0F8 D100 CP 248(3,13),256(3,13) TS2=8 OPT=0
000314 4770 B10A BC 7,266(0,11) GN=10(000322) |
MVC and OI for the packed unsigned field, then compare packed to the OPT=0 field previously stored. Curiously, this time the OPT=0 hasn't been refreshed, even though the current value is a preferred sign.
| Code: |
000088 MOVE
000318 F223 A058 A000 PACK 88(3,10),0(4,10) W-COMP3PD-SIZE4-UT W-DISPNUM-SIZE4-S
00031E 960F A05A OI 90(10),X'0F' W-COMP3PD-SIZE4-UT+2
|
Pack and OI, nothing surprising.
OPT, PFD
| Code: |
000087 IF
0002D8 F922 A058 D100 CP 88(3,10),256(3,13) W-COMP3PD-SIZE4-UT OPT=0
0002DE 4770 B0D4 BC 7,212(0,11) GN=10(0002EC)
|
Compare Packed (because unsigned) to the previously stored OPT=0.
| Code: |
000088 MOVE
0002E2 F223 A058 A000 PACK 88(3,10),0(4,10) W-COMP3PD-SIZE4-UT W-DISPNUM-SIZE4-S
0002E8 960F A05A OI 90(10),X'0F' W-COMP3PD-SIZE4-UT+2
|
Pack and OI.
Because it is interesting above that an OPT=0 with a preferred sign is used for OPT, NOPFD, let's just check by looking at where it is established as well.
| Code: |
000080 IF
0002E2 D202 D108 D100 MVC 264(3,13),256(13) OPT=8 OPT=0
0002E8 F822 D100 D100 ZAP 256(3,13),256(3,13) OPT=0 OPT=0
0002EE F922 A050 D100 CP 80(3,10),256(3,13) W-COMP3PD-SIZE4-ST OPT=0
0002F4 4770 B0EC BC 7,236(0,11) GN=9(000304)
000081 MOVE
0002F8 F223 A050 A000 PACK 80(3,10),0(4,10) W-COMP3PD-SIZE4-ST W-DISPNUM-SIZE4-S
0002FE F822 A050 A050 ZAP 80(3,10),80(3,10) W-COMP3PD-SIZE4-ST W-COMP3PD-SIZE4-ST
000304 GN=9 EQU *
000087 IF
000304 D202 D0F8 A058 MVC 248(3,13),88(10) TS2=8 W-COMP3PD-SIZE4-UT
00030A 960F D0FA OI 250(13),X'0F' TS2=10
00030E F922 D0F8 D100 CP 248(3,13),256(3,13) TS2=8 OPT=0
000314 4770 B10A BC 7,266(0,11) GN=10(000322)
|
The ZAP-to-itself at displacement 0002E8 is the last instruction which updates OPT=0. Out of the ZAP the sign is preferred. When we go to the next IF instruction, the already preferred OPT=0 is used (even though the sign doesn't matter, as long as valid, for the CP).
This does not follow the previous usage of OPT=0 in these examples. There, if the sign was "rectified", the OPT=0 would be refreshed. Here, not. |
|
| Back to top |
|
 |
PeterHolland
Global Moderator

Joined: 27 Oct 2009 Posts: 2481 Location: Netherlands, Amstelveen
|
|
|
|
| Oh my goodness, and now? |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
I suppose I am a little "over interested"? When I see those tantalising little bits in the manual, I can't help but wonder why? Sometimes helps. Never hurts (me :-) ).
I get the point. |
|
| Back to top |
|
 |
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
OK, starting to wind this up.
NUMPROC(NOPFD) does "sign fixing" (another term for this is "sign rectification"). This is not as bad as it sounded to me originally. Previously I had known "sign fixing" in Cobol as the extra code generated to ensure that an unsigned field remained unsigned, so I was concerned about how NOPFD did this for potential "non-preferred signs".
From the Priciples of Operation (POP).
| Quote: |
The preferred sign codes are 1100 for plus and
1101 for minus. These are the sign codes generated
for the results of the decimal-arithmetic
instructions and the CONVERT TO DECIMAL
instruction.
|
The result generated, by the CPU, before anyone can get their sticky fingers on it, can only be sign C or D. ZAP is a decimal-arithmetic instruction. ZAP-to-itself is possible (operates right-to-left in this case). So a field which might potentially contain a non-preferred sign can have it "recitified" by a ZAP-to-itself. Compare Packed knows about non-preferred signs, and will compare them correctly.
One other "rectification" is carried out with NOPFD. If a field is unsigned, NOPFD will ensure that it is unsigned for all references to that field (source or receiver).
Two other rectifications are not to do with the NOPFD option, but are the way that Cobol works.
An alphanumeric (PIC X(n)) as a sending field always results in a positive (C) in a signed field (and an F in an unsigned field).
An unsigned field as the source always gives a positive (C) in a signed receiving field.
For a packed receiver this is achieved by using MVN (Move Numerics) on the last byte of the field (ironic, because in that byte the "numeric" is the sign, but it achieves the affect).
For a zoned receiver this is achieved by Or Immediate (OI) to get the F (unsigned) and OI followed by And Immediate (NI) to get the positive (C).
NOPFD relieves heavily on Compare Packed (CP) for "IF tests". This is traditionally the case. With decimal fields, you expect a decimal compare. You can also expect a S0C7 if either field is invalid.
NOPFD will use Compare Logical (CLC) for some compares. If you are comparing two unsigned decimals, either zoned or packed or mixed, and of equal or different size, NOPFD will generate a CLC. You cannot expect an S0C7 (or any abend) in this instance if either field is invalid.
NUMPROC(PFD) does not do "sign fixing", except where required to obey the Cobol rules, as NOPFD does. PFD assumes that a signed field can only contain a C or D sign (F may not give valid results) and an unsiged field can only contain an F sign.
PFD uses Compare Logical (CLC) for "IF tests" more heavily than does NOPFD. You cannot expect an S0C7 (or any abend) in this instance if either field is invalid.
PFD will use Compare Packed (CP) for some compares. If the fields are not the same length by the time a compare of some sort is going to be generated, or one field is signed and the other not, PFD will generate a CP (yes, there is a chicken-or-the-egg situation that is resolved for this). You can expect a S0C7 if either field is invalid.
Both NOPFD and PFD generate CLCs. Both generate CPs. NOPFD will likely generate fewer CLCs.
NOPFD will generate more code, and will tend to generate code options which take longer to execute (because the need for non-preferred processing precludes shorter execution time options).
NOPFD does not optimise very well. Using the ZAP for sign-rectification reduces optimisation options, even the use of OPT fields to retain a value which can be used more than once in a block of code (if a field theoretically has to be packed five times in a block of code, but its value does not change, then it only needs to be packed once and then the value is already available for the other four places).
PFD already produces fairly "good" code from a performance point of view, but still has more possibilities for optimisation that NOPFD.
For decimal fields, PFD OPT is up to 20% faster than NOPFD OPT. This does not mean your program will be up to 20% faster, because your program will be doing many things other than processing decimal fields. If you are processing a lot of decimal fields a lot of time you would expect to be able to notice the difference in CPU usage between the two options.
Remember, you can't just decide to use a different option for your development cycle. Use what you use in production for that. Only change an option in production after very long consideration if potential impacts. PFD works is all your fields are signed correctly, NOPFD works if some (or even all) of your fields have non-preferred signs.
The worst culprits for the amount of code generated are unsigned fields. If you are calculating with the field, give it a sign. If you are not calculating with it, unsigned makes sense. The Oldies amongst us know this from way back. However, with NOPFD, even testing an unsigned field gets you sign-rectification. As does moving to an unsiged field.
Last thought for this post. A non-preferred sign that you do anything to as a receiving field, becomes a preferred sign, with NOPFD. With PFD, if a field contains a non-preffered or F sign, any calculation (including ZAP) will "rectify" it. |
|
| Back to top |
|
 |
|
|
 |
All times are GMT + 6 Hours |
|