1. Overview of the Hawk Computer

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

Contents

1.1. Summary
1.2. Memory Resources
1.3. CPU Resources
1.3.1. General Purpose Registers
1.3.2. Program Counter
1.3.3. Coprocessor Status Register
1.3.4. Processor Control Registers
1.3.4.1. Processor Status Word and Condition Codes
1.3.4.2. Trap Program Counter
1.3.4.3. Trap Memory Address
1.3.4.4. Trap Save Register
1.3.4.5. Cycle Counter Register
1.3.4.6. Memory-Management Unit Data Register
1.3.5. Memory-Management Unit
1.4. The Instruction Execution Cycle
1.5. Other Notational Conventions


1.1. Summary

The Hawk computer is a fictional machine that incorporates many features of modern RISC processors without slavish adherance to any particular real machine. The Hawk instruction set is based on a 32 bit word, typical for modern machines, and includes 15 general registers, a modest number by modern standards. All instructions are single-cycle, in the RISC tradition of machines like the IBM/Apple/Motorola Power architecture, the DEC Alpha architecture, the SGI MIPS architecture and the HP PA architecture. Unlike these machines, some of the Hawk instructions are variable-length, as with the older Intel 80x86/Pentium and Motorola 680x0 architectures.

With all computers, it is conventional to number the bits and other fields within in a word. The numbering of is entirely arbitrary; for the Hawk, we will arrange things as shown below:

Word Format
31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
byte 3 byte 2 byte 1 byte 0
halfword 1 halfword 0

This numbering conforms to the numbering used in DEC's 16, 32 and 64 bit computers; a numbering scheme that was later used by Intel. IBM mainframes and Motorola's microcomputers number bits and fields in the opposite order.

The Hawk word is 32 bits, while the 16 bit quantity is called a halfword. This usage is exactly the same as has been used on IBM mainframes since 1965, but it differs from early Intel, Motorola and DEC usage, all of which used 16-bit words in the early 1970's and continued to call 16 bits a word on their 32-bit machines. As with bit numbering, the particular unit called a word or a byte is arbitrary.
 

1.2. Memory Resources

A Hawk memory address is a 32 bit quantity (one word) with the following layout:

Memory Address Format
31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
page word in page byte

The high 30 bits of the address specifies one word in memory, while the low two bits may be used to specify a byte in that word. Thus, the Hawk memory consists of up to 230 words or up to 232 bytes, 4 gigabytes. These figures are typical of computers designed since the 1970's, but as with most computers, it is unlikely that all memory addresses will refer to real memory.

For some purposes, the word field of the memory address may be broken into page and word-in-page fields. Each page consists of 210 words, and the entire address space contains 220 pages.

In the following descritpion, the Hawk memory will be viewed as an array of words, with addresses ranging from 0 to 232–1, with groups of 4 consecutive addresses all referencing the same word in memory. Thus, addresses 0, 1, 2 and 3 all refer to the first word in memory, addresses 4, 5, 6 and 7 all refer to the second word, and so on up to addresses 232–4, 232–3, 232–2 and 232–1, which all refer to the final word in memory. To simplify discussion, memory addresses will frequently be described as viewed as records with a 30 bit word field and a 2 bit byte field.

The Hawk memory may also be viewed as an array of bytes, with addresses ranging from 0 to 232–1, so that address 0 refers to the first byte, which is stored in the first word, and address 1 refers to the second byte, which is also stored in the first word. This overlapped view of memory as either an array of bytes or of words dates back to the IBM System 360 family of mainframes, introduced in 1965, and this view is shared by all but the very smallest of modern computers.

The Hawk instruction set does not directly support non-aligned memory references. Thus, if bytes 3, 4, 5 and 6 are to be treated as one word, user software must compose this from byte 3, stored in one word, and bytes 4, 5 and 6, stored in the next consecutive word.

1.3. CPU Resources

The Hawk Central Processing Unit contains 18 registers visible to application programs and 5 additional registers visible only to privileged code. 15 of these registers are general purpose registers, each of which holds one word and each of which may be used to hold variables during the execution of a program. In addition, one special register is reserved to hold the address of the next instruction to be fetched by the CPU. This is the program counter. The condition code register is used to record results of computations and to control the CPU response to various special conditions, and the coprocessor status register is used to control interaction with any coprocessors that may be present.

1.3.1. General Purpose Registers

The Hawk has 15 general-purpose registers, numbered 1 to 15; these may be viewed as an array of 15 words. Note that reference to general purpose register 0 is allowed, but the meaning of this special case depends on the context. This usage is closely related to that on the IBM 360 family, dating back to 1965; many other computers, including the highly influential DEC VAX share similar ideas.

In assembly language programs, the names R1 to R15 should be used for the general purpose registers, and the name R0 may be used for the 16th register in some contexts. In formal descriptions of the architecture, registers will be referenced as r[0] through r[15].

