3. Hawk Memory Reference Instructions

Part of the Hawk Manual
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Contents

3.1. Memory Reference Format
3.2. Load Effective Address
3.3. Load
3.4. Jump and Call
3.5. Store


3.1. Memory Reference Format

07060504 03020100 15141312 11100908
1 1 1 1 dst 0 - - - x

15141312 11100908 07060504 03020100
disp

Long-format memory reference instructions occupy 32 bits and are not supported on the Sparrowhawk; the extra 16 bits come from the next successive instruction halfword. The second halfword holds disp, the displacement. The effective memory address (ea) is computed by sign-extending the displacement to 32 bits and adding it to index register x, unless x is zero, in which case the program counter is used:

if (x = 0)
then ea = pc + sx(disp)
else ea = r[x] + sx(disp)

Because the program counter is incremented as a side effect of instruction fetch, indexed addressing using the program counter is relative to the address of the immediately following instruction.

The LOAD instruction for loading a value from memory into a register is the prototypical memory reference instruction. All of these instructions share the same assembly language formats:

	LOAD	dst,x,disp
	LOAD	dst,label

The three argument form is used for indexed addressing, where x is one of R1 through R15. The second form is used for PC relative addressing, where x is implicitly R0 (pc), and the assembler automatically computes disp as the difference between the current location and the given label. Thus, the following two lines of assembly code are exactly equivalent in that they generate identical machine code.

	LOAD	R5,R0,label-(.+2)
	LOAD	R5,label

The documentation that follows gives the format of the first halfword of each instruction. The second halfword is always as documented above.
 

3.2. Load Effective Address

07060504 03020100 15141312 11100908                        
1 1 1 1 dst (nz) 0 1 1 1 x (pc) LEA dst,x,disp r[dst] = ea
1 1 1 1 dst (x) 0 1 1 0 x (pc) LEACC dst,x,disp r[dst] = ea

LEA       NZVC unchanged
 
LEACC N = r[dst]:31  — result is negative                    
Z = (r[dst] = 0)  — result is zero
V = ( r[dst]:31 ⊕ ( r[x]:31 ≡ disp:15 ))
C = carry out of computation of ea

The LEA and LEACC (load effective address setting condition codes) instructions load the effective address, ea, into the destination register, r[dst]. In the case of the LEACC instruction, the N, Z, V and C condition codes are set to indicate the result of the add used in effective address computation. If some word of memory is to be repeatedly referenced, it can be more efficient to load the address of that word into a register once and then use short memory reference instructions for the repeated references.

LEACC can serve to add a constant to a register. Assemblers should support this with the alternative mnemonic ADDI (add immediate). Programmers should use LEACC when the purpose is to manipulate a memory address, and ADDI when the purpose is numerical computation. If dst is zero, the result is discarded. As a result, LEACC can also be used to compare a register and a constant by adding the negated constant. Assemblers should support this with the CMPI (compare immediate) mnemonic. Assembly of CMPI should negate the displacement.

07060504 03020100 15141312 11100908                        
1 1 1 1 dst (x) 0 1 1 0 x (pc) ADDI dst,x,disp r[dst] = ea
1 1 1 1 0 0 0 0 0 1 1 0 x (pc) CMPI x,-disp

LEACC R1,R1,16 and ADDI R1,R1,16 should produce identical machine code adding the constant 16 to R1:

LEACC R0,R1,-5 and CMPI R1,5 should produce identical machine code to compare R1 with the constant 5:

3.3. Load

07060504 03020100 15141312 11100908                        
1 1 1 1 dst (pc) 0 1 0 1 x (pc) LOAD dst,x,disp r[dst] = m[ea]
1 1 1 1 dst (x) 0 1 0 0 x (pc) LOADCC dst,x,disp r[dst] = m[ea]

LOAD      NZVC unchanged
 
LOADCC N = r[dst]:31  — result is negative                    
Z = (r[dst] = 0)  — result is zero
V = 0
C = (r[dst]:31:24 = 0) ∨ (r[dst]:23:16 = 0) ∨ (r[dst]:15:8 = 0) ∨ (r[dst]:7:0 = 0)

The LOAD and LOADCC (load setting condition codes) instructions load the contents of the designated word of memory, m[ea], into the destination register, r[dst]. In the case of the LOADCC instruction, the N and Z condition codes are set to indicate whether the indicated word is negative or zero, the V condition code is cleared, and the C condition code is set if any byte in the loaded value is zero. This feature allows for fast string operatons working with 4 bytes at a time.

If dst is zero, LOAD sets pc to the value loaded. In the case of LOADCC, the loaded value is discarded when dst is zero; this allows the operand in memory to be tested without changing the contents of any register. Hawk assemblers should provide the mnemonic TEST for this purpose.

07060504 03020100 15141312 11100908                        
1 1 1 1 0 0 0 0 0 1 0 0 x (pc) TEST x,disp

The following instructions are equivalent:

	LOADCC	R0,R0,label-(.+2)
	LOADCC	R0,label
	TEST	R0,label-(.+2)
	TEST	label
All 4 instructions listed above should generate exactly the same machine code, producing a LOADCC instruction that uses the program counter as an index register to address the memory location with the given label, and then discards the result after setting the condition codes appropriately.

The Hawk architecture does not allow direct loading or storing of bytes or halfwords. See the EXTB and EXTH instructions for efficient support of byte and halfword addressing.

 

3.4. Jump and Call

07060504 03020100 15141312 11100908                        
1 1 1 1 dst (x) 0 0 1 1 x (pc) JSR dst,x,disp r[dst] = pc; pc = ea

JSR       NZVC unchanged

The JSR (jump to subroutine) instruction stores the old value of the program counter, pc, in the destination register as a return address, and then sets the program counter to the effective address. The condition codes are not changed.

If dst is zero, the value is discarded. In the case of the JSR instruction, this is useful because it allows for a simple jump to the effective address.

07060504 03020100 15141312 11100908                        
1 1 1 1 0 0 0 0 0 0 1 1 x (pc) JUMP x,disp pc = ea

Assembly of the following instructions should produce exactly the same machine instructions:

	JUMP	label
	JUMP	R0,label-(.+2)
	JSR	R0,label
	JSR	R0,R0,label-(.+2)
All 4 lines generate a JSR instruction that discards the return address and uses PC-relative addressing to transfer control to the indicated label.

3.5. Store

07060504 03020100 15141312 11100908                        
1 1 1 1 srcx (0) 0 0 1 0 x (pc) STORE srcx,x,disp m[ea] = r[srcx]

JSR       NZVC unchanged

The STORE instruction stores the contents of the designated designated register, r[srcx] into the indicated word of memory m[ea]. The condition codes are not changed. Note that the mnemonic srcx used here refers to the register field usually known as dst, but here it is the source of the operand, not the destination.

Note that PC-relative STORE instructions should never be used when code is executed from read-only memory or from a read-only segment of the address space. Since one or the other of these will usually be the case, the PC-relative form of STORE should rarely be of any use!

The Hawk architecture does not allow direct loading or storing of bytes or halfwords. See the STUFFB and STUFFH instructions for efficient support of byte and halfword addressing.