This project started with a request from Robin Stokke, a senior lecturer at the University of Oslo for an improved LMC. He was looking for something to use with first year undergraduates with a wide range of previous experience, that would be as simple as the LMC but allow more complex projects. In particular they wanted modes other than decimal and a larger output area. After some discussion we realised that the existing RISC simulator had most of the features they wanted and could potentially support the LMC instructions as a subset.
Once I had prototyped something, we enlarged the output area and added an instruction counter. This enables tasks to be set along the lines of "write a program that executes in the minimum number of instructions". I also added tool-tips (the feature where you move the mouse over a memory or register location and the alternate interpretations of the bit pattern are shown) and instruction execution indication (so the assembly languauge statement for the current instruction is highlighted).
It was clear at this point that all that had been removed from V1 of the RISC simulator was a couple of rarely used branch tests (both of which can be done in two instructions, so the functions are still possible). Everything else is upwards compatible so it made sense to make this RISC V2
It is compatible at the assembly language level with my LMC simulator. It uses r0 as the accumulator. Some other implementations have added extra instructions (indirect for example) and, while you can do that using the RISC instructions, we don't support those non-standard LMC features. The memory locations hold a 16 bit word, so the signed range is -32768 to 32767 instead of the normal LMC -999 to +999.
Every straightforward LMC program I have tried works correctly and if you find one that doesn't please email me at plh256 at hotmail.com. The main issues have been people using short labels, like sp or mul which are now reserved as register names or instructions. So be prepared to change any two or three letter labels it rejects.
Clearly, anything that wraps will give different answers. So 999 + 999 on my LMC gives -1, whereas with RISC V2 the same code gives 1998 (because it does not wrap in 16 bits). Similarly the instruction encodings are not the same, so if you construct an LDA instruction on the LMC by adding an address to 500, that won't work. However if you start with "LDA 0" and add an address, it will work the same on both systems (as will STA). The bubble sort example has been changed to work this way by starting with LDA/STA 80 and 81 and adding one each loop. (Since self modifying code is not recommended, using the RISC instructions is better. For example, calculate an address in r1 and then do LDA r0,(r1).)
The only other restriction I know of is that there are now additional codes that cannot be used as labels. The LMC does not does not have anything (like the : in other simulators) that indicates a label and hence cannot allow instruction codes to be used as labels. I could not see a sensible alternative to extending the restriction to the RISC instruction codes, although I have improved the error message. (For example "BRA HLT" could be either a label BRA with an instruction HLT or an instruction BRA to the label HLT. There is no way to tell.)
The IR (Instruction Register) display now shows the decode of the instruction, in the form "name","register","register","operand", as in the example below. Name is the name (mnemonic) of the instruction code that has been decoded. For all LMC compatible instructions, the first register will be empty or 0 and the second will be empty. The operand will normally be a memory address except for HLT (empty) and INP/OUT/OTP where it is a device code. Almost all modern computers have variable length operation fields and this simulator does as well. (You can see this even with the LMC where INP and OUT both have top digit 9.) The actual value underneath as a.b.c/n. This value encoding is similar to the way IP addresses are sometimes represented except that each of a/b/c is 4 bits (in decimal). The n is the number of bits used by this operation code.
Name | Description | Value/Bits | ||||
HLT | Stop (Little Man has a rest). | 0.0/5 | ||||
ADD | Add the contents of the memory address to the Accumulator. | 12/4 | ||||
SUB | Subtract the contents of the memory address from the Accumulator. | 13/4 | ||||
STA or STO | Store the value in the Accumulator in the memory address given. | 14/4 | ||||
LDA | Load the Accumulator with the contents of the memory address given. | 15/4 | ||||
BRA | Branch - use the address given as the address of the next instruction. | 8.0/7 | ||||
BRZ | Branch to the address given if the Accumulator is zero. | 9.4/7 | ||||
BRP | Branch to the address given if the Accumulator is zero or positive. | 9.0/7 | ||||
INP | Input a number into the Accumulator. | 7.1.0/9 | ||||
OUT | Output a number from the Accumulator. | 7.1.8/9 | ||||
OTC | Output accumulator as a character. (Non-standard LMC instruction.) | 7.1.8/9 | ||||
DAT | Used to indicate a location that contains data. |
At the moment, the first ten examples under SELECT are taken from the LMC and the remaining four show how the full instruction set of RISC can be used.
You can find it here www.peterhigginson.co.uk/RISC/V2.php.
© 2016-23 Peter L Higginson (plh256 at hotmail.com) and as usual, please don't do synchonised bulk loads in classrooms.