Dr Jefyll wrote:
From section 3.5.20 of the '816 data sheet:
Quote:
The second and third bytes of the instruction are added to the Program Counter, which has been updated to point to the opcode of the next instruction. [...] the result is stored on the stack.
This the second of the two calculations Garth mentioned.
Thanks for your patience. What I've been looking for is a concrete, but correct example, that defines the value that the assembler places in the instruction stream. It appears to me that the values given for the
PER operand fields in the Eyes and Lichty manual are all incorrect.
The addressing mode discussed in the '816 data sheet paragraph referenced above apparently applies to both
PER and
BRL. The effect of using
PER followed by
BRL is to synthesize a
BSR rel16 instruction.
The usage being described is as follows:
Code:
PER RETURN - 1 ; Push return address onto stack
BRL SUBROUTINE ; Branch to subroutine using relocatable method
RETURN:
.
.
.
.
SUBROUTINE:
.
.
RTS ; Return to location RETURN
This following is the text from the Eyes and Lichty manual that describes the code example provided above:
Eyes & Lichty - Page 179 wrote:
The 65802 and 65816 can synthesize the BSR function using their PER instruction. You use PER to compute and push the current run-time return address; since its operand is the return address’ relative offset (from the current address of the PER instruction), PER provides relocatability. As Fragment 12.2 shows, once the correct return address is on the stack, a BRA or BRL completes the synthesized BSR operation.
In this case, you specify as the assembler operand the symbolic location of the routine you want to return to minus one. Remember that the return address on the stack is pulled, then incremented, before control is passed to it. The assembler transforms the source code operand, RETURN – 1, into the instruction’s object code operand, a relative displacement from the next instruction to RETURN – 1. In this case, the displacement is $0002, the difference between the first byte of the BRL instruction and its last byte. (Remember, PER works the same as the BRL instruction; in both cases, the assembler turns the location you specify into a relative displacement from the program counter.) When the instruction is executed, the processor adds the displacement ($0002, in this case) to the current program counter address (the address of the BRL instruction); the resulting sum is the current absolute address of RETURN – 1, which is what is pushed onto the stack.
If at run-time the PER instruction is at $1000, then the BRL instruction will be at $1003, and RETURN at $1006. Execution of PER pushes $1005 onto the stack, and the program branches to SUBR1. The RTS at the end of the subroutine causes the $1005 to be pulled from the stack, incremented to $1006 (the address of RETURN), and loaded into the program counter.
If, on the other hand, the instructions are at $2000, $2003, and $2006, then $2005 is pushed onto the stack by execution of PER, then pulled off again when RTS is encountered, incremented to $2006 (the current run-time address of RETURN), and loaded into the program counter.
Am I missing something from this discussion? The whole purpose of the foregoing discussion was to demonstrate that the
PER RETURN - 1 (0x620200) pushed the sum of the PC for the
BRL instruction (0x1003) plus the operand of the
PER instruction (0x0002) onto the stack. It appears to me that the same result could have been achieved by
PEA RETURN - 1 instruction (0xF40510) followed by the
BRL SUBROUTINE instruction in far fewer cycles.
I suppose that the answer to my earlier question regarding how to access data in a relocatable manner is that the
PER instruction pushes the sum of the run-time PC of the instruction which follows the
PER instruction plus the relative displacement of the
PER instruction. To access the data in a relocatable manner, a post-indexed stack relative instruction must be used:
LDA (sp,S),Y;
STA (sp,S),Y; etc.
I guess I will have to give the implementation of
PER a bit more thought. I have added the capability to the M65C02A core to perform a
BSR rel16 operation. Thus, there is no need to synthesize that instruction using
PER followed by
BRA rel16. I will have to see if the capability to perform
rel16 operations will allow me to perform the 16-bit offset calculation required for
PER. The architecture of the M65C02A does not currently allow that resultant to be pushed onto the stack; it is used as the target address, i.e. the destination of
BRA rel16 or
BSR rel16. Since it is possible to push the PC, it may be a simple matter to add a multiplexer to push the MAR (Memory Address Register) instead of {PCH, PCL} when
PER is the instruction.
It does seem that if
BSR rel16 is available, and the post-indexed stack relative addressing modes are supported,
(sp,S),Y, then the M65C02A should strive to support
PER rel16. Otherwise, a high cycle count instruction sequence would be required to provide relocatable access to data structures.