Technical Reference Manual
The interface to the operating system is via the SWI hardware instruction followed by the vector number of the operating system service required, i.e.
SWI ; software interrupt .BYTE VECTOR_NUMBER ; required service vector HERE:
After execution of the SWI call, execution continues after the byte containing the vector number, at the label HERE in the example above.
Parameters to the service are passed in one or more of the A,B (or D), and X registers and for a small number of services in memory locations UTW_S0 and UTW_S1 which are zero page locations. Certain services also require information in the runtime buffer RTT_BF. The description of each service details the information required to be passed to it. In addition the results of a system service are returned in the machine registers A,B (or D) or X as required.
In general it should be assumed that all registers (A,B and X) are trashed by system services. If this is not the case then the system service description will explicitly state which registers are preserved.
All system services which indicate that they have error returns may set the carry flag on exit from the system service and return the error code in the B register. Note that system services such as KB$GETK, which do not return any errors, may not clear the carry flag.
Throughout the operating system description examples will be provided which use a macro called OS which is as follows:
.MACRO OS XX .BYTE $3f,XX .ENDM
Using this macro to get a key, for example, will be coded as follows:
and calling a system service which can return an error such as AL$GRAB should be called as follows:
CLR A CLR B OS AL$GRAB BCC 1$ ; HANDLE THE ERROR WHOSE CODE IS IN THE B REGISTER. 1$: ; CALL SUCCESSFUL AND X HAS THE TAG OF THE CELL.
In the following description refer to chapter Memory Usage for the addresses of the variables described.
The six words of memory storage labeled UTW_S0 to UTW_S5 are a set of scratch variables used by the operating system which any service may trash as required. Thus no values can be held in these words while making a call to an operating system service, although they may be used for storing intermediate values between calls to the operating system.
The seven words of memory storage labeled UTW_R0 to UTW_R6 are a set of fixed variables which are not trashed by the operating system service routines. The service routines actually use these variables but always push their contents on the stack before use and then recover them by popping them off the stack again. Application programs may use these variables as long as they maintain their integrity by pushing and popping.
As a code saving device there is a system service to push and pop these variables as follows:
OS BT$PPRG ; PSH UTW_R0 .BYTE 1 ; INSTRUCTION BYTE TO BT$PPRG ; CAN NOW USE UTW_R0 OS BT$PPRG ; POP UTW_R0 .BYT $81 ; INSTRUCTION BYTE TO BT$PPRG
The byte following the call to BT$PPRG instructs the service whether to push or pop the variables from the stack and which variables to push or pop. The format of the byte is as follows:
Thus if the byte value is $5 then UTW_R2 and UTW_R0 will be pushed.
When pushing, the higher address variables are pushed first and when popping, the lower address variables are popped first. Thus if UTW_R5 and UTW_R2 are pushed and UTW_R2 and UTW_R1 are popped then UTW_R1 will get the old value of UTW_R2 and UTW_R2 will get the old value of UTW_R5.
Included in the file errors.inc are all the symbolic names of the error numbers returned by the operating system services.
These error numbers are always returned in the B register after an operating system service has signaled an error by returning with the carry flag set.
Included in the file swi.inc are all the operating system service names and numbers. The system services are briefly explained in this manual. Please refer to the System Services page for an in depth discussion.
Note that vectors 0 to 125 are available on all machines, 126 is available from OS version 2.5 on and 127 from OS version 2.7 on. Vector 128 is available on multi-lingual machines only.
Vectors 129 to 179 are only available on LZ machines.
A call to an unavailable vector may cause a system crash, therefor it is advisable to check the system version before calling one of these services.
The machine can be switched on in 3 different ways.
On power up the program counter is loaded from the system restart vector at address $FFFE in the operating system ROM. The system restart vector is set to address $8000 in all versions of the operating system, which is the base address of the operating system ROM. The restart code is then executed in the following sequence.
The next task performed by the operating system is to determine whether a warm or cold start is required. Essentially a cold start is when the machine is starting up for the first time after a power failure and as such all operating system variables must be initialized. A warm start is when the machine only needs to carry on from when it was powered down, as all RAM values are still valid.
The Hitachi HD6303X microprocessor has an internal flag to determine whether power to the internal RAM in the processor has failed at any stage. This flag is the top bit in PORT 5. If the flag is clear then power to the internal RAM has failed at some stage and so a cold start is required. If the flag is still set then the internal RAM is still intact and so a warm start is required. As the external RAM is on the same power rail as the processor the above flag also serves to describe the validity of the external RAM.
On executing a cold start the machine performs the following procedures:
Multi-lingual machines present the language menu after displaying the copyright message. One language must be selected (ON/CLEAR will do nothing) before the top-level menu is displayed in the language chosen. Devices are rebooted whenever a language is selected.
On deciding that a warm start is required the operating system performs the following code:
LDS BTA_SAVSTACK LDX BTA_WRM JMP 0,X
The power off service BT$SWOF stores the stack pointer in BTA_SAVSTACK before switching off the machine to enable the machine to restart at the same place it was at when the machine was switched off. With the stack restored to the value that it had in BT$SWOF, an "RTS" will continue execution after the call to BT$SWOF. Next the vector for warm starting is used to jump to a warm start routine. The warm start routine may be replaced by another routine but the operating system warm start routine should be called as well. If it is not the operating system will not work correctly. See section Vectors on replacing vectored routines.
The system warm start routine performs the following actions:
The machine can be switched off by calling the POWER DOWN service routine BT$SWOF. This routine is vectored through BTA_SOF as follows:
STS BTA_SAVSTACK LDX BTA_SOF JMP 0,X
The power down routine may be replaced by another routine but the operating system power down routine should be called as well. If it is not the operating system will not work correctly. See section Vectors on replacing vectored routines.
The system power down service performs the following steps:
The LZ may be powered down for a specified time, if so, step 8 is performed as if an alarm was due at that time.
The operating system uses four of the ten hardware interrupts to perform various services. The remainder are just directed to a RTI instruction. However, all interrupts are vectored through RAM so that they may be intercepted or replaced in total. For the interrupts used by the operating system it is recommended that the interrupt only be intercepted and not be replaced if it is required that the operating system performs according to specification.
The semi-custom chip will deliver an NMI to the processor exactly once every second to provide an accurate system clock, provided the address SCA_NMIMPU has been accessed.
The NMIs to the processor can be disabled by accessing the address SCA_NMICOUNTER. Note that this is an unusual feature since NMIs, as their name implies, cannot normally be disabled.
The NMI service routine performs the following actions:
The timer 1 compare interrupt is used to scan the keyboard to allow keyboard buffering and to provide a timing service. This interrupt is referred to in the documentation as the KEYBOARD INTERRUPT (KI).
The interrupt is generated every time the free running counter matches the count in the timer 1 compare register. As the free running counter is being clocked by the system clock of 921600 HZ, extremely accurate timing can be performed using this interrupt.
The time between interrupts is controlled by the variable KBW_TDEL which is initialized on cold start to be $B3DD. This value makes the KI interrupt occur exactly every 50 milliseconds and is used extensively by the operating system for timing purposes. The value in KBW_TDEL can be changed, but all system timing will be destroyed as a result and the operating system may fail to perform correctly.
The KI service routine performs the following steps:
This interrupt is used to provide the interface between applications and the operating system. When a SWI instruction is executed the following code is executed:
LDX BTA_SWI JMP 0,X
The SWI service routine provided by the operating system is as follows:
PUL A STA A,BTB_4DONTUSE ;SAVE STATUS FLAG PUL B PUL A STD BTW_1DONTUSE ;SAVE THE D REGISTER PULX STX BTW_2DONTUSE ;SAVE THE X REGISTER PULX ;GET THE ADDRESS OF THE BYTE LDA B,0,X ;FOLLOWING THE SWI INSTRUCTION INX ;INCREMENT TO SKIP OVER THE BYTE PSHX ;PUSH BACK AS RETURN ADDRESS LDX BTA_VECT ;GET THE VECTOR TABLE ADDRESS ABX ;DOUBLE THE VECTOR NUMBER AND ABX ;ADD TO VECTOR TABLE LDX 0,X ;GET ADDRESS OF ROUTINE PSHX ;SAVE ON STACK FOR DUMMY RETURN LDX BTW_2DONTUSE ;RESTORE X REGISTER LDD BTW_1DONTUSE ;RESTORE D REGISTER PSH A ;SAVE A REGISTER LDA A,BTB_4DONTUSE ;GET STATUS FLAGS TAP ;RESTORE STATUS FLAGS PUL A ;RESTORE A REGISTER RTS ;JUMP TO REQUIRED ROUTINE
The operating system routine to handle the trap interrupt simply clears the LCD display and displays "TRAP" on the screen until the battery is removed and the machine is COLD started again. It is intended that this trap remain free for use with a debugger and as such should not be used.
In order to provide flexibility in the operating system all the hardware interrupts are vectored through RAM vectors so that they may be intercepted or even replaced. In addition a number of operating system services are provided through vectors as well so that they may be intercepted or replaced more easily than intercepting the SWI interrupt.
If the operating system is using an interrupt, it is strongly recommended that the interrupt is just intercepted and not replaced entirely. This can be done in the following way for example to intercept the NMI interrupt routine.
LDX BTA_NMI ; CURRENT SERVICE ROUTINE ADDRESS STX OLD_NMI ; SAVE THE ADDRESS SOMEWHERE LDX #NEW_NMI ; NEW NMI ROUTINE ADDRESS STX BTA_NMI ; RE-DIRECT THE OPERATING SYSTEM
New NMI routine:
NEW_NMI: ; PERFORM NEW NMI USER CODE LDX OLD_NMI ; OLD NMI ROUTINE ADDRESS JMP 0,X ; RUN THE OLD ROUTINE
The following is a list of hardware interrupts and their vectors in RAM.
This system service routine switches off NMIs to the processor.
NOTE: As the NMI interrupt is used to provide the system clock the system time will be invalid. It is possible to switch off NMIs and still maintain a valid system time. See the system service BT$NOF.
If NMIs are switched off with this service then they should be switched back on with the BT$NMEN service.
This system service routine switches on NMIs to the processor. BT$NMEN should only be used to reestablish NMIs if they have been disabled with the BT$NMDN service.
This system service routine switches off NMIs to the processor in such a way that the system time will be preserved.
The NMI interrupt is generated from the semi-custom chip every second to provide a very accurate system clock. When NMIs are switched off the processor, an internal counter in the semi-custom chip is connected to the NMI line so that NMIs can still be counted.
This service ensures that the counter in the semi-custom chip is reset properly so that on switching NMIs back to the processor the time can be updated properly. In order to do this it is imperative that the BT$NON service is used to switch on NMIs. The maximum time that can be stored in the counter is 2048 seconds, so BT$NON must be called before this time has elapsed.
There is a disadvantage to this pair of services, in that on restoring NMIs to the processor the BT$NON service must wait for the first NMI before counting the number of NMIs that have occurred while NMIs were switched off. This means that depending on when in the cycle the BT$NON service is called a delay of between 0 and 1 second can occur. See chapter System Timing for more information on the timing services.
Finally note that the counter used to count NMIs when they are disabled from the processor is also used to scan the keyboard and as such any keyboard interrupt occurring after BT$NOF has been called will destroy the NMI counter. Thus to disable NMIs and preserve the system time, interrupts should also be disabled before calling BT$NOF. Keyboard services must not be called, as they will poll the keyboard directly when interrupts are disabled.
TPA ; GET CURRENT STATUS PSH A ; SAVE IT SEI ; DISABLE INTERRUPTS OS BT$NOF ; SWITCH NMIS OFF. ; CODE PERFORMED WITH NO INTERRUPTS OCCURRING. OS BT$NON ; SWITCH NMIS BACK ON AND UPDATE TIME. PUL A ; RESTORE PREVIOUS STATUS TAP ; SET STATUS REGISTER
This system service routine switches on NMIs to the processor. BT$NON should only be used to reestablish NMIs if they have been disabled with the BT$NOF service.
This system service routine will push or pop the seven variables UTW_R0 to UTW_R6 on the machine stack.
This system service may be called to switch off the Organiser II.
BT$TOFF (LZ only)