Allows the user to specify a base address and assign a base register number.
.using | Expression,Register |
The .using pseudo-op specifies an expression as a base address, and assigns a base register, assuming that the Register parameter contains the program address of Expression at run time. Symbol names do not have to be previously defined.
Note: The .using pseudo-op does not load the base register; the programmer should ensure that the base address is loaded into the base register before using the implicit address reference.
The .using pseudo-op only affects instructions with an implicit-based address. It can be issued on the control section (csect) name and all labels in the csects. It can also be used on the dsect name and all the labels in the dsects. Other types of external symbols are not allowed (.extern).
The range of a .using pseudo-op (using range) is -32768 or 32767 bytes, beginning at the base address specified in the .using pseudo-op. The assembler converts each implicit address reference (or expression), which lies within the using range, to an explicit-based address form. Errors are reported for references outside the using range.
Two using ranges overlap when the base address of one .using pseudo-op lies within the ranges of another .using pseudo-op. When using range overlap happens, the assembler converts the implicit address reference by choosing the smallest signed offset from the base address as the displacement. The corresponding base register is used in the explicit address form. This applies only to implicit addresses that appear after the second .using pseudo-op.
In the next example, the using range of base2 and data[PR] overlap. The second l instruction is after the second .using pseudo-op. Because the offset from data[PR] to d12 is greater than the offset from base2 to d12 , base2 is still chosen.
.csect data[PR] .long 0x1 dl: .long 0x2 base2: .long 0x3 .long 0x4 .long 0x4 .long 0x5 d12: .long 0x6 l 12, data_block.T(2) # Load addr. of data[PR] into r12 ca1 14, base2(12) # Load addr. of base2 into r14 .using base2, 14 l 4, d12 # Convert to 1 4, 0xc(14) .using data[PR], 12 l 4, d12 # Converts to 1 4, 0xc(14) # because base2 is still chosen .toc data_block.T: tc data_block[tc], data[PR]
There is an internal using table that is used by the assembler to track the .using pseudo-op. Each entry of the using table points to the csect that contains the expression or label specified by the Expression parameter of the .using pseudo-op. The using table is only updated by the .using pseudo-ops. The location of the .using pseudo-ops in the source program influences the result of the conversion of an implicit-based address. The next two examples illustrate this conversion.
.using label1,4 .using label2,5 .csect data[RW] label1: .long label1 .long label2 .long 8 label1_a: .long 16 .long 20 label2: .long label2 .long 28 .long 32 label2_a: .long 36 .long 40 .csect sub1[pr] 1 6,label1_a # base address label2 is # chosen, so convert to: # 1 6, -8(5) 1 6,label2_a # base address label2 is # chosen, so convert to: # 1 6, 0xc(5)
.csect data[RW] label1: .long label1 .long label2 .long 12 label1_a: .long 16 .long 20 label2: .long label2 .long 28 .csect sub2[pr] .using label1,4 1 6,label1_a # base address label1 is # chosen, so convert to: # 1 6, 0xc(4) .using label2,5 1 6,label1_a # base address label2 is # chosen, so convert to: # 1 6, -8(5)
Two using ranges coincide when the same base address is specified in two different .using pseudo-ops, while the base register used is different. The assembler uses the lower numbered register as the base register when converting to explicit-based address form, because the using table is searched from the lowest numbered register to the highest numbered register. The next example shows this case:
.csect data[PR] .long 0x1 dl: .long 0x2 base2; .long 0x3 .long 0x4 .long 0x5 dl2: .long 0x6 1 12, data_block.T(2) # Load addr. of data[PR] into r12 1 14, data_block.T(2) # Load addr. of data[PR] into r14 .using data[PR], 12 1 4, dl2 # Convert to: 1 4, 0x14(12) .using data[PR], 14 1 4, dl2 # Convert to: 1 4, 0x14(12) .toc data_block.T: .tc data_block[tc], data[PR]
The domain of a .using pseudo-op (the using domain) begins where the .using pseudo-op appears in a csect and continue to the end of the source module except when:
These two exceptions provide a way to use a new base address. The next two examples illustrate these exceptions:
.csect data[PR] .long 0x1 dl: .long 0x2 base2; .long 0x3 .long 0x4 .long 0x5 dl2: .long 0x6 1 12, data_block.T(2) # Load addr. of data[PR] into r12 ca1 14, base2(12) # Load addr. of base2 into r14 .using base2, 14 1 4, dl2 # Convert to: 1 4, 0xc(14) # base address base2 is used 1 14, data_block.T(2) # Load addr. of data[PR] into r14 .using data[PR], 14 1 4, dl2 # Convert to: 1 4, 0x14(14) .toc data_block.T: .tc data_block[tc], data[PR]
.csect data[PR] .long 0x1 dl: .long 0x2 base2; .long 0x3 .long 0x4 .long 0x5 dl2: .long 0x6 1 12, data_block.T(2) # Load addr. of data[PR] into r12 ca1 14, base2(12) # Load addr. of base2 into r14 .using base2, 14 1 4, dl2 # Convert to: 1 4, 0xc(14) .drop 14 .using data[PR], 12 1 4, dl2 # Convert to: 1 4, 0x14(12) .toc data_block.T: .tc data_block[tc], data[PR]
Note: The assembler does not convert the implicit address references that are outside the Using Domain. So, if these implicit address references appear before any .using pseudo-op that defines a base address of the current csect, or after the .drop pseudo-ops drop all the base addresses of the current csect, an error is reported.
The next example shows the error conditions:
.csect data[PR] .long 0x1 dl: .long 0x2 base2; .long 0x3 .long 0x4 .long 0x5 dl2: .long 0x6 1 4, dl2 # Error is reported here 1 12, data_block.T(2) # Load addr. of data[PR] into r12 1 14, data_block.T(2) # Load addr. of data[PR] into r14 .using data[PR], 12 1 4, dl2 1 4, 0x14(12) .drop 12 1 4, dl2 # Error is reported here .using data[PR], 14 1 4, dl2 1 4, 0x14(14) .toc data_block.T: .tc data_block[tc], data[PR] .csect data1[PR] dl3: .long 0x7 .using data[PR], 5 1 5, dl3 # Error is reported # here, dl3 is in csect # data1[PR] and # Using table has no entry of # csect data1[PR] l 5, dl2 # No error, because dl2 is in # data [PR]
The following example demonstrates the use of the .using pseudo-op:
.csect data[rw] .long 0x0, 0x0 d1: .long 0x25 # A read/write csect contains the label d1. .csect text[pr] .using data[rw], 12 l 4,d1 # This will actually load the contents of # the effective address, calculated by # adding the address d1 to the address in # GPR 12, into GPR 4
The .csect pseudo-op, .drop pseudo-op.