Emulating Instructions
Useful links:
Problem 1: Design Problem: Adding LDB/STB in software
See the instructions below.
Use the Bsim instance below to enter your code. To complete this design problem, you should
assemble your program, then run the simulation to completion.
The built-in test will either report any discrepencies between the
expected and actual outputs, or, if your code is correct, it will
record the test passed.
{ "required_tests": ["-369169648"],
"initial_state": {
"beta.uasm": "url:../exercises/beta.uasm",
"checkoff.uasm": "url:../exercises/illop/checkoff.uasm"
},
"state":{
"LDB_STB":".include \u0022beta.uasm\u0022\n.include \u0022checkoff.uasm\u0022\n\nUI:\n ... your assembly language code here ...\n"
}
}
Instructions
The goal of this lab is to add support for two new instructions to
the Beta. But instead of adding hardware, we'll support the
instructions in software (!) by writing the appropriate emulation code
in the handler for "illegal instruction" exceptions.
The new instructions implement load and store operations for byte
(8-bit) data:
LDB |
Usage: | LDB(Ra, literal, Rc) |
Opcode: |
|
Operation: | PC <= PC+4
EA <= Reg[Ra] + SEXT(literal)
MDATA <= Mem[EA]
Reg[Rc]7:0 <= if EA1:0 = 0b00 then MDATA7:0
else if EA1:0 = 0b01 then MDATA15:8
else if EA1:0 = 0b10 then MDATA23:16
else if EA1:0 = 0b11 then MDATA31:24
Reg[Rc]31:8 <= 0x000000
|
The effective address EA is computed by adding
the contents of register Ra to the sign-extended 16-bit displacement
literal. The byte location in memory specified by EA is read into the
low-order 8 bits of register Rc; bits 31:8 of Rc are cleared.
|
STB |
Usage: | STB(Rc, literal, Ra) |
Opcode: |
|
Operation: | PC <= PC+4
EA <= Reg[Ra] + SEXT(literal)
MDATA <= Mem[EA]
if EA1:0 = 0b00 then MDATA7:0 <= Reg[Rc]7:0
if EA1:0 = 0b01 then MDATA15:8 <= Reg[Rc]7:0
if EA1:0 = 0b10 then MDATA23:16 <= Reg[Rc]7:0
if EA1:0 = 0b11 then MDATA31:24 <= Reg[Rc]7:0
Mem[EA] <= MDATA
|
The effective address EA is computed by adding
the contents of register Ra to the sign-extended 16-bit displacement
literal. The low-order 8-bits of register Rc are written into the
byte location in memory specified by EA. The other bytes of the
memory word remain unchanged.
|
When the Beta hardware, which doesn't know about these
instructions, detects either of the two opcodes above, it will cause
an "illegal instruction" exception (see section 6.4 of the Beta
documentation) and set the PC to 4.
The checkoff code has loaded location 4 with BR(UI) that
branches to an assembly language routine labeled UI which handles
illegal instructions -- this is the routine that you need to write. It
should do the following:
- Determine if the opcode for the illegal instruction is for LDB
or STB. The address of the instruction after the illegal instruction
has been loaded into register XP by the hardware (i.e., the illegal
instruction is at memory address Reg[XP]-4).
- If the illegal instruction is not LDB
or STB, your routine should branch to the label
_IllegalInstruction -- note the leading underscore. Before branching,
the contents of all the registers should be the same as they were when
your routine was entered. So you should save and restore any
registers you use in Step 1.
- If the illegal instruction is LDB or STB,
your routine should perform the appropriate memory and register
accesses to emulate the operation of these instructions. Your routine
will have to decode the instruction at Reg[XP]-4 to determine what
registers and memory locations to use.
Note:For this assignment, assume that kernel-mode MMU context
and the user-mode MMU context are the same, i.e., that the kernel can
access user-mode virtual addresses without first having to perform
a virtual-to-physical address translation. So LD and ST instructions
in your emulation code that access user-mode memory can simply use
the addresses derived from the contents of user-mode registers.
- When your emulation is complete, return control to the
interrupted program at the instruction following the LDB or STB. The
contents of all the registers should be the same as they were when
your routine was entered, except for the register changed by LDB. So
you need to save and restore any registers you use in steps 1 and 3.
To test your code, we'll be using the BSim Beta simulator. In
order to interface properly with the checkoff code, your assembly
language program should follow the template below:
.include "beta.uasm"
.include "checkoff.uasm"
UI:
... your assembly language code here ...
checkoff.uasm contains the checkoff code for this
lab. When execution begins, it does the appropriate initialization
(setting SP to point to an area of memory used for the stack, etc.)
and then executes a small test program that includes LDB and STB
instructions that test your emulation routine. The program will type
out messages as it executes, reporting any errors it detects. When it
types "Checkoff tests completed successfully!", you'll receive credit
for completing this problem.
To help you get started here's an example illegal instruction
handler that emulates a new instruction swapreg(RA,RC) which
interchanges the values in registers RA and RC.
This example utilizes some useful macros (defined in beta.uasm)
for saving/restoring registers and extracting bit fields from a 32-bit
word.
.include "beta.uasm"
// Handler for opcode 1 extension:
// swapreg(RA,RC) swaps the contents of the two named registers.
// UASM defn = .macro swapreg(RA,RC) betaopc(0x01,RA,0,RC)
regs:
RESERVE(32) // Array used to store register contents
UI:
save_all_regs(regs)
LD(xp,-4,r0) // illegal instruction
extract_field(r0,31,26,r1) // extract opcode, bits 31:26
CMPEQC(r1,0x1,r2) // OPCODE=1?
BT(r2, swapreg) // yes, handle the swapreg instruction.
LD(r31,regs,r0) // Its something else. Restore regs
LD(r31,regs+4,r1) // we've used, and go to the system's
LD(r31,regs+8,r2) // Illegal Instruction handler.
BR(_IllegalInstruction)
swapreg:
extract_field(r0,25,21,r1) // extract rc field from trapped instruction
MULC(r1, 4, r1) // convert to byte offset into regs array
extract_field(r0,20,16,r2) // extract ra field from trapped instruction
MULC(r2, 4, r2) // convert to byte offset into regs array
LD(r1, regs, r3) // r3 <- regs[rc]
LD(r2, regs, r4) // r4 <- regs[ra]
ST(r4, regs, r1) // regs[rc] <- old regs[ra]
ST(r3, regs, r2) // regs[ra] <- old regs[rc]
restore_all_regs(regs)
JMP(xp)
_IllegalInstruction:
// code to handle an actual illegal instruction goes here...
// for this lab this code is supplied by checkoff.uasm
HALT()
c8acc3e54bd241b2634e7925