R372 ISA

The ISA will will implement is CSE 372 is called R372. It is a simple RISC ISA that resembles MIPS. However, it has the following differences and simplifications.

R372 Definition

The following table contains the R372 definition.
Insn Syntax Semantics Code
HALT  HALT  HALT;  0000 0XXX XXXX XXXX
RETN  RETN  PC = r7;  0000 1XXX XXXX XXXX
JUMP  JUMP imm11 (label)  PC = ZEXT(imm11);  0001 0iii iiii iiii
CALL  CALL imm11 (label)  r7 = PC + 1; PC = ZEXT(imm11);  0001 1iii iiii iiii
SLED  SLED rs  LEDS[rs] = rd;  0010 0ddd sssX XXXX
LSWI  LSWI rd  rd = SWITCHES[rs];  0010 1ddd sssX XXXX
LCTR  LCTR rd imm1  rd = COUNTERS[imm1];  0011 0ddd XXXX XXXi
CCTR  CCTR rd imm1  COUNTERS[imm1] = 0;  0011 1XXX XXXX XXXi
BEQZ  BEQZ rd imm8 (label)  if (rd == 0) PC = PC + SEXT(imm8);  0100 0ddd iiii iiii
BNEZ  BNEZ rd imm8 (label)  if (rd != 0) PC = PC + SEXT(imm8);  0100 1ddd iiii iiii
BLTZ  BLTZ rd imm8 (label)  if (rd < 0) PC = PC + SEXT(imm8);  0101 0ddd iiii iiii
BGEZ  BGEZ rd imm8 (label)  if (rd >= 0) PC = PC + SEXT(imm8);  0101 1ddd iiii iiii
BGTZ  BGTZ rd imm8 (label)  if (rd > 0) PC = PC + SEXT(imm8);  0110 0ddd iiii iiii
BLEZ  BLEZ rd imm8 (label)  if (rd <= 0) PC = PC + SEXT(imm8);  0110 1ddd iiii iiii
ORHI  ORHI rd imm8  rd = rd | (imm8 << 8);  0111 0ddd iiii iiii
ORLO  ORLO rd imm8  rd = rd | ZEXT(imm8);  0111 1ddd iiii iiii
LOAD  LOAD rd rs imm5  rd = mem[rs + SEXT(imm5)];  1000 0ddd sssi iiii
STOR  STOR rd rs imm5  mem[rs + SEXT(imm5)] = rd;  1000 1ddd sssi iiii
ANDI  ANDI rd rs imm5  rd = rs & ZEXT(imm5);  1001 0ddd sssi iiii
IORI  IORI rd rs imm5  rd = rs | ZEXT(imm5);  1001 1ddd sssi iiii
ADDI  ADDI rd rs imm  rd = rs + SEXT(imm5);  1010 0ddd sssi iiii
SLLI  SLLI rd rs imm  rd = rs << (imm & 15);  1010 1ddd sssX iiii
SRLI  SRLI rd rs imm  rd = ZEXT(rs >> (imm & 15));  1011 0ddd sssX iiii
SRAI  SRAI rd rs imm  rd = SEXT(rs >> (imm & 15));  1011 1ddd sssX iiii
ADDR  ADDR rd rs rt  rd = rs + rt;  1100 0ddd ssst ttXX
SUBR  SUBR rd rs rt  rd = rs - rt;  1100 1ddd ssst ttXX
MULR  MULR rd rs rt  rd = rs * rt;  1101 0ddd ssst ttXX
unused  unused  undefined  1101 1XXX XXXX XXXX
XORR  XORR rd rs rt  rd = rs ^ rt;  1110 0ddd ssst ttXX
NOTR  NOTR rd rt  rd = ~rt;  1110 1ddd XXXt ttXX
ANDR  ANDR rd rs rt  rd = rs & rt;  1111 0ddd ssst ttXX
IORR  IORR rd rs rt  rd = rs | rt;  1111 1ddd ssst ttXX

