P37X ISA

The ISA will will implement in CSE 371/372 is called P37X. It is a simple RISC ISA that resembles a combination of MIPS and LC3. The following analogy is roughly true: P37X is to LC3 as MIPS is to x86.

P37X shares the following features with LC3 (and differences with MIPS):

P37X shares the following features with MIPS (and differences with LC3):

Machine Instructions

The following table contains the P37X machine instructions, the ones the hardware can execute directly.

The P37X assembler is of course symbolic, and it allows you to specify PC offsets as symbolic label references rather than numeric constants. A label can (optionally) prepend every instruction or be on a line by itself. A label is a string consisting of letters, digits, and underscores, e.g., FOO, FOO0, or _FOO_0:. A label cannot begin with a digit. This is similar to the LC3 assembler. Notice, that in P37X all PC-relative instructions are actually relative to PC+1.

Assembly syntax Semantics Encoding
Arithmetic, Logical, and Shifts
unused undefined 0000 ddds sstt t000
unused undefined 0000 ddds sstt t001
unused undefined 0000 ddds sstt t010
unused undefined 0000 ddds sstt t011
ADD rd, rs, rt regs[rd] = regs[rs] + regs[rt] 0000 ddds sstt t100
SUB rd, rs, rt regs[rd] = regs[rs] - regs[rt] 0000 ddds sstt t101
MUL rd, rs, rt regs[rd] = regs[rs] * regs[rt] 0000 ddds sstt t110
unused undefined 0000 ddds sstt t111
OR rd, rs, rt regs[rd] = regs[rs] | regs[rt] 0001 ddds sstt t000
NOT rd, rs regs[rd] = ~regs[rs] 0001 ddds ssXX X001
AND rd, rs, rt regs[rd] = regs[rs] & regs[rt] 0001 ddds sstt t010
XOR rd, rs, rt regs[rd] = regs[rs] ^ regs[rt] 0001 ddds sstt t011
SLL rd, rs, rt regs[rd] = regs[rs] << (regs[rt] & 15) 0001 ddds sstt t100
SRL rd, rs, rt regs[rd] = ZEXT(regs[rs] >> (regs[rt] & 15)) 0001 ddds sstt t101
SRA rd, rs, rt regs[rd] = SEXT(regs[rs] >> (regs[rt] & 15)) 0001 ddds sstt t110
unused undefined 0001 ddds sstt t111
Traps and Returns from Trap
TRAP imm8 regs[r7] = PC + 1
PC = imm8
PSR[15]=1
0010 XXXX iiii iiii
RTT rd PC = regs[rd]
PSR[15] = 0
0011 dddX XXXX XXXX
Calls and Jumps
JUMP imm12 (label) PC = PC + 1 + SEXT(imm12) 0100 iiii iiii iiii
JUMPR rd PC = regs[rd] 0101 dddX XXXX XXXX
JSR imm12 (label) regs[r7] = PC + 1
PC = PC + 1 + SEXT(imm12)
0110 iiii iiii iiii
JSRR rd regs[r7] = PC + 1
PC = regs[rd]
0111 dddX XXXX XXXX
Conditional Branches
NOOP PC = PC + 1 1000 XXX0 00XX XXXX
BRP rd, imm6 (label) if (regs[rd] > 0) PC = PC + 1 + SEXT(imm6) 1000 ddd0 01ii iiii
BRZ rd, imm6 (label) if (regs[rd] == 0) PC = PC + 1 + SEXT(imm6) 1000 ddd0 10ii iiii
BRZP rd, imm6 (label) if (regs[rd] >= 0) PC = PC + 1 + SEXT(imm6) 1000 ddd0 11ii iiii
BRN rd, imm6 (label) if (regs[rd] < 0) PC = PC + 1 + SEXT(imm6) 1000 ddd1 00ii iiii
BRNP rd, imm6 (label) if (regs[rd] != 0) PC = PC + 1 + SEXT(imm6) 1000 ddd1 01ii iiii
BRNZ rd, imm6 (label) if (regs[rd] <= 0) PC = PC + 1 + SEXT(imm6) 1000 ddd1 10ii iiii
BRNZP rd, imm6 (label) PC = PC + 1 + SEXT(imm6) 1000 ddd1 11ii iiii
Constants
CONST rd, imm9 regs[rd] = SEXT(imm9) 1001 dddi iiii iiii
INC rd, imm9 regs[rd] = regs[rd] + SEXT(imm9) 1010 dddi iiii iiii
LEA rd, imm9 (label) regs[rd] = PC + 1 + SEXT(imm9) 1011 dddi iiii iiii
Loads and Stores
LDR rd, rs, imm6 regs[rd] = mem[regs[rs] + SEXT(imm6)] 1100 ddds ssii iiii
STR rd, rs, imm6 mem[regs[rs] + SEXT(imm6)] = regs[rd] 1101 ddds ssii iiii
LD rd, imm9 (label) regs[rd] = mem[PC + 1 + SEXT(imm9)] 1110 dddi iiii iiii
ST rd, imm9 (label) mem[PC + 1 + SEXT(imm9)] = regs[rd] 1111 dddi iiii iiii

