: Relative subroutine call, conditional Four addressing modes (register direct, register indirect, register indirect with post increment and register indirect with pre decrement):
0F 90 (MOVE 0x) , R0 0F 0100 (MOVE 0x) , R1 LOOP ADD R1, R0 3F 0100 (SUB 0x) , R1 FF8B ABRA LOOP,! Z E 06 HALT
The QNICE assembler program shown on the left sums all values from 0x (to 0x) .
This example is really simple – the main idea is to count backwards from 0x 1100 to 0x and using the Z (zero) flag of the status register R 16 as a control condition for the central loop.
Due to the possibility of making all branches and subroutine calls conditional by prefixing them with the name of one of the eight status register status bits the loop effectively consists of only two instructions, a subtraction and an absolute branch (
Prefixing the flag controlling the instruction with an exclamation mark inverts the flag (without modifying the status register’s contents) prior to testing thus the instruction
ABRA LOOP,! Z will perform an absolute branch to the location labeled LOOP if the zero flag is not set.
The code example below is a bit more complex and shows a subroutine which performs a string comparison (like the C standard library function strcmp). This function expects two pointers to the strings to be compared in the registers R9 and R and will return the result of the comparison in R8.
Since the routine needs some registers for temporary storage of data is has to make sure that the contents of these registers are somehow saved at the entry of the subroutine and restored just before jumping back to the calling program.
In traditional architectures this would involve pushing the registers to a stack (either explicitly, register by register, or controlled by a bit mask). Since QNICE features a register bank for its registers R0 to R7 saving and restoring the contents of these eight registers just makes it necessary to increment the register bank pointer which is made up by the eight upper bits of the status register R thus giving the routine access to its “own” set of registers R0 to R7. Before returning to the calling program the register bank pointer will be decremented making sure that the original register contents will be accessible again.
Incrementing the register bank pointer is done by performing the instruction
ADD 0x , R
- , decrementing it by one is done at the label STR $ _STRCMP_EXIT
- using the subtraction
SUB 0x 823, R
; ; ; STR $ STRCMP compares two strings ; ; R9: Pointer to the first string (S0), ; R : Pointer to the second string (S1), ; ; R8: negative if (S0 S1) ; ; The contents of R8 and R9 are being preserved during the run of ; this function ; ; STR $ STRCMP ADD 0x 0100, R ; Get a new register page MOVE R9, R0; Save arguments MOVE R 13, R1 STR $ _STRCMP_LOOP MOVE @ R0, R8; while s1==s2 ) MOVE @ R1 , R2 SUB R8, R2 RBRA STR $ _STRCMP_END,! Z MOVE @ R0 , R8; if s1 ==0) RBRA STR $ _STRCMP_EXIT, Z; return 0; RBRA STR $ _STRCMP_LOOP, 1; end-of-while-loop STR $ _STRCMP_END MOVE @ - R1, R2; return s1 - (- s2)); SUB R2, R8 STR $ _STRCMP_EXIT SUB 0x 450, R ; Restore previous register page MOVE @R 18 , R ; and return to calling program part ;
A typical call to this routine would look like this:
MOVE QMON $ COMMAND, R9 MOVE QMON $ CMD_HALT, R 15 RSUB STR $ STRCMP, 1; Was a halt command issued?
| Contents of the Distribution Kit
The QNICE distribution kit currently contains the following items:
A short documentation of the processor architecture in form of a slide show prepared for a talk at a German DECUS symposium. The source code of a QNICE cross assembler written entirely in pure C (this has been proven to run on LINUX, Mac OS X, OpenVMS and Windows). The source code of the QNICE emulator, written in pure C, too. This emulator not only emulates the processor itself but also a 2681 UART (serial input / output is read from stdin / written to stdout) as well as a simple IDE disk. Both devices are memory mapped in the last 1 k Block of memory. (Since the UART emulation required the use of the curses library, the portability is a bit questionable – on systems like OpenVMS the usage of the UART part can be inhibited by undefining a constant in
- Some introductory examples like the summation program shown above and the first couple of routines for a monitor program.
| Current state of the project
The project is currently in the alpha state – the assembler and emulator are both fully operational. The next steps will involve the following tasks:
Write a complete monitor program based on
qmon1.asm found in the
- directory. Create a hardware implementation of QNICE – either using TTL technology or (preferred) an FPGA.
Currently our main goal is to interest people in the QNICE architecture in general and in the implementation of the processor in hardware. If you are interested in joining the project, please contact the project administrators as shown on the project summary page .