22C:18, Lecture 6, Fall 1996

Douglas W. Jones
University of Iowa Department of Computer Science

The Hawk Instruction Set

The basic Hawk instruction execution cycle is:

	repeat
	    IR = M[PC] (fetching a halfword)
	    PC = PC + 2
	    decode and execute IR
	forever
This is given in more detail in the Hawk Architecture Overview section on the Instruction Execution Cycle. The actual instruction set is defined by the decode and execute step. This breaks IR into 4 fields.
 _______________________________
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|15   12|11    8|7     4|3     0|
|  op   |  dst  |
For all Hawk instructions, the op field (the high 4 bits of IR) tells the CPU how to decode the rest of the instruction! For example, all memory reference isntructions use op=1111. Most Hawk instructions use the dst field to specify the register to be manipulated (usually, this is the destination register).

Loading and Storing

The most elementary memory reference instructions are LOADS and STORES (load and store, short format). These are fully defined in the Load and Store sections of the Hawk Architecture Manual. These instructions have the following format:

 _______________________________
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|15   12|11    8|7     4|3     0|
|1 1 1 1|  dst  |  op1  |   x   |

A short load moves a 32 bit word from the memory location pointed to by r[x] to r[dst]; this is coded with op1=0110. A short store moves from r[dst] to the memory location pointed to by r[x]; this is coded with op1=0010. More formally:
	LOADS:  r[dst] = m[r[x]]
	STORES: m[r[x]] = r[dst]
To put the instruction LOADS R3,R2 in memory, it would be legal to write the SMAL assembly code:
	H #F362
Recall that the leading # (pound sign) means hexadecimal, so #F362 is equivalent to F36216. Using hexadecimal to code a program is not terribly readable, so a file of standard definitions is provided so that this instruction can instead be written in assembly language as:
	LOADS R3,R2
It is important to remember that LOADS and STORES always move a full 32 bit word to or from memory. The least significant 2 bits of r[x] are ignored in doing this!

Loading Constants

Programs must deal not only with variables -- words in memory, but with constants. The Hawk architecture provides three basic instructions for loading constants into registers; the first of these is Load Immediate Long, or LIL. This is documented in the Hawk manual section on Long Immediate Format Instructions.

 _______________________________
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|15   12|11    8|7     4|3     0|
|1 1 1 0|  dst  |     const     |
 _______________________________
|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
|15                            0|
|             const             |

This instruction is 32 bits long; the 8 bits from bits 7 to 0 of the first halfowrd of the instruction go in bits 23 to 16 of the destination register, while the second halfowrd of the instruction goes in the low halfword of the destination register. The constant is sign extended to fill the full destination register.

Sign extension of 2's complement numbers involves repeating the sign bit of the number to fill all bit positions above that number. Thus, to sign extend a 24 bit constant to fill a 32 bit register, the most significant bit of the 24 bit constant (bit 23) is duplicated into the high 8 bits of the 32 bit register (bits 32 to 24).

The Load Immediate Short instruction is faster and more compact than LIL it is used to load a sign extended 8 bit value into a register. The Or Register Immediate Shifted instruction is designed to complement LIL, allowing fast loading of 32 bit constants. These are fully documented in the Hawk manual section on Short Immediate Format Instructions.

Running the Hawk Computer

Once you type the command:

	source /group/22c018/setup
two commands are enabled, the smal command, which runs our symbolic macro assembly language, and the hawk command, which runs the Hawk computer emulator.

Assembly language programs for the Hawk computer should be built on top of the following skeleton:

	TITLE	-your name and program purpose here-
	USE	"/group/22c018/hawk.macs"
	S	.

	... your code goes here ...

	END
All of these assembly directives used here are documented in the Miscelaneous Assembly Directives section of the SMAL manual. The TITLE directive adds a title to each page of the assembly listing. The USE directive inserts the text from the named file before your own program text, and the S directive sets the starting address.

