SPARC is a
load–store architecture (also known as a
register–register architecture); except for the
load/store instructions used to access
memory, all instructions operate on the registers, in accordance with the RISC design principles. A SPARC processor includes an integer unit (IU) that performs integer load, store, and arithmetic operations. RD is the "destination register", where the output of the operation is deposited. The majority of SPARC instructions have at least this register, so it is placed near the "front" of the instruction format. RS1 and RS2 are the "source registers", which may or may not be present, or replaced by a constant.
Instructions Loads and stores Load and store instructions have a three-operand format, in that they have two operands representing values for the address and one operand for the register to read or write to. The address is created by adding the two address operands to produce an address. The second address operand may be a constant or a register. Loads take the value at the address and place it in the register specified by the third operand, whereas stores take the value in the register specified by the first operand and place it at the address. To make this more obvious, the
assembler language indicates address operands using square brackets with a plus sign separating the operands, instead of using a comma-separated list. Examples:
ALU operations Arithmetic and logical instructions also use a three-operand format, with the first two being the operands and the last being the location to store the result. The middle operand can be a register or a 13-bit signed integer constant; the other operands are registers. Any of the register operands may point to G0; pointing the result to G0 discards the results, which can be used for tests. Examples include: add %L1,%L2,%L3 !add the values in %L1 and %L2 and put the result in %L3 add %L1,1,%L1 !increment %L1 add %G0,%G0,%L4 !clear any value in %L4 The list of mathematical instructions is , , , , , and negated versions , , and . One quirk of the SPARC design is that most arithmetic instructions come in pairs, with one version setting the NZVC condition code bits in the
status register, and the other not setting them, with the default being
not to set the codes. This is so that the compiler has a way to move instructions around when trying to fill delay slots. If one wants the condition codes to be set, this is indicated by adding to the instruction: subcc %L1,10,%G0 !compare %L1 to 10 and ignore the result, but set the flags add and sub also have another modifier, X, which indicates whether the operation should set the carry bit: addx %L1,100,%L1 !add 100 to the value in %L1 and track carry SPARC V7 does not have multiplication or division instructions, but it does have , which does one step of a multiplication testing one bit and conditionally adding the multiplicand to the product. This was because can complete over one clock cycle in keeping with the RISC philosophy. SPARC V8 added (unsigned multiply), (signed multiply), (unsigned divide), and (signed divide) instructions, with both versions that do not update the condition codes and versions that do. and the multiply instructions use the Y register to hold the upper 32 bits of the product; the divide instructions use it to hold the upper 32 bits of the dividend. The instruction reads the value of the Y register into a general-purpose register; the instruction writes the value of a general-purpose register to the Y register. SPARC V9 added , which multiplies two 64-bit values and produces a 64-bit result, , which divides a 64-bit signed dividend by a 64-bit signed divisor and produces a 64-bit signed quotient, and , which divides a 64-bit unsigned dividend by a 64-bit unsigned divisor and produces a 64-bit signed quotient; none of those instructions use the Y register.
Branching Conditional branches test condition codes in a
status register, as seen in many instruction sets such the
IBM System/360 architecture and successors and the
x86 architecture. This means that a test and branch is normally performed with two instructions; the first is an ALU instruction that sets the condition codes, followed by a branch instruction that examines one of those flags. The SPARC does not have specialized test instructions; tests are performed using normal ALU instructions with the destination set to %G0. For instance, to test if a register holds the value 10 and then branch to code that handles it, one would: subcc %L1,10,%G0 !subtract 10 from %L1, setting the zero flag if %L1 is 10 be WASEQUAL !if the zero flag is set, branch to the address marked WASEQUAL In a conditional branch instruction, the
icc or
fcc field specifies the condition being tested. The 22-bit displacement field is the address, relative to the current PC, of the target, in words, so that conditional branches can go forward or backward up to 8 megabytes. The
ANNUL (A) bit is used to get rid of some delay slots. If it is 0 in a conditional branch, the delay slot is executed as usual. If it is 1, the delay slot is only executed if the branch is taken. If it is not taken, the instruction following the conditional branch is skipped. There are a wide variety of conditional branches: (branch always, essentially a jmp), (branch never), (equals), (not equals), (less than), (less or equal), (less or equal, unsigned), (greater), (greater or equal), (greater unsigned), (positive), (negative), (carry clear), (carry set), (overflow clear), (overflow set). The FPU and CP have sets of condition codes separate from the integer condition codes and from each other; two additional sets of branch instructions were defined to test those condition codes. Adding an F to the front of the branch instruction in the list above performs the test against the FPU's condition codes, while, in SPARC V8, adding a C tests the flags in the otherwise undefined CP. The (jump to subroutine) instruction uses a 30-bit
program counter-relative
word offset. As the target address is specifying the start of a word, not a byte, 30-bits is all that is needed to reach any address in the 4 gigabyte address space. The CALL instruction deposits the return address in register R15, also known as output register O7. The (jump and link) instruction is a three-operand instruction, with two operands representing values for the target address and one operand for a register in which to deposit the return address. The address is created by adding the two address operands to produce a 32-bit address. The second address operand may be a constant or a register.
Large constants As the instruction opcode takes up some bits of the 32-bit instruction word, there is no way to load a 32-bit constant using a single instruction. This is significant because addresses are manipulated through registers and they are 32-bits. To ease this, the special-purpose instruction copies its 22-bit immediate operand into the high-order 22 bits of any specified register, and sets each of the low-order 10 bits to 0. In general use, SETHI is followed by an or instruction with only the lower 10 bits of the value set. To ease this, the assembler includes the and macros. For example: sethi %hi(0x89ABCDEF),%L1 !sets the upper 22 bits of L1 or %L1,%lo(0x89ABCDEF),%L1 !sets the lower 10 bits of L1 by ORing The hi and lo macros are performed at assembly time, not runtime, so it has no performance hit yet makes it clearer that L1 is set to a single value, not two unrelated ones. To make this even easier, the assembler also includes a "synthetic instruction", , that performs these two operations in a single line: set 0x89ABCDEF,% L1 This outputs the two instructions above if the value is larger than 13 bits, otherwise it will emit a single with the value.
Synthetic instructions As noted earlier, the SPARC assembler uses "synthetic instructions" to ease common coding tasks. Additional examples include (among others): ==SPARC architecture licensees==