Advanced
Features of Macro Instructions
This lecture will focus on some
of the advanced features of the
macro language as implemented by the IBM/System 360 assembler.
We shall focus on our stack
handling macros.
Some of the features to be
covered by this lecture include.
1. The
use of concatenation to generate type–specific instructions.
2. Some
standard system variable symbols.
3. The
use of one system variable symbol to solve the branch problem.
4. Conditional
assembly.
5. The
use of conditional assembly as a help in writing STKPOP.
7. The ABEND macro and its
use in signaling run–time errors.
8. A
completed version of our stack macros.
Concatenation:
Building Operations
In
a model statement, it is possible to concatenate two strings of characters.
Consider
the macro prototype to load a register from one of several sources.
Note the use of the string “&NAME” to allow this to be a branch target.
MACRO
&NAME LOAD ®,&TYPE,&ARG
&NAME L&TYPE ®,&ARG
MEND
Consider
a number of invocations.
LOAD R7,R,R6 becomes LR R7,R6
LOAD R7,H,HW becomes LH R7,HW
LOAD R7,,FW becomes L R7,FW
Note
here: the second argument is empty. The
empty string is concatenated to “F”.
We shall now extend the stack
operations to push and pop contents of
half–words and full–words, as well as registers.
Pushing from Various Sources
We
look first at the handling of our STKPUSH. The only
restriction on the
stack is that every value pushed be treated as a 32–bit fullword.
As
a result, a 16–bit halfword will be sign–extended to a 32–bit fullword
before being pushed onto the stack. This
is similar to the function of the
LH
instruction, which loads a register from a halfword.
The
key instruction in the original STKPUSH macro is the following.
ST &R,0(3,2) STORE THE ITEM INTO THE STACK
In
this case, the item to be placed on the stack is found in the register
indicated by the symbolic parameter &R.
The
way to extend this instruction to all data types is as follows.
1. Select
a register to be a fixed source for the word on the stack, and
2. Construct
instructions to load that fixed register from the source.
What Shall Be Stored on the Stack?
At
this point, we have a decision to make.
What data types to store?
The
size restriction on the stack limits the simple choices to addresses and the
contents of registers, halfwords, and fullwords.
We
must select a working register for the new macro. I select R4.
The “key code” becomes as follows.
Stacking
an address LA R4,&ARG Load address into R4.
ST R4,&R,0(3,2)
Stacking
a halfword LH R4,&ARG Load halfword into R4.
ST R4,&R,0(3,2)
Stacking
a fullword L R4,&ARG
Load fullword into R4.
ST R4,&R,0(3,2)
Stacking a register LR R4,&ARG Load
value from source
register into R4.
ST R4,&R,0(3,2)
Passing the Type in a Macro Invocation
The
solution adopted to the problem above is to pass the type in the
macro call and use concatenation to build the load operator.
Here is
some code taken from a macro definition that has been run and tested.
First, we show the macro prototype.
&L2 STKPUSH &ARG,&TYP
Next we
show the “key instruction” in the macro body.
L&TYP R4,&ARG
Here are
four typical invocations of the macro.
STKPUSH R7,R PUSH VALUE IN REGISTER.
STKPUSH HHW,H PUSH A HALFWORD VALUE.
STKPUSH FFW,A PUSH AN ADDRESS.
STKPUSH FFW PUSH A FULLWORD.
Note that the last invocation lacks a second
argument. In the expansion, this
causes &TYP to be set to ‘ ’, a blank; “L&TYP” becomes “L ”.
The Macro Definition
Here is
the definition for the macro at this stage of its development.
MACRO
&L2 STKPUSH &ARG,&TYP
&L2 LH
R3,STKCOUNT
LA
R2,THESTACK
L&TYP R4,&ARG
ST
R4,0(3,2)
LH
R3,STKCOUNT
AH
R3,=H'1'
STH
3,STKCOUNT
MEND
Again,
the “&L2”
allows the macro invocation to be a branch target.
Some Invocations of this Macro
91 STKPUSH R7,R
92+ LH
R3,STKCOUNT
93+
94+ LA
R2,THESTACK
95+ LR R4,R7
96+ ST
R4,0(3,2)
97+ LH
R3,STKCOUNT
98+ AH
R3,=H'1'
99+ STH
3,STKCOUNT
100 STKPUSH HHW,H
101+ LH
R3,STKCOUNT
102+
103+ LA
R2,THESTACK
104+ LH R4,HHW
105+ ST
R4,0(3,2)
106+ LH
R3,STKCOUNT
107+ AH
R3,=H'1'
108+ STH
3,STKCOUNT
More Invocations of this Macro
109 STKPUSH FFW
110+ LH
R3,STKCOUNT
111+
112+ LA
R2,THESTACK
113+ L R4,FFW
114+ ST
R4,0(3,2)
115+ LH
R3,STKCOUNT
116+ AH
R3,=H'1'
117+ STH
3,STKCOUNT
118 STKPUSH FFW,A
119+ LH
R3,STKCOUNT
120+
121+ LA
R2,THESTACK
122+ LA R4,FFW
123+ ST
R4,0(3,2)
124+ LH
R3,STKCOUNT
125+ AH
R3,=H'1'
126+ STH
3,STKCOUNT
NOTE:
The originals of the program listing are found at the end of the slides.
Saving the Work Registers
As
written, this macro has the side effect of changing the values of three
registers: R2, R3, & R4. The value
of R4 is preserved only if it is being pushed.
We
should write macros so that they operate without side effects. The only
way to do this is to save and restore the values of the work registers.
There
are many ways to do this. The simplest
is to alter the stack data structure.
Here is the new version.
STKCOUNT DC H‘0’
NUMBER OF ITEMS STORED ON STACK
STKSIZE DC H‘64’ MAXIMUM STACK CAPACITY
STKSAV2 DC F‘0’ SAVES CONTENTS OF R2
STKSAV3 DC
F‘0’ SAVES CONTENTS OF R3
STKSAV4 DC F‘0’ SAVES CONTENTS OF R4
THESTACK DC 64F‘0’
THE STACK HOLDS 64 FULLWORDS
This new
definition does not alter the STKINIT macro. It does
affect the
other two macros: STKPOP and STKPUSH. We illustrate
the latter.
The First Revision of STKPUSH
Here is
the revision that allows the work registers to be saved.
MACRO
&L2 STKPUSH &ARG,&TYP
&
ST
R3,STKSAV3 IS NOT IMPORTANT.
ST
R4,STKSAV4
LH
R3,STKCOUNT
LA
R2,THESTACK
L&TYP R4,&ARG
ST
R4,0(3,2)
LH
R3,STKCOUNT
AH
R3,=H'1'
STH
R3,STKCOUNT
L
R4,STKSAV4 THE ORDER OF
RESTORATION
L
R3,STKSAV3 IS NOT IMPORTANT
EITHER.
L
R2,STKSAV2
MEND
The Status of the Macros at This Point
There
are a few issues to be addressed at this point.
The only
macro that will not change is the initialization macro, STKINIT.
1. We
have not yet dealt with generalizing the STKPOP macro.
2. We
have not yet dealt with either the stack empty problem or
that of the stack being
full. Each has to be addressed.
Each of
these issues demands the use of techniques we have not yet discussed.
Consider
the first problem. We shall want to pop
the following from the stack:
register values, halfwords, and fullwords.
The type for the argument refers to
the destination; an address can be popped into either a register or fullword.
In order
to see the problem for STKPOP, consider the “key instruction”.
Halfword: STH R4,&ARG
Fullword: ST R4,&ARG
Register: LR &ARG,R4 No STR for store register.
We could
write a STR
macro, but I want to use another solution.
Some System Variable Symbols
There
are a number of system variable symbols.
I mention three.
&SYSDATE The
system date, in the 8 character form “MM/DD/YY”.
Use in the form
of a declaration of initialized storage, as in
TODAY DC C‘&SYSDATE’
&SYSTIME The
system time of day, in the five character form “HH.MM”.
Also used in
the form of a declaration, as in
NOW DC C‘&SYSTIME’
&SYSNDX The
macro expansion index. For the first
macro expansion,
the Assembler
initializes &SYSNDX to the string “0001”.
Each macro
invocation increases the value represented by 1,
giving rise to
the sequence “0001”, “0002”, “0003”, etc.
The &SYSNDX system
variable symbol can prevent a macro from generating
duplicate labels. The system symbol is
concatenated to a leading character,
which begins the label and must be unique within the macro definition.
More on the Macro Expansion Index
First
consider the following string, used as a label in a macro definition.
L&SYSNDX L R4,STKSAV4
Note
that the string “L&SYSNDX”, as written, contains eight characters:
the initial character “L” followed by the 7 character sequence “&SYSNDX”.
On
expansion, this will be converted to labels such as “L0001”, “L0002”, etc.
In the
macro definition, this takes the maximum eight characters allowed for
a properly formatted listing. For this
reason, I suggest that the better form for
the label in the macro definition is Single_Letter&SYSNDX.
In actual
fact, the requirement for the leading characters, to which the &SYSNDX
is to be appended can be any sequence of one to four characters, provided only
that the first character is a letter.
Thus the following are valid.
A12&SYSNDX ... This label might become A120003.
WXYZ&SYSNDX ... This might become WXYZ0117.
I
suggest use of a single leading letter, this allows 26 labels per macro.
A Simple Example of Label Generation
Consider
the simple macro used for packed division in the previous lecture.
We adapt it to prevent division by zero.
MACRO
&LABEL DIVID ",&DIVIDEND,&DIVISOR
&LABEL ZAP &QOUT,&DIVIDEND
CP
&DIVISOR,=P‘0’ IS IT ZERO
BNE
A&SYSNDX NO, DIVISION
IS OK
ZAP
",=P‘0’ YES, SET
QUOTIENT TO 0
B
B&SYSNDX
A&SYSNDX
DP ",&DIVISOR
B&SYSNDX NOPR R3 DO NOTHING
MEND
Note
that the format of the NOPR instruction requires a register number
(here R3),
even though the instruction does nothing.
Sample Expansion of the Macro
With the
above definition, consider the following expansions.
A10START DIVID X,Y,Z
+A10START ZAP X,Y
+ CP
Z,=P‘0’ IS IT ZERO
+ BNE
A0001 NO,
DIVISION IS OK
+ ZAP
X,=P‘0’ YES, SET QUOTIENT TO 0
+ B
B0001
+A0001 DP X,Z
+B0001 NOPR
R3 DO NOTHING
A20DOIT
DIVID A,B,C
+A20DOIT ZAP A,B
+ CP
C,=P‘0’ IS IT ZERO
+ BNE
A0002 NO, DIVISION IS OK
+ ZAP
X,=P‘0’ YES, SET QUOTIENT TO 0
+ B
B0002
+A0002 DP A,C
+B0002 NOPR
R3 DO NOTHING
Note
that each invocation has distinct labels.
This removes the name clashes.
Another Design Strategy for DIVID
In this
variant, a zero divisor will cause the program to terminate abnormally.
MACRO
&LABEL DIVID ",&DIVIDEND,&DIVISOR
&LABEL ZAP &QOUT,&DIVIDEND
CP
&DIVISOR,=P‘0’ IS IT ZERO
BNE
A&SYSNDX NO, DIVISION
IS OK
ABEND INVOKE THE MACRO TO
TERMINATE
EXECUTION.
A&SYSNDX
DP ",&DIVISOR
MEND
The First Revision of STKINIT
Here is
a revision of the STKINIT code that allows initialization of its size.
35 MACRO
36 &L1 STKINIT &SIZE
37 &
38 SR R3,R3
39 STH R3,STKCOUNT
40 L
R3,STKSAV3
41 B
L&SYSNDX
42 STKCOUNT DC H'0'
43 STKSIZE DC H'&SIZE'
44 STKSAV2 DC F'0'
45 STKSAV3 DC F'0'
46 STKSAV4 DC F'0'
47 THESTACK DC
&SIZE.F'0'
48 L&SYSNDX
49 MEND
Note the “.” in the definition of THESTACK. This
concatenates the value
of the symbolic parameter with “F‘0’”, as in “128F‘0’”
The Second Revision of STKPUSH
MACRO
&L2 STKPUSH &ARG,&TYP
&
LH
R3,STKCOUNT GET COUNT OF ITEMS ON
THE STACK
CH
R3,STKSIZE IS THE STACK FULL?
BNL
Z&SYSNDX YES, DO NOT ADD
ANOTHER.
ST
R4,STKSAV4 NO, WE CAN PUSH
ANOTHER ITEM.
ST
R2,STKSAV2 START BY SAVING THE
OTHER 2 REGISTERS
LA
R2,THESTACK
L&TYP R4,&ARG FORM THE ADDRESS
ST
R4,0(3,2) STORE THE ITEM
LH
R3,STKCOUNT GET THE OLD COUNT OF
ITEMS
AH
R3,=H'1' INCREMENT THE COUNT
BY 1
STH
R3,STKCOUNT STORE THE CURRENT COUNT
L
R4,STKSAV4 RESTORE THE
REGISTERS.
L
R2,STKSAV2
Z&SYSNDX L R3,STKSAV3
MEND
This is
the final version of the STKPUSH macro.
We must
discuss another basic topic before addressing STKPOP.
Conditional Assembly
We have
already seen how concatenation can be used to construct
different instructions in a macro expansion.
We now
investigate conditional assembly, in which the expansion of a macro
can lead to a number of distinct code sequences.
Conditional
assembly permits the testing of attributes such as data format, data
value, or field length, and to use the results of such testing to generate
source
code that is specific to the case in question.
This
lecture will focus on five specific conditional assembly instructions.
AGO an
unconditional branch
AIF a
conditional branch. This means “Ask If”.
ANOP A NOP
that can be the branch target for either AGO or AIF.
MNOTE print a
programmer defined message at assembly time
MEXIT exit
the macro definition.
Attributes for Use by Conditional Assembly
The
assembler can generate code specified by certain attributes of
the arguments to the macro definition at the time it is expanded.
There
are six types of attributes that can be associated with a parameter.
Here are three if the more useful attributes.
L’ Length The length of the symbolic parameter
I’ Integer The integer attribute of a fixed–point,
floating–point,
or packed decimal number.
T’ Type The type of the parameter, as specified
by the
DC or DS
declaration with which it is defined.
Some
types for the T’ attribute are as follows.
A Address C Character H Halfword P Packed
Decimal
B Binary F Fullword I Instruction X Hexadecimal
The Ask If (AIF) Instruction
The AIF instruction has
two parts.
1. A
logical expression in parentheses, and
2. A
sequence symbol immediately following, which serves
as the branch target.
The AIF logical expression
may use the following relational operators, which
are quite similar to those seen in early versions of the FORTRAN language.
EQ Equal To NE Not Equal
To
LT Less Than GE Greater
Than or Equal To
GT Greater
Than LE Less Than or Equal To
If the
type of &AMT is packed, go to .B23PACK
AIF(T’&AMT EQ ‘P’).B23PACK
If the
type of &LINK is not an instruction, go to .R30ERROR
AIF(T’&LINK NE ‘I’).R30ERROR
Testing the Value of a Symbolic Parameter
What we
want for the STKPOP instruction is a conditional assembly
based on the value of the second parameter.
The prototype will be
something like
&L1
STKPOP &ARG,&TYP
What we
want to issue is an AIF statement such as
AIF (&TYP EQ ‘R’).ISREG
There is
a well–known peculiarity in assembler language, not just in the
IBM Assembler, that disallows this straightforward construct.
We must
put the symbolic parameter in single quotes.
The statement is thus:
AIF (‘&TYP’ EQ
‘R’).ISREG
If &TYP is the
character R, the logical expression becomes (‘R’ EQ ‘R’),
which immediately evaluates to True, and the branch is taken.
Reference
Page 384, High Level Assembler for
z/OS & z/VM & z/VSE Language
Reference Manual,
Release 6 (July 2008), SC26–4940–05
Targets for Use by Conditional Assembly
Each of
the AGO and AIF instructions is a
branch instruction that takes
effect at assembly time. Neither
persists into the assembly source code.
It
should be expected that the targets for either of these conditional
assembly branch instructions should be of a distinct type.
The
targets for these are called sequence
symbols.
The
format of a sequence symbol is as follows.
A sequence symbol begins with a
period (.) followed by one to seven letters
or digits, the first of which must be a letter.
Unlike
the symbols created by use of the &SYSNDX system symbol,
sequence symbols do not persist into assembly time, and thus
cannot generate a name conflict for the assembler.
A Sample of Conditional Assembly
Here is
the DIVID macro, with conditional assembly instructions to
insure that it is expanded only for parameters that are packed decimal.
MACRO
&LABEL DIVID ",&DIVIDEND,&DIVISOR
AIF
(T’&
AIF
(T’&
AIF
(T’&
AGO
.DOIT
.NOTPAK MNOTE
‘ONE PARAMETER IS NOT PACKED DECIMAL’
MEXIT
.DOIT ANOP
&LABEL ZAP
&QOUT,&DIVIDEND
CP
&DIVISOR,=P‘0’ IS IT ZERO
BNE
A&SYSNDX NO, DIVISION
IS OK
ZAP
",=P‘0’ YES, SET
QUOTIENT TO 0
B
B&SYSNDX
A&SYSNDX DP ",&DIVISOR
B&SYSNDX NOPR R3 DO NOTHING
MEND
Some Examples of the Conditional Assembly Divide Macro
In the
following, assume that each of X, Y, and Z is defined by a DC
statement as packed decimal, but that A, B, and C are defined as halfwords.
Here are
some possible expansions.
F10DOIT
DIVID X,Y,Z
+F10DOIT ZAP X,Y
+ CP
Z,=P‘0’ IS IT ZERO
+ BNE
A0032 NO, DIVISION IS OK
+ ZAP
X,=P‘0’ YES,
SET QUOTIENT TO 0
+ B
B0032
+A0032 DP X,Z
+B0032 NOPR
R3 DO NOTHING
F25NODO
DIVID A,B,C
+ONE PARAMETER IS NOT PACKED
DECIMAL
The Original Definition of Macro STKPOP
We
now begin our redefinition of the STKPOP macro.
We begin with the original definition, which popped a value into a register.
*STKPOP
MACRO
&L3
STKPOP &R
&L3
LH 3,STKCOUNT GET THE STACK COUNT
SH 3,=H’1’
SUBTRACT 1 WORD OFFSET OF TOP
STH
3,STKCOUNT STORE AS NEW SIZE
LA
2,THESTACK ADDRESS OF STACK BASE
L &R,0(3,2) LOAD ITEM INTO THE REGISTER.
MEND
*
Again, this macro has one
symbolic parameter: &R. Again, a
register number.
We want
to expand this definition in a number of ways.
We begin
by introducing the type &TYP.
At this
point, it will become necessary to have another work register.
Mechanics of the Revised STKPOP
The new
design will use register R4 to transfer the value at the top of the stack.
The new
prototype will be as follows.
&L3 STKPOP &ARG,&TYP
Each
type of instruction will include the following as the first statement
in the “key code” – that which actually places the value into the destination.
L R4,0(3,2)
LOAD ITEM INTO REGISTER R4.
The
second statement of the “key code” depends on the type of the destination.
&TYP == H STH R4,&ARG
&TYP == F ST
R4,&ARG
&TYP == A ST
R4,&ARG (SAME AS FULLWORD)
&TYP == R LR &ARG,R4 COPY R4 INTO REGISTER
Again, I
could define a STR macro and avoid the use of conditional assembly.
For a number of reasons, I have chosen not to do so.
The Key Code as Reflected in Conditional Assembly
Again,
the new prototype will be as follows.
&L3
STKPOP &ARG,&TYP
Here is
the key code section, with the conditional assembly.
The
first statement is common to all types.
L R4,0(3,2) LOAD ITEM INTO REGISTER R4.
AIF (‘&TYPE’ EQ ‘R’).ISREG
ST&TYP R4,&ARG
AGO .CONT
.ISREG
LR &ARG,R4
.CONT
The next statement.
STKPOP: Revision 2
Here I
am going to add some code to save and restore the work registers.
MACRO
&L3
STKPOP &ARG,&TYP
&
ST R3,STKSAV3
ST R4,STKSAV4
LH R3,STKCOUNT
GET THE STACK COUNT
SH R3,=H’1’
SUBTRACT 1 WORD OFFSET OF TOP
STH
R3,STKCOUNT STORE AS NEW SIZE
LA R2,THESTACK
ADDRESS OF STACK BASE
L R4,0(3,2)
LOAD ITEM INTO REGISTER R4.
AIF
(‘&TYPE’ EQ ‘R’).ISREG
ST&TYP R4,&ARG
AGO
.CONT
.ISREG LR
&ARG,R4
.CONT L R4,STKSAV4
L R3,STKSAV3
L R2,STKSAV2
MEND
STKPOP: The Complete Version
MACRO
&L3
STKPOP &ARG,&TYP
&
LH R3,STKCOUNT
GET THE STACK COUNT
CH R3,=H‘0’ IS THE COUNT POSITIVE
BNH Z&SYSNDX NO, WE
CANNOT POP.
SH R3,=H’1’
SUBTRACT 1 WORD OFFSET OF TOP
STH
R3,STKCOUNT STORE AS NEW SIZE
ST R2,STKSAV2 SAVE REGISTER R2
ST R4,STKSAV4 SAVE REGISTER R4
LA R2,THESTACK
ADDRESS OF STACK BASE
L R4,0(3,2)
LOAD ITEM INTO REGISTER R4.
AIF
(‘&TYPE’ EQ ‘R’).ISREG
ST&TYP R4,&ARG
AGO
.CONT
.ISREG LR
&ARG,R4
.CONT L R4,STKSAV4
L R2,STKSAV2
Z&SYSNDX L
R3,STKSAV3
MEND
Original Code for the Macro Expansions
33 * MACRO DEFINITIONS
34 *
35 MACRO
36
&L2 STKPUSH
&ARG,&TYP
37
&L2 LH R3,STKCOUNT
38
39 LA
R2,THESTACK
40
L&TYP R4,&ARG
41 ST
R4,0(3,2)
42 LH
R3,STKCOUNT
43 AH
R3,=H'1'
44 STH
3,STKCOUNT
45 MEND
46 *
89 * SOME MACRO INVOCATIONS
90 *
91 STKPUSH R7,R
00004A 4830 C0C6 000CC 92+
LH R3,STKCOUNT
00004E 8B30 0002 00002 93+
000052 4120 C0CA 000D0 94+
LA R2,THESTACK
000056 1847 95+ LR R4,R7
000058 5043 2000 00000 96+
ST R4,0(3,2)
00005C 4830 C0C6 000CC 97+
LH R3,STKCOUNT
000060 4A30 C43A 00440 98+
AH R3,=H'1'
000064 4030 C0C6 000CC 99+
STH 3,STKCOUNT
100 STKPUSH HHW,H
000068 4830 C0C6 000CC 101+
LH R3,STKCOUNT
00006C 8B30 0002 00002 102+
000070 4120 C0CA 000D0 103+
LA R2,THESTACK
000074 4840 C1CE 001D4 104+
LH
R4,HHW
000078 5043 2000 00000 105+
ST R4,0(3,2)
00007C 4830 C0C6 000CC
106+ LH R3,STKCOUNT
000080 4A30 C43A 00440 107+
AH R3,=H'1'
000084 4030 C0C6 000CC 108+
STH 3,STKCOUNT
109 STKPUSH FFW
000088 4830 C0C6 000CC 110+
LH R3,STKCOUNT
00008C 8B30 0002 00002 111+
000090 4120 C0CA 000D0 112+
LA R2,THESTACK
000094 5840 C1CA 001D0 113+
L
R4,FFW
000098 5043 2000 00000 114+
ST R4,0(3,2)
00009C 4830 C0C6 000CC 115+
LH R3,STKCOUNT
0000A0 4A30 C43A 00440 116+ AH
R3,=H'1'
0000A4 4030 C0C6 000CC 117+
STH 3,STKCOUNT
118 STKPUSH FFW,A
0000A8 4830 C0E6 000EC 119+
LH R3,STKCOUNT
0000AC 8B30 0002 00002 120+
0000B0 4120 C0EA 000F0 121+
LA R2,THESTACK
0000B4 4140 C1EA 001F0 122+
LA
R4,FFW
0000B8 5043 2000 00000 123+
ST R4,0(3,2)
0000BC 4830 C0E6 000EC 124+
LH R3,STKCOUNT
0000C0 4A30 C45A 00460 125+
AH R3,=H'1'
0000C4 4030 C0E6 000EC 126+
STH 3,STKCOUNT
127 *
136
**********************************
Revised Code for the Macros
The next few pages show the listing of the final forms
of the macros, as actually
coded and tested. These are followed by
listings of the expanded macros.
002900 *
002910
MACRO
002911 &L1 STKINIT
002912 &L1 ST R3,STKSAV3
002913
SR R3,R3
002914
STH R3,STKCOUNT CLEAR
THE COUNT
002915
L R3,STKSAV3
002920
MEND
002930 *
003000
MACRO
003100 &L2 STKPUSH &ARG,&TYP
003110 &L2 ST
R3,STKSAV3 SAVE REGISTER
R3
003200
LH R3,STKCOUNT GET THE CURRENT SIZE
003210
CH R3,STKSIZE IS THE STACK FULL?
003220
BNL Z&SYSNDX YES, DO NOT PUSH
003230
ST R4,STKSAV4 OK, SAVE R2 AND R4
003240
ST R2,STKSAV2
003300
SLA R3,2 MULTIPLY BY FOUR
003310
LA R2,THESTACK ADDRESS OF STACK START
003320
L&TYP R4,&ARG
LOAD R4 WITH VALUE
003330
ST R4,0(3,2) STORE INTO THE STACK
003331
LH R3,STKCOUNT
003332
AH R3,=H'1'
003333
STH 3,STKCOUNT
003334
L R4,STKSAV4
003335
L R2,STKSAV2
003336 Z&SYSNDX L R3,STKSAV3
003337
MEND
003338 *
003339 *
003340
MACRO
003341 &L3 STKPOP &ARG,&TYP
003342 &L3 ST
R3,STKSAV3
003343
LH R3,STKCOUNT GET THE STACK COUNT
003344
CH R3,=H'0' IS THE COUNT POSITIVE?
003345
BNH Z&SYSNDX NO, WE CANNOT POP
003346
SH R3,=H'1' SUBTRACT 1 WORD OFFSET
003347
STH R3,STKCOUNT STORE THE NEW SIZE
003348
SLA R3,2 BYTE OFFSET OF STACK TOP
003349
ST R2,STKSAV2 SAVE REGISTER R2
003350
ST R4,STKSAV4 SAVE REGISTER R4
003351
LA R2,THESTACK ADDRESS OF STACK BASE
003352
L R4,0(3,2) LOAD ITEM INTO R4
003353
AIF ('&TYP' EQ
'R').ISREG
003354
ST&TYP R4,&ARG
003355
AGO .CONT
003356 .ISREG
LR &ARG,R4
003357 .CONT
L R4,STKSAV4
003358
L R2,STKSAV2
003359 Z&SYSNDX L R3,STKSAV3
003360
MEND
003361 *
Revised Code for the Macro Expansions
128 * SOME MACRO INVOCATIONS
129 *
130 STKINIT
00004A
5030 C22E 00234 131+
ST R3,STKSAV3
00004E
1B33 132+ SR R3,R3
000050
4030 C226 0022C 133+
STH R3,STKCOUNT
000054
5830 C22E 00234 134+
L R3,STKSAV3
135 *
136 STKPUSH R7,R
000058
5030 C22E 00234 137+
ST R3,STKSAV3
00005C
4830 C226 0022C 138+
LH R3,STKCOUNT
000060
4930 C228 0022E 139+
CH R3,STKSIZE
000064
47B0 C08C 00092
140+ BNL Z0010
000068
5040 C232 00238 141+
ST R4,STKSAV4
00006C
5020 C22A 00230 142+
ST R2,STKSAV2
000070
8B30 0002 00002 143+
SLA R3,2
000074
4120 C236 0023C 144+
LA R2,THESTACK
000078
1847 145+ LR R4,R7
00007A
5043 2000 00000 146+
ST R4,0(3,2)
00007E
4830 C226 0022C 147+
LH R3,STKCOUNT
000082
4A30 C5A2 005A8 148+
AH R3,=H'1'
000086
4030 C226 0022C 149+
STH 3,STKCOUNT
00008A
5840 C232 00238 150+
L R4,STKSAV4
00008E
5820 C22A 00230 151+
L R2,STKSAV2
000092
5830 C22E 00234 152+Z0010 L
R3,STKSAV3
153 STKPUSH HHW,H
000096
5030 C22E 00234 154+
ST R3,STKSAV3
00009A
4830 C226 0022C 155+
LH R3,STKCOUNT
00009E
4930 C228 0022E 156+
CH R3,STKSIZE
0000A2
47B0 C0CC 000D2 157+
BNL Z0011
0000A6
5040 C232 00238 158+
ST R4,STKSAV4
0000AA
5020 C22A 00230 159+
ST R2,STKSAV2
0000AE
8B30 0002 00002 160+
SLA R3,2
0000B2
4120 C236 0023C 161+
LA R2,THESTACK
0000B6
4840 C33A 00340 162+
LH
R4,HHW
0000BA
5043 2000 00000 163+
ST R4,0(3,2)
0000BE
4830 C226 0022C 164+
LH R3,STKCOUNT
0000C2
4A30 C5A2 005A8 165+
AH R3,=H'1'
0000C6
4030 C226 0022C 166+
STH 3,STKCOUNT
0000CA
5840 C232 00238 167+
L R4,STKSAV4
0000CE
5820 C22A 00230 168+
L R2,STKSAV2
0000D2
5830 C22E 00234 169+Z0011 L
R3,STKSAV3
170 STKPUSH FFW
0000D6
5030 C22E 00234 171+
ST R3,STKSAV3
0000DA
4830 C226 0022C
172+ LH R3,STKCOUNT
0000DE
4930 C228 0022E 173+
CH R3,STKSIZE
0000E2
47B0 C10C 00112 174+
BNL Z0012
0000E6
5040 C232 00238 175+
ST R4,STKSAV4
0000EA
5020 C22A 00230 176+
ST R2,STKSAV2
0000EE
8B30 0002 00002 177+
SLA R3,2
0000F2
4120 C236 0023C 178+
LA R2,THESTACK
0000F6
5840 C336 0033C 179+
L
R4,FFW
0000FA
5043 2000 00000 180+
ST R4,0(3,2)
0000FE
4830 C226 0022C 181+
LH R3,STKCOUNT
000102
4A30 C5A2 005A8 182+
AH R3,=H'1'
000106
4030 C226 0022C 183+
STH 3,STKCOUNT
00010A
5840 C232 00238 184+
L R4,STKSAV4
00010E
5820 C22A 00230 185+
L R2,STKSAV2
000112
5830 C22E 00234 186+Z0012 L
R3,STKSAV3
187 STKPUSH FFW,A
000116
5030 C22E 00234 188+
ST R3,STKSAV3
00011A
4830 C226 0022C 189+
LH R3,STKCOUNT
00011E
4930 C228 0022E 190+
CH R3,STKSIZE
000122
47B0 C14C 00152 191+
BNL Z0013
000126
5040 C232 00238 192+
ST R4,STKSAV4
00012A
5020 C22A 00230 193+
ST R2,STKSAV2
00012E
8B30 0002 00002 194+
SLA R3,2
000132
4120 C236 0023C 195+
LA R2,THESTACK
000136
4140 C336 0033C 196+
LA
R4,FFW
00013A
5043 2000 00000 197+
ST R4,0(3,2)
00013E
4830 C226 0022C 198+
LH R3,STKCOUNT
000142
4A30 C5A2 005A8 199+
AH R3,=H'1'
000146
4030 C226 0022C 200+
STH 3,STKCOUNT
00014A
5840 C232 00238 201+
L R4,STKSAV4
00014E
5820 C22A 00230 202+
L R2,STKSAV2
000152
5830 C22E 00234 203+Z0013 L
R3,STKSAV3
204 *
205 STKPOP R8,R
000156
5030 C22E 00234 206+
ST R3,STKSAV3
00015A
4830 C226 0022C 207+
LH R3,STKCOUNT
00015E
4930 C5A4 005AA 208+
CH R3,=H'0'
000162
47D0 C186 0018C 209+
BNH Z0014
000166
4B30 C5A2 005A8 210+
SH R3,=H'1'
00016A
4030 C226 0022C 211+
STH R3,STKCOUNT
00016E
8B30 0002 00002 212+
SLA R3,2
000172
5020 C22A 00230 213+
ST R2,STKSAV2
000176
5040 C232 00238 214+
ST R4,STKSAV4
00017A
4120 C236 0023C 215+
LA R2,THESTACK
00017E
5843 2000 00000 216+
L R4,0(3,2)
000182
1884 217+ LR R8,R4
000184
5840 C232 00238 218+
L R4,STKSAV4
000188
5820 C22A 00230 219+
L R2,STKSAV2
00018C
5830 C22E 00234 220+Z0014 L
R3,STKSAV3
221 STKPOP FFW
000190
5030 C22E 00234 222+
ST R3,STKSAV3
000194
4830 C226 0022C 223+
LH R3,STKCOUNT
000198
4930 C5A4 005AA 224+
CH R3,=H'0'
00019C
47D0 C1C2 001C8 225+
BNH Z0015
0001A0
4B30 C5A2 005A8 226+
SH R3,=H'1'
0001A4
4030 C226 0022C 227+
STH R3,STKCOUNT
0001A8
8B30 0002 00002 228+
SLA R3,2
0001AC
5020 C22A 00230 229+
ST R2,STKSAV2
0001B0
5040 C232 00238 230+
ST R4,STKSAV4
0001B4
4120 C236 0023C 231+
LA R2,THESTACK
0001B8
5843 2000 00000 232+
L R4,0(3,2)
0001BC
5040 C336 0033C 233+
ST
R4,FFW
0001C0
5840 C232 00238 234+
L R4,STKSAV4
0001C4
5820 C22A 00230 235+
L R2,STKSAV2
0001C8
5830 C22E 00234
236+Z0015 L
R3,STKSAV3
237 STKPOP HHW,H
0001CC
5030 C22E 00234 238+
ST R3,STKSAV3
0001D0
4830 C226 0022C 239+
LH R3,STKCOUNT
0001D4
4930 C5A4 005AA 240+
CH R3,=H'0'
0001D8
47D0 C1FE 00204 241+
BNH Z0016
0001DC
4B30 C5A2 005A8 242+
SH R3,=H'1'
0001E0
4030 C226 0022C
243+ STH R3,STKCOUNT
0001E4
8B30 0002 00002 244+
SLA R3,2
0001E8
5020 C22A 00230 245+
ST R2,STKSAV2
0001EC
5040 C232 00238 246+
ST R4,STKSAV4
0001F0
4120 C236 0023C 247+
LA R2,THESTACK
0001F4
5843 2000 00000 248+
L R4,0(3,2)
0001F8
4040 C33A 00340 249+
STH
R4,HHW
0001FC
5840 C232 00238 250+
L R4,STKSAV4
000200
5820 C22A 00230 251+
L R2,STKSAV2
000204
5830 C22E 00234 252+Z0016 L
R3,STKSAV3
253 *
Revised Code for the Macro STKINIT
Here is an expansion of the newer
definition of STKINIT,
which allows the stack size to be specified.
138 STKINIT 128
00004A 5030 C05E 00064 139+
ST R3,STKSAV3
00004E 1B33 140+ SR R3,R3
000050 4030 C056 0005C 141+
STH R3,STKCOUNT
000054 5830 C05E 00064 142+
L R3,STKSAV3
000058 47F0 C266 0026C 143+
B L0009
00005C 0000 144+STKCOUNT DC
H'0'
00005E 0080 145+STKSIZE DC H'128'
000060 00000000 146+STKSAV2 DC F'0'
000064 00000000 147+STKSAV3 DC F'0'
000068 00000000 148+STKSAV4 DC F'0'
00006C 0000000000000000 149+THESTACK DC 128F'0'
00026C 8B30 0000 00000 150+L0009
SLA R3,0