Home > Intruction Set |
|
The instruction register of Niloofar 1 is a 16-bit register. The ISA is same as ISA for RiSC 16 [Jac01] which is a teaching ISA that is based on the Little Computer (LC-896) developed by Peter Chen at the University of Michigan. There are three machine-code instruction formats.
| Bits : | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 3 bits | 3 bits | 3 bits | 4 bits | 3 bits | ||||||||||||
| Type 1 : | opcode | reg A | reg B | 0 | reg C | |||||||||||
| 3 bits | 3 bits | 3 bits | 7 bits | |||||||||||||
| Type 2 : | opcode | reg A | reg B | signed immediate (-64 to 63) | ||||||||||||
| 3 bits | 3 bits | 10 bits | ||||||||||||||
| Type 3 : | opcode | reg A | immediate (0 to 0x3FF) | |||||||||||||
3 bits used for the opcode and there are 8 instructions.
| Bits : | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 3 bits | 3 bits | 3 bits | 4 bits | 3 bits | ||||||||||||
| ADD : | 000 | reg A | reg B | 0 | reg C | |||||||||||
| 3 bits | 3 bits | 3 bits | 7 bits | |||||||||||||
| ADDI : | 001 | reg A | reg B | signed immediate (-64 to 63) | ||||||||||||
| 3 bits | 3 bits | 3 bits | 4 bits | 3 bits | ||||||||||||
| NAND : | 010 | reg A | reg B | 0 | reg C | |||||||||||
| 3 bits | 3 bits | 10 bits | ||||||||||||||
| LUI : | 011 | reg A | immediate (0 to 0x3FF) | |||||||||||||
| 3 bits | 3 bits | 3 bits | 7 bits | |||||||||||||
| SW : | 100 | reg A | reg B | signed immediate (-64 to 63) | ||||||||||||
| 3 bits | 3 bits | 3 bits | 7 bits | |||||||||||||
| LW : | 101 | reg A | reg B | signed immediate (-64 to 63) | ||||||||||||
| 3 bits | 3 bits | 3 bits | 7 bits | |||||||||||||
| BEQ : | 110 | reg A | reg B | signed immediate (-64 to 63) | ||||||||||||
| 3 bits | 3 bits | 3 bits | 7 bits | |||||||||||||
| JALR : | 111 | reg A | reg B | 0 | ||||||||||||
The following table describes the different instruction operations.
| Mnemonic | Name | Opcode | Assembly Format | Action |
| add | Add | 000 | add rA, rB, rC | Add contents of regB with
regC, store result in regA. |
| addi | Add Immediate | 001 | addi rA, rB, imm | Add contents of regB with
imm, store result in regA. |
| nand | Nand | 010 | nand rA, rB, rC | Nand contents of regB with
regC, store result in regA. |
| lui | Load Upper Immediate |
011 | lui rA, imm | Place the 10 bits of the 16-bit
imm into the 10 bits of regA, setting the bottom 6 bits of regA to zero. |
| sw | Store Word | 100 | sw rA, rB, imm |
Store value from regA into memory. |
| lw | Load Word | 101 | lw rA, rB, imm | Load value from memory into
regA. Memory address is formed by adding imm with contents of regB. |
| beq | Branch if Equal | 110 | beq rA, rB, imm | If the contents of regA
and regB are the same, branch to the address PC+1+imm, where PC is the address of the beq instruction. |
| jalr | Jump And Link | 111 | jalr rA, rB | Branch to the address in regB. Store PC+1 into regA, where PC is the address of the jalr instruction. |
Assembler:
An Intel executable version of assembler for
RiSC-16 has been used as Niloofar 1's assembler. There was some slight
modifications. The description of common parts is as follows:
The format for a line of assembly code is:
label:<whitespace>opcode<whitespace>field0, field1, field2<whitespace># comments
The leftmost field on a line is the label field. Valid labels are any combination of letters and numbers followed by a colon. The colon at the end of the label is not optional—a label without a colon is interpreted as an opcode. After the optional label is whitespace (space/s or tab/s). Then follows the opcode field, where the opcode can be any of the assembly-language instruction mnemonics listed in the above table. After more whitespace comes a series of fields separated by commas and possibly whitespace (you need to have either whitespace or a comma or both in between each field). All register value fields are given as decimal numbers, optionally preceded by the letter ‘r’ ... as in r0, r1, r2, etc. Immediate-value fields are given in either decimal, octal, or hexadecimal form. Octal numbers are preceded by the character ‘0’ (zero). For example, 032 is interpreted as the octal number which corresponds to the decimal number 26. It is not interpreted as the decimal number 32. Hexadecimal numbers are preceded by the string ‘0x’ (zero x). For example, 0x12 is ‘hex-one-two’ and corresponds to the decimal number 18, not decimal 12. For those of you who know the C programming language, you should be perfectly at home. The number of fields depends on the instruction. The following table describes the instructions.
| Assembly-Code Format | Meaning |
| add regA, regB, regC | R[regA] ß R[regB] + R[regC] |
| addi regA, regB, imm | R[regA] ß R[regB] + imm |
| nand regA, regB, regC | R[regA] ß ~(R[regB] + R[regC]) |
| lui regA, imm | R[regA] ß imm & 0xFFC0 |
| sw regA, regB, imm | R[regA] à Mem[R[regB] + imm] |
| lw regA, regB, imm | R[regA] ß Mem[R[regB] + imm] |
| beq regA, regB, imm |
if (R[regA]
==
R[regB])
{ PC ß PC + 1 + imm (if label, PC ß label) } |
| jalr regA, regB | PC ß R[regB], R[regA] ß PC + 1 |
Anything after a pound sign (‘#’) is considered
a comment and is ignored. The comment field ends at the end of the line.
Comments are vital to creating understandable assembly-language programs,
because the instructions themselves are rather cryptic.
We will use just four assembler directives: nop, movi, .fill,
and .space (note the leading periods for .fill and .space, which simply
signifies that these represent data values, not executable instructions).
| Assembly-Code Format | Meaning |
| nop | do nothing |
| movi regA, imm | R[regA] ß imm |
| .fill imm | initialize data with value imm |
| .space imm | zero-filled data array of size imm |
The following paragraphs describe these pseudo-instructions in more detail:
The nop pseudo-instruction means “do not do anything this cycle” and is replaced by the instruction add r0, r0, r0 (which clearly does nothing).
The movi pseudo-instruction is just shorthand for the lui+addi combination. Note, however, that the movi instruction looks like it only represents a single instruction, whereas in fact it represents two. This can throw off your counting if you are expecting a certain distance between instructions. Thus, it is always a good idea to use labels wherever possible.
The .fill directive tells the assembler to put a number into the place where the instruction would normally be stored. The .fill directive uses one field, which can be either a numeric value or a symbolic address. For example, “.fill 32” puts the value 32 where the instruction would normally be stored. Using .fill with a symbolic address will store the address of the label. In the example below, the line “.fill start” will store the value 2, because the label “start” refers to address 2.
The .space directive takes one integer n as an argument and is replaced by n copies of “.fill 0” in the code; i.e., it results in the creation of n 16-bit words all initialized to zero.
The following is an assembly-language program that counts down from 5, stopping when it hits 0.
| 00: | lw r1, r0, count # load reg1 with 5 (uses symbolic address) |
| 01: | lw r2, r1, 4 # load reg2 with -1 (uses numeric address) |
| 02: | start: add r1, r1, r2 # decrement reg1, could have been addi r1, r1, -1 |
| 03: | beq r0, r1, 1 # goto end of program when reg1==0 |
| 04: | beq r0, r0, start # go back to the beginning of the loop |
| 05: | halt: movi r7, halt |
| 07: | jalr r7, r7 # end of program |
| 08: | count: .fill 5 |
| 09: | neg1: .fill -1 |
| 0A: |
startAddr: .fill start # will contain the address of start (2) |
It is okay to have a line that is blank, whether it is commented out (i.e., the line begins with a pound sign) or not (i.e., just a blank line). However, a label cannot appear on a line by itself; it must be followed by a valid instruction on the same line (a .fill directive or nop/etc counts as an instruction).
| Phases | Timing | Branch Hazards | Synthesis |