Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
435b7f8a3c | ||
|
|
8d52c34f1a | ||
|
|
5d44a9158b | ||
|
|
f57a1ff9aa | ||
|
|
cecaf1cd31 | ||
|
|
9a85d3193f | ||
|
|
8c747c5743 |
@@ -1,3 +1,7 @@
|
|||||||
html {
|
html {
|
||||||
scroll-padding-top: 5rem;
|
scroll-padding-top: 5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h3.hx\:sr-only + * {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,122 @@
|
|||||||
+++
|
+++
|
||||||
title = "LC-2"
|
title = "LC-2"
|
||||||
weight = 100
|
weight = 100
|
||||||
draft = true
|
|
||||||
+++
|
+++
|
||||||
|
|
||||||
|
LC-2 is the first architecture in the Little Computer family that looks like a
|
||||||
|
real ISA. Built as a successor to the minimalist LC-1,[^lc1-successor] it
|
||||||
|
introduced eight general-purpose registers and a three-state condition code
|
||||||
|
system, the foundation that every subsequent architecture in the family would
|
||||||
|
inherit.[^lc-family-evolution]
|
||||||
|
|
||||||
|
[^lc1-successor]: {{< cite-ics edition="1" chapter="1. Welcome Aboard" page="2" >}}
|
||||||
|
[^lc-family-evolution]: {{< cite-talk
|
||||||
|
author="Patt, Yale N."
|
||||||
|
title="LC-3, x86, or MIPS: The First ISA for Students to Study"
|
||||||
|
type="Keynote"
|
||||||
|
event="Workshop on Computer Architecture Education"
|
||||||
|
location="San Diego, CA"
|
||||||
|
date="June 9, 2007"
|
||||||
|
url="https://www.csc2.ncsu.edu/faculty/efg/wcae/ISCA2007/FinalProgram.html"
|
||||||
|
format="PowerPoint presentation"
|
||||||
|
accessed="June 8, 2026"
|
||||||
|
url-archived="https://web.archive.org/web/20250129103001/https://www.csc2.ncsu.edu/faculty/efg/wcae/ISCA2007/FinalProgram.html"
|
||||||
|
url-archived-date="January 29, 2025"
|
||||||
|
>}}
|
||||||
|
|
||||||
|
LC-2 operates on a 16-bit data bus and a 16-bit address bus, giving a linear
|
||||||
|
address space of 65,536 word-sized locations, 128 KiB of addressable memory in
|
||||||
|
total. Every instruction is exactly 16 bits wide, with the top 4 bits reserved
|
||||||
|
for the opcode. This fixed encoding means that the opcode, operands, and any
|
||||||
|
immediate values must all fit within those 16 bits, a constraint that shapes the
|
||||||
|
design of every instruction in the set.[^lc2-overview]
|
||||||
|
|
||||||
|
[^lc2-overview]: {{< cite-ics edition="1" chapter="Appendix A: The LC-2 ISA" page="429" >}}
|
||||||
|
|
||||||
|
## Registers
|
||||||
|
|
||||||
|
LC-2 has a small but complete set of registers. All registers are 16 bits wide,
|
||||||
|
matching the data bus width of the architecture.
|
||||||
|
|
||||||
|
### General-Purpose Registers
|
||||||
|
|
||||||
|
LC-2 provides eight general-purpose registers, named R0 through R7. They are
|
||||||
|
symmetric: no register has a special hardware role, and any of them can be used
|
||||||
|
as a source or destination in any instruction that operates on
|
||||||
|
registers.[^lc2-overview] That said, two registers have a conventional role: R6
|
||||||
|
is typically used as the stack pointer,[^lc2-stack] [^lc2-rti] and R7 is used
|
||||||
|
by some instructions to store the return address.[^lc2-jsr-jsrr] [^lc2-ret]
|
||||||
|
[^lc2-trap] See the [instructions page](instructions/) for details.
|
||||||
|
|
||||||
|
[^lc2-stack]: {{< cite-ics edition="1" chapter="10.1.3 Implementation in Memory" page="197" page-end="200" >}}
|
||||||
|
[^lc2-rti]: {{< cite-ics edition="1" chapter="Appendix A.3 The Instruction Set" page="444" >}}
|
||||||
|
[^lc2-jsr-jsrr]: {{< cite-ics edition="1" chapter="Appendix A.3 The Instruction Set" page="436" page-end="437" >}}
|
||||||
|
[^lc2-ret]: {{< cite-ics edition="1" chapter="Appendix A.3 The Instruction Set" page="443" >}}
|
||||||
|
[^lc2-trap]: {{< cite-ics edition="1" chapter="Appendix A.3 The Instruction Set" page="448" >}}
|
||||||
|
|
||||||
|
### Special-Purpose Registers
|
||||||
|
|
||||||
|
Beyond the general-purpose registers, LC-2 has some special-purpose registers
|
||||||
|
that control the execution of the processor. None of these registers are
|
||||||
|
directly accessible from assembly, with the exception of the CC, which is
|
||||||
|
implicitly read by conditional branch instructions.
|
||||||
|
|
||||||
|
* The **Program Counter** (**PC**) holds the address of the next instruction to
|
||||||
|
be fetched from memory. It is incremented by 1 after each fetch, before the
|
||||||
|
instruction is executed, so that by the time the instruction runs, the PC
|
||||||
|
already points to the following one.[^lc2-fetch]
|
||||||
|
|
||||||
|
[^lc2-fetch]: {{< cite-ics edition="1" chapter="4.2.2 The Instruction Cycle" page="82" page-end="83" >}}
|
||||||
|
|
||||||
|
* The **Instruction Register** (**IR**) holds the instruction currently being
|
||||||
|
executed. After the PC is used to fetch an instruction from memory, the
|
||||||
|
instruction is loaded into the IR, where it remains for the duration of the
|
||||||
|
decode and execute phases.[^lc2-fetch]
|
||||||
|
|
||||||
|
* The **Memory Address Register** (**MAR**) holds the address of the memory
|
||||||
|
location to be accessed. Before any memory operation, the address is loaded
|
||||||
|
into the MAR, which then drives the address bus during the read or write
|
||||||
|
cycle.[^lc2-memory]
|
||||||
|
|
||||||
|
[^lc2-memory]: {{< cite-ics edition="1" chapter="4.1.1 Memory" page="75" page-end="77" >}}
|
||||||
|
|
||||||
|
* The **Memory Data Register** (**MDR**) holds the data being transferred to or
|
||||||
|
from memory. On a read, the MDR receives the value fetched from the location
|
||||||
|
addressed by the MAR. On a write, the MDR holds the value to be stored before
|
||||||
|
it is placed onto the data bus.[^lc2-memory]
|
||||||
|
|
||||||
|
* The **Condition Code** register (**CC**) is a 3-bit register that tracks the
|
||||||
|
sign of the last value written to any general-purpose register. It has three
|
||||||
|
mutually exclusive states: N (negative), Z (zero), and P (positive). Exactly
|
||||||
|
one of the three bits is set at any given time.[^lc2-overview]
|
||||||
|
|
||||||
|
Not all instructions update the CC. Only instructions that write a value to a
|
||||||
|
general-purpose register will modify it. As an example, an `ADD` instruction
|
||||||
|
that stores its result in R0 will update the CC based on the sign of that
|
||||||
|
result, while a `STR` instruction that writes to memory will
|
||||||
|
not.[^lc2-condition-codes]
|
||||||
|
|
||||||
|
[^lc2-condition-codes]: {{< cite-ics edition="1" chapter="5.1.7 Condition Codes" page="95" >}}
|
||||||
|
|
||||||
|
## Startup Behavior
|
||||||
|
|
||||||
|
The ISA does not specify a default starting address or reset vector. Where the
|
||||||
|
PC is initialized when the processor powers on or resets is left entirely to
|
||||||
|
the implementation. {{< citation-needed >}}
|
||||||
|
|
||||||
|
## Interrupt Support
|
||||||
|
|
||||||
|
LC-2 provides support for vectored interrupts. When an interrupt is serviced,
|
||||||
|
the processor pushes the current PC and CC onto the stack, then reads an 8-bit
|
||||||
|
value from the interrupting device, called the interrupt vector (`INTV`).
|
||||||
|
`INTV` is zero-extended to 16 bits and used as a memory address into the
|
||||||
|
interrupt table: the value stored at that address is loaded into the PC,
|
||||||
|
transferring control to the interrupt handler.{{< citation-needed >}}
|
||||||
|
|
||||||
|
The `RTI` (Return from Interrupt) instruction reverses this process, popping
|
||||||
|
the PC and CC from the stack to resume the interrupted
|
||||||
|
program.{{< citation-needed >}}
|
||||||
|
|
||||||
|
Beyond this, the ISA does not specify the interrupt protocol in further detail:
|
||||||
|
the bus signaling and acknowledgment mechanism used to deliver `INTV` are left
|
||||||
|
to the implementation.
|
||||||
|
|||||||
|
After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 60 KiB |
@@ -0,0 +1,390 @@
|
|||||||
|
+++
|
||||||
|
title = "Instructions"
|
||||||
|
weight = 120
|
||||||
|
+++
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="ADD"
|
||||||
|
short="Addition"
|
||||||
|
|
||||||
|
formats=`ADD DR, SR1, SR2
|
||||||
|
ADD DR, SR1, imm5`
|
||||||
|
|
||||||
|
encoding="../imgs/add.drawio.png"
|
||||||
|
encoding-dark="../imgs/add-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`if (bit[5] == 0) {
|
||||||
|
DR = SR1 + SR2;
|
||||||
|
} else {
|
||||||
|
DR = SR1 + SEXT(imm5);
|
||||||
|
}
|
||||||
|
|
||||||
|
setcc(DR);`
|
||||||
|
|
||||||
|
examples=`ADD R2, R3, R4 ; R2 ← R3 + R4
|
||||||
|
ADD R2, R3, #7 ; R2 ← R3 + 7`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
If bit [5] is 0, the second-source operand is obtained from SR2. If bit [5] is
|
||||||
|
1, the second-source operand is obtained by sign-extending the imm5 field to 16
|
||||||
|
bits. In both cases, the second source operand is added to the contents of SR1,
|
||||||
|
and the result stored in DR. The condition codes are set, based on whether the
|
||||||
|
result is negative, zero, or positive.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="AND"
|
||||||
|
short="Bitwise logical AND"
|
||||||
|
|
||||||
|
formats=`AND DR, SR1, SR2
|
||||||
|
AND DR, SR1, imm5`
|
||||||
|
|
||||||
|
encoding="../imgs/and.drawio.png"
|
||||||
|
encoding-dark="../imgs/and-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`if (bit[5] == 0) {
|
||||||
|
DR = SR1 & SR2;
|
||||||
|
} else {
|
||||||
|
DR = SR1 & SEXT(imm5);
|
||||||
|
}
|
||||||
|
|
||||||
|
setcc(DR);`
|
||||||
|
|
||||||
|
examples=`AND R2, R3, R4 ; R2 ← R3 AND R4
|
||||||
|
AND R2, R3, #7 ; R2 ← R3 AND 7`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
If bit [5] is 0, the second-source operand is obtained from SR2. If bit [5] is
|
||||||
|
1, the second-source operand is obtained by sign-extending the imm5 field to 16
|
||||||
|
bits. In either case, the second-source operand and the contents of SR1 are
|
||||||
|
bitwise ANDed, and the result stored in DR. The condition codes are set, based
|
||||||
|
on whether the binary value produced, taken as a 2's complement integer, is
|
||||||
|
negative, zero, or positive.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="BR"
|
||||||
|
short="Conditional Branch"
|
||||||
|
|
||||||
|
formats=`BR LABEL
|
||||||
|
BRn LABEL
|
||||||
|
BRz LABEL
|
||||||
|
BRp LABEL
|
||||||
|
BRnz LABEL
|
||||||
|
BRnp LABEL
|
||||||
|
BRzp LABEL
|
||||||
|
BRnzp LABEL`
|
||||||
|
|
||||||
|
encoding="../imgs/br.drawio.png"
|
||||||
|
encoding-dark="../imgs/br-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`if ((n && N) || (z && Z) || (p && P)) {
|
||||||
|
PC = PC[15:9] @ pgoffset9;
|
||||||
|
}`
|
||||||
|
|
||||||
|
examples=`BRzp LOOP ; Branch to LOOP if the last result was zero or positive.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Test the condition codes specified by the state of bits [11:9]. If bit [11] is
|
||||||
|
set, test N; if bit [11] is clear, do not test N. If bit [10] is set, test Z,
|
||||||
|
etc. If any of the condition codes tested is set, branch to the location
|
||||||
|
specified by pgoffset9 on the same page as the branch instruction,
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic=`JMP / JSR`
|
||||||
|
short=`Jump / Jump to Subroutine`
|
||||||
|
|
||||||
|
formats=`JMP LABEL (L = 0)
|
||||||
|
JSR LABEL (L = 1)`
|
||||||
|
|
||||||
|
encoding="../imgs/jmp-jsr.drawio.png"
|
||||||
|
encoding-dark="../imgs/jmp-jsr-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`if (L == 1) {
|
||||||
|
R7 = PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
PC = PC[15:9] @ pgoffset9;`
|
||||||
|
|
||||||
|
examples=`JMP FOO ; Jump to FOO.
|
||||||
|
JSR FOO ; Jump to FOO, put return PC into R7.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Unconditionally jump to the location specified by pgoffset9 on the same page as
|
||||||
|
the JSR/JMP instruction. If the link bit L is set, the PC is saved in R7,
|
||||||
|
enabling a subsequent return to the instruction physically following the JSR
|
||||||
|
instruction.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic=`JMPR / JSRR`
|
||||||
|
short=`Jump, Base + Offset / Jump to Subroutine, Base + Offset`
|
||||||
|
|
||||||
|
formats=`JMPR BaseR, index6 (L = 0)
|
||||||
|
JSRR BaseR, index6 (L = 1)`
|
||||||
|
|
||||||
|
encoding="../imgs/jmpr-jsrr.drawio.png"
|
||||||
|
encoding-dark="../imgs/jmpr-jsrr-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`if (L == 1) {
|
||||||
|
R7 = PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
PC = BaseR + ZEXT(index6);`
|
||||||
|
|
||||||
|
examples=`JMPR R2, #10 ; Jump to R2 + #10.
|
||||||
|
JSRR R2, #10 ; Jump to R2 + #10, put return PC into R7.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Unconditionally jump to the location specified by adding ZEXT(index6) to the
|
||||||
|
contents of the base register. If the link bit L is set, the PC is saved in R7,
|
||||||
|
enabling a subsequent return to the instruction physically following the JSRR
|
||||||
|
instruction.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="LD"
|
||||||
|
short="Load Direct"
|
||||||
|
|
||||||
|
formats=`LD DR, LABEL`
|
||||||
|
|
||||||
|
encoding="../imgs/ld.drawio.png"
|
||||||
|
encoding-dark="../imgs/ld-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`DR = mem[PC[15:9] @ pgoffset9];
|
||||||
|
|
||||||
|
setcc(DR);`
|
||||||
|
|
||||||
|
examples=`LD R4, COUNT ; R4 ← mem[COUNT].`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Load the register specified by DR from the location specified by pgoffset9 on
|
||||||
|
the same page as the LD instruction. The condition codes are set, based on
|
||||||
|
whether the value loaded is negative, zero, or positive.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="LDI"
|
||||||
|
short="Load Indirect"
|
||||||
|
|
||||||
|
formats=`LDI DR, LABEL`
|
||||||
|
|
||||||
|
encoding="../imgs/ldi.drawio.png"
|
||||||
|
encoding-dark="../imgs/ldi-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`DR = mem[mem[PC[15:9] @ pgoffset9]];
|
||||||
|
|
||||||
|
setcc(DR);`
|
||||||
|
|
||||||
|
examples=`LDI R4, POINTER ; R4 ← mem[mem[POINTER]].`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Load the register specified by DR as follows: Construct an address by
|
||||||
|
concatenating the top seven bits of the program counter with the pgoffset9
|
||||||
|
field of the LDI instruction. The contents of memory at that address is the
|
||||||
|
address of the data to be loaded into DR. The condition codes are set, based on
|
||||||
|
whether the value loaded is negative, zero, or positive.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="LDR"
|
||||||
|
short="Load Base + Offset"
|
||||||
|
|
||||||
|
formats=`LDR DR, BaseR, index6`
|
||||||
|
|
||||||
|
encoding="../imgs/ldr.drawio.png"
|
||||||
|
encoding-dark="../imgs/ldr-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`DR = mem[BaseR + ZEXT(index6)];
|
||||||
|
|
||||||
|
setcc(DR);`
|
||||||
|
|
||||||
|
examples=`LDR R4, R2, #10 ; R4 ← contents of mem[R2 + #10].`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Load the register specified by DR from the location specified by a base
|
||||||
|
register and index, as follows: The index is zero-extended to 16 bits and added
|
||||||
|
to the contents of BaseR to form a memory address. The contents of memory at
|
||||||
|
this address are loaded into DR. The condition codes are set, based on whether
|
||||||
|
the value loaded is negative, zero, or positive.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="LEA"
|
||||||
|
short="Load Effective Address"
|
||||||
|
|
||||||
|
formats=`LEA DR, LABEL`
|
||||||
|
|
||||||
|
encoding="../imgs/lea.drawio.png"
|
||||||
|
encoding-dark="../imgs/lea-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`DR = PC[15:9] @ pgoffset9;
|
||||||
|
|
||||||
|
setcc(DR);`
|
||||||
|
|
||||||
|
examples=`LEA R4, FOO ; R4 ← address of FOO.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Load the register specified by DR with the address formed by concatenating the
|
||||||
|
top seven bits of the program counter with the pgoffset9 field of the
|
||||||
|
instruction. The condition codes are set, based on whether the value loaded is
|
||||||
|
negative, zero, or positive.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="NOT"
|
||||||
|
short="Bitwise Complement"
|
||||||
|
|
||||||
|
formats=`NOT DR, SR`
|
||||||
|
|
||||||
|
encoding="../imgs/not.drawio.png"
|
||||||
|
encoding-dark="../imgs/not-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`DR = ~SR;
|
||||||
|
|
||||||
|
setcc(DR);`
|
||||||
|
|
||||||
|
examples=`NOT R4, R2 ; R4 ← NOT(R2).`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Perform the bitwise complement operation on the contents of SR and place the
|
||||||
|
result in DR. The condition codes are set.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="RET"
|
||||||
|
short="Return from Subroutine"
|
||||||
|
|
||||||
|
formats=`RET`
|
||||||
|
|
||||||
|
encoding="../imgs/ret.drawio.png"
|
||||||
|
encoding-dark="../imgs/ret-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`PC = R7;`
|
||||||
|
|
||||||
|
examples=`RET ; PC ← R7.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Load the PC with the value in R7. This causes a return from a previous JSR or
|
||||||
|
JSRR instruction.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="RTI"
|
||||||
|
short="Return from Interrupt"
|
||||||
|
|
||||||
|
formats=`RTI`
|
||||||
|
|
||||||
|
encoding="../imgs/rti.drawio.png"
|
||||||
|
encoding-dark="../imgs/rti-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`NZP = mem[R6];
|
||||||
|
R6 = R6 - 1;
|
||||||
|
PC = mem[R6];
|
||||||
|
R6 = R6 - 1;`
|
||||||
|
|
||||||
|
examples=`RTI ; NZP, PC ← top two values popped off stack.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Pop the top two elements off the stack; load them into NZP, PC.
|
||||||
|
|
||||||
|
<h4>Notes</h4>
|
||||||
|
|
||||||
|
On an external interrupt, the initiating sequence pushes the current PC onto
|
||||||
|
the stack before loading the PC with the starting address of the service
|
||||||
|
routine. The last instruction in the service routine is RTI, which returns
|
||||||
|
control to the interrupted program by popping the stack and loading the value
|
||||||
|
popped into the PC. (This instruction is included in this appendix for
|
||||||
|
completeness. Its purpose and use are beyond the scope of what is normally
|
||||||
|
covered in an introductory textbook.)
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="ST"
|
||||||
|
short="Store Direct"
|
||||||
|
|
||||||
|
formats=`ST SR, LABEL`
|
||||||
|
|
||||||
|
encoding="../imgs/st.drawio.png"
|
||||||
|
encoding-dark="../imgs/st-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`mem[PC[15:9] @ pgoffset9] = SR;`
|
||||||
|
|
||||||
|
examples=`ST R4, COUNT ; mem[COUNT] ← R4.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Store the contents of the register specified by SR into the memory location
|
||||||
|
specified by pgoffset9 on the same page as the ST instruction.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="STI"
|
||||||
|
short="Store Indirect"
|
||||||
|
|
||||||
|
formats=`STI SR, LABEL`
|
||||||
|
|
||||||
|
encoding="../imgs/sti.drawio.png"
|
||||||
|
encoding-dark="../imgs/sti-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`mem[mem[PC[15:9] @ pgoffset9]] = SR;`
|
||||||
|
|
||||||
|
examples=`STI R4, POINTER ; mem[mem[POINTER]] ← R4.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Store the contents of the register specified by SR into the memory location
|
||||||
|
whose address is obtained as follows: Construct an address by concatenating the
|
||||||
|
top seven bits of the program counter with the pgoffset9 field of the STI
|
||||||
|
instruction. The contents of memory at that address is the address of the
|
||||||
|
location to which the data in SR is to be stored.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="STR"
|
||||||
|
short="Store Base+Offset"
|
||||||
|
|
||||||
|
formats=`STR SR, BaseR, index6`
|
||||||
|
|
||||||
|
encoding="../imgs/str.drawio.png"
|
||||||
|
encoding-dark="../imgs/str-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`mem[BaseR + ZEXT(index6)] = SR;`
|
||||||
|
|
||||||
|
examples=`STR R4, R2, #10 ; mem[R2 + #10] ← R4.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Store the contents of the register specified by SR into the memory location
|
||||||
|
whose address is specified as follows: The six-bit offset is zero-extended to
|
||||||
|
16 bits and added to the contents of BaseR to form a memory address. This is
|
||||||
|
the address of the location into which the contents of SR is to be stored.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
{{% instruction
|
||||||
|
mnemonic="TRAP"
|
||||||
|
short="Operating System Call"
|
||||||
|
|
||||||
|
formats=`TRAP trapvec8`
|
||||||
|
|
||||||
|
encoding="../imgs/trap.drawio.png"
|
||||||
|
encoding-dark="../imgs/trap-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`R7 = PC;
|
||||||
|
PC = mem[ZEXT(trapvect8)];`
|
||||||
|
|
||||||
|
examples=`TRAP x23 ; Direct the operating system to execute the "IN" system call.`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
Load the PC with the contents of the memory location obtained by zero-extending
|
||||||
|
trapvec8 to 16 bits. This is the starting address of the system call
|
||||||
|
specified by trapvec8. Load R7 with the PC, which enables a return to the
|
||||||
|
instruction physically following the TRAP instruction in the original program
|
||||||
|
after the service routine has completed.
|
||||||
|
|
||||||
|
<h4>Notes</h4>
|
||||||
|
|
||||||
|
Memory locations x0020 through x00FF, 192 in all, are available to contain
|
||||||
|
starting addresses for system calls specified by their corresponding
|
||||||
|
trap vectors. This region of memory is called the trap vector table. See Table
|
||||||
|
A.3. Memory locations x0000 through x001F are not part of the trap vector
|
||||||
|
table; therefore, x00 through x1F may not be used as trap vectors.
|
||||||
|
{{% /instruction %}}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
+++
|
||||||
|
title = "Memory"
|
||||||
|
weight = 110
|
||||||
|
+++
|
||||||
|
|
||||||
|
LC-2 has a 16-bit address bus, giving a linear address space of 65,536
|
||||||
|
locations, numbered from `0x0000` to `0xFFFF`. Memory is canonically divided
|
||||||
|
into 2<sup>7</sup> pages of 2<sup>9</sup> words each. There is no segmentation,
|
||||||
|
no paging, and no virtual memory: every address maps directly to a physical
|
||||||
|
location.[^lc2-overview]
|
||||||
|
|
||||||
|
[^lc2-overview]: {{< cite-ics edition="1" chapter="Appendix A: The LC-2 ISA" page="429" >}}
|
||||||
|
|
||||||
|
Addressability is 16 bits: each location in memory holds exactly one word,
|
||||||
|
matching the width of the data bus. A single memory access always transfers a
|
||||||
|
full 16-bit value, never a partial word, which is also why the concept of
|
||||||
|
endianness does not apply here: there is no multi-byte value to order within a
|
||||||
|
single access.
|
||||||
|
|
||||||
|
## Memory Map
|
||||||
|
|
||||||
|
The memory map below reflects the conventions of the standard LC-2 operating
|
||||||
|
system, not the ISA itself. The ISA only defines the trap vector table at
|
||||||
|
`0x0000 - 0x00FF`. Everything else, from the location of the OS to the boundary
|
||||||
|
of userspace, is a software convention rather than a hardware requirement.
|
||||||
|
|
||||||
|
| Range | Purpose |
|
||||||
|
|:-------------------:|:-----------------------------------------------------------------------------:|
|
||||||
|
| `0x0000` - `0x00FF` | Trap Vector Table[^lc2-trap] / [Interrupt Vector Table](..#interrupt-support) |
|
||||||
|
| `0x0100` - `0x2FFF` | Operating System[^matt-postiff-guide] |
|
||||||
|
| `0x3000` - `0xCFFF` | Userspace |
|
||||||
|
| `0xD000` - `0xFFFF` | Device Registers |
|
||||||
|
|
||||||
|
[^lc2-trap]: {{< cite-ics edition="1" chapter="Appendix A.3 The Instruction Set" page="448" page-end="449" >}}
|
||||||
|
[^matt-postiff-guide]: {{< cite-web
|
||||||
|
author="Postiff, Matthew A."
|
||||||
|
title="LC-2 Programmer's Reference and User Guide"
|
||||||
|
site="University of Texas"
|
||||||
|
url="https://www.cs.utexas.edu/~fussell/courses/cs310h/simulator/lc2.pdf"
|
||||||
|
format="PDF"
|
||||||
|
accessed="August 31, 2026"
|
||||||
|
url-archived="https://web.archive.org/web/20251205052350/https://www.cs.utexas.edu/~fussell/courses/cs310h/simulator/lc2.pdf"
|
||||||
|
url-archived-date="December 05, 2025"
|
||||||
|
>}}
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
The ISA does not define a stack as a distinct hardware structure, but it
|
||||||
|
assumes one exists by convention. R6 is used as the stack pointer, and the
|
||||||
|
stack is assumed to grow toward `0xFFFF`.
|
||||||
|
|
||||||
|
This convention is not optional in practice: the `RTI` instruction relies on it
|
||||||
|
directly. When an interrupt is serviced, the CC and PC are pushed onto the
|
||||||
|
stack. `RTI` pops them back in reverse order to resume execution. Any deviation
|
||||||
|
from the R6 convention would break interrupt handling.[^lc2-rti]
|
||||||
|
|
||||||
|
[^lc2-rti]: {{< cite-ics edition="1" chapter="Appendix A.3 The Instruction Set" page="444" >}}
|
||||||
|
|
||||||
|
## Memory-Mapped I/O
|
||||||
|
|
||||||
|
LC-2 uses memory-mapped I/O: devices are accessed using the same load and store
|
||||||
|
instructions used for regular memory, with no dedicated I/O instructions in the
|
||||||
|
ISA.[^lc2-mmio]
|
||||||
|
|
||||||
|
[^lc2-mmio]: {{< cite-ics edition="1" chapter="8.1.2 Memroy Mapped I/O Versus Special Input/Output Instructions" page="158" >}}
|
||||||
|
|
||||||
|
The standard LC-2 operating system maps the following devices into the top of
|
||||||
|
the address space. These are not defined by the ISA: they are the devices
|
||||||
|
assumed by the reference implementation and its OS.
|
||||||
|
|
||||||
|
| Address | Register | Description |
|
||||||
|
|:--------:|:-------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `0xF3FC` | Video Status Register (`CRTSR`)[^lc2-devices-registers] | Bit 15, the ready bit, indicates whether the video device is ready to receive another character to print on the screen. |
|
||||||
|
| `0xF3FD` | Horizontal Screen Position[^matt-postiff-guide] | Not implemented. |
|
||||||
|
| `0xF3FE` | Vertical Screen Position | Not implemented. |
|
||||||
|
| `0xF3FF` | Video Data Register (`CRTDR`) | A character written in the low byte of this register will be displayed on screen. |
|
||||||
|
| `0xF400` | Keyboard Status Register (`KBSR`) | Bit 15, the ready bit, indicates whether the keyboard has received a new character. |
|
||||||
|
| `0xF401` | Keyboard Data Register (`KBDR`) | The lower byte contain the last character typed on the keyboard. |
|
||||||
|
| `0xFFFF` | Machine Control Register (`MCR`) | Bit 15 is the clock enable bit. When cleared, instruction processing stops because the clock signal stops pulsing. |
|
||||||
|
|
||||||
|
[^lc2-devices-registers]: {{< cite-ics edition="1" chapter="Appendix A: The LC-2 ISA" page="430" >}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<sup>[<i><a href="https://en.wikipedia.org/wiki/Citation_needed" target="_blank">citation needed</a></i>]</sup>
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
{{- /*
|
||||||
|
instruction - Standardized instruction reference card, following the layout
|
||||||
|
used in the Patt & Patel textbook: mnemonic title, short description, assembler
|
||||||
|
formats, encoding diagram, high-level operation, and usage examples.
|
||||||
|
|
||||||
|
@param {string} mnemonic Instruction mnemonic(s), comma-separated if more
|
||||||
|
than one (e.g. "ADD" or "JSR, JSRR").
|
||||||
|
@param {string} short Short two-to-three word description (e.g.
|
||||||
|
"Addition").
|
||||||
|
@param {string} formats Assembler format(s). Use a backtick-quoted
|
||||||
|
string for multiple lines.
|
||||||
|
@param {string} encoding Filename of the encoding diagram
|
||||||
|
@param {string} encoding-dark Optional dark mode variant of the encoding
|
||||||
|
diagram. If set, `encoding` is only shown in
|
||||||
|
light mode and this is shown in dark mode.
|
||||||
|
@param {string} encoding-bits Optional accessible bit-level breakdown of the
|
||||||
|
encoding, for screen readers and crawlers. Use
|
||||||
|
lines of "bits:value:meaning", one per row.
|
||||||
|
Separate multiple variants with a line
|
||||||
|
containing only "---".
|
||||||
|
@param {string} operation High-level operation, typically pseudo-C. Use a
|
||||||
|
backtick-quoted string for multiple lines.
|
||||||
|
@param {string} examples Usage examples in LC-2 assembly. Use a
|
||||||
|
backtick-quoted string for multiple lines.
|
||||||
|
|
||||||
|
@example {{% instruction
|
||||||
|
mnemonic="ADD"
|
||||||
|
short="Addition"
|
||||||
|
|
||||||
|
formats=`ADD DR, SR1, SR2
|
||||||
|
ADD DR, SR1, imm5`
|
||||||
|
|
||||||
|
encoding="add.drawio.png"
|
||||||
|
encoding-dark="add-dark.drawio.png"
|
||||||
|
|
||||||
|
operation=`if (bit[5] == 0) {
|
||||||
|
DR = SR1 + SR2;
|
||||||
|
} else {
|
||||||
|
DR = SR1 + SEXT(imm5);
|
||||||
|
}
|
||||||
|
|
||||||
|
setcc(DR);`
|
||||||
|
|
||||||
|
examples=`ADD R2, R3, R4 ; R2 ← R3 + R4
|
||||||
|
ADD R2, R3, #7 ; R2 ← R3 + 7`
|
||||||
|
|
||||||
|
%}}
|
||||||
|
If bit [5] is 0, the second-source operand is obtained from SR2. If bit [5] is
|
||||||
|
1, the second-source operand is obtained by sign-extending the imm5 field to 16
|
||||||
|
bits. In both cases, the second source operand is added to the contents of SR1,
|
||||||
|
and the result stored in DR. The condition codes are set, based on whether the
|
||||||
|
result is negative, zero, or positive.
|
||||||
|
{{% /instruction %}}
|
||||||
|
|
||||||
|
*/ -}}
|
||||||
|
|
||||||
|
{{- $mnemonic := .Get "mnemonic" -}}
|
||||||
|
{{- $short := .Get "short" -}}
|
||||||
|
{{- $formats := .Get "formats" -}}
|
||||||
|
{{- $encoding := .Get "encoding" -}}
|
||||||
|
{{- $encodingDark := .Get "encoding-dark" -}}
|
||||||
|
{{- $encodingBits := .Get "encoding-bits" -}}
|
||||||
|
{{- $operation := .Get "operation" -}}
|
||||||
|
{{- $examples := .Get "examples" -}}
|
||||||
|
{{- $description := .Inner -}}
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Sligtly edited version of Hextra's `details` shortcode
|
||||||
|
<https://github.com/imfing/hextra/blob/main/layouts/_shortcodes/details.html>
|
||||||
|
-->
|
||||||
|
<details class="hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group">
|
||||||
|
<summary class="hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[''] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90">
|
||||||
|
<strong class="hx:text-xl">{{ $mnemonic }}</strong>
|
||||||
|
</summary>
|
||||||
|
<div class="hx:p-2 hx:overflow-hidden">
|
||||||
|
|
||||||
|
<!-- Hidden heading: For TOC entry and permalink only -->
|
||||||
|
### {{ $mnemonic }} {.hx:sr-only}
|
||||||
|
|
||||||
|
> {{ $short }}
|
||||||
|
|
||||||
|
<h4>Assembler Formats</h4>
|
||||||
|
|
||||||
|
```
|
||||||
|
{{ $formats }}
|
||||||
|
```
|
||||||
|
|
||||||
|
<h4>Encoding</h4>
|
||||||
|
|
||||||
|
{{ if $encodingDark }}
|
||||||
|
<img src="{{ $encoding }}" alt="{{ $mnemonic }} instruction encoding" class="hx:dark:hidden">
|
||||||
|
<img src="{{ $encodingDark }}" alt="{{ $mnemonic }} instruction encoding" class="hx:hidden hx:dark:block">
|
||||||
|
{{ else }}
|
||||||
|
<img src="{{ $encoding }}" alt="{{ $mnemonic }} instruction encoding">
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if $encodingBits }}
|
||||||
|
{{ $variants := (split $encodingBits "---") }}
|
||||||
|
{{ $html := printf "<div id=\"%s-encoding-table\" class=\"hx:sr-only\">" ($mnemonic | lower) }}
|
||||||
|
{{ range $variantIndex, $variant := $variants }}
|
||||||
|
{{ $html = print $html "<table>" }}
|
||||||
|
{{ $html = print $html (printf "<caption>%s encoding%s</caption>" $mnemonic (cond (gt (len $variants) 1) (printf ", variant %d" (add $variantIndex 1)) "")) }}
|
||||||
|
{{ $html = print $html "<thead><tr><th>Bits</th><th>Value</th><th>Meaning</th></tr></thead>" }}
|
||||||
|
{{ $html = print $html "<tbody>" }}
|
||||||
|
{{ range (split (trim $variant "\n") "\n") }}
|
||||||
|
{{ $parts := split . "|" }}
|
||||||
|
{{ $html = print $html (printf "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" (index $parts 0) (index $parts 1) (index $parts 2)) }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $html = print $html "</tbody></table>" }}
|
||||||
|
{{ end }}
|
||||||
|
{{ $html = print $html "</div>" }}
|
||||||
|
{{ $html | safeHTML }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<h4>Operation</h4>
|
||||||
|
|
||||||
|
```c
|
||||||
|
{{ $operation }}
|
||||||
|
```
|
||||||
|
|
||||||
|
<h4>Description</h4>
|
||||||
|
|
||||||
|
{{ $description }}
|
||||||
|
|
||||||
|
<h4>Examples</h4>
|
||||||
|
|
||||||
|
```
|
||||||
|
{{ $examples }}
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||