R372 Tools

I have written some tools to help you write and debug programs in this ISA. The tools are in the ENIAC directory ~amir/cse371/r372/bin/ (the directory ~amir is on the mount /mnt/eniac/home8/a/) and are compiled for Linux. In other words, you cannot run these tools from Red or Blue. If you must, or if you want to run the tools on your machines at home, the sources are in ~amir/cse371/r372/src/. You can compile them for whatever platform you choose. However, be forewarned that I will not provide compilation help or tech support for any platform other than Linux.

There are two primary tools.

assembler: assembler -[x|b] <filename>. Given a file <filename>.a containing R372 assembly code will generate a file <filename>.imem.in which is an R372 "executable". The -x flag formats the executable in 16-bit space-delimited hexadecimal. The -b option formats the executable in binary. When initially developing programs, it helps to do everything in hexadecimal mode. In this mode, it is easy to create sample input files. Use binary mode only when you are ready to run your programs on the simulated hardware in the lab. In addition to the instruction mnemonics in the table above, the assembler also accepts comments (which it recognizes as lines starting with //) and labels (which it recognizes as lines starting with :). The assembler is not industrial strength, and will get confused by blank lines, extra spaces, missing commas, etc. Watch out for this and send mail to the newsgroup if you are having problems.

simulator: simulator -[x|b] -[s|t] <filename>. Given input files <filename>.imem.in containing R372 machine code and <filename>.dmem.in containing an input data memory image, will run the executable and generate a file <filename>.dmem.out which is the output data memory image of the program. Again, with the -x option, all files are in 16-bit space-delimited hexadecimal. With the -b option, they are all binary. The -[s|t] option is quite useful as well. With -s, the simulator runs silently. With -t, it prints out an annotated instruction level trace of your program, including the data inputs and outputs to each dynamic instruction. This should make it easier to debug your programs.

Here are a few more notes you should understand about the structure of the simulator and its input and output files.

R372 is a 16-bit ISA which means it can address 64K 16-bit memory words. These memory words are divided into two regions: instructions and data. Instruction memory is the lower 32K words starting at address 0 and ending at address (1<<15)-1. In 16-bit hex, these addresses are 0000 and 7FFF. The start PC (i.e., the address of the instruction that executes when the processor first boots is 0000. Data memory is the upper 32K words and goes from address (1<<15) to (1<<16)-1, or from 8000 to FFFF. When the simulator boots, it loads the file <filename>.imem.in into the instruction memory region, starting at address 0000. It also loads the file <filename>.dmem.in into the data memory region starting at address 8000. The <filename>.imem.in file is created by the assembler. The <filename>.dmem.in file is created by you. Hexadecimal files (the ones expected by the simulator when run in -x mode) can be easily created in emacs or any other text editor. For instance to create an initial data memory image with the number 11 in the first memory word and the number 3 in the second memory word, simply create a file called <filename>.dmem.in and make the contents of that file be "000B 0003".

As far as data memory, programs typically need both a "stack" area and a "heap" area, and the convention is that the heap area starts at the lower end of memory (8000) and grows up while the stack starts at the upper end (FFFF) of memory and grows down. The reason for this is that arrays are typically placed in the heap and it is easier to have a stack that grows down than to have a compiler that reverses all array access calculations. Anyway, you are free to use whatever convention you want, but this is probably easiest. The first thing your program should do when it boots is set up pointers to the stack and heap. R372 has 8 registers. You basically have to reserve one of them to be the stack pointer. You can initialize register R1 to FFFF using the following instruction sequence: SUBR R1, R1, R1; ORHI R1, -1; ORLO R1, -1. The first instruction sets R1 to 0. The second ors the bits FF into the upper half of R1 (the 8 bit binary representation of -1 is FF). After the second instruction, the contents of R1 are FF00. The final instruction ors the bits FF into the lower half of R1. You can set a register to the value of the first heap address in a similar manner.