Arithmetic / logical / shift instructionsUsing the memory access instructions, we can move data between the processor's registers and memory. Now let's discuss the instructions used to manipulate the data once it is loaded into the registers. This set of register-based instructions is used to:
The syntax we will see most often used in this set of instructions follows : instruction sreg, reg_or_imm, dreg In this syntax, sreg and reg_or_imm are the source operands and dreg is the destination register where the result of the instruction is stored. Most often, sreg contains the data to be manipulated, and reg_or_imm is the value used in conjunction with the data to generate the final result. reg_or_imm can be either another register or a signed 13-bit value. Let's look at an example: add %g2, 1, %g2 This example instruction's source register, sreg , is register %g2 . The reg_or_imm is simply a value of 1. The contents of %g2 and the value of 1 are added together. The result is stored in the destination register, dreg , register %g2 . Note The sreg , reg_or_imm and dreg values in arithmetic / logical / shift instructions may reference the same registers. Integer arithmeticOkay, let's start off with the most commonly used arithmetic instructions: Table B-8. SPARC arithmetic instructions
We've already seen one example of these instructions. What do you think this next example instruction does? sub %g4, %l3, %g4 In programming terms, this might be expressed as: %g4 = %g4 - %l3 The contents of local register %l3 is subtracted from the contents of global register %g4 and the result is stored back into %g4 . Here's another instruction. addxcc %l0, 20, %l1 This instruction adds the contents of %l0 and 20. It also adds in the PSR icc carry bit, which is either 0 or 1. The result is stored in %l1 . Meanwhile, any integer condition codes occurring during the addition are recorded in the PSR icc fields. For example, if the result of the addition was negative, the icc negative bit would be set. The next set of integer arithmetic instructions are not used often and are unlikely to appear during the course of system crash dump analysis. Table B-9. SPARC integer arithmetic instructions
Tagged arithmetic operations assume tagged-format data where the least significant two bits of the operands have special meaning. Languages such as LISP and Smalltalk use tagged arithmetic for dynamically typed data. The tagged arithmetic instructions taddcctv and tsubcctv can cause tag overflow traps that would be handled by the operating system. These traps would not cause the system to panic and crash. Logical instructionsThe logical instructions perform bitwise operations. The general syntax used is the same as the integer arithmetic instructions: instruction sreg, reg_or_imm, dreg Here are the instructions. Table B-10. SPARC logical instructions
Let's try a few examples. Given that %g4 contains 0x055, what would register %l2 contain after each of the following instructions? and %l0, 73, %l2 Answer: 51 or %l0, 73, %l2 Answer: 77 xor %l0, 73, %l2 Answer: 26 xnor %l0, 73, %l2 Answer: ffff ffd6 If you aren't clear about how these answers were reached, you might want to talk to a programmer or refer to a good programming book. None of the logical instructions generate traps. Shift instructionsThe shift instructions use the same general syntax we've seen in the integer arithmetic and logical instructions. instruction sreg, reg_or_imm, dreg The shift instructions shift the value in sreg left or right by a certain number of bit positions , as represented by reg_or_imm , and place the result in dreg . As the shift occurs, bits that drop off the end of the working register are lost. The PSR icc fields are not modified by the shift instructions. There are no true "rotate" instructions in the SPARC instruction set. However, if a rotate is needed, the clever assembly language programmer can use the addcc instruction and the PSR icc overflow bit to his advantage. Here are the three shift instructions: Table B-11. SPARC shift instructions
The logical shifts replace the vacated bits with zeroes. The arithmetic shift replaces the vacated bits with the most significant bit of the value in sreg . Here is an example of a shift instruction. sll %l7, 2, %l7 If the contents of %l7 started as 0x04, the result after shifting left two positions would be 0x10. Note In effect, each shift left by 1 is the same as multiplying by 2. Shift rights are like divides. This is good to remember as, on some SPARC implementations , the integer multiply and divide instructions take longer to execute than the shift instructions. The shift instructions do not generate traps. Miscellaneous arithmetic / logical / shift instructionsThere are only a few miscellaneous instructions in the arithmetic / logical /shift set of SPARC instructions. Unlike the others, these instructions have differing syntaxes. The sethi instruction is usually used in conjunction with a second command, such as a load. Let's look at an example. sethi %hi(0xf0155000), %o3 ld [%o3 + 0x2a0], %l2 The sethi instruction sets the high-order 22 bits of output register %03 to the high-order 22 bits of the value 0xf0155000. The load instruction then reads the value stored in memory location [ %o3 + 0x2a0 ] (which calculates to 0xf01552a0) into local register %l2 . Why was this method used to read the value at memory location f01552a0? If you remember, due to the 32-bit width restriction of SPARC instructions, it is not possible to say "put 0xf01552a0 into %03 ." If we add up the number of opcode bits used to identify the put instruction, the 32 bits of the value 0xf01552a0 and the bits needed to point to %03 , we would have an instruction that is well over 32 bits in width. The sethi instruction only contains the high-order 22 bits of the value 0xf01552a0 (thus, f0155000). The load instruction can include an offset of 13 bits in the [ address ] field, more than is needed to construct a valid memory address. The nop instruction is actually a variation of the sethi instruction, as shown below. sethi 0, %g0 Register %g0 is rather like the /dev/null of registers. Reading %g0 always results in zero. Writing to %g0 has no effect. The nop instruction is actually executed, but it makes no modifications to the registers or memory. nops are used when timing delays are required. There are actually many different instructions which could serve equally well as a nop . The compiler uses sethi . adb should recognize other varieties and display them as nop . The mulscc instruction is a very busy little instruction that conditionally shifts a value, conditionally performs addition and updates the icc fields. You will see the mulscc instruction used on systems that do not have the integer multiply and divide instructions implemented in the hardware. save and restore instructions are used to manipulate the register windows. In the set of miscellaneous arithmetic / logical / shift instructions, only the save and restore instructions can generate traps. The save instruction can cause a "window overflow" trap and the restore can cause a "window underflow" trap. Neither of these traps will cause the system to crash. Instead, the kernel kicks in and does some special window handling. We discuss windows in more detail in Chapter 17, "Stacks." |