Showing posts with label z/architecture assembler. Show all posts
Showing posts with label z/architecture assembler. Show all posts

07 November 2012

An ongoing list of z/Architecture assembler things that you forget if you don't use them often enough

This blog entry will be updated and reposted whenever I come across things that I should remember but my brain has forgotten due to infrequent contact with the item.

  • TRT munches GPR2. That's why the subsequent compare failed miserably.
  • Man, there are a lot of SVCs and PCs that won't work in AR mode. Make sure you switch out of AR mode before calling macros like WAIT.

16 October 2012

Little bitty z/Architecture assembler tips and tricks not worthy of their own blog entry

This blog entry will be updated continually and reposted when I come up with little tips and techniques not worthy of their own blog entry.


High half register check

Can't use those bitchin' new high-half register instructions because you have customers not on the latest z196/z114? Need to check the upper half of a register for non-zero so your AMODE 64 doesn't run amok? Use the following:
CLG   R0,=X'00000000FFFFFFFF'
JH    THERE_IS_SOMETHING_IN_THE_HIGH_HALF_OF_THE_REGISTER
And you also have an example of a label longer than 8 characters.


Make sure your base register is clean in AR mode

LAE is a nice instruction for setting a base register if you aren't sure your code will be called in primary or AR mode. If the B2 field is 0, when you are in AR mode, 00000000 is placed into the corresponding R1 access register, so you can code 

LAE   R12,0(R15)

and get your entry point without the possibility of getting messed up by a stray ALET in AR12.


WAIT LONG=YES and baseless programming (z/OS, 1.12 and earlier)

If you've tried this combination before, you've gotten bit because the macro generates a BCR GPR8,0 instruction followed by an ICM of the second byte via an "*-1" operand. If you're baseless, this fails because you are baseless. However, there is no need to fret. The following code works and gets around this issue.

         IILH  GPR0,X'8000'
         IILL  GPR0,1
         WAIT  (0),ECB=MYECB

The macro generates an unnecessary LR GPR0,GPR0 followed by the appropriate code. If you are using an ECBLIST, just put the number of this-many-POSTed ECBs in GPR0; in this case, it might be easier to load GPR0 first, then use an OILH GPR0,X'8000' instruction.

As noted in the comments below, starting with 1.13, if you are SYSSTATE ARCHLVL=2, WAIT will generate appropriate code for baseless situations.

More to come as I think of them...


25 July 2012

LOCTR - very powerful, and makes it very easy to shoot yourself in the foot

I promise that I will get Martin's blog up in a couple of days, and I hope that part 3 of "TCBs, SRBs, and FRRs, oh my!" will be posted in a couple of weeks (shifting work priorties), but I thought I'd throw this little tidbit out there for you.

I am updating our standard entry/exit macros to support AMODE 64, and support various types of AMODEs and ASCs on entry. As a part of this, I've had to add some more LOCTRs to the definition of our work areas. But let me demonstrate this little trap for you:

WORK     DSECT ,
WORKLOC1 LOCTR ,
DW10     DS    D
WORKLOC2 LOCTR ,
DW20     DS    D
WORKLOC1 LOCTR ,
DW11     DS    D
WORKLOC2 LOCTR ,
DW21     DS    D
WORKLOC1 LOCTR ,
DW13     DS    D
* All done!
WORKLEN  EQU   *-WORK

         LHI   R0,WORKLEN
         STORAGE OBTAIN,LENGTH=(0)

What value is loaded into R0 by the LHI instruction, and how many bytes of storage will be obtained? Raise your hand. How many say 40? OK, a couple. How many say 24? Aha, those are the ones who have worked with LOCTR and have been bit by this little gotcha.

Those of you who said 40, can you figure it why it's 24? Yep, that's right. I'll go ahead and redo the above with location counters, so the reason becomes clear:


00000000 WORK     DSECT ,

00000000 WORKLOC1 LOCTR ,
00000000 DW10     DS    D
00000018 WORKLOC2 LOCTR ,
00000018 DW20     DS    D
00000008 WORKLOC1 LOCTR ,
00000008 DW11     DS    D
00000020 WORKLOC2 LOCTR ,
00000020 DW21     DS    D
00000010 WORKLOC1 LOCTR ,
00000010 DW13     DS    D
* All done!
00000018 WORKLEN  EQU   *-WORK

The EQU is in WORKLOC1, and it correctly calculates the length of the WORKLOC1 LOCTR area. There are two ways to correct this: 1) insert a WORKLOC2 LOCTR before the equate; 2) my preferred solution, which is to introduce a new LOCTR (call it WORK_END) before the EQU. In either case,  WORKLEN will now be the actual length of the WORK DSECT, 40 bytes.

LOCTR is very powerful, as it allows you to define items in macros but yet segregate; such as putting required constants in a CONSTANT LOCTR area, out of the instruction pipeline. But, like any powerful tool in the system developer's arsenal, it must be used with great caution, and always take a sanity look at the assembler listing. The hour of debugging you save may be your own!

And a few more things...

  1. Please try to avoid hard-coded offsets. It may have made sense to the person who originally wrote this code 20 years ago, but when someone new comes along, having nice, identifiable labels and DSECTs will make that person's life easier when trying to decipher your control block chaining. The time you spend coding the DSECT and labels now may preserve someone's sanity down the road.
  2. When you do switch to DSECTs, remember to put the right register in the USING statement. (That's more of a *headdesk* moment for me.)
  3. Don't use PRINT OFF unless you really need it. Nothing ticks me off more that looking at a listing file and seeing that the entry macro has issued PRINT OFF, and nothing follows.