The file /group/22c018/hawk.macs contains a set of standard definitions, including names of registers (R1 to R15), and, most important, a set of macro definitions for the machine instructions of the Hawk!

Note that, when your program is assembled and put in memory, the code will not end up at location zero! Instead, your program will land in location #1000 (assembly notation for 100016 or 409610). This is the result of program relocation, and it is done to reserve the first 1000 words of memory for the operating system. As a general rule, the low 100016 words of memory in the Hawk should not be used for user code!

If your program includes variables in memory, you should extend the skeleton above as follows:

	TITLE	-your name and program purpose here-
	USE	"/group/22c018/hawk.macs"
	S	.

	... your code goes here ...

	COMMON	VARS, VSIZE
	.=VARS

	... your variables go here ...

	VSIZE=.
	END
The new assembly directives used above are documented in the common subsection and the directives subsection of the SMAL manual.

The purpose of the COMMON directive and the line that follows it is to tell the linker to put the variables in RAM (which starts at memory address #10000 for our system); the final assignment directive is used to record the size of the variable region in your program.

It is possible to rewrite the above skeleton in far simpler terms! Consider the following:

	TITLE	-your name and program purpose here-
	USE	"/group/22c018/hawk.macs"
	.=#1000
	S	.

	... your code goes here ...

	.=#10000

	... your variables go here ...

	END
Here, we have simply told the assembler, directly, to put the code in location 100016 of memory, and the variables in location 1000016. This bypasses any talk of relocation, but it also prevents the program from being linked to external subroutine libraries and it prevents the program from being divided into separately assembled pieces when it grows large.

To assemble and run a SMAL Hawk program stored in a file called test.a, first type:

	smal test.a
If the assembler indicates any errors, fix them. You may need to look at test.l, the assembler listing, to find the errors. When there are no assembly errors, the assembler output test.o can be run by typing:
	link test.o
	hawk link.o
The command link is used to convert the assembler's output (test.o here) into a memory image that the hawk emulator can execute. The link command takes care of relocation and also adds in an operating system so that errors in your program will be reported in comprehensible form. The command hawk actually starts your program running, using the output of the linker (link.o here) The Hawk emulator begins by displaying the state of the Hawk machine, with your program in memory and the program counter set to the starting address specified in your code. If your program began as suggested above, PC should be 00001000, an address in ROM:

 HAWK EMULATOR
   /------------------CPU------------------\   /----MEMORY----\
   PC:  00001000                R8: 00000000   000FFA: #0000
   PSW: 00000000  R1: 00000000  R9: 00000000   000FFC: #0000
   NZVC: 0 0 0 0  R2: 00000000  RA: 00000000   000FFE: #0000
                  R3: 00000000  RB: 00000000 ->001000: LIL     #1,#001000
                  R4: 00000000  RC: 00000000   001004: LIS     #2,#20
                  R5: 00000000  RD: 00000000   001006: LIL     #3,#012345
                  R6: 00000000  RE: 00000000   00100A: ORIS    #3,#67
                  R7: 00000000  RF: 00000000   00100C: LIL     #4,#00101C

 **HALTED**  r(run) s(step) q(quit) ?(help)
The menu at the bottom shows the commands that are currently active. Typing ? will display other available commands. When the emulator is halted, the following commands are available:
r - run
starts a program running, from the current location

s - step
execute one single instruction

q - quit
quit the emulator and return to the UNIX shell

any hexadecimal digit
memory addresses may be entered in hex. The address currently entered is only displayed if it is nonzero.

m - show memory
Show the contents of memory starting at the address most recently entered.

+- - scroll through memory
The + and - keys can be used to scroll the memory display

t - toggle the memory display mode
The contents of memory can be displayed in hex and ASCII (appropriate if you are examining your program's variables) or it can be disassembled to show the machine instructions (appropriate if you are examining your code).
Students are strongly encouraged to experiment with small programs that demonstrate the instructions discussed in this lecture using the emulator and single-stepping through small programs, watching the registers change values as each instruction is executed.