3. 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 (see Chapter 16).

Each memory-reference instruction corresponds to a short memory-reference instruction (see Chapter 2) with an extra halfword following it to hold the displacement, disp.

The instructions in the memory-reference group begin by computing the effective address, ea (see Section 1.2). The effective address is the sum of the index register r[x] and the displcement disp, or if x is zero, the sum of the program counter and the disp. In computing these sums the 16-bit displacement is sign-extended to 32 bits before addition.

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

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

The prototypical memory-reference instruction is LOAD (see Section 1.2). This loads a value from memory to a register. These instructions all 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 R0 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 the sense 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

Both LEA and LEACC (load effective address setting condition codes) load the effective address, ea, into the destination register, r[dst]. These instructions do not use the effective address as a memory address. If disp is zero, these are equivalent to MOVE and MOVECC (see Section 2.2). When the displacement is not zero, these add the displacement to the index register and place the result in the destination.

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 with LEA and then use short memory-reference instructions like LOADS and STORES (see Section 2.3) instead of using long-form memory-reference instructions like LOAD and STORE (see Section 3.3).

LEA does not change the condition codes. LEA R0,Rx,disp should not be used; if used, it will cause an illegal instruction trap (see Chapter 13). Assemblers should flag LEA R0,Rx,disp as an error. Had this been permitted, either the use of R[0] would imply discarding the result, making it equivalent to a sequence of two NOP instructions (see Section 12.3), or R[0] would refer to the program counter, making it equivalent to JUMP Rx,disp (see Section 3.4).

LEACC sets the N, Z, V and C condition codes to indicate the result of the addition used in effective address computation. (see Section 1.3.4.1).

LEACC can be used to add a constant to a register. Assemblers should support this by allowing ADDI Rd,Rs,const (add immediate) as a synonym for LEACC Rd,Rs,const. Programmers should use LEACC when the purpose is to compute an indexed memory address and ADDI when the purpose is numerical computation.

LEACC R0 will discard the effective address after setting the condition codes. As a result LEACC can be used for comparing the contents of a register with a constant. Assemblers should support this by allowing CMPI Rs,const (compare immediate) as a synonym for LEACC R0,Rs,-const. Note that adding a negated value is the same as subtracting, and note that checking the condition codes after subtraction is the standard way to do comparison on machines with condition codes.

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

Note that LEACC sets the bcd-carry field of the processor status word (see Section 1.3.4.1). As a result, ADDI followed by ADJUST may be used to add binary-coded decimal constants up to +7999 (see Section 11.2). This does not work for adding negative BCD values represented in 10's complement form, nor does it work for excess-three representation.

Note that ADDI Rd,Rd,const can be replaced with ADDSI Rd,const for constant values between –8 and +8, inclusive. (see Section 9.4).

Note that CMPI Rx,0 can always be replaced with TESTR Rx (see Section 2.2).

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)

Both LOAD and LOADCC (load setting condition codes) instructions use the effective address ea as a memory address to load the contents of a word of memory, m[ea], into the destination register, r[dst].

LOAD does not change the condition codes. LOAD R0,Rx,disp loads the data from memory into the program counter.

LOADCC changes the condition codes (see Section 1.3.4.1). N and Z are set to indicate whether the indicated word is negative or zero, V is cleared, and C 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.

LOADCC R0,Rx,disp discards the loaded value after setting the condition codes. This allow th referenced word of memory to be tested without changing the contents of any general-purpose register. Hawk assemblers should support TEST Rx,disp as a synonym for LOADCC R0,Rx,disp.

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 all synonyms:

	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 (see Chapter 7).

 

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.

JSR R0,Rx,disp discards the return address. This is useful because it allows a simple jump to the instruction at the effective address ea. Assemblers shoud support JUMPS Rx,disp as a synonym for JUMPS R0,Rx,disp.

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

The following instructions are all synonyms:

	JUMP	label
	JUMP	R0,label-(.+2)
	JSR	R0,label
	JSR	R0,R0,label-(.+2)
All 4 instructions listed above should generate exactly the same machine code, producing 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

STORE uses the effective address ea to store 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 (see Chapter 7) .