64-bit HLASM: z/Architecture Instructions and AMODE 64

TT

64-bit HLASM: z/Architecture Instructions and AMODE 64

IBM z/Architecture introduced 64-bit registers and instructions in 2000 (z900). Today, most z/OS software runs in AMODE 31 or AMODE 64. This module covers the 64-bit instruction set, addressing modes, and how to write or migrate HLASM code for 64-bit operation.

64-bit Registers

In z/Architecture, all 16 general-purpose registers are 64 bits wide. The 32-bit instructions (L, ST, A, S, etc.) use only the low 32 bits. The 64-bit instructions operate on the full 64-bit register.

hlasm
* 32-bit load — high 32 bits of register are sign-extended
         L     3,MYFW          Load 32-bit value, sign-extend to 64 bits

* 64-bit load — full 64-bit register is loaded
         LG    3,MYDW          Load 64-bit value from doubleword

Addressing Modes

AMODEMax addressInstruction pointer
2416MB (X'FFFFFF')24-bit PSW
312GB (X'7FFFFFFF')31-bit PSW
6416EB (X'7FFFFFFFFFFFFFFF')64-bit PSW

Most z/OS applications use AMODE 31. Use AMODE 64 when:

  • You need to address more than 2GB of virtual storage
  • You're writing new code and want to follow modern z/OS conventions
  • You're calling 64-bit system services
hlasm
MYPROG   CSECT
MYPROG   AMODE 64
MYPROG   RMODE ANY

64-bit Load and Store Instructions

hlasm
* Load 64-bit (G = "Gigabyte", actually meaning 64-bit)
         LG    3,MYDW          Load 64-bit doubleword into reg 3
         LGR   3,4             Load register: reg3 = reg4 (64-bit)
         LGF   3,MYFW          Load 32-bit fullword, sign-extend to 64-bit
         LGHI  3,42            Load halfword immediate (sign-extended to 64-bit)

* Store 64-bit
         STG   3,MYDW          Store 64-bit reg 3 to doubleword
MYDW     DS    D               8-byte doubleword

64-bit Arithmetic

hlasm
* Add
         AGR   3,4             reg3 = reg3 + reg4 (64-bit)
         AG    3,MYDW          reg3 = reg3 + doubleword from storage

* Subtract
         SGR   3,4             reg3 = reg3 - reg4 (64-bit)
         SG    3,MYDW

* Multiply (no pair needed — result fits in 64 bits for most cases)
         MSGR  3,4             reg3 = reg3 * reg4 (signed 64-bit, low 64 bits)
         MSG   3,MYDW

* Multiply full (128-bit result in register pair)
         MLGR  2,4             regs 2-3 = reg3 * reg4 (unsigned 128-bit)

* Divide (128-bit / 64-bit)
         DLGR  2,4             reg3 = quotient, reg2 = remainder

64-bit Compare

hlasm
         CGR   3,4             Compare 64-bit registers (signed)
         CG    3,MYDW          Compare reg 3 with doubleword storage
         CLGR  3,4             Compare 64-bit registers (unsigned)

64-bit Addressing

In AMODE 64, addresses are 64 bits. The base-displacement addressing still works the same way, but the base register holds a 64-bit address:

hlasm
MYPROG   CSECT
MYPROG   AMODE 64
         STG   14,8(13)        Store 64-bit return address
         LARL  12,MYPROG       Load relative address into reg 12 (AMODE 64 friendly)
         USING MYPROG,12

LARL (Load Address Relative Long) loads an address relative to the current instruction, without needing a base register. It's the preferred way to set up a base register in AMODE 64.

STMG / LMG — 64-bit Save and Restore

hlasm
* AMODE 64 standard entry
MYPROG64 CSECT
MYPROG64 AMODE 64
         STMG  14,12,144(13)   Save 64-bit registers 14-12 (offset 144 in save area)
         LARL  12,MYPROG64
         USING MYPROG64,12
         LA    11,SAVEAREA
         STG   13,128(11)      Store caller's save area (64-bit pointer)
         STG   11,136(13)      Forward chain
         LGR   13,11

The 64-bit save area is 216 bytes (larger than the 72-byte 31-bit save area).

Migrating 31-bit Code to 64-bit

Common changes required:

31-bit64-bit equivalent
L reg,addrLG reg,addr (if pointer)
ST reg,addrSTG reg,addr (if pointer)
STM 14,12,12(13)STMG 14,12,144(13)
LM 14,12,12(13)LMG 14,12,144(13)
BALR 12,0LARL 12,label
DC A(label)DC AD(label) (8-byte address constant)
DS ADS AD

Key principle: change storage area addresses (pointers) to 64-bit; leave data values (amounts, counts) as 32-bit unless they genuinely exceed 32-bit range.

Frequently Asked Questions

Q: Do I need to rewrite existing AMODE 31 programs for 64-bit? Not necessarily. Most AMODE 31 programs continue to run correctly on z/Architecture without change. AMODE 64 is needed when you need to address more than 2GB of virtual storage, when called by an AMODE 64 program that expects 64-bit linkage, or when using 64-bit system services. IBM recommends new programs use AMODE 64 for future-proofing, but migrating working AMODE 31 code purely for the sake of it is rarely justified.

Q: Why is the offset for STMG 144 instead of 12? The 64-bit linkage convention uses a larger save area (216 bytes vs 72 bytes). In the 64-bit save area, the register save area starts at offset 144 (not offset 12 as in 31-bit). Registers are 8 bytes each in 64-bit mode, so 14 registers (14,15,0,1,...,12) × 8 bytes = 112 bytes, stored at offset 144. Using offset 12 for STMG would overwrite the save area chain pointers — a common bug when converting code.

Q: Can a 64-bit HLASM routine call a 31-bit routine? Yes, using BASSM 14,15 which saves and sets the addressing mode. The called routine runs in AMODE 31. On return, the mode reverts to AMODE 64. Mixed-mode calling works but requires careful management of pointer sizes — a 64-bit address passed to a 31-bit routine will have its high 33 bits ignored, potentially causing addressing errors.


Part of HLASM Mastery Course — Module 20 of 22.