1.3.2. Program Counter

The CPU executes programs by fetching and executing successive instructions from memory. The program-counter holds the address of the next instruction in memory that is awaiting execution. All Hawk instructions consist of 16 bit half-words (as in the IBM 360), so the program counter may be viewed either as a 32 bit register with a least significant that should always be 0 or as a 31 bit register. In either case, 30 bits of the program counter specify the word containing the next instruction, while 1 bit selects the half-word to use. In formal descriptions, the program counter is referenced as pc, with fields pc.word (the top 30 bits) and pc.byte (the bottom 2 bits).

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
word byte

An attempt to set the least significant bit of pc to 1 will cause a bus trap with the reason code in TMA set to 01.

1.3.3. Coprocessor Status Register

Some systems may have up to seven coprocessors. Interface with these is through two instructions, COGET and COSET. These allow transfer of data between the CPU and any of 16 coprocessor registers. Coprocessor register zero (COSTAT) is shared by all coprocessors and may be thought of as part of the CPU, but if no coprocessors are present, the coprocessor interface instructions may be ununimplemented. This register indicates which, if any, of the coprocessors is currently active and it sets options for the active coprocessor. Typical coprocessors might support floating-point or cryptographic operations.

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
unused coop u select enable u

Bits 1 to 7 are coprocessor enable bits, one per coprocessor. Turning one on enables the associated coprocessor, turning it off disables it, possibly powering it down. If a coprocessor is not present, the corresponding bit can still be turned on or off.

Bits 8 to 10 select a particular coprocessor. Only the selected coprocessor may be manipulated by COGET and COSET. A coprocessor that is present and enabled but not selected is sleeping; its registers retain their values in this state. Setting select to zero forces all coprocessors to sleep. If COGET or COSET are used to access a nonexistant coprocessor or one that is not enabled, there will be a coprocessor trap. This allows software virtualization of missing coprocessors, and in the absense of such virtualization, it allows testing for the presence of a

Bits 12 to 15 (coop) set the operating mode of the currently selected coprocessor (if it has modes).

1.3.4. Processor Control Registers

The Hawk CPU includes 6 special registers:

The bottom four bits of the processor status word matter to all programmers. These condition codes report results of selected instructions. The other special registers only matter to system programmers.

1.3.4.1. Processor Status Word and Condition Codes

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
level prior unused bcd carry unused N Z V C
priority & privilege extended arithmetic condition codes

The condition code field is the only part of the processor status word most programmers care about. These 4 bits are used to summarize the results from selected instructions for later testing. The IBM System 360 from 1965 gave us the idea of condition codes. The DEC PDP-11 from 1970 gave us the codes used here. Those instructions that set the condition codes generally use the following meanings:

In formal descriptions, the processor status word will be called psw, and the individual named bits will be referenced by their names.

1.3.4.2. Trap Program Counter

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
word byte

When an instruction causes a trap, for example, when an instruction references an illegal address or when the opcode field is invalid, the program counter is saved in the Trap Program Counter register. The value saved is the address of the offending instruction. When an interrupt is requested, the trap program counter is used to save the address of the instruction to be executed on return from interrupt.

1.3.4.3. Trap Memory Address

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
page word in page cause

When a trap is caused by an illegal memory reference, the offending memory address is saved in the high 30 bits of the Trap Memory Address register. The least significant bits of the TMA register give the reason the memory address was illegal. In the case of a bus trap, caused by an illegal physical memory address, the following reason codes apply:

If the memory-management unit is turned on (psw.level > 7), it may trigger an MMU trap when the access requested by the CPU violate the access permitted by the R, W, X and V bits in the memory-management unit data register. The nature of the violation will be reported in the reason codes:

1.3.4.4. Trap Save Register

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
saved value

This is a simple 32 bit register, with no special hardware function. It is needed as a temporary register in order to save and restore registers during trap service entry and exit.

1.3.4.5. Cycle Counter Register

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
count

This is a simple 32 bit register that increments whenever the CPU performs any memory operation (fetch, load or store). Sampling the cycle count is a useful way to measure program performance.

1.3.4.6. Memory-Management Unit Data Register

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
physical page number unused G C R W X V

The memory-management unit data register is used to load or store information about pages in the virtual address space.

A read from the MMU Data Register gives the information associated with the page currently selected by the Trap Memory Address register; a write to the MMU Data Register causes the MMU to associate the data with the page selected by the Trap Memory Address register.

The least significant bits of the MMU Data Register are defined as follows:

Normally, the G bit will be zero; in this case, the information in the MMU Data Register applies to only one page in the virtual address space. If the G bit is one on write, the physical page number is ignored and the contents of the C, R, W, X and V bits are ANDed with the corresponding field for every page known to the memory-management unit. This may be used, for example, to invalidate all pages known to the MMU.

1.3.5. Memory-Management Unit

