From 63c6ed89e2d339d2debb101626bf0a597e6922a7 Mon Sep 17 00:00:00 2001 From: Jeffrey Dong Date: Mon, 23 Feb 2015 04:22:20 -0800 Subject: [PATCH 1/6] Added proj1-2 starter files --- link-in/linker1.out | 17 ++ link-in/linker2.out | 38 ++++ link-in/linker3A.out | 14 ++ link-in/linker3B.out | 14 ++ link-out/ref/output1_ref | 6 + link-out/ref/output2_ref | 27 +++ link-out/ref/output3_ref | 13 ++ linker | 1 + linker-src/file_utils.s | 91 +++++++++ linker-src/linker.s | 321 +++++++++++++++++++++++++++++++ linker-src/linker_utils.s | 273 ++++++++++++++++++++++++++ linker-src/parsetools.s | 187 ++++++++++++++++++ linker-src/string.s | 127 ++++++++++++ linker-src/symbol_list.s | 235 ++++++++++++++++++++++ linker-tests/test_core.s | 117 +++++++++++ linker-tests/test_linker_utils.s | 138 +++++++++++++ linker-tests/test_parsetools.s | 62 ++++++ linker-tests/test_string.s | 126 ++++++++++++ linker-tests/test_symbol_list.s | 105 ++++++++++ 19 files changed, 1912 insertions(+) create mode 100755 link-in/linker1.out create mode 100755 link-in/linker2.out create mode 100755 link-in/linker3A.out create mode 100755 link-in/linker3B.out create mode 100755 link-out/ref/output1_ref create mode 100755 link-out/ref/output2_ref create mode 100755 link-out/ref/output3_ref create mode 100755 linker create mode 100755 linker-src/file_utils.s create mode 100755 linker-src/linker.s create mode 100755 linker-src/linker_utils.s create mode 100755 linker-src/parsetools.s create mode 100755 linker-src/string.s create mode 100755 linker-src/symbol_list.s create mode 100755 linker-tests/test_core.s create mode 100755 linker-tests/test_linker_utils.s create mode 100755 linker-tests/test_parsetools.s create mode 100755 linker-tests/test_string.s create mode 100755 linker-tests/test_symbol_list.s diff --git a/link-in/linker1.out b/link-in/linker1.out new file mode 100755 index 0000000..be1be79 --- /dev/null +++ b/link-in/linker1.out @@ -0,0 +1,17 @@ +.text +1109ffff +1509fffe +08000000 +1509fffe +0c000000 +1109fffa + +.symbol +0 label1 +0 label2 +8 label3 +16 label4 + +.relocation +8 label2 +16 label1 diff --git a/link-in/linker2.out b/link-in/linker2.out new file mode 100755 index 0000000..3b4b01a --- /dev/null +++ b/link-in/linker2.out @@ -0,0 +1,38 @@ +.text +24040abc +2405000a +0c000000 +3c01000a +3422bcde +24080000 +11050012 +00884821 +812a0000 +924bfffd +254a0001 +00a72025 +24080003 +0128302a +0128302b +000a5fc0 +354b0123 +3c0b0214 +a12a0000 +ad2a8000 +8d2b7fff +016a082a +1420ffee +25290001 +08000000 +03e00008 +1564ffea + +.symbol +20 myFunc +24 startLoop +64 random +100 endLoop + +.relocation +8 myFunc +96 startLoop diff --git a/link-in/linker3A.out b/link-in/linker3A.out new file mode 100755 index 0000000..38370fe --- /dev/null +++ b/link-in/linker3A.out @@ -0,0 +1,14 @@ +.text +8fa40000 +0c000000 +244b0000 +03e00008 +3c01abcd +34221234 +03e00008 + +.symbol +16 func3 + +.relocation +4 func2 diff --git a/link-in/linker3B.out b/link-in/linker3B.out new file mode 100755 index 0000000..305ba7e --- /dev/null +++ b/link-in/linker3B.out @@ -0,0 +1,14 @@ +.text +000420c0 +0085082a +14200002 +0c000000 +2442ffff +03e00008 + +.symbol +0 func2 +20 done + +.relocation +12 func3 diff --git a/link-out/ref/output1_ref b/link-out/ref/output1_ref new file mode 100755 index 0000000..00e412a --- /dev/null +++ b/link-out/ref/output1_ref @@ -0,0 +1,6 @@ +1109ffff +1509fffe +08100000 +1509fffe +0c100000 +1109fffa diff --git a/link-out/ref/output2_ref b/link-out/ref/output2_ref new file mode 100755 index 0000000..bce15e5 --- /dev/null +++ b/link-out/ref/output2_ref @@ -0,0 +1,27 @@ +24040abc +2405000a +0c100005 +3c01000a +3422bcde +24080000 +11050012 +00884821 +812a0000 +924bfffd +254a0001 +00a72025 +24080003 +0128302a +0128302b +000a5fc0 +354b0123 +3c0b0214 +a12a0000 +ad2a8000 +8d2b7fff +016a082a +1420ffee +25290001 +08100006 +03e00008 +1564ffea diff --git a/link-out/ref/output3_ref b/link-out/ref/output3_ref new file mode 100755 index 0000000..9b08068 --- /dev/null +++ b/link-out/ref/output3_ref @@ -0,0 +1,13 @@ +8fa40000 +0c100007 +244b0000 +03e00008 +3c01abcd +34221234 +03e00008 +000420c0 +0085082a +14200002 +0c100004 +2442ffff +03e00008 diff --git a/linker b/linker new file mode 100755 index 0000000..9aa384e --- /dev/null +++ b/linker @@ -0,0 +1 @@ +mars nc sm linker-src/linker.s pa $@ diff --git a/linker-src/file_utils.s b/linker-src/file_utils.s new file mode 100755 index 0000000..28862aa --- /dev/null +++ b/linker-src/file_utils.s @@ -0,0 +1,91 @@ +# CS 61C Spring 2015 Project 1-2 +# file_utils.s +# +# Utilities for opening and closing files + +.data +cannot_open_files: .asciiz "Error opening files. Exiting program.\n" + +.text +#------------------------------------------------------------------------------ +# function open_files() +#------------------------------------------------------------------------------ +# Given an array of filenames, opens each file. If a file cannot be opened, exits +# the program. +# +# Arguments: +# $a0 = an array filename strings +# $a1 = length of the array +# +# Returns: an array of file pointers corresponding to the filenames +#------------------------------------------------------------------------------ +open_files: + addiu $sp, $sp, -12 # Begin open_files() + sw $s0, 8($sp) + sw $s1, 4($sp) + sw $ra, 0($sp) + move $s0, $a0 # $s0 = file array + move $s1, $a1 # $s1 = number of items + # Alloc space for array: + sll $a0, $a1, 2 # $a0 = # bytes needed for array + li $v0, 9 + syscall + move $v1, $v0 # $v1 = array of file ptrs + # Setup flags + li $a1, 0 # flag = read only + li $t0, 0 # $t0 = counter +open_files_begin: + beq $t0, $s1, open_files_done + sll $t1, $t0, 2 # offset in bytes + addu $t2, $s0, $t1 # compute current filename loc + lw $a0, 0($t2) + li $v0, 13 + syscall # open input file + blt $v0, 0, open_files_err + addu $t3, $v1, $t1 # compute current file ptr loc + sw $v0, 0($t3) # store file descriptor in array + addiu $t0, $t0, 1 + j open_files_begin +open_files_done: + move $v0, $v1 # $v0 = file descriptors + lw $s0, 8($sp) + lw $s1, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 12 + jr $ra +open_files_err: + # Error file input failed + move $a0, $v1 # $a0 = file descriptor array + move $a1, $t0 # $a1 = number of files currently open + jal close_files + la $a0, cannot_open_files + li $v0, 4 + syscall + li $a0, 1 + li $v0, 17 # exit program + syscall # End open_files() + +#------------------------------------------------------------------------------ +# function close_files() +#------------------------------------------------------------------------------ +# Given an array of file pointers, closes all files +# +# Arguments: +# $a0 = an array of file pointers +# $a1 = length of the array +# +# Returns: none +#------------------------------------------------------------------------------ +close_files: + move $t0, $a0 # Begin open_files() + sll $a1, $a1, 2 + li $t1, 0 # $t1 = counter +cf_begin: slt $t2, $t1, $a1 # $a1 = loop end condition (in bytes) + beq $t2, $0, cf_end + addu $t3, $t0, $t1 + lw $a0, 0($t3) # load file descriptor + li $v0, 16 + syscall # close file + addiu $t1, $t1, 4 + j cf_begin +cf_end: jr $ra # End close_files() diff --git a/linker-src/linker.s b/linker-src/linker.s new file mode 100755 index 0000000..1404ae1 --- /dev/null +++ b/linker-src/linker.s @@ -0,0 +1,321 @@ +# CS 61C Spring 2015 Project 1-2 +# linker.s + +#============================================================================== +# Project 1-2 Part 4 +# Linker README +#============================================================================== +# In this file you will be implementing the write_machine_code() function, +# which will copy machine code from an object file into the final executable. +# +# Please read the README in linker_utils.s before proceeding. The function you +# are implementing performs the actual write operation, copying the .text +# section from an object file to the final executable. +# +# When you complete this function, your linker should be able to link object +# files! +#============================================================================== + +.include "linker_utils.s" +.include "file_utils.s" + +.data +base_addr: .word 0x00400000 +hex_buffer: .space 10 + +.globl main +.text +#------------------------------------------------------------------------------ +# function write_machine_code() +#------------------------------------------------------------------------------ +# Write the contents of the .text section of the input file to the output file. +# Fill in the blanks labeled YOUR_INSTRUCTIONS_HERE according to the descriptions +# above. Each blank may require one or more MIPS instructions, but no blank +# requires a lot of instructions (the maximum we used for one blank is 6). +# There are seven such blanks in total. +# +# Note: You may need to store additional registers onto the stack. You should +# change stack poineter appropriately. +# +# Arguments: +# $a0 = The output file pointer +# $a1 = The input file pointer +# $a2 = The symbol table, which you can pass into relocate_inst() if needed +# $a3 = The relocation table, which you can pass into relocate_inst() if needed +# +# Returns: 0 on success and -1 on fail. +#------------------------------------------------------------------------------ +write_machine_code: + # You may need to save additional items onto the stack. Feel free to + # change this part. + addiu $sp, $sp, -24 + sw $s0, 20($sp) + sw $s1, 16($sp) + sw $s2, 12($sp) + sw $s3, 8($sp) + sw $s4, 4($sp) + sw $ra, 0($sp) + # We'll save the arguments since we are making function calls. + move $s0, $a0 # $s0 = output file ptr + move $s1, $a1 # $s1 = input file ptr + move $s2, $a2 # $s2 = symbol table + move $s3, $a3 # $s3 = relocation table + # We find the start of the .text section by reading each line and + # checking to see if we find ".text". +write_machine_code_find_text: + move $a0, $s1 + jal readline + blt $v0, $0, write_machine_code_error # Invalid line reached + move $a0, $v1 + la $a1, textLabel + jal streq + bne $v0, $0, write_machine_code_find_text + # Now, we are at the start of the text section (ie. next time we call + # readline(), we will read in the first instruction). Fill in the + # blanks below with the correct instruction(s). + + # 1. Initialize the byte offset to zero. We will need this for any instructions + # that require relocation: + # YOUR_INSTRUCTIONS_HERE + +write_machine_code_next_inst: + # 2. Call readline() while passing in the correct arguments: + # YOUR_INSTRUCTIONS_HERE + + # Check whether readline() returned an error. + blt $v0, $0, write_machine_code_error + # Store whether end-of-file was reached into $s4. We will check this later. + move $s4, $v0 + # We check whether there are any characters besides the NUL terminator below. + lbu $t0, 0($v1) + beq $t0, $0, write_machine_code_done + + # 3. Looks like there is another instruction. Call parse_int() with base=16 + # to convert the instruction into a number, and store it into a register: + # YOUR_INSTRUCTIONS_HERE + + # 4. Check if the instruction needs relocation. If it does not, branch to + # the label write_machine_code_to_file: + # YOUR_INSTRUCTIONS_HERE + + # 5. Here we handle relocation. Call relocate_inst() with the appropriate + # arguments, and store the relocated instruction in the appropriate register: + # YOUR_INSTRUCTIONS_HERE + +write_machine_code_to_file: + # 6. Write the instruction into a string buffer via hex_to_str(): + # YOUR_INSTRUCTIONS_HERE + + # 7. Increment the byte offset by the appropriate amount: + # YOUR_INSTRUCTIONS_HERE + + # Here, we use the write to file syscall. WE specify the output file as $a0. + move $a0, $s0 + # Set $a1 = the buffer that we will write. + la $a1, hex_buffer + # Set $a2 = number of bytes to write. 8 digits + newline = 9 bytes + li $a2, 9 + li $v0, 15 + syscall + # Finally, we check whether end-of-file was reached. If not, keep going. + bne $s4, $0, write_machine_code_next_inst +write_machine_code_done: + li $v0, 0 + j write_machine_code_end +write_machine_code_error: + li $v0, -1 +write_machine_code_end: + # Don't forget to change this part if you saved more items onto the stack! + lw $s0, 20($sp) + lw $s1, 16($sp) + lw $s2, 12($sp) + lw $s3, 8($sp) + lw $s4, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 24 + jr $ra + +############################################################################### +# DO NOT MODIFY ANYTHING BELOW THIS POINT +############################################################################### + +#------------------------------------------------------------------------------ +# function build_tables() +#------------------------------------------------------------------------------ +# Build tables +# $a0 = input file arr, $a1 = input arr len, $a2 = global offset +# $v0 = symbol table, $v1 = reloc_data +#------------------------------------------------------------------------------ +build_tables: + addiu $sp, $sp, -32 # Begin build_tables() + sw $s0, 28($sp) + sw $s1, 24($sp) + sw $s2, 20($sp) + sw $s3, 16($sp) + sw $s4, 12($sp) + sw $s5, 8($sp) + sw $s6, 4($sp) + sw $ra, 0($sp) + # Store arguments: + move $s0, $a0 # $s0 = input file array + move $s1, $a1 # $s1 = number of files + move $s2, $a2 # $s2 = base offset + # Open files: + jal open_files + move $s3, $v0 # $s3 = file descriptors + # Alloc space for reloc_data + sll $a0, $s1, 3 # 8 * (# files) + li $v0, 9 + syscall + move $s4, $v0 # $s4 = array of reloc_data + # Loop through and build table: + li $s5, 0 # $s5 = counter + li $s6, 0 # $s6 = symbol table (empty) +build_tables_loop: + beq $s5, $s1, build_tables_end + + sll $t0, $s5, 2 + addu $t5, $s3, $t0 # $a0 = current file handle + lw $a0, 0($t5) + move $a1, $s6 # $a1 = current symobl table + sll $t1, $t0, 1 + addu $a2, $s4, $t1 # $a2 = current entry in reloc_data + move $a3, $s2 # $a3 = current global offset + jal fill_data + blt $v0, $0, build_tables_error + move $s6, $v1 # update symbol table + sll $t1, $s5, 3 + addu $t2, $s4, $t1 # current entry in reloc_data + lw $t3, 0($t2) + addu $s2, $s2, $t3 # update offset + addiu $s5, $s5, 1 # increment count + j build_tables_loop +build_tables_error: + move $a0, $s3 + move $a1, $s1 + jal close_files + la $a0, error_parsing + li $v0, 4 + syscall + li $a0, 1 + li $v0, 17 # exit on error + syscall +build_tables_end: + move $a0, $s3 + move $a1, $s1 + jal close_files + # Set return values + move $v0, $s6 # set symbol table + move $v1, $s4 # set reloc_data + # Stack stuff + lw $s0, 28($sp) + lw $s1, 24($sp) + lw $s2, 20($sp) + lw $s3, 16($sp) + lw $s4, 12($sp) + lw $s5, 8($sp) + lw $s6, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 32 + jr $ra # End build_tables() + + +#------------------------------------------------------------------------------ +# function main() +#------------------------------------------------------------------------------ +# argc = num args, argv = char** +#------------------------------------------------------------------------------ +main: bge $a0, 2, m_arg_ok + # Error not enough arguments + la $a0, error_args + li $v0, 4 + syscall + li $a0, 1 + li $v0, 17 + syscall # exit with error +m_arg_ok: + addiu $s0, $a0, -1 # $s0 = num inputs + move $s1, $a1 # $s1 = array of filenames + sll $t0, $s0, 2 + addu $t1, $s1, $t0 + lw $s2, 0($t1) # $s2 = output filename + + # Build symbol/reloc table: + move $a0, $s1 + move $a1, $s0 + la $t0, base_addr + lw $a2, 0($t0) + jal build_tables + move $s3, $v0 # $s3 = symbol table + move $s4, $v1 # $s4 = reloc_data + + # Open input & output files for writing: + move $a0, $s1 + move $a1, $s0 + jal open_files + move $s1, $v0 # $s1 = array of file ptrs + move $a0, $s2 + li $a1, 1 + li $v0, 13 + syscall # open output file + blt $v0, 0, m_fopen_error + move $s2, $v0 # $s2 = output file descriptor + + # Begin writing: + li $s5, 0 +m_write_loop: + beq $s5, $s0, m_write_done + move $a0, $s2 # $a0 = output file + sll $t0, $s5, 2 # sizeof(file_ptr) = 4 + addu $t1, $s1, $t0 + lw $a1, 0($t1) # $a1 = input file + move $a2, $s3 # $a2 = symbol table + sll $t0, $s5, 3 # sizeof(reloc_data) = 8 + addu $t2, $s4, $t0 + lw $a3, 4($t2) # $a3 = reloc table + jal write_machine_code + blt $v0, $0, m_write_error + addiu $s5, $s5, 1 + j m_write_loop +m_write_done: + move $a0, $s1 + move $a1, $s0 + jal close_files + move $a0, $s2 + li $v0, 16 + syscall + la $a0, link_success + li $v0, 4 + syscall + li $v0, 10 + syscall # exit without errors +m_write_error: + move $a0, $s1 + move $a1, $s0 + jal close_files + move $a0, $s2 + li $v0, 16 + syscall + la $a0, error_write + li $v0, 4 + syscall + li $a0, 1 + li $v0, 17 + syscall # exit with errors +m_fopen_error: + move $a0, $s1 + move $a1, $s0 + jal close_files + la $a0, error_fopen + li $v0, 4 + syscall + li $a0, 1 + li $v0, 17 + syscall # exit with errors + +.data +error_args: .asciiz "Error not enough arguments. Exiting.\n" +error_parsing: .asciiz "Error parsing files. Exiting.\n" +error_fopen: .asciiz "Error opening output file. Exiting.\n" +error_write: .asciiz "Error during write. Exiting.\n" +link_success: .asciiz "Operation completed successfully.\n" diff --git a/linker-src/linker_utils.s b/linker-src/linker_utils.s new file mode 100755 index 0000000..164dfc2 --- /dev/null +++ b/linker-src/linker_utils.s @@ -0,0 +1,273 @@ +# CS 61C Spring 2015 Project 1-2 +# linker_utils.s + +#============================================================================== +# Project 1-2 Part 3b +# Linker Utils README +#============================================================================== +# Implement inst_needs_relocation() and relocate_inst(). +# +# It may be helpful to understand how our linker works first. Our linker first +# opens each file, reads, and stores the symbol and relocation data (found in +# the .symbol and .relocation section of each object file). During this pass +# it also computes the size of each text segment so that the final addresses of +# each symbol is known. The function fill_data(), located at the bottom of this +# file, performs this operation on a single file. The linker calls fill_data() +# on each object file. +# +# At this step, the symbol table contains the absolute address of every symbol +# as well as the relative byte offsets of each item that needs relocation (why +# is one absolute and the other relative?). The linker then copies the contents +# of each .text segment into the same executable. However, certain instructions +# need relocation. The inst_needs_relocation() function checks whether an +# instruction need relocation. If so, the relocate_inst() function will perform +# the relocation. +#============================================================================== + +.include "symbol_list.s" +.include "parsetools.s" + +.data +textLabel: .asciiz ".text" +symLabel: .asciiz ".symbol" +relocLabel: .asciiz ".relocation" + +.text + +#------------------------------------------------------------------------------ +# function inst_needs_relocation() +#------------------------------------------------------------------------------ +# Returns whether the given instruction needs relocation. +# +# Arguments: +# $a0 = 32-bit MIPS instruction +# +# Returns: 1 if the instruction needs relocation, 0 otherwise. +#------------------------------------------------------------------------------ +inst_needs_relocation: + # YOUR CODE HERE + jr $ra + +#------------------------------------------------------------------------------ +# function relocate_inst() +#------------------------------------------------------------------------------ +# Given an instruction that needs relocation, relocates the instruction based +# on the given symbol and relocation table. +# +# You should return error if 1) the addr is not in the relocation table or +# 2) the symbol name is not in the symbol table. You may assume otherwise the +# relocation will happen successfully. +# +# Arguments: +# $a0 = an instruction that needs relocating +# $a1 = the byte offset of the instruction in the current file +# $a2 = the symbol table +# $a3 = the relocation table +# +# Returns: the relocated instruction, or -1 if error +#------------------------------------------------------------------------------ +relocate_inst: + # YOUR CODE HERE + jr $ra + +############################################################################### +# DO NOT MODIFY ANYTHING BELOW THIS POINT +############################################################################### + +#------------------------------------------------------------------------------ +# function calc_text_size() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Returns number of bytes that the text section takes up. This function assumes +# that when called, the file pointer is currently at the beginning of the text +# section. It also assumes that there will be one instruction per line, and +# that the .text section ends with a blank line. +# +# Arguments: +# $a0 = file pointer, must be pointing to +# +# Returns: size of the text section in bytes +#------------------------------------------------------------------------------ +calc_text_size: + addiu $sp, $sp, -12 + sw $s0, 8($sp) + sw $s1, 4($sp) + sw $ra, 0($sp) + + li $s0, 0 # Initialize counter + move $s1, $a0 # store file handle into $s1 +calc_text_size_next: + move $a0, $s1 # $a0 = file handle + jal readline + blt $v0, $0, calc_text_size_error + lbu $t0, 0($v1) # $t0 = first character in buffer + beq $t0, $0, calc_text_size_done # Reached a line without instructions + addiu $s0, $s0, 4 # each instruction = 4 bytes + bne $v0, $0, calc_text_size_next # did not reached end of file +calc_text_size_done: + move $v0, $s0 + j calc_text_size_exit +calc_text_size_error: + li $v0, -1 +calc_text_size_exit: + lw $s0, 8($sp) + lw $s1, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 12 + jr $ra + +#------------------------------------------------------------------------------ +# function add_to_symbol_list() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Adds entries from the .symbol or .relocation section into the SymbolList. Each +# line must be of the format "\t\n", and the section ends with +# a blank line. The file pointer must be at the begining of the section (so the +# line immediately after .symbol or .relocation). Returns the status code in $v0 +# and the new SymbolList in $v1. +# +# Arguments: +# $a0 = file pointer +# $a1 = the SymbolList to add to (may or may not be empty) +# $a2 = base address offset +# +# Returns: $v0 = 0 if no errors, -1 if error +# $v1 = the new SymbolList +#------------------------------------------------------------------------------ +add_to_symbol_list: + addiu $sp, $sp, -20 + sw $s0, 16($sp) + sw $s1, 12($sp) + sw $s2, 8($sp) + sw $s3, 4($sp) + sw $ra, 0($sp) + + move $s0, $a0 # store file handle into $s0 + move $s1, $a1 # store symbol list into $s1 + move $s2, $a2 # store symbol offset into $s2 +atsl_next: + move $a0, $s0 # $a0 = file handle + jal readline + blt $v0, $0, atsl_error + + lbu $t0, 0($v1) # $t0 = first character in buffer + beq $t0, $0, atsl_done # Reached a line with only '\n' + move $s3, $v0 # store whether EOF was reached into $s3 + + move $a0, $v1 + jal tokenize + move $a0, $s1 # $a0 = symbol list + addu $a1, $s2, $v0 # $a1 = symbol offset (bytes) + move $a2, $v1 # $a2 = symbol name (string) + jal add_to_list + move $s1, $v0 + beq $s3, $0, atsl_done + j atsl_next +atsl_done: + li $v0, 0 + move $v1, $s1 + j atsl_end +atsl_error: + li $v0, -1 +atsl_end: + lw $s0, 16($sp) + lw $s1, 12($sp) + lw $s2, 8($sp) + sw $s3, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 20 + jr $ra + +#------------------------------------------------------------------------------ +# function fill_data() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Builds the symbol/relocation data for a single file. Calls calc_text_size() +# and add_to_symbol_list(). +# +# Arguments: +# $a0 = file handle +# $a1 = symbol table +# $a2 = ptr to an reloc_data struct +# $a3 = base offset +# +# The format of reloc_data (if it were declared in C) is: +# struct reloc_data { +# int text_size; +# SymbolList* list; +# } +# +# Returns: $v0 = 0 if no error, -1 if error +# $v1 = the new symbol table ($a2 should be updated) +#------------------------------------------------------------------------------ +fill_data: + addiu $sp, $sp, -28 + sw $s0, 24($sp) + sw $s1, 20($sp) + sw $s2, 16($sp) + sw $s3, 12($sp) + sw $s4, 8($sp) + sw $s5, 4($sp) + sw $ra, 0($sp) + + move $s0, $a0 # store file handle into $s0 + move $s1, $a1 # store symbol table into $s1 + move $s2, $a2 # store relocdata ptr into $s2 + move $s3, $a3 # store offset into $s3 +fill_data_next: + move $a0, $s0 # $a0 = file handle + jal readline + blt $v0, $0, fill_data_error + beq $v0, $0, fill_data_done + move $s4, $v1 # store read string into $s4 + + move $a0, $s4 # Test if reached .text section + la $a1, textLabel + jal streq + beq $v0, $0, fill_data_text_size + + move $a0, $s4 # Test if reached .symbol section + la $a1, symLabel + jal streq + beq $v0, $0, fill_data_symbol + + move $a0, $s4 # Test if reached .relocation section + la $a1, relocLabel + jal streq + beq $v0, $0, fill_data_reloc + + j fill_data_next +fill_data_text_size: + move $a0, $s0 + jal calc_text_size + sw $v0, 0($s2) + j fill_data_next +fill_data_symbol: + move $a0, $s0 + move $a1, $s1 + move $a2, $s3 + jal add_to_symbol_list + bne $v0, $0, fill_data_error + move $s5, $v1 + j fill_data_next +fill_data_reloc: + move $a0, $s0 + lw $a1, 4($s2) + li $a2, 0 + jal add_to_symbol_list + bne $v0, $0, fill_data_error + sw $v1, 4($s2) + j fill_data_next +fill_data_error: + li $v0, -1 + j fill_data_end +fill_data_done: + li $v0, 0 +fill_data_end: + move $v1, $s5 + lw $s0, 24($sp) + lw $s1, 20($sp) + lw $s2, 16($sp) + lw $s3, 12($sp) + lw $s4, 8($sp) + lw $s5, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 28 + jr $ra diff --git a/linker-src/parsetools.s b/linker-src/parsetools.s new file mode 100755 index 0000000..a122fe6 --- /dev/null +++ b/linker-src/parsetools.s @@ -0,0 +1,187 @@ +# CS 61C Spring 2015 Project 1-2 +# parsetools.s + +#============================================================================== +# Project 1-2 Part 3a +# parsetools.s README +#============================================================================== +# Implement hex_to_str() only. Do not modify any other functions. +#============================================================================== + +.text + +#------------------------------------------------------------------------------ +# function hex_to_str() +#------------------------------------------------------------------------------ +# Writes a 32-bit number in hexadecimal format to a string buffer, followed by +# the newline character and the NUL-terminator. The output must contain 8 digits +# so if neccessary put leading 0s in the buffer. Therefore, you should always +# be writing 10 characters (8 digits, 1 newline, 1 NUL-terminator). +# +# For example: +# 0xabcd1234 => "abcd1234\n\0" +# 0x134565FF => "134565ff\n\0" +# 0x38 => "00000038\n\0" +# +# Write hex letters using lowercase, not uppercase. Do not add the prefix '0x'. +# +# Hint: Consider each group of 4 bits at a time and look at an ASCII table. If +# you code has more than a few branch statements, you are probably not doing +# things very efficiently. +# +# Arguments: +# $a0 = int to write +# $a1 = character buffer to write into +# +# Returns: none +#------------------------------------------------------------------------------ +hex_to_str: + # YOUR CODE HERE + jr $ra + +############################################################################### +# DO NOT MODIFY ANYTHING BELOW THIS POINT +############################################################################### + +#------------------------------------------------------------------------------ +# function parse_int() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Parses the string as an unsigned integer. The only bases supported are 10 and +# 16. We will assume that the number is valid, and that overflow does not happen. +# +# Arguments: +# $a0 = string containing a number +# $a1 = base (will be either 10 or 16) +# +# Returns: the number +#------------------------------------------------------------------------------ +parse_int: + li $v0, 0 # Begin parse_int() + li $t1, 'A' + li $t2, 'F' +parse_int_loop: + lb $t0, 0($a0) + beq $t0, $0, parse_int_done + mul $v0, $v0, $a1 # multiply by the base + blt $t0, $t1, parse_int_dec + ble $t0, $t2, parse_int_hex_upper + # parse as lowercase hex: + addiu $t0, $t0, -87 # 'a' - 10 + j parse_int_common +parse_int_dec: + addiu $t0, $t0, -48 # 0 - '0' + j parse_int_common +parse_int_hex_upper: + addiu $t0, $t0, -55 # 'A' - 10 +parse_int_common: + addu $v0, $v0, $t0 + addiu $a0, $a0, 1 + j parse_int_loop +parse_int_done: + jr $ra # End parse_int() + +#------------------------------------------------------------------------------ +# function tokenize() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Converts a line of symbol/relocation table output into a numerical address +# and a name string, which can then be added into the appropriate SymbolList +# after you add the appropriate offset to the addr. Note that this function +# returns TWO values. This is just a shortcut to make the MIPS shorter. +# +# Arguments: +# $a0 = string containing a line from symbol/relocation table output +# +# Returns: $v0: the address of the symbol +# $v1: name of the string +#------------------------------------------------------------------------------ +tokenize: + addiu $sp, $sp, -20 # Begin tokenize() + sw $s0, 16($sp) + sw $s1, 12($sp) + sw $s2, 8($sp) + sw $s3, 4($sp) + sw $ra, 0($sp) + move $s0, $a0 # $s0 = start of string + li $s1, 0 # $s1 = offset from start + li $s2, 9 # $s2 = tab character +tokenize_loop: + addu $t0, $s0, $s1 + lb $t1, 0($t0) + beq $t1, $0, tokenize_fail + beq $t1, $s2, tokenize_done + addiu $s1, $s1, 1 + j tokenize_loop +tokenize_done: + sb $0, 0($t0) + li $a1, 10 + jal parse_int # $v0 = int result + addu $v1, $s0, $s1 + addiu $v1, $v1, 1 # $v1 = beginning of string +tokenize_fail: # fallthrough (we should never directly jump to here unless input is invalid) + lw $s0, 16($sp) + lw $s1, 12($sp) + lw $s2, 8($sp) + lw $s3, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 20 + jr $ra # End tokenize() + +#------------------------------------------------------------------------------ +# function readline() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Reads the next line from the file until a newline or end of file is reached. +# If a newline was reached, the last newline character is discarded. A NUL- +# terminator is added to the end of the string read. +# +# The buffer is returned in $v1. It is VOLATILE - the next time readline() is +# called, the buffer will be overwritten. This should be fine for most linker +# functions except for the symbol/relocation table (you will have to create a +# copy of the string then -- see add_to_list() in Part 2). +# +# Arguments: +# $a0 = File handle +# +# Returns: $v0: the # of bytes read, or -1 if error and nothing was read +# $v1: pointer to buffer with chars read +#------------------------------------------------------------------------------ +readline: + la $t0, buffer # Begin readline() + li $t1, 512 + la $a1, buffer + li $a2, 1 +readline_next: + li $v0, 14 # read until a newline is reached + syscall + beq $v0, $0, readline_done # only end-of-file is left, nothing was read + blt $v0, $0, readline_err # error, nothing was read + lbu $t2, 0($a1) + li $t3, 0x0a # newline char + beq $t2, $t3, readline_done + addiu $a1, $a1, 1 + subu $t4, $a1, $t0 + bgt $t4, $t1, readline_err2 + j readline_next +readline_done: # at this point, $v0 contains the # bytes read + sb $0, 0($a1) + move $v1, $t0 + jr $ra +readline_err: + la $a0, readline_err_syscall + li $v0, 4 + syscall + li $v0, -1 + jr $ra +readline_err2: + la $a0, readline_err_bufsize + li $v0, 4 + syscall + li $v0, -1 + jr $ra # End readline() + +.data +buffer: .space 1024 +.data +readline_err_syscall: + .asciiz "Error in readline: Could not read from file.\n" +readline_err_bufsize: + .asciiz "Error in readline: Exceeded maximum buffer size.\n" diff --git a/linker-src/string.s b/linker-src/string.s new file mode 100755 index 0000000..a23e3bd --- /dev/null +++ b/linker-src/string.s @@ -0,0 +1,127 @@ +# CS 61C Spring 2015 Project 1-2 +# string.s + +#============================================================================== +# Project 1-2 Part 1 +# String README +#============================================================================== +# In this file you will be implementing some utilities for manipulating strings. +# The functions you need to implement are: +# - strlen() +# - strncpy() +# - copy_of_str() +# Test cases are in linker-tests/test_string.s +#============================================================================== + +.data +newline: .asciiz "\n" +tab: .asciiz "\t" + +.text +#------------------------------------------------------------------------------ +# function strlen() +#------------------------------------------------------------------------------ +# Arguments: +# $a0 = string input +# +# Returns: the length of the string +#------------------------------------------------------------------------------ +strlen: + # YOUR CODE HERE + jr $ra + +#------------------------------------------------------------------------------ +# function strncpy() +#------------------------------------------------------------------------------ +# Arguments: +# $a0 = pointer to destination array +# $a1 = source string +# $a2 = number of characters to copy +# +# Returns: the destination array +#------------------------------------------------------------------------------ +strncpy: + # YOUR CODE HERE + jr $ra + +#------------------------------------------------------------------------------ +# function copy_of_str() +#------------------------------------------------------------------------------ +# Creates a copy of a string. You will need to use sbrk (syscall 9) to allocate +# space for the string. strlen() and strncpy() will be helpful for this function. +# In MARS, to malloc memory use the sbrk syscall (syscall 9). See help for details. +# +# Arguments: +# $a0 = string to copy +# +# Returns: pointer to the copy of the string +#------------------------------------------------------------------------------ +copy_of_str: + # YOUR CODE HERE + jr $ra + +############################################################################### +# DO NOT MODIFY ANYTHING BELOW THIS POINT +############################################################################### + +#------------------------------------------------------------------------------ +# function streq() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Arguments: +# $a0 = string 1 +# $a1 = string 2 +# +# Returns: 0 if string 1 and string 2 are equal, -1 if they are not equal +#------------------------------------------------------------------------------ +streq: + beq $a0, $0, streq_false # Begin streq() + beq $a1, $0, streq_false +streq_loop: + lb $t0, 0($a0) + lb $t1, 0($a1) + addiu $a0, $a0, 1 + addiu $a1, $a1, 1 + bne $t0, $t1, streq_false + beq $t0, $0, streq_true + j streq_loop +streq_true: + li $v0, 0 + jr $ra +streq_false: + li $v0, -1 + jr $ra # End streq() + +#------------------------------------------------------------------------------ +# function dec_to_str() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Convert a number to its unsigned decimal integer string representation, eg. +# 35 => "35", 1024 => "1024". +# +# Arguments: +# $a0 = int to write +# $a1 = character buffer to write into +# +# Returns: the number of digits written +#------------------------------------------------------------------------------ +dec_to_str: + li $t0, 10 # Begin dec_to_str() + li $v0, 0 +dec_to_str_largest_divisor: + div $a0, $t0 + mflo $t1 # Quotient + beq $t1, $0, dec_to_str_next + mul $t0, $t0, 10 + j dec_to_str_largest_divisor +dec_to_str_next: + mfhi $t2 # Remainder +dec_to_str_write: + div $t0, $t0, 10 # Largest divisible amount + div $t2, $t0 + mflo $t3 # extract digit to write + addiu $t3, $t3, 48 # convert num -> ASCII + sb $t3, 0($a1) + addiu $a1, $a1, 1 + addiu $v0, $v0, 1 + mfhi $t2 # setup for next round + bne $t2, $0, dec_to_str_write + jr $ra # End dec_to_str() diff --git a/linker-src/symbol_list.s b/linker-src/symbol_list.s new file mode 100755 index 0000000..55b133f --- /dev/null +++ b/linker-src/symbol_list.s @@ -0,0 +1,235 @@ +# CS 61C Spring 2015 Project 1-2 +# symbol_list.s + +#============================================================================== +# Project 1-2 Part 2 +# SymbolList README +#============================================================================== +# In this file you will be implementing a linked list-based data structure for +# storing symbols. Its purpose is analogous to SymbolTable from Proj1-1, but to +# disinguish it we will call it SymbolList. +# +# Each node in the SymbolList contains a (addr, name) pair. An empty SymbolList +# is simply a pointer to NULL. As (addr, name) pairs are added to a SymbolList, +# new list nodes are dynamically allocated and appended to the front of the list. +# However, as there is no free() in MARS, you do not need to write a free_list() +# function. You may use the functions in string.s during your implementation. +# +# You do not need to perform error checking on duplicate addr or name entries +# in SymbolList, nor do you need to do alignment checking. Don't worry about +# provided addresses being too big. +# +# If SymbolList were to be written in C, each list node would be declared as +# follows: +# typedef struct symbollist { +# int addr; +# char* name; +# struct symbollist* next; +# } SymbolList; +# +# You need to write addr_for_symbol() and add_to_list(). +# You will find test cases in linker-tests/test_symbol_list.s +#============================================================================== + +.include "string.s" + +.text + +#------------------------------------------------------------------------------ +# function addr_for_symbol() +#------------------------------------------------------------------------------ +# Iterates through the SymbolList and searches for an entry with the given name. +# If an entry is found, return that addr. Otherwise return -1. +# +# Arguments: +# $a0 = pointer to a SymbolList (NULL indicates empty list) +# $a1 = name to look for +# +# Returns: address of symbol if found or -1 if not found +#------------------------------------------------------------------------------ +addr_for_symbol: + # YOUR CODE HERE + jr $ra + +#------------------------------------------------------------------------------ +# function add_to_list() +#------------------------------------------------------------------------------ +# Adds a (name, addr) pair to the FRONT of the list. You should call new_node() +# to create a new node. You do not need to perform error checking on duplicate +# addr or name entries in SymbolList, nor do you need to do alignment checking. +# +# As with Project 1-1, you WILL need to create a copy of the string that was +# passed in. copy_of_str() from Part 1 will be useful. After new entry has been +# added to the list, return the new list. +# +# Arguments: +# $a0 = ptr to list (may be NULL) +# $a1 = address of symbol (integer) +# $a2 = pointer to name of symbol (string) +# +# Returns: the new list +#------------------------------------------------------------------------------ +add_to_list: + # YOUR CODE HERE + jr $ra + +############################################################################### +# DO NOT MODIFY ANYTHING BELOW THIS POINT +############################################################################### + +#------------------------------------------------------------------------------ +# function symbol_for_addr() +#------------------------------------------------------------------------------ +# Iterates through the SymbolList and searches for an entry with the given addr. +# If an entry is found, return a pointer to the name. Otherwise return NULL. +# +# Arguments: +# $a0 = pointer to a SymbolList (NULL indicates empty list) +# $a1 = addr to look for +# +# Returns: a pointer to the name if found or NULL if not found +#------------------------------------------------------------------------------ +symbol_for_addr: + beq $a0, $0, symbol_not_found # Begin symbol_for_addr + lw $t0, 0($a0) + beq $t0, $a1, symbol_found + lw $a0, 8($a0) + j symbol_for_addr +symbol_found: + lw $v0, 4($a0) + jr $ra +symbol_not_found: + li $v0, 0 + jr $ra # End addr_for_symbol + +#------------------------------------------------------------------------------ +# function print_list() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Arguments: +# $a0 = pointer to a SymbolList (NULL indicates empty list) +# $a1 = print function +# $a2 = file pointer +#------------------------------------------------------------------------------ +print_list: + addiu $sp, $sp, -16 # Begin print_list + sw $s0, 12($sp) + sw $s1, 8($sp) + sw $s2, 4($sp) + sw $ra, 0($sp) + move $s0, $a0 + move $s1, $a1 + move $s2, $a2 +print_list_loop: + beq $s0, $0, print_list_end + lw $a0, 0($s0) + lw $a1, 4($s0) + move $a2, $s2 + jalr $s1 + lw $s0, 8($s0) + j print_list_loop +print_list_end: + lw $s0, 12($sp) + lw $s1, 8($sp) + lw $s2, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 16 + jr $ra # End print_list + +#------------------------------------------------------------------------------ +# function print_symbol() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Prints one symbol to standard output. +# +# Arguments: +# $a0 = addr of symbol +# $a1 = name of symbol +# $a2 = file pointer (this argument is actually ignored) +# +# Returns: none +#------------------------------------------------------------------------------ +print_symbol: + li $v0, 36 # Begin print_symbol() + syscall + la $a0, tab + li $v0, 4 + syscall + move $a0, $a1 + syscall + la $a0, newline + syscall + jr $ra # End print_symbol() + +#------------------------------------------------------------------------------ +# function write_symbol() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Writes one symbol to the file specified +# +# Arguments: +# $a0 = addr of symbol +# $a1 = name of symbol +# $a2 = file pointer +# +# Returns: none +#------------------------------------------------------------------------------ +write_symbol: + addiu $sp, $sp, -20 # Begin write_symbol() + sw $s0, 16($sp) + sw $s1, 12($sp) + sw $a1, 8($sp) + sw $a2, 4($sp) + sw $ra, 0($sp) + + la $s0, temp_buf + + move $a1, $s0 + jal dec_to_str # write int + move $s1, $v0 + + addu $a0, $s0, $s1 + addiu $s1, $s1, 1 + la $a1, tab + li $a2, 1 + jal strncpy # write tab + + lw $a0, 8($sp) + jal strlen + + addu $a0, $s0, $s1 + addu $s1, $s1, $v0 + lw $a1, 8($sp) + move $a2, $v0 + jal strncpy # write string + + addu $a0, $s0, $s1 + addiu $s1, $s1, 1 + la $a1, newline + li $a2, 1 + jal strncpy # write newline + + lw $a0, 4($sp) # file ptr + move $a1, $s0 # buffer to write + move $a2, $s1 # num chars to write + li $v0, 15 + syscall # write to file + + lw $s0, 16($sp) + lw $s1, 12($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 20 + jr $ra # End write_symbol() + +#------------------------------------------------------------------------------ +# function new_node() - DO NOT MODIFY THIS FUNCTION +#------------------------------------------------------------------------------ +# Creates a new uninitialized SymbolList node. +# Arguments: none +# Returns: pointer to a SymbolList node +#------------------------------------------------------------------------------ +new_node: + li $a0, 12 # Begin new_node() + li $v0, 9 + syscall + jr $ra # End new_node() + +.data +temp_buf: .space 1024 diff --git a/linker-tests/test_core.s b/linker-tests/test_core.s new file mode 100755 index 0000000..f5b7ffa --- /dev/null +++ b/linker-tests/test_core.s @@ -0,0 +1,117 @@ +# CS 61C Spring 2015 Project 1-2 +# linker-tests/test_core.s +# +# Contains core testing utilities + +.data +nl_separator: .asciiz "\n" # to avoid naming conflicts + +tc_actual_str: .asciiz "actual: " +tc_expected_str: .asciiz " expected: " +tc_expected_str2: .asciiz "\nexpected: " +tc_testpass_str: .asciiz " ...test passes\n" +tc_testfail_str: .asciiz " ...test FAILS\n" + +#================================== +# Macros - EASY TO INTRODUCE BUGS WITH +# Be careful when using these +#================================== + +#------------------------------------------- +# Prints a newline +# CLOBBERS: $a0 and $v0 +#------------------------------------------- +.macro print_newline() + la $a0, nl_separator + li $v0, 4 + syscall +.end_macro + +#------------------------------------------- +# Prints the string +# %test_reg = label containing address of string +# CLOBBERS: $a0 and $v0 +#------------------------------------------- +.macro print_str(%str_label) + la $a0, %str_label + li $v0, 4 + syscall +.end_macro + +#------------------------------------------- +# Checks whether the actual result matches the expected result +# Treats arguments as signed ints +# %actual_reg = register containing actual result +# %expected_val = expected value of register +# CLOBBERS: $a0, $v0, and $t0 +#------------------------------------------- +.macro check_int_equals(%actual_reg, %expected_val) + move $t0, %actual_reg + print_str(tc_actual_str) + move $a0, $t0 + li $v0, 1 + syscall + print_str(tc_expected_str) + li $a0, %expected_val + li $v0, 1 + syscall + bne $t0, $a0, notequal + print_str(tc_testpass_str) + j end +notequal: + print_str(tc_testfail_str) +end: +.end_macro + +#------------------------------------------- +# Checks whether the actual result matches the expected result +# Treats arguments as unsigned ints +# %actual_reg = register containing actual result +# %expected_val = expected value of register +# CLOBBERS: $a0, $v0, and $t0 +#------------------------------------------- +.macro check_uint_equals(%actual_reg, %expected_val) + move $t0, %actual_reg + print_str(tc_actual_str) + move $a0, $t0 + li $v0, 36 + syscall + print_str(tc_expected_str) + li $a0, %expected_val + li $v0, 36 + syscall + bne $t0, $a0, notequal + print_str(tc_testpass_str) + j end +notequal: + print_str(tc_testfail_str) +end: +.end_macro + +#------------------------------------------- +# Checks whether the actual result matches the expected result +# Arguments should be strings +# %actual_reg = register containing actual result +# %expected_val = label to expected string +# CLOBBERS: $a0, $v0, and $t0 +#------------------------------------------- +.macro check_str_equals(%actual_reg, %expected_val) + move $t0, %actual_reg + print_str(tc_actual_str) + move $a0, $t0 + li $v0, 4 + syscall + print_str(tc_expected_str2) + print_str(%expected_val) + print_newline() + move $a0, $t0 + la $a1, %expected_val + jal streq + bne $v0, $0, notequal + print_str(tc_testpass_str) + j end +notequal: + print_str(tc_testfail_str) +end: + print_newline() +.end_macro diff --git a/linker-tests/test_linker_utils.s b/linker-tests/test_linker_utils.s new file mode 100755 index 0000000..b405aa8 --- /dev/null +++ b/linker-tests/test_linker_utils.s @@ -0,0 +1,138 @@ +# CS 61C Spring 2015 Project 1-2 +# linker-tests/test_linker_utils.s + +#============================================================================== +# linker_utils.s Test Cases +#============================================================================== + +.include "../linker-src/linker_utils.s" +.include "test_core.s" + +#------------------------------------------- +# Test Data - Feel free to add your own +#------------------------------------------- + +.data +# Test strings +test_label1: .asciiz "Label 1" +test_label2: .asciiz "Label 2" +test_label3: .asciiz "Label 3" +test_label4: .asciiz "Label 4" +test_label5: .asciiz "Label 5" +test_label6: .asciiz "Label 6" +test_label7: .asciiz "Label 7" +test_label8: .asciiz "Label 8" + +# Symbol Table +sym_7: .word 0xc test_label7 0 +sym_6: .word 0xf4 test_label6 sym_7 +sym_5: .word 0xabc test_label5 sym_6 +sym_4: .word 0x24 test_label4 sym_5 +sym_3: .word 0xa8 test_label3 sym_4 +sym_2: .word 0x0aaaaaac test_label2 sym_3 +sym_tbl: .word 0x0ababab0 test_label1 sym_2 + +# Relocation Table +rel_5: .word 40 test_label5 0 +rel_4: .word 100 test_label8 rel_5 +rel_3: .word 128 test_label2 rel_4 +rel_2: .word 32 test_label1 rel_3 +rel_tbl: .word 24 test_label3 rel_2 + +.globl main +.text +#------------------------------------------- +# Test driver +#------------------------------------------- +main: + print_str(test_header_name) + + print_newline() + jal test_inst_needs_relocation + + print_newline() + jal test_relocate_inst + + li $v0, 10 + syscall + +#------------------------------------------- +# Tests inst_needs_relocation() from linker_utils.s +#------------------------------------------- +test_inst_needs_relocation: + addiu $sp, $sp, -4 + sw $ra, 0($sp) + print_str(test_inst_needs_relocation_name) + + li $a0, 0x0c001234 + jal inst_needs_relocation + check_int_equals($v0, 1) + + li $a0, 0x08100010 + jal inst_needs_relocation + check_int_equals($v0, 1) + + li $a0, 0x09100010 + jal inst_needs_relocation + check_int_equals($v0, 1) + + li $a0, 0x2a00c0f0 + jal inst_needs_relocation + check_int_equals($v0, 0) + + li $a0, 0x0 + jal inst_needs_relocation + check_int_equals($v0, 0) + + lw $ra, 0($sp) + addiu $sp, $sp, 4 + jr $ra + +#------------------------------------------- +# Tests calc_relocate_inst() from linker_utils.s +#------------------------------------------- +test_relocate_inst: + addiu $sp, $sp, -4 + sw $ra, 0($sp) + print_str(test_relocate_inst_name) + + la $a0, 0x0c001234 + li $a1, 40 + la $a2, sym_tbl + la $a3, rel_tbl + jal relocate_inst + check_uint_equals($v0, 0x0c0002af) + + la $a0, 0x09100010 + li $a1, 32 + la $a2, sym_tbl + la $a3, rel_tbl + jal relocate_inst + check_uint_equals($v0, 0x0aaeaeac) + + # Not in symbol table + la $a0, 0x0c001234 + li $a1, 100 + la $a2, sym_tbl + la $a3, rel_tbl + jal relocate_inst + check_int_equals($v0, -1) + + # Not in reloc table + la $a0, 0x0c001234 + li $a1, 200 + la $a2, sym_tbl + la $a3, rel_tbl + jal relocate_inst + check_int_equals($v0, -1) + + lw $ra, 0($sp) + addiu $sp, $sp, 4 + jr $ra + + +.data +test_header_name: .asciiz "Running test linker_utils:\n" + +test_inst_needs_relocation_name: .asciiz "Testing inst_needs_relocation():\n" +test_relocate_inst_name: .asciiz "Testing relocate_inst():\n" diff --git a/linker-tests/test_parsetools.s b/linker-tests/test_parsetools.s new file mode 100755 index 0000000..f3092e3 --- /dev/null +++ b/linker-tests/test_parsetools.s @@ -0,0 +1,62 @@ +# CS 61C Spring 2015 Project 1-2 +# linker-tests/test_parsetools.s + +#============================================================================== +# parsetools.s Test Cases +#============================================================================== + +.include "../linker-src/parsetools.s" +.include "test_core.s" +.include "../linker-src/string.s" + +#------------------------------------------- +# Test Data - Feel free to add your own +#------------------------------------------- +.data +hex_str1: .asciiz "abcdef12\n" +hex_str2: .asciiz "00034532\n" + +.globl main +.text +#------------------------------------------- +# Test driver +#------------------------------------------- +main: + print_str(test_header_name) + + print_newline() + jal test_hex_to_str + + li $v0, 10 + syscall + +#------------------------------------------- +# Tests hex_to_str() from parsetools.s +#------------------------------------------- +test_hex_to_str: + addiu $sp, $sp, -4 + sw $ra, 0($sp) + print_str(test_hex_to_str_name) + + li $a0, 2882400018 + la $a1, test_buffer + jal hex_to_str + la $a0, test_buffer + check_str_equals($a0, hex_str1) + + li $a0, 214322 + la $a1, test_buffer + jal hex_to_str + la $a0, test_buffer + check_str_equals($a0, hex_str2) + + lw $ra, 0($sp) + addiu $sp, $sp, 4 + jr $ra + +.data +test_header_name: .asciiz "Running test parsetools:\n" + +test_hex_to_str_name: .asciiz "Testing hex_to_str():\n" + +test_buffer: .space 10 diff --git a/linker-tests/test_string.s b/linker-tests/test_string.s new file mode 100755 index 0000000..dc74e1e --- /dev/null +++ b/linker-tests/test_string.s @@ -0,0 +1,126 @@ +# CS 61C Spring 2015 Project 1-2 +# linker-tests/test_string.s + +#============================================================================== +# string.s Test Cases +#============================================================================== + +.include "../linker-src/string.s" +.include "test_core.s" + +#------------------------------------------- +# Test Data - Feel free to add your own +#------------------------------------------- +.data +test_str1: .asciiz "a9bw enijn webb" +test_str2: .asciiz "a9bw en" +test_str3: .asciiz "" + +.globl main +.text +#------------------------------------------- +# Test driver +#------------------------------------------- +main: + print_str(test_header_name) + + print_newline() + jal test_strlen + + print_newline() + jal test_strncpy + + print_newline() + jal test_copy_of_str + + li $v0, 10 + syscall + +#------------------------------------------- +# Tests strlen() +#------------------------------------------- +test_strlen: + addiu $sp, $sp, -4 + sw $ra, 0($sp) + print_str(test_strlen_name) + + la $a0, test_str1 + jal strlen + check_uint_equals($v0, 15) + + la $a0, test_str3 + jal strlen + check_uint_equals($v0, 0) + + la $a0, test_str2 + jal strlen + check_uint_equals($v0, 7) + + lw $ra, 0($sp) + addiu $sp, $sp, 4 + jr $ra + +#------------------------------------------- +# Tests strncpy() +#------------------------------------------- +test_strncpy: + addiu $sp, $sp, -4 + sw $ra, 0($sp) + print_str(test_strncpy_name) + + la $a0, test_buffer + la $a1, test_str1 + li $a2, 16 # note: len + 1 + jal strncpy + check_str_equals($v0, test_str1) + + la $a0, test_buffer + la $a1, test_str2 + li $a2, 8 # note: len + 1 + jal strncpy + check_str_equals($v0, test_str2) + + lw $ra, 0($sp) + addiu $sp, $sp, 4 + jr $ra + +#------------------------------------------- +# Tests copy_of_str() +#------------------------------------------- +test_copy_of_str: + addiu $sp, $sp, -12 + sw $s0, 8($sp) + sw $s1, 4($sp) + sw $ra, 0($sp) + print_str(test_copy_of_str_name) + + la $a0, test_str1 + jal copy_of_str + move $s0, $v0 + + la $a0, test_str2 + jal copy_of_str + move $s1, $v0 + + check_str_equals($s0, test_str1) + check_str_equals($s1, test_str2) + + lw $s0, 8($sp) + lw $s1, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 4 + jr $ra + +.data +test_header_name: .asciiz "Running util tests:\n" + +test_strlen_name: .asciiz "Testing strlen():\n" +test_strncpy_name: .asciiz "Testing strncpy():\n" +test_copy_of_str_name: .asciiz "Testing copy_of_str():\n" + +# 20 byte buffer x 5 = 100 byte buffer +test_buffer: .word 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF + .word 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF + .word 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF + .word 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF + .word 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF diff --git a/linker-tests/test_symbol_list.s b/linker-tests/test_symbol_list.s new file mode 100755 index 0000000..c6165ce --- /dev/null +++ b/linker-tests/test_symbol_list.s @@ -0,0 +1,105 @@ +# CS 61C Spring 2015 Project 1-2 +# linker-tests/test_symbols.s + +#============================================================================== +# symbol_list.s Test Cases +#============================================================================== +# Note that test_add_to_list() does NOT output whether the test passes or fails +# because it is written to standard output. +#============================================================================== + +.include "../linker-src/symbol_list.s" +.include "test_core.s" + +#------------------------------------------- +# Test Data - Feel free to add your own +#------------------------------------------- +.data +# Test strings +test_label1: .asciiz "Label 1" +test_label2: .asciiz "Label 2" +test_label3: .asciiz "Label 3" + +# Test nodes +node1: .word 1234 test_label1 0 +node2: .word 3456 test_label2 node1 +node3: .word 5678 test_label3 node2 + +.globl main +.text +#------------------------------------------- +# Test driver +#------------------------------------------- +main: + print_str(test_header_name) + + print_newline() + la $a0, node3 + jal test_addr_for_symbol + + print_newline() + jal test_add_to_list + + li $v0, 10 + syscall + +#------------------------------------------- +# Tests addr_for_symbol() +# $a0 = address of beginning of list +#------------------------------------------- +test_addr_for_symbol: + addiu $sp, $sp, -8 + sw $a0, 4($sp) + sw $ra, 0($sp) + print_str(test_addr_for_symbol_name) + + lw $a0, 4($sp) + la $a1, test_label1 + jal addr_for_symbol + check_uint_equals($v0, 1234) + + lw $ra, 0($sp) + addiu $sp, $sp, 8 + jr $ra + +#------------------------------------------- +# Tests add_to_list() +# $a0 = address of beginning of list +#------------------------------------------- +test_add_to_list: # Begin test_add_to_list + addiu $sp, $sp, -8 + sw $s0, 4($sp) + sw $ra, 0($sp) + + print_str(test_add_to_list_name) + li $a0, 0 + li $a1, 1234 + la $a2, test_label1 + jal add_to_list # Test label 1 + move $a0, $v0 + li $a1, 3456 + la $a2, test_label2 + jal add_to_list # Test label 2 + move $a0, $v0 + li $a1, 5678 + la $a2, test_label3 + jal add_to_list # Test label 3 + move $s0, $v0 + + move $a0, $s0 + la $a1, print_symbol + li $a2, 0 # dummy argument + jal print_list + print_str(expected_print_list) + + lw $s0, 4($sp) + lw $ra, 0($sp) + addiu $sp, $sp, 8 + jr $ra + +.data +test_header_name: .asciiz "Running symbol list tests:\n" +test_addr_for_symbol_name:.asciiz "Testing addr_for_symbol():\n" +test_add_to_list_name: .asciiz "Testing add_to_list():\n" + +expected_print_list: .asciiz "expected:\n5678\tLabel 3\n3456\tLabel 2\n1234\tLabel 1\n" From a400074485947260a3f45da500936861664ead9a Mon Sep 17 00:00:00 2001 From: Jeffrey Dong Date: Mon, 23 Feb 2015 04:25:56 -0800 Subject: [PATCH 2/6] Fixed typo --- linker-tests/test_linker_utils.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linker-tests/test_linker_utils.s b/linker-tests/test_linker_utils.s index b405aa8..2c834a4 100755 --- a/linker-tests/test_linker_utils.s +++ b/linker-tests/test_linker_utils.s @@ -89,7 +89,7 @@ test_inst_needs_relocation: jr $ra #------------------------------------------- -# Tests calc_relocate_inst() from linker_utils.s +# Tests relocate_inst() from linker_utils.s #------------------------------------------- test_relocate_inst: addiu $sp, $sp, -4 From 50818e4d4a4a25c4b45d068e7507b81d26916c98 Mon Sep 17 00:00:00 2001 From: Jeffrey Dong Date: Mon, 23 Feb 2015 05:00:00 -0800 Subject: [PATCH 3/6] Changed SymbolTable to allow for both unique and non-unique names --- assembler.c | 4 ++-- src/tables.c | 13 +++++++++---- src/tables.h | 4 ++++ test_assembler.c | 14 ++++++++++++-- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/assembler.c b/assembler.c index 4011a2e..26d7255 100644 --- a/assembler.c +++ b/assembler.c @@ -191,8 +191,8 @@ static void close_files(FILE* input, FILE* output) { int assemble(const char* in_name, const char* tmp_name, const char* out_name) { FILE *src, *dst; int err = 0; - SymbolTable* symtbl = create_table(); - SymbolTable* reltbl = create_table(); + SymbolTable* symtbl = create_table(SYMTBL_UNIQUE_NAME); + SymbolTable* reltbl = create_table(SYMTBL_NON_UNIQUE); if (in_name) { printf("Running pass one: %s -> %s\n", in_name, tmp_name); diff --git a/src/tables.c b/src/tables.c index d77425c..88972f6 100644 --- a/src/tables.c +++ b/src/tables.c @@ -6,6 +6,9 @@ #include "utils.h" #include "tables.h" +const int SYMTBL_NON_UNIQUE = 0; +const int SYMTBL_UNIQUE_NAME = 1; + /******************************* * Helper Functions *******************************/ @@ -34,8 +37,10 @@ void write_symbol(FILE* output, uint32_t addr, const char* name) { /* Creates a new SymbolTable containg 0 elements and returns a pointer to that table. Multiple SymbolTables may exist at the same time. If memory allocation fails, you should call allocation_failed(). + Mode will be either SYMTBL_NON_UNIQUE or SYMTBL_UNIQUE_NAME. You will need + to store this value for use during add_to_table(). */ -SymbolTable* create_table() { +SymbolTable* create_table(int mode) { /* YOUR CODE HERE */ return NULL; } @@ -53,9 +58,9 @@ void free_table(SymbolTable* table) { store the NAME pointer. You must store a copy of the given string. If ADDR is not word-aligned, you should call addr_alignment_incorrect() and - return -1. If NAME already exists in the table, you should call - name_already_exists() and return -1. If memory allocation fails, you should - call allocation_failed(). + return -1. If the table's mode is SYMTBL_UNIQUE_NAME and NAME already exists + in the table, you should call name_already_exists() and return -1. If memory + allocation fails, you should call allocation_failed(). Otherwise, you should store the symbol name and address and return 0. */ diff --git a/src/tables.h b/src/tables.h index e7fb32f..ebf8079 100644 --- a/src/tables.h +++ b/src/tables.h @@ -3,6 +3,9 @@ #include +extern const int SYMTBL_NON_UNIQUE; // allows duplicate names in table +extern const int SYMTBL_UNIQUE_NAME; // duplicate names not allowed + /* Complete the following definition of SymbolTable and implement the following functions. You are free to declare additional structs or functions, but you must build this data structure yourself. @@ -18,6 +21,7 @@ typedef struct { Symbol* tbl; uint32_t len; uint32_t cap; + int mode; } SymbolTable; /* Helper functions: */ diff --git a/test_assembler.c b/test_assembler.c index a08200c..4381940 100644 --- a/test_assembler.c +++ b/test_assembler.c @@ -92,7 +92,7 @@ void test_translate_num() { void test_table_1() { int retval; - SymbolTable* tbl = create_table(); + SymbolTable* tbl = create_table(SYMTBL_UNIQUE_NAME); CU_ASSERT_PTR_NOT_NULL(tbl); retval = add_to_table(tbl, "abc", 8); @@ -118,12 +118,22 @@ void test_table_1() { char* arr[] = { "Error: name 'q45' already exists in table.", "Error: address is not a multiple of 4." }; check_lines_equal(arr, 2); + + SymbolTable* tbl2 = create_table(SYMTBL_NON_UNIQUE); + CU_ASSERT_PTR_NOT_NULL(tbl2); + + retval = add_to_table(tbl, "q45", 16); + CU_ASSERT_EQUAL(retval, 0); + retval = add_to_table(tbl, "q45", 24); + CU_ASSERT_EQUAL(retval, 0); + + free_table(tbl2); } void test_table_2() { int retval, max = 100; - SymbolTable* tbl = create_table(); + SymbolTable* tbl = create_table(SYMTBL_UNIQUE_NAME); CU_ASSERT_PTR_NOT_NULL(tbl); char buf[10]; From 7e2fa8a79f86a013ead6c067e9a6fd29982727ba Mon Sep 17 00:00:00 2001 From: Jeffrey Dong Date: Mon, 23 Feb 2015 06:28:29 -0800 Subject: [PATCH 4/6] Clarified behavior on error, fixed p1_errors test case output --- assembler.c | 3 ++- log/ref/p1_errors_ref.txt | 4 ---- out/ref/p1_errors_ref.int | 3 --- out/ref/p1_errors_ref.out | 8 +++----- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/assembler.c b/assembler.c index 26d7255..7370d64 100644 --- a/assembler.c +++ b/assembler.c @@ -107,7 +107,8 @@ static int add_if_label(uint32_t input_line, char* str, uint32_t byte_offset, 2. If the first token is not a label, treat it as the name of an instruction. 3. Everything after the instruction name should be treated as arguments to that instruction. If there are more than MAX_ARGS arguments, call - raise_extra_arg_error() and pass in the first extra argument. + raise_extra_arg_error() and pass in the first extra argument. Do not + write that instruction to the output file (eg. don't call write_pass_one()) 4. Only one instruction should be present per line. You do not need to do anything extra to detect this - it should be handled by guideline 3. 5. A line containing only a label is valid. The address of the label should diff --git a/log/ref/p1_errors_ref.txt b/log/ref/p1_errors_ref.txt index ac62365..c57d77e 100644 --- a/log/ref/p1_errors_ref.txt +++ b/log/ref/p1_errors_ref.txt @@ -3,8 +3,4 @@ Error - invalid label at line 7: 3hello Error - extra argument at line 9: sll Error: name 'label' already exists in table. Error - extra argument at line 13: 5 -Error - invalid instruction at line 9: l2: addiu $t3 $t1 -Error - invalid instruction at line 11: addiu $t3 $t5 3 -Error - invalid instruction at line 12: ori $t1 $t0 0xFFFFFFFF -Error - invalid instruction at line 13: bne $t0 $t1 not_found One or more errors encountered during assembly operation. diff --git a/out/ref/p1_errors_ref.int b/out/ref/p1_errors_ref.int index ec1876a..928ec75 100644 --- a/out/ref/p1_errors_ref.int +++ b/out/ref/p1_errors_ref.int @@ -1,12 +1,9 @@ -addu $v0 $a0 $a1 or $a2 $a3 $t0 jr $t1 slt $t2 $t2 $s0 -sltu $s1 $s2 $s3 lui $t3 123 lb $t0 0 $s0 jal label -l2: addiu $t3 $t1 ori $t3 $t2 0xABC addiu $t3 $t5 3 ori $t1 $t0 0xFFFFFFFF diff --git a/out/ref/p1_errors_ref.out b/out/ref/p1_errors_ref.out index 9f4166e..e0b9d63 100644 --- a/out/ref/p1_errors_ref.out +++ b/out/ref/p1_errors_ref.out @@ -1,17 +1,15 @@ .text -00851021 00e83025 01200008 0150502a -0253882b 3c0b007b 82080000 0c000000 354b0abc .symbol -4 label -32 l1 +0 label +24 l1 .relocation -28 label +20 label From aaf1447a200636d2347868d4e6115180d57469a3 Mon Sep 17 00:00:00 2001 From: Jeffrey Dong Date: Mon, 23 Feb 2015 14:27:52 -0800 Subject: [PATCH 5/6] Fixed incorrect names -- should be tbl2 --- test_assembler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test_assembler.c b/test_assembler.c index 4381940..69871dc 100644 --- a/test_assembler.c +++ b/test_assembler.c @@ -122,9 +122,9 @@ void test_table_1() { SymbolTable* tbl2 = create_table(SYMTBL_NON_UNIQUE); CU_ASSERT_PTR_NOT_NULL(tbl2); - retval = add_to_table(tbl, "q45", 16); + retval = add_to_table(tbl2, "q45", 16); CU_ASSERT_EQUAL(retval, 0); - retval = add_to_table(tbl, "q45", 24); + retval = add_to_table(tbl2, "q45", 24); CU_ASSERT_EQUAL(retval, 0); free_table(tbl2); From 0b03645da68bb5c14303e1d191b91e4de8795c32 Mon Sep 17 00:00:00 2001 From: Jeffrey Dong Date: Mon, 23 Feb 2015 15:31:46 -0800 Subject: [PATCH 6/6] Error handling only requires log output to match; also replaced with 9 in p1_errors.s and p2_errors.s to avoid penalizing students who translated extra registers --- input/p1_errors.s | 2 +- input/p2_errors.s | 4 ++-- log/ref/p2_errors_ref.txt | 4 ++-- out/ref/p1_errors_ref.int | 10 ---------- out/ref/p1_errors_ref.out | 15 --------------- out/ref/p2_errors_ref.int | 5 ----- out/ref/p2_errors_ref.out | 6 ------ 7 files changed, 5 insertions(+), 41 deletions(-) delete mode 100644 out/ref/p1_errors_ref.int delete mode 100644 out/ref/p1_errors_ref.out delete mode 100644 out/ref/p2_errors_ref.int delete mode 100644 out/ref/p2_errors_ref.out diff --git a/input/p1_errors.s b/input/p1_errors.s index 90185cf..14d3af5 100644 --- a/input/p1_errors.s +++ b/input/p1_errors.s @@ -14,6 +14,6 @@ l1: l2: addiu $t3, $t1, 5 # Multiple labels on one line ori $t3, $t2, 0xABC # Things to ignore - addiu $t3, $t5, 3 # invalid register + addiu $t3, $99, 3 # invalid register ori $t1, $t0, 0xFFFFFFFF # invalid immediate bne $t0, $t1, not_found # nonexistant label \ No newline at end of file diff --git a/input/p2_errors.s b/input/p2_errors.s index f7759fb..6e17e37 100644 --- a/input/p2_errors.s +++ b/input/p2_errors.s @@ -1,7 +1,7 @@ addiu $t0, $t3, $t3 # not a number label: jal # no label - ori $t2, $t5, 0xAB # invalid register + ori $t2, $99, 0xAB # invalid register bne $t0, $t1, not_found # nonexistant label - addiu $t3 $t5 0x80808080 # number too large + addiu $t3 $t2 0x80808080 # number too large # Can you think of any others? \ No newline at end of file diff --git a/log/ref/p2_errors_ref.txt b/log/ref/p2_errors_ref.txt index f755e54..0f9c84e 100644 --- a/log/ref/p2_errors_ref.txt +++ b/log/ref/p2_errors_ref.txt @@ -1,6 +1,6 @@ Error - invalid instruction at line 1: addiu $t0 $t3 $t3 Error - invalid instruction at line 2: jal -Error - invalid instruction at line 3: ori $t2 $t5 0xAB +Error - invalid instruction at line 3: ori $t2 $99 0xAB Error - invalid instruction at line 4: bne $t0 $t1 not_found -Error - invalid instruction at line 5: addiu $t3 $t5 0x80808080 +Error - invalid instruction at line 5: addiu $t3 $t2 0x80808080 One or more errors encountered during assembly operation. diff --git a/out/ref/p1_errors_ref.int b/out/ref/p1_errors_ref.int deleted file mode 100644 index 928ec75..0000000 --- a/out/ref/p1_errors_ref.int +++ /dev/null @@ -1,10 +0,0 @@ -or $a2 $a3 $t0 -jr $t1 -slt $t2 $t2 $s0 -lui $t3 123 -lb $t0 0 $s0 -jal label -ori $t3 $t2 0xABC -addiu $t3 $t5 3 -ori $t1 $t0 0xFFFFFFFF -bne $t0 $t1 not_found diff --git a/out/ref/p1_errors_ref.out b/out/ref/p1_errors_ref.out deleted file mode 100644 index e0b9d63..0000000 --- a/out/ref/p1_errors_ref.out +++ /dev/null @@ -1,15 +0,0 @@ -.text -00e83025 -01200008 -0150502a -3c0b007b -82080000 -0c000000 -354b0abc - -.symbol -0 label -24 l1 - -.relocation -20 label diff --git a/out/ref/p2_errors_ref.int b/out/ref/p2_errors_ref.int deleted file mode 100644 index 1b25d3e..0000000 --- a/out/ref/p2_errors_ref.int +++ /dev/null @@ -1,5 +0,0 @@ -addiu $t0 $t3 $t3 -jal -ori $t2 $t5 0xAB -bne $t0 $t1 not_found -addiu $t3 $t5 0x80808080 diff --git a/out/ref/p2_errors_ref.out b/out/ref/p2_errors_ref.out deleted file mode 100644 index b5d6fa3..0000000 --- a/out/ref/p2_errors_ref.out +++ /dev/null @@ -1,6 +0,0 @@ -.text - -.symbol -4 label - -.relocation