Another mode of operation provided is Simple Mode, in which the opcode space for the regular memory-reference instructions is not compressed by taking advantage of the bits left unused when only aligned operands are present.
shows how certain basic operate instructions and the 16-bit shift instructions combine with the standard register-to-register and memory-reference instructions in the organization of this mode.
The jump instructions and related operate instructions that start with 111 in Normal Mode start with 000 in this mode, and thus they are fully available.
The opcode is divided into two parts: the first part indicates the type of number the instruction works with:
0100 Medium 48-bit floating-point 0101 Floating 32-bit floating-point 0110 Double 64-bit floating-point 0111 Quad 128-bit floating-point 100 Byte 8-bit integer 101 Halfword 16-bit integer 110 Integer 32-bit integer 111 Long 64-bit integer
and the second part indicates the operation performed by the instruction:
0000 000 Swap 0001 001 Compare 0010 010 Load 0011 011 Store 0100 100 Add 0101 101 Subtract 0110 110 Multiply 0111 111 Divide 1000 Insert 1001 Unsigned Compare 1010 Unsigned Load 1011 XOR 1100 AND 1101 OR 1110 Multiply Extensibly 1111 Divide Extensibly
The first eight operations apply both to floating-point numbers and integers; the second eight operations apply only to integers.
Incidentally, the sequence of types differs from that in the original design, where the integer types came first, and their opcodes started from zero. In this way, the opcodes for the 16-bit shift instructions, and other instructions associated with them, remain constant across all modes. As included among those instructions is that for changing modes, this makes it possible for programs to start from an unknown mode and set the mode they require.
Integer operations working with long, or 64-bit integers, have as their destination a pair of registers, beginning with an even-numbered register. The location of an operand in memory can begin with any byte, as addresses are byte addresses, but there may be a performance penalty if an operand is fetched from an unaligned location. In the case of floating-point numbers of the medium type, 48 bits in length, an aligned operand is one that begins on the boundary of a unit of 16 bits; for other types, an aligned operand is one whose address is an integer multiple of its length in bytes, so that all memory could be evenly divided into units of that length with no bytes left over at the beginning or the end. Note that it may be attempted by an implementation to fetch more than 16 bits of a medium floating-point number in a single operation, in which case a performance penalty may be experienced on aligned operands on this type which cross a block boundary; the rules for this would be both more complicated and implementation-dependent.
For integers shorter than 32 bits, the insert and unsigned load instructions are used as possible alternatives to the load instruction. The difference between the three instructions is as follows:
The load instruction performs sign extension. A quantity loaded into a 32-bit register is loaded into its rightmost, or least significant, bits, and the first bit of that quantity is also used as the value to which to set all the bits to the left of those filled by the quantity. This ensures that a negative number represented in a variable occupying less than 32 bits of memory is converted to the same negative number in 32-bit form.
The unsigned load instruction fills the bits to the left of the number with zeroes. This allows using variables to represent positive numbers only, and recovering the use of the first bit to allow larger positive numbers to be represented.
The insert instruction does not alter the bits to the left of the number. This allows a 32-bit number to be built up out of smaller pieces.
Other instructions that may need some explanation are as follows:
The compare instruction sets certain status bits in the same way that an ideal subtraction would set them. That is, the status bits indicate "negative" if the destination is less than the source, "zero" if they are equal, and "positive" if the destination is larger than the source, even if performing an actual subtraction for the same argument type would result in an overflow.
The unsigned compare instruction treats its operands as unsigned numbers, since this makes a difference in what the result of a comparison would be, even though two's complement representation means that a subtraction produces the same resulting pattern of bits in both cases.
The multiply extensibly instruction has a destination which is as long as the source on entry, but twice as long as its source on exit. This means that it produces a double-length product of two values, allowing it to be used in performing multi-precision arithmetic.
The divide extensibly instruction has a destination which is twice as long as the source on entry, and which consists of two consecutive registers, or groups of registers, the first twice as long as the source, and the second as long as the source, on exit. It divides the destination by the source, and places the quotient in the first part of the destination, while leaving the remainder in the second, shorter, part of the destination.
Note that because not only the dividend, but also the quotient, is twice as long as the divisor and the remainder with this instruction, the condition known as a "divide check", where a large dividend and a small divisor results in a quotient that will not fit into the result field on exit cannot occur.
The other instructions are self-explanatory.
The swap instruction exchanges the contents of the source and destination.
Add, subtract, multiply, and divide perform the indicated operation, producing results of the same type as their operands.
AND, OR, and XOR perform the basic logical operations:
a b a AND b a OR b a XOR b -------------------------------------- 0 0 0 0 0 0 1 0 1 1 1 0 0 1 1 1 1 1 1 0
in a bitwise fashion on their operands, storing the result in the destination.
A store instruction takes the value at the location specified by the destination field, and stores it at the location specified by the source field. By reversing the normal uses of destination and source, it allows values in registers to be written back out to memory.
Not all the possible combinations of the bits shown above are valid instructions. The Insert and Unsigned Load instructions only apply to byte and halfword operands. Also, Multiplication and division are not provided for byte operands. Instead, the instruction that would have been Divide Extensibly Byte is Store if Greater Byte: this instruction compares the destination byte (which is in a register) to the source byte (which may be in memory), and if the source byte is less than the destination byte, the byte at the destination is copied to the source location, overwriting its contents. This specialized instruction is used to allow semaphores to be used to control the sharing of resources between processes.
Thus, the seven bit opcodes that are defined are as follows, when their mnemonics are shown in a compact tabular form:
0100 0101 0110 0111 SWM SWF SWD SWQ 000 CM CF CD CQ 001 LM LF LD LQ 010 STM STF STD STQ 011 AM AF AD AQ 100 SM SF SD SQ 101 MM MF MD MQ 110 DM DF DD DQ 111 1000 1001 1010 1011 1100 1101 1110 1111 SWB IB SWH IH SW SWL 000 CB UCB CH UCH C UC CL UCL 001 LB ULB LH ULH L LL 010 STB XB STH XH ST X STL XL 011 AB NB AH NH A N AL NL 100 SB OB SH OH S O SL OL 101 MH MEH M ME ML MEL 110 STGB DH DEH D DE DL DEL 111
and listed in full, they are:
040xxx SWM Swap Medium 041xxx CM Compare Medium 042xxx LM Load Medium 043xxx STM Store Medium 044xxx AM Add Medium 045xxx SM Subtract Medium 046xxx MM Multiply Medium 047xxx DM Divide Medium 050xxx SWF Swap Floating 051xxx CF Compare Floating 052xxx LF Load Floating 053xxx STF Store Floating 054xxx AF Add Floating 055xxx SF Subtract Floating 056xxx MF Multiply Floating 057xxx DF Divide Floating 060xxx SWD Swap Double 061xxx CD Compare Double 062xxx LD Load Double 063xxx STD Store Double 064xxx AD Add Double 065xxx SD Subtract Double 066xxx MD Multiply Double 067xxx DD Divide Double 070xxx SWQ Swap Quad 071xxx CQ Compare Quad 072xxx LQ Load Quad 073xxx STQ Store Quad 074xxx AQ Add Quad 075xxx SQ Subtract Quad 076xxx MQ Multiply Quad 077xxx DQ Divide Quad 100xxx SWB Swap Byte 101xxx CB Compare Byte 102xxx LB Load Byte 103xxx STB Store Byte 104xxx AB Add Byte 105xxx SB Subtract Byte 110xxx IB Insert Byte 111xxx UCB Unsigned Compare Byte 112xxx ULB Unsigned Load Byte 113xxx XB XOR Byte 114xxx NB AND Byte 115xxx OB OR Byte 117xxx STGB Store if Greater Byte 120xxx SWH Swap Halfword 121xxx CH Compare Halfword 122xxx LH Load Halfword 123xxx STH Store Halfword 124xxx AH Add Halfword 125xxx SH Subtract Halfword 126xxx MH Multiply Halfword 127xxx DH Divide Halfword 130xxx IH Insert Halfword 131xxx UCH Unsigned Compare Halfword 132xxx ULH Unsigned Load Halfword 133xxx XH XOR Halfword 134xxx NH AND Halfword 135xxx OH OR Halfword 136xxx MEH Multiply Extensibly Halfword 137xxx DEH Divide Extensibly Halfword 140xxx SW Swap 141xxx C Compare 142xxx L Load 143xxx ST Store 144xxx A Add 145xxx S Subtract 146xxx M Multiply 147xxx D Divide 151xxx UC Unsigned Compare 153xxx X XOR 154xxx N AND 155xxx O OR 156xxx ME Multiply Extensibly 157xxx DE Divide Extensibly 160xxx SWL Swap Long 161xxx CL Compare Long 162xxx LL Load Long 163xxx STL Store Long 164xxx AL Add Long 165xxx SL Subtract Long 166xxx ML Multiply Long 167xxx DL Divide Long 171xxx UCL Unsigned Compare Long 173xxx XL XOR Long 174xxx NL AND Long 175xxx OL OR Long 176xxx MEL Multiply Extensibly Long 177xxx DEL Divide Extensibly Long
Note that when the base register field of an instruction is zero, this indicates that the instruction specifies an operation between two registers rather than an operation involving memory, and, for instructions that refer to memory, when the index register field of an instruction is zero, indexing does not take place.