|
| 1 | +#!/bin/bash |
| 2 | +if [ ${#} -ne 2 ] || ([ "$1" != '-s' ] && [ "$1" != '-p' ]); then |
| 3 | + echo "usage: ./hexify [-s | -p] <input file path> > <output file path>" |
| 4 | + echo "example: ./hexify -p input > output" |
| 5 | + exit |
| 6 | +fi |
| 7 | + |
| 8 | +# If you choose to interpret file contents as a string literal. |
| 9 | +if [ "$1" == '-s' ]; then |
| 10 | + # Convert entire file into hexadecimal, split by every 8 characters to get word. |
| 11 | + words=$(echo $(xxd -pu <<< "$(cat $2)") | sed 's/.\{8\}/& /g') |
| 12 | + for word in $words; do |
| 13 | + # Add trailing zeroes to remaining word. |
| 14 | + while [ ${#word} -lt 8 ]; do |
| 15 | + word="${word}0" |
| 16 | + done |
| 17 | + # Write word to wordasm. |
| 18 | + echo ".word 0x$word" |
| 19 | + done |
| 20 | + exit |
| 21 | +fi |
| 22 | + |
| 23 | +# Adds leading zeroes to $1 until it has reached a length of $2. |
| 24 | +addLeadingZeroes() { |
| 25 | + str=$1 |
| 26 | + while [ ${#str} -lt "$2" ]; do |
| 27 | + str="0$str" |
| 28 | + done |
| 29 | + echo $str |
| 30 | +} |
| 31 | + |
| 32 | +# Converts decimal $1 to a binary string of length $2. |
| 33 | +dec2bin() { |
| 34 | + use2scomplement=false |
| 35 | + decimal=$1 |
| 36 | + # Set 'use2scomplement' flag to true and strip '-' from negative values. |
| 37 | + if [[ "$decimal" = '-'* ]]; then |
| 38 | + decimal=${decimal#'-'} |
| 39 | + use2scomplement=true |
| 40 | + fi |
| 41 | + binary=$(echo "obase=2;$decimal" | bc) |
| 42 | + binary=$(addLeadingZeroes "$binary" "$2") |
| 43 | + if [ "$use2scomplement" = true ]; then |
| 44 | + # Flip all bits and add one to binary string. |
| 45 | + binary=$(tr 01 10 <<< "$binary") |
| 46 | + binary=$(echo "obase=2;ibase=2;$binary+1" | bc -l) |
| 47 | + fi |
| 48 | + echo $binary |
| 49 | +} |
| 50 | + |
| 51 | +# Converts binary string $1 to a hexadecimal word of length 8. |
| 52 | +bin2hex() { |
| 53 | + word=$(echo "obase=16;ibase=2;$1" | bc) |
| 54 | + word=$(addLeadingZeroes "$word" 8) |
| 55 | + echo ".word 0x$word" |
| 56 | +} |
| 57 | + |
| 58 | +while IFS='' read -r line || [[ -n "$line" ]]; do |
| 59 | + components=($line) |
| 60 | + # Strip characters until every command argument is a decimal, then convert to binary. |
| 61 | + for i in {1..3}; do |
| 62 | + if [ "${components[i]}" == '' ]; then |
| 63 | + break |
| 64 | + fi |
| 65 | + # Remove ',' after certain arguments. |
| 66 | + components[$i]=${components[$i]%$','} |
| 67 | + # Strip ')' from lw and sw commands, and split the offset and register values into separate components. |
| 68 | + if [[ ${components[i]} = *')' ]]; then |
| 69 | + components[$i]=${components[$i]%$')'} |
| 70 | + subComponents=(${components[$i]//(/ }) |
| 71 | + components[$i]=${subComponents[0]} |
| 72 | + components[$i+1]=${subComponents[1]} |
| 73 | + fi |
| 74 | + # Determine register or immediate value, and convert to binary. |
| 75 | + if [[ ${components[i]} = '$'* ]]; then |
| 76 | + components[$i]=${components[$i]#'$'} |
| 77 | + components[$i]=$(dec2bin "${components[$i]}" 5) |
| 78 | + else |
| 79 | + components[$i]=$(dec2bin "${components[$i]}" 16) |
| 80 | + fi |
| 81 | + done |
| 82 | + # Command interpreter. |
| 83 | + cmd=${components[0]} |
| 84 | + if [ "$cmd" == '.word' ]; then |
| 85 | + echo $(bin2hex "${components[1]}") |
| 86 | + elif [ "$cmd" == "add" ]; then |
| 87 | + echo $(bin2hex "000000${components[2]}${components[3]}${components[1]}00000100000") |
| 88 | + elif [ "$cmd" == "sub" ]; then |
| 89 | + echo $(bin2hex "000000${components[2]}${components[3]}${components[1]}00000100010") |
| 90 | + elif [ "$cmd" == "mult" ]; then |
| 91 | + echo $(bin2hex "000000${components[1]}${components[2]}0000000000011000") |
| 92 | + elif [ "$cmd" == "multu" ]; then |
| 93 | + echo $(bin2hex "000000${components[1]}${components[2]}0000000000011001") |
| 94 | + elif [ "$cmd" == "div" ]; then |
| 95 | + echo $(bin2hex "000000${components[1]}${components[2]}0000000000011010") |
| 96 | + elif [ "$cmd" == "divu" ]; then |
| 97 | + echo $(bin2hex "000000${components[1]}${components[2]}0000000000011011") |
| 98 | + elif [ "$cmd" == "mfhi" ]; then |
| 99 | + echo $(bin2hex "0000000000000000${components[1]}00000010000") |
| 100 | + elif [ "$cmd" == "mflo" ]; then |
| 101 | + echo $(bin2hex "0000000000000000${components[1]}00000010010") |
| 102 | + elif [ "$cmd" == "lis" ]; then |
| 103 | + echo $(bin2hex "0000000000000000${components[1]}00000010100") |
| 104 | + elif [ "$cmd" == "lw" ]; then |
| 105 | + echo $(bin2hex "100011${components[3]}${components[1]}${components[2]}") |
| 106 | + elif [ "$cmd" == "sw" ]; then |
| 107 | + echo $(bin2hex "101011${components[3]}${components[1]}${components[2]}") |
| 108 | + elif [ "$cmd" == "slt" ]; then |
| 109 | + echo $(bin2hex "000000${components[2]}${components[3]}${components[1]}00000101010") |
| 110 | + elif [ "$cmd" == "sltu" ]; then |
| 111 | + echo $(bin2hex "000000${components[2]}${components[3]}${components[1]}00000101011") |
| 112 | + elif [ "$cmd" == "beq" ]; then |
| 113 | + echo $(bin2hex "000100${components[1]}${components[2]}${components[3]}") |
| 114 | + elif [ "$cmd" == "bne" ]; then |
| 115 | + echo $(bin2hex "000101${components[1]}${components[2]}${components[3]}") |
| 116 | + elif [ "$cmd" == "jr" ]; then |
| 117 | + echo $(bin2hex "000000${components[1]}000000000000000001000") |
| 118 | + elif [ "$cmd" == "jalr" ]; then |
| 119 | + echo $(bin2hex "000000${components[1]}000000000000000001001") |
| 120 | + fi |
| 121 | +done < "$2" |
0 commit comments