Memory-Mapped I/O Devices

The P37X has several memory-mapped I/O devices and control registers:

Input:

Output:

Control:

Static Data and Assembler Directives

Like the LC3 assembler, the P37X assembler supports static data declarations and a number of other assembler directives. An assembler directive is different than an instruction or even a pseudo-instruction in that it doesn't actually correspond to any instruction execution at runtime. P37X uses the same exact directives as LC3, and they all start with a period. Directives can also be labeled.

In case you forgot, the following table summarizes the P37X (LC3) directives.

Syntax Comment
.ORIG imm16 Following code/data will be placed at static address imm16
.FILL imm16 imm16 is statically written into the current code/data address
.BLKW imm16 A block of imm16 words are reserved starting current static address
.STRINGZ "string" Equivalent to the following loop:
for (i = 0; i < strlen(string); i++)
   .FILL string[i]
.FILL 0x0000
.END Marks the end of the program source

"OS" Trap Routines

P37X also supports all of LC3's trap codes and the associated "OS" routines, although it sometimes gives them different mnemonic names. It also implements them in a different way. In LC3, the trap-vector is a vector of addresses and the TRAP instruction saves the return address, changes privilege mode, dereferences this vector at the proper position, and jumps to the dereferenced address. Basically an LC3 TRAP does a load and a call in one instruction.

Since such a compound operation would be complex to implement in hardware, P37X TRAP instructions work differently. A P37X TRAP saves the return address, changes the privilege mode, and jumps to the trap-vector. The trap-vector itself contains not the address of the routine, but an instruction that jumps to that address. Instead of doing a load and a call in one instruction, P37X implements traps by doing a call (the TRAP) and a jump in two instructions.

At this point you may be wondering "Why doesn't LC3 implement traps using separate load and call instructions?" The answer has to do with the fact that a call actually performs two steps: i) it saves the return address (link), and ii) jumps to the target address. In an LC3 TRAP, these two steps have to take place on either side of the load: the link has to happen before the load, the jump has to happen after.

Anyway, implementation aside, the traps work the same from the programmer's perspective. In case you forgot, the following table summarizes the P37X (LC3) trap codes and routines.

Syntax Comment
TRAP x20 (GETC) Reads a single, un-echoed character from the console to r0
TRAP x21 (PUTC) Writes a single character in r0 to the console
TRAP x22 (PUTS) Writes an unpacked zero-terminated string (e.g., .STRINGZ) at address regs[r0] to the console
TRAP x23 (EGETC) Prints a prompt and reads a single, echoed character from the console to r0
TRAP x24 (PUTSP) Writes a packed zero-terminated string (e.g., .STRINGZP) at address regs[r0] to the console
TRAP x25 (HALT) Halts the processor