[part 3] 1. The two MVHHI (move halfword immediate to halfword storage) instructions are setting up the edit mask. This would be the same as the MVC in COBOL 4, but it is using immediate instructions. The immediate values can't be larger than a halfword, so it takes 2 instructions.
Note: In my code if I had to move > 2 bytes, I just define a constant. This code is more efficient at the expense of understandability for humans reading it. 2. Same LH and CVD to convert the binary field to packed decimal. 3. OI is doing a sign-fix; it is converting the packed decimal sign (probably x'0C') to zoned decimal (x'0F'). COBOL 4 didn't need this because it was ED'ig a packed-decimal field. But it looks like we're going to... 4. UNPK is unpacking the packed-decimal field into zoned decimal. Note that I would normally unpack first, then fix the sign. 5. CDPT (new instruction!) is converting from packed-decimal to Decimal Floating Point (DFP) format. The result is stored in a floating point register (FP0) 6. ESDTR is extracting the number of significant digits in FP0 and putting that in register 2. I think that's the whole point of the DFP instructions: it is trying to count how many non-zero characters are at the right of the number. So 123 has 3, 012 is 2, 005 would be 1, 000 would be 0. I think 7. IILF is Insert Immediate Low Fullword; it is inserting the edit mask into the low half of register 4 (compare to COBOL 4 where the edit mask was moved to storage). Since registers are really 64 bits, IILF really means load 4 bytes into the register. I think it is using IILF because there's no other way to load a 4 byte immediate value into a register. 8. ICM is Insert Character under Mask. This is where it gets weird. The mask is x'7', which is b'0111'. That means it is moving the first 3 bytes in the field that we unpacked in step 4, to the same register as we just did the IILF in. It will overlay the result of the previous instruction. So if the number is 123, we'd end up with x'40' and then 123. So what was the '202120' for? 9. OILL is Or Immediate, in this case to the lower halfword of the register (16 bits). It is oring x'F0', which I think would be assembled as x'00F0', so this looks like a sign fix. 10. ST is storing the result to memory. But notice it is overlaying what we put in memory at that position in step 1, which as far as I can tell, it never used. 11. LLC is Load Logical Character. It is like a fullword load except that it doesn't treat the value as a signed number. So this is loading R4 with something that's at 2888 off of R3 + R2. Remember R2 was the number of significant digits (step 6). 12. LTR is Load and Test Register, but notice it is the same register. It is doing this so that it can test if it is zero or not. 13. JE is Jump if Equal, but here I think it is really jumping if it is equal to zero. In that case it skips the next two instructions. 14. AHI is Add Halfword Immediate. I think this is a weird way of subtracting 1, which is needed to set up the next instruction. Lengths in instructions are 0 based, so if you want to move 5 bytes, you need to use a length of 4. 15. EXRL is Execute Relative Long. The instruction it is executing is MVC 353(1,R13),352(R13), where the "1" (the move length) is zapped with what's in R4. In step 10 we stored 4 bytes at R13 + 352. Here we're shifting it x bytes to the right, where x is what was put in R4 and then modified.