The cc65 instruction set only supports the WAI (Wait for Interrupt) and STP (Stop) instructions when used with the 65816 CPU (accessed via the --cpu command line option of the ca65 macro assembler). The 65C02 core used in this example supports these two instructions, and in fact the system benefits from the use of both the WAI and STP instructions.
In order to use the WAI instruction in this case, a C routine named "wait" was created that consists of the WAI opcode followed by a subroutine return. It was convenient in this example to put the IRQ interrupt enable in this subroutine as well, since interrupts should only be enabled when the code is in this wait condition.
For both the WAI and STP instructions, the assembler is "fooled" into placing those opcodes into memory by inserting a single byte of data that just happens to be the opcode for those instructions. The assembly code routines are placed in a file, named "wait.s", which is shown below:
; ---------------------------------------------------------------------------
; wait.s
; ---------------------------------------------------------------------------
;
; Wait for interrupt and return
.export _wait, _stop
; ---------------------------------------------------------------------------
; Wait for interrupt: Forces the assembler to emit a WAI opcode ($CB)
; ---------------------------------------------------------------------------
.segment "CODE"
.proc _wait: near
CLI ; Enable interrupts
.byte $CB ; Inserts a WAI opcode
RTS ; Return to caller
.endproc
; ---------------------------------------------------------------------------
; Stop: Forces the assembler to emit a STP opcode ($DB)
; ---------------------------------------------------------------------------
.proc _stop: near
.byte $DB ; Inserts a STP opcode
.endproc
The label _wait
, when exported, can be called by using the
wait ()
subroutine call in C. The section is marked as
code so that it will be stored in read-only memory, and the procedure is
tagged for 16-bit absolute addressing via the "near"
modifier. Similarly, the _stop
routine can be called from
within the C-level code via a call to stop ()
. In
addition, the routine can be called from assembly code by calling
_stop
(as was done in the interrupt service routine).