The Hawk CPU contains a memory-management unit. This unit is fairly simple compared to those of many computers, but like those of other computers, it translates the virtual addresses of user programs into physical memory addresses. As on other machines, most programmers can ignore the presence of the memory-management unit, but system programmers must deal with it.

The Hawk memory-management unit is turned off whenever the high bit of the processor status word level field is zero. As a result, interrupts and traps always turn off the memory-management unit.

The Hawk memory-management unit consists of an array of mapping registers, each of which is seen as two 32 bit fields by the software. The first of these fields corresponds to the Trap Memory Address register, while the second field corresponds to the MMU Data Register:

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
virtual page number unused

31302928 27262524 23222120 19181716 15141312 11100908 07060504 03020100
physical page number unused C R W X V

In operation, whenever the CPU issues a virtual address, the memory-management unit searches for a mapping register that contains the corresponding virtual page number field, and then substitutes the physical page number for the virtual page number in order to construct a physical address.

If the CPU attempts to reference an address that involves an invalid memory-management unit entry, or if the CPU attempts to read, write or execute using an address where those operations are forbidden because the R, W or X bits are zero, the memory-management unit will force a trap, storing the address that caused the trap in the Trap Memory Address Register with an indication of the cause.

The number of mapping registers and the search algorithm used by the memory-management unit may vary between machines. When a new association is stored in the memory-management unit, an internal MMU replacement policy determines which mapping register to use. None of these details matter to software, although they have a great impact on performance.

To invalidate the contents of all mapping registers, store to the MMU data register may be invalidated by using the G bit in the MMU Data Register with the V bit set to zero.

1.4. The Instruction Execution Cycle

The instruction execution cycle of any computer can be described by a computer program that performs the same computations. Therefore, the definitive descriptions of most new architectures developed since 1970 have been given in an algorithmic form. At the top level, the Hawk architecture looks like many others, with an instruction execution cycle described as follows:

    repeat
        if pc.byte = 0
	    ir = Memory[ pc.word ](bits 15 to 0)
        else pc.byte = 2
            ir = Memory[ pc.word ](bits 31 to 16)
        pc = pc + 2
        decode ir
        execute ir
    forever

This instruction execution cycle is essentially that proposed by Berks, Goldstein and Von Neumann in 1946, even to the details of packing two instructions into each machine word. The original Von Neumann architecture was much simpler than the Hawk, with just one accumulator instead of many general purpose registers, and it had a 40 bit word, not 32-bits.

Instruction Register Format

The instruction register (ir) has four fields. Many of these fields have multiple functions and thus multiple names. The instruction register is a two-byte register. It can also be viewed as a halfword, but the first byte (bits 0 to 7) is the most significant from the point of view of instruction decoding and is therefore shown to the left, against the usual Hawk convention for byte order.

07060504 03020100 15141312 11100908
op dst
srcx
cond
s1
op1
s2
x
src
op2
const
disp

Note the discontinuity in the numbering of the bits in the above, reflecting the fact that byte 0 of each instruction halfword is the most important. This byte-reversed presentation is merely a convention used in documentation. Instruction halfwords in memory look like this:

15141312 11100908 07060504 03020100
s1
op1
s2
x
src
op2
op dst
srcx
cond
const
disp

The most significant field is the op field, bits 4 to 7, the most significant bits of the first byte. All of the other fields have multiple names that document their uses in different contexts, as determined by the op field. Details of the fields used by each group of instrucions are given with the definitions of those instructions. In all cases, the op field(s) are used to determine which instruction is used. In summary:

Zero has a special meaning in some fields. This is given in parentheses: "src (16)" means that zero encodes the constant 16, "src (pc)" means it refers to the program counter, and "dst (x)" means discard the value.

1.5. Other Notational Conventions

In descriptions of the effects of instructions, the following notations will commonly be used:

a ∧ b   a ∨ b   ~a
Logical and, or and not operations. When applied to words or other identical objects, each bit of the result is computed from the corresponding bits of the operands using the indicated logical function.
a ⊕ b   a ≡ b
Logical exclusive or and equivalence operations. exclusive or is true when the bits being compared are different, while equivalence is true when the bits being compared are the same. As with and and or, these may be applied to words, where they operate bit by bit.
a « b   a » b   a ›» b
Shift operators applied to words. The right operand, a, is shifted left or right the number of places indicated by b. In the case of a left shift, zeros are shifted in from the right. For right shifts, » is a signed shift, shifting in copies of the sign bit, while ›» is unsigned, shifting in zeros.
a:b   a:b:c
Bit number b of the word (or other object) a and bit numbers b through c of the word a. Bits are numbered from the right starting with zero. For example, if a is a 32-bit word, a»5 = a:31:5
sx(x)
Sign extends x to the size of the field to which it is being assigned. that is, if x is a 4 bit value 1011, sx(x) is ...11111011, while if x was 0101, sx(x) is ...00000101. Where sx() is not used, padding with zeros is implied.