Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for relocatable data words #20

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/main/kotlin/venus/assembler/Assembler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,20 @@ internal class AssemblerPassOne(private val text: String) {

".word" -> {
for (arg in args) {
val word = userStringToInt(arg)
prog.addToData(word.toByte())
prog.addToData((word shr 8).toByte())
prog.addToData((word shr 16).toByte())
prog.addToData((word shr 24).toByte())
try {
val word = userStringToInt(arg)
prog.addToData(word.toByte())
prog.addToData((word shr 8).toByte())
prog.addToData((word shr 16).toByte())
prog.addToData((word shr 24).toByte())
} catch (e: NumberFormatException) {
/* arg is not a number; interpret as label */
prog.addDataRelocation(arg, currentDataOffset - MemorySegments.STATIC_BEGIN)
prog.addToData(0)
prog.addToData(0)
prog.addToData(0)
prog.addToData(0)
}
currentDataOffset += 4
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/main/kotlin/venus/linker/Linker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ import venus.riscv.insts.dsl.relocators.Relocator
*/
data class RelocationInfo(val relocator: Relocator, val offset: Int, val label: String)

/**
* Describes how to relocate data bytes
*
* @param offset the byte offset in the data segment
* @param label the target label
*/
data class DataRelocationInfo(val offset: Int, val label: String)

/**
* A singleton which links a list of programs into one program.
*
Expand All @@ -39,6 +47,7 @@ object Linker {
val linkedProgram = LinkedProgram()
val globalTable = HashMap<String, Int>()
val toRelocate = ArrayList<RelocationInfo>()
val toRelocateData = ArrayList<DataRelocationInfo>()
var textTotalOffset = 0
var dataTotalOffset = 0

Expand Down Expand Up @@ -81,6 +90,20 @@ object Linker {
}
}

for ((offset, label) in prog.dataRelocationTable) {
val toAddress = prog.labels.get(label)
val location = dataTotalOffset + offset
if (toAddress != null) {
linkedProgram.prog.overwriteData(location, toAddress.toByte())
linkedProgram.prog.overwriteData(location + 1, (toAddress shr 8).toByte())
linkedProgram.prog.overwriteData(location + 2, (toAddress shr 16).toByte())
linkedProgram.prog.overwriteData(location + 3, (toAddress shr 24).toByte())
} else {
/* need to relocate globally */
toRelocateData.add(DataRelocationInfo(location, label))
}
}

textTotalOffset += prog.textSize
dataTotalOffset += prog.dataSize
}
Expand All @@ -93,6 +116,15 @@ object Linker {
relocator(mcode, offset, toAddress)
}

for ((location, label) in toRelocateData) {
val toAddress = globalTable.get(label) ?:
throw AssemblerError("label $label used but not defined")
linkedProgram.prog.overwriteData(location, toAddress.toByte())
linkedProgram.prog.overwriteData(location + 1, (toAddress shr 8).toByte())
linkedProgram.prog.overwriteData(location + 2, (toAddress shr 16).toByte())
linkedProgram.prog.overwriteData(location + 3, (toAddress shr 24).toByte())
}

return linkedProgram
}
}
21 changes: 21 additions & 0 deletions src/main/kotlin/venus/riscv/Program.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package venus.riscv

import venus.assembler.DebugInfo
import venus.linker.DataRelocationInfo
import venus.linker.RelocationInfo
import venus.riscv.insts.dsl.relocators.Relocator

Expand All @@ -17,6 +18,7 @@ class Program(val name: String = "anonymous") {
val debugInfo = ArrayList<DebugInfo>()
val labels = HashMap<String, Int>()
val relocationTable = ArrayList<RelocationInfo>()
val dataRelocationTable = ArrayList<DataRelocationInfo>()
val dataSegment = ArrayList<Byte>()
var textSize = 0
var dataSize = 0
Expand All @@ -42,6 +44,16 @@ class Program(val name: String = "anonymous") {
dataSize++
}

/**
* Overwrites a byte of data in the program's data segment
*
* @param offset the offset at which to overwrite
* @param byte the value to overwrite with
*/
fun overwriteData(offset: Int, byte: Byte) {
dataSegment[offset] = byte
}

/**
* Adds debug info to the instruction currently being assembled.
*
Expand Down Expand Up @@ -86,6 +98,15 @@ class Program(val name: String = "anonymous") {
fun addRelocation(relocator: Relocator, label: String, offset: Int = textSize) =
relocationTable.add(RelocationInfo(relocator, offset, label))

/**
* Adds a line to the data relocation table.
*
* @param label the label to relocate
* @param offset the byte offset the label is at (from the start of the data section)
*/
fun addDataRelocation(label: String, offset: Int = textSize) =
dataRelocationTable.add(DataRelocationInfo(offset, label))

/**
* Makes a label global.
*
Expand Down
42 changes: 42 additions & 0 deletions src/test/kotlin/assembler/LinkerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,46 @@ class LinkerTest {
assertTrue(true)
}
}

@Test fun dataRelocation() {
val (prog, _) = Assembler.assemble("""
.data
A:
.word 42
B:
.word A
.text
la x1, A
lw x2, B
lw x3, 0(x2)
""")
val linked = Linker.link(listOf(prog))
val sim = Simulator(linked)
sim.run()
assertEquals(sim.getReg(1), sim.getReg(2))
assertEquals(42, sim.getReg(3))
}

@Test fun dataRelocationAcrossFiles() {
val (prog1, _) = Assembler.assemble("""
.data
.globl A
.globl B
A:
.word 42
B:
.word A
""")
val (prog2, _) = Assembler.assemble("""
.text
la x1, A
lw x2, B
lw x3, 0(x2)
""")
val linked = Linker.link(listOf(prog1, prog2))
val sim = Simulator(linked)
sim.run()
assertEquals(sim.getReg(1), sim.getReg(2))
assertEquals(42, sim.getReg(3))
}
}