Skip to content

Commit

Permalink
Added non-jal subroutine call detection in SV.
Browse files Browse the repository at this point in the history
Until now only jal instructions were used to detect subroutine calls.
From now on, $ra updates and subsequent jump instructions will also
be detected as subroutine calls.
  • Loading branch information
gzachos committed Jan 30, 2021
1 parent 8e283c9 commit 4beb127
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 8 deletions.
38 changes: 30 additions & 8 deletions mars/tools/StackVisualizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ public class StackVisualizer extends AbstractMarsToolAndApplication {
*/
/** Register number of stack pointer (29) */
private final int SP_REG_NUMBER = RegisterFile.STACK_POINTER_REGISTER;
/** Register number of return address (31) */
private final int RA_REG_NUMBER = RegisterFile.getNumber("$ra");
/** Stack pointer's initial address/value */
private final int SP_INIT_ADDR = Memory.stackPointer;
private final Memory memInstance = Memory.getInstance();
Expand All @@ -136,6 +138,8 @@ public class StackVisualizer extends AbstractMarsToolAndApplication {
private String regNameToBeStoredInStack = null;
/** Name of the (subroutine) frame to be allocated in stack segment. */
private String frameNameToBeCreated = null;
/** Whether $ra was written/updated in the last instruction. */
private boolean raWrittenInPrevInstr = false;
/**
* Return Address Stack. Target addresses of jal instructions are pushed and
* then are popped and matched when jr instructions are encountered.
Expand Down Expand Up @@ -419,7 +423,7 @@ protected void initializePostGUI() {
@Override
public void actionPerformed(ActionEvent e) {
if (connectButton.isConnected()) {
restoreBackStepper(); // TODO We really need this?
restoreBackStepper();
} else {
/*
* User program should be recompiled (and executed) after
Expand Down Expand Up @@ -547,6 +551,7 @@ protected void addAsObserver() {
*/
addAsObserver(RegisterFile.getRegisters()[SP_REG_NUMBER]);
addAsObserver(Memory.textBaseAddress, Memory.textLimitAddress);
addAsObserver(RegisterFile.getRegisters()[RA_REG_NUMBER]);
}


Expand Down Expand Up @@ -579,7 +584,7 @@ else if (notice instanceof RegisterAccessNotice) {


private void processRegisterAccessNotice(RegisterAccessNotice notice) {
// Currently only $sp is observed
// Currently only $sp is observed ($ra also but not for stack modification ops)
// TODO: What about observing frame pointer?
if (notice.getAccessType() == AccessNotice.READ)
return;
Expand All @@ -597,6 +602,8 @@ private void processRegisterAccessNotice(RegisterAccessNotice notice) {
addNewTableRows(5);
}
table.repaint(); // Required for coloring $sp position during popping.
} else if (notice.getRegisterName().equals("$ra")) {
raWrittenInPrevInstr = true;
}
}

Expand Down Expand Up @@ -722,14 +729,16 @@ private void processTextMemoryUpdate(MemoryAccessNotice notice) {
// System.out.println();
regNameToBeStoredInStack = RegisterFile.getRegisters()[operands[I_RS_OPERAND_LIST_INDEX]].getName();
}
else if (isJumpInstruction(instrName) || isJumpAndLinkInstruction(instrName)) { // TODO handle jal equivalent?
else if (isJumpInstruction(instrName) || isJumpAndLinkInstruction(instrName)) {
int targetAdrress = stmnt.getOperand(J_ADDR_OPERAND_LIST_INDEX) * WORD_LENGTH_BYTES;
String targetLabel = addrToTextSymbol(targetAdrress);
if (isJumpAndLinkInstruction(instrName)) {
ras.add(stmnt.getAddress());
frameNameToBeCreated = targetLabel;
Integer count = activeFunctionCallStats.addCall(targetLabel);
frameNameToBeCreated += " (" + count + ")";
registerNewSubroutineCall(stmnt, targetLabel);
} else if (isJumpInstruction(instrName)) {
if (raWrittenInPrevInstr == true) {
raWrittenInPrevInstr = false;
registerNewSubroutineCall(stmnt, targetLabel);
}
}
if (targetLabel != null) {
if (debug) {
Expand Down Expand Up @@ -783,6 +792,19 @@ else if (isJumpRegInstruction(instrName)) {
}


/**
* Update {@code ras}, {@code activeFunctionCallStats} and {@code frameNameToBeCreated}
* as of a new subroutine call.
* @param stmnt the jump/jal instruction statement that invokes the new subroutine call.
* @param targetLabel the name/label of the new subroutine that is called.
*/
private void registerNewSubroutineCall(ProgramStatement stmnt, String targetLabel) {
ras.add(stmnt.getAddress());
Integer count = activeFunctionCallStats.addCall(targetLabel);
frameNameToBeCreated = targetLabel + " (" + count + ")";
}


/**
* @param instrName instruction name.
*
Expand Down Expand Up @@ -1036,7 +1058,7 @@ private void onSimulationStart() {
if (!isObserving())
return;
// System.err.println("SIMULATION - END: " + inSteppedExecution());
if (VenusUI.getReset()) { // TODO verify
if (VenusUI.getReset()) {
ras.clear();
activeFunctionCallStats.reset();
resetStoredRegAndFrameNameColumns(0, numberOfRows-1);
Expand Down
124 changes: 124 additions & 0 deletions tests/lab03_solution-gzz-laj.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Calculate the product of data elements of a list
for MYΥ-505 - Computer Architecture
# Department of Computer Engineering, University of Ioannina
# Aris Efthymiou

# Same as lab03_solution-gzz.asm but jal instructions are replaced by la and j.

.globl mulproc, listProd # declare the label main as global.

###############################################################################
# Data input.
###############################################################################
.data
# Leaving a 2 word (= 1 list node) offset so that the address of n1_d isn't 0x0 (null pointer)
# in "Compact, Data at Address 0" memory configuration.
offset_d: .word 0x7777
offset_n: .word 0x7777

# 1st item - head of the list!
n1_d: .word 1
n1_n: .word n2_d # point to (beginning of) n2

# 3rd item
n3_d: .word 3
n3_n: .word n4_d

# 2nd item
n2_d: .word 2
n2_n: .word n3_d

# 5th item
n5_d: .word 5
n5_n: .word 0 # This is the last iterm in the list

# 4th item
n4_d: .word 4
n4_n: .word n5_d

# Alternative head of list. Value 0 to test mult by 0
na_d: .word 0
na_n: .word n2_d # point to (beginning of) n2

.text
# These are for providing input and testing, don't change in your
# final submission
la $a0, n1_d
la $ra, t1
j listProd
t1:
addu $s0, $v0, $zero # Move the result to s0
# Try it with a null pointer
addu $a0, $zero, $zero
la $ra, t2
j listProd
t2:
addu $s1, $v0, $zero # Move the result to s1
# Try it with 1 item list
la $a0, n5_d
la $ra, t3
j listProd
t3:
addu $s2, $v0, $zero # Move the result to s2
# ----- Try mult by 0
la $a0, na_d
la $ra, t4
j listProd
t4:
addu $s3, $v0, $zero # Move the result to s3


addiu $v0, $zero, 10 # system service 10 is exit
syscall # we are outta here.
########################################################################
# Write your code here. Leave main as is.
########################################################################

# Only works for unsigned numbers
mulproc:
addiu $sp, $sp, -12
sw $ra, 0x8($sp)
sw $a0, 0x4($sp)
sw $a1, 0x0($sp)
addu $v0, $zero, $zero # result = 0
sltu $t0, $a0, $a1
bne $t0, $zero, loop_mult
# swap by xor
xor $a0, $a0, $a1
xor $a1, $a1, $a0
xor $a0, $a0, $a1
# now a0 < a1
loop_mult:
beq $a0, $zero, leave_mult
addu $v0, $v0, $a1
addiu $a0, $a0, -1
j loop_mult
leave_mult:
lw $a1, 0x0($sp)
lw $a0, 0x4($sp)
lw $ra, 0x8($sp)
addiu $sp, $sp, 12
jr $ra # return


listProd:
addiu $sp, $sp, -8
sw $ra, 0x4($sp)
sw $a0, 0x0($sp)
addiu $v0, $zero, 1
beq $a0, $zero, leave_listProd
lw $a0, 4($a0) # get next address
la $ra, t5
j listProd
t5:
addu $a1, $v0, $zero # move result into a1
lw $a0, 0x0($sp) # get my original parameter
lw $a0, 0($a0) # get data
la $ra, leave_listProd
j mulproc
leave_listProd:
lw $ra, 0x4($sp)
addiu $sp, $sp, 8
jr $ra


0 comments on commit 4beb127

Please sign in to comment.