R.O.M.E.68000 Home
Prev. Table of Cont. Help Cont. of This Ch.

This is the R.O.M.E.68000 Manual version 0.51.
This is an experimental version.
Copyright © 1997 by G. Mezzetti; last update: January 1, 1999.


4. Overview of Instructions of the ``Control'' Class

Ordinary instructions of the ``Control'' class are specifically designed to manage number-type data and to govern the program flow; in a word, they implement all those actions which are needed to control the activity of a program, and it is for this reason that they've got their name. Instructions that move number-type data, perform arithmetic operations, manage pointers, jump, or call subroutines, all belong to this group. Before describing them in detail, let us have a panoramic picture of them.

Data Movement

Two instructions are provided for moving number-type data: MOVE and EXNG. The former simply copies the first operand onto the second, whilst the latter exchanges the two operands. Please note that these instructions work only with number-type data: to move or exchange word-type data you have to use the corresponding instructions MOVEBW and EXNGBW.

Arithmetic Operations

The four arithmetic operations are performed by the virtual processor (of course, on number-type data) in the way described in Section 9 of Chapter 1, by means of the usual instructions ADD, SUB, MULT, and EDIV (Euclidean division); the instruction AMOD, which computes the arithmetical modulus, is also provided to simplify the task of ``wrapping around'' indexes into a data structure of arbitrary length. There is also a unary instruction, CHS, which computes the opposite (i.e., the complement to 65536) of a number.

Creation, Movement and Management of Pointers

Relative pointers are created by means of the MVAD instruction, which puts in its second operand the relative address of the first; it is very similar to the instruction named LEA (load effective address) of some real processors.

Since they are relative, pointers need to be handled with special care. Even for simple copying, you cannot use the MOVE instruction, because otherwise after having been moved the pointer would not point to the correct location (see fig. 25); to avoid this, you have to use a special instruction named MVPT, which adjusts the copy of the pointer in such a way to make it point to the same location as the original it comes from. A similar instruction, named XGPT, lets you correctly exchange two pointers.

Figure 25: Comparison between MOVE and MVPT

The same problem appears under other forms too. For instance, to compare two pointers and discover whether they are equal, or which one is pointing beyond the other, a special instruction is needed, named CFPT (confront pointers): it calculates the offset (which, hence, is an absolute value) between the locations pointed at by the two pointers. Finally, there are two instructions whose usefulness you will learn as you become experienced in programming the 68000: DNPT and RNPT. The first takes a relative pointer and a location, and converts the pointer, which is relative to itself, to a ``non-standard pointer'' relative to the address of the given location (it ``de-normalizes'' the pointer, or ``absolutizes'' it with respect to the given location); the second reverts the action of the first. Note that none of these six instructions violates the rule which forbids to 68000 programs to know the absolute address of anything in the core; but the last two let you know the address of a thing with respect to everything else.

Jump Instructions

Besides the unconditional JUMP instruction, the two classical conditional jumps, JMZ (jump if zero) and JMNZ (jump if non zero) are included in the 68000 instruction set. The JZDC instruction decrements a counter unless it is equal to zero, and if it is zero, it jumps to a given location: it is a ``while ... do ...''-like instruction, used to control loops. The JNAD instruction is useful only in the context of the Core Cold War to hunt your opponent's alterable data items.

Conditional Skip

An entire family of instructions takes here the place of the old CMP instruction found in Dewdney's redcode; the SKcc family (skip if ``condition code'') contains ten variations of a single model of instruction, which skips the next instruction if a certain condition is satisfied. In the present version, the ten conditions tested are equality and inequality, plus the usual combination of less, equal or greater, according to both kinds of ordering described in Section 9 of Chapter I.

Subroutines

To help programmers to structure complex programs, and also to keep them small in size, we have introduced subroutines in the 68000 architecture [1]. You use the JSBR instruction to jump to a subroutine, and the RTN instruction to conclude it and return to the calling program. JSBR puts on the top of a stack a relativized copy of the current IP, and then jumps to the address of its first operand; RTN takes a pointer from the top of a stack, converts it to an absolute address and loads this address into the IP. Since, of course, CW programs cannot use a stack pointer held internally in the virtual processor, the stack pointer appears as an explicit operand in both these instructions; it must be a register, that is, a location of the register page. You also have to assure that the right stack pointer is used at the right place.

Miscellaneous

For the sake of synchronizing multi-threaded programs, we supply you with the TMOV instruction, which performs a ``test and set'' action. In other cases, synchronization can be obtained by means of the EXNG or EXNGBW instructions: you should use TMOV only for infra-unit communication (see Chapter XI), and EXNGBW for inter-unit communication. This is not because of problems arising from the virtual processor, but is a matter of strategy: from this point of view, communications between threads are a very subtle topic, which is deeply discussed in Chapter XI.

Some instructions signal a condition by skipping one location: for instance, CMPRBW skips one instruction if two blocks of words are perfectly equal. It can happen that the condition signalled is the negation of the one you would want; in that case you can put a SKIP instruction just after the one performing the conditional skip, to negate the tested condition. In fact, SKIP unconditionally skips the next instruction, so that, at the outset, its effect is precisely that of negating the tested condition. SKIP is hence semantically equal to JUMP 2, but it is more readable and simpler to type in.

The NOP instruction is also present: it performs no operation, and can be useful in some circumstances (actually, only in one). Of course, NOP is semantically equal to JUMP 1, but it is much more readable and elegant, as well as simpler to type in.


Prev. Table of Cont. Help Cont. of This Ch.

Notes

[1] One might think that using subroutines increases the risk of a CW program being killed, since a damaged instruction in the subroutine code has many chances to be executed. But the opposite is true: if the code were repeated everywhere it is needed, the probabilties that at least one copy gets damaged would be greater. In general, the smaller your program is, the harder it is to hit! For strategic considerations about subroutines, consult Chapter XI.


Gustavo MEZZETTI  /  mezzetti@math.unipd.it