speed optimization
This commit is contained in:
@@ -12,5 +12,14 @@ for arg in "$@"; do
|
|||||||
CMD_OPTS="$CMD_OPTS$SEP$arg"
|
CMD_OPTS="$CMD_OPTS$SEP$arg"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
[ -z "$AWK" ] && AWK=awk
|
if [ -z "$AWK" ]; then
|
||||||
od -An -v -tu1 "$1" | POSIXLY_CORRECT=1 $AWK -f amach.awk -v LVA="$LVA" -v CMD_OPTS="$CMD_OPTS"
|
if command -v mawk >/dev/null 2>&1; then
|
||||||
|
AWK=mawk
|
||||||
|
else
|
||||||
|
AWK=awk
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
TMPFILE=$(mktemp)
|
||||||
|
od -An -v -tu1 "$1" > "$TMPFILE"
|
||||||
|
POSIXLY_CORRECT=1 $AWK -f amach.awk -v LVA="$LVA" -v CMD_OPTS="$CMD_OPTS" -- "$TMPFILE"
|
||||||
|
rm -f "$TMPFILE"
|
||||||
|
|||||||
@@ -20,13 +20,16 @@ function trapout(msg, fd) {
|
|||||||
# helper functions
|
# helper functions
|
||||||
|
|
||||||
function uint32(val) {
|
function uint32(val) {
|
||||||
val = int(val) % 4294967296
|
val = int(val)
|
||||||
|
if (val >= 0 && val < 4294967296) return val
|
||||||
|
val = val % 4294967296
|
||||||
return (val < 0) ? (val + 4294967296) : val
|
return (val < 0) ? (val + 4294967296) : val
|
||||||
}
|
}
|
||||||
|
|
||||||
function setreg(idx, val) {
|
function setreg(idx, val) {
|
||||||
if(idx > 0) {
|
if(idx > 0) {
|
||||||
val = uint32(val)
|
val = int(val) % 4294967296
|
||||||
|
if(val < 0) val += 4294967296
|
||||||
REG[idx] = (val >= 2147483648) ? (val - 4294967296) : val
|
REG[idx] = (val >= 2147483648) ? (val - 4294967296) : val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,11 +66,22 @@ function bw_xor(a, b) {return bw_op(a, b, "^")}
|
|||||||
|
|
||||||
function read_mem(addr, bytes, signed, i, val, max_val) {
|
function read_mem(addr, bytes, signed, i, val, max_val) {
|
||||||
addr = uint32(addr)
|
addr = uint32(addr)
|
||||||
val = 0
|
if (bytes == 1) {
|
||||||
for(i=0; i<bytes; i++) val += MEM[(addr+i)%4294967296] * (256^i)
|
val = MEM[addr]
|
||||||
if(signed) {
|
if (signed && val >= 128) val -= 256
|
||||||
max_val = 256^bytes
|
} else if (bytes == 2) {
|
||||||
if(val >= max_val/2) val -= max_val
|
val = MEM[addr] + MEM[addr+1] * 256
|
||||||
|
if (signed && val >= 32768) val -= 65536
|
||||||
|
} else if (bytes == 4) {
|
||||||
|
val = MEM[addr] + MEM[addr+1] * 256 + MEM[addr+2] * 65536 + MEM[addr+3] * 16777216
|
||||||
|
if (signed && val >= 2147483648) val -= 4294967296
|
||||||
|
} else {
|
||||||
|
val = 0
|
||||||
|
for(i=0; i<bytes; i++) val += MEM[addr+i] * (256^i)
|
||||||
|
if(signed) {
|
||||||
|
max_val = 256^bytes
|
||||||
|
if(val >= max_val/2) val -= max_val
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
@@ -75,7 +89,19 @@ function read_mem(addr, bytes, signed, i, val, max_val) {
|
|||||||
function write_mem(addr, val, bytes, i) {
|
function write_mem(addr, val, bytes, i) {
|
||||||
addr = uint32(addr)
|
addr = uint32(addr)
|
||||||
val = uint32(val)
|
val = uint32(val)
|
||||||
for(i=0; i<bytes; i++) MEM[(addr+i)%4294967296] = int(val / (256^i)) % 256
|
if (bytes == 1) {
|
||||||
|
MEM[addr] = val % 256
|
||||||
|
} else if (bytes == 2) {
|
||||||
|
MEM[addr] = val % 256
|
||||||
|
MEM[addr+1] = int(val / 256) % 256
|
||||||
|
} else if (bytes == 4) {
|
||||||
|
MEM[addr] = val % 256
|
||||||
|
MEM[addr+1] = int(val / 256) % 256
|
||||||
|
MEM[addr+2] = int(val / 65536) % 256
|
||||||
|
MEM[addr+3] = int(val / 16777216) % 256
|
||||||
|
} else {
|
||||||
|
for(i=0; i<bytes; i++) MEM[addr+i] = int(val / (256^i)) % 256
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_word(addr) {return read_mem(addr, 4, 1)}
|
function read_word(addr) {return read_mem(addr, 4, 1)}
|
||||||
@@ -225,6 +251,9 @@ function amach_exit(code, fd) {
|
|||||||
# syscall emulation
|
# syscall emulation
|
||||||
|
|
||||||
function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, reclen, cmd, line, arr) {
|
function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, reclen, cmd, line, arr) {
|
||||||
|
ECALL_COUNT++
|
||||||
|
if(ECALL_COUNT == 1) POST_ECALL_IC = ic
|
||||||
|
printf("ECALL #%d: call=%d a0=%d a1=0x%X a2=%d pc=0x%X ic=%d\n", ECALL_COUNT, callnum, a0, uint32(a1), a2, pc-4, ic) > "/dev/stderr"
|
||||||
if(callnum == 34) { # sys_mkdirat
|
if(callnum == 34) { # sys_mkdirat
|
||||||
a1 = resolve_path(a0, read_str(a1))
|
a1 = resolve_path(a0, read_str(a1))
|
||||||
if(path_exists(a1)) setreg(10, -17) # -EEXIST
|
if(path_exists(a1)) setreg(10, -17) # -EEXIST
|
||||||
@@ -348,9 +377,13 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, reclen, cmd, line, ar
|
|||||||
} else setreg(10, -9) # -EBADF
|
} else setreg(10, -9) # -EBADF
|
||||||
} else if(callnum == 63) { # sys_read
|
} else if(callnum == 63) { # sys_read
|
||||||
if(a0 == 0) {
|
if(a0 == 0) {
|
||||||
getline a3 < "/dev/tty"
|
STARTED_IO = 1
|
||||||
a4 = length(a3); if(a4 > a2) a4 = a2
|
if(length(STDIN_BUF) == 0) {
|
||||||
for(i = 0; i < a4; i++) MEM[uint32(a1 + i)] = ord(substr(a3, i + 1, 1))
|
if((getline a3 < "-") > 0) STDIN_BUF = a3 "\n"
|
||||||
|
}
|
||||||
|
a4 = length(STDIN_BUF); if(a4 > a2) a4 = a2
|
||||||
|
for(i = 0; i < a4; i++) MEM[uint32(a1 + i)] = ord(substr(STDIN_BUF, i + 1, 1))
|
||||||
|
STDIN_BUF = substr(STDIN_BUF, a4 + 1)
|
||||||
setreg(10, a4)
|
setreg(10, a4)
|
||||||
} else if(a0 >= 3 && (a0 in FD_PATH) && !(a0 in FD_DIRENT_COUNT)) {
|
} else if(a0 >= 3 && (a0 in FD_PATH) && !(a0 in FD_DIRENT_COUNT)) {
|
||||||
a3 = FD_OFFSET[a0] # idx
|
a3 = FD_OFFSET[a0] # idx
|
||||||
@@ -361,12 +394,16 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, reclen, cmd, line, ar
|
|||||||
for(i = 0; i < a2; i++)
|
for(i = 0; i < a2; i++)
|
||||||
MEM[uint32(a1 + i)] = FD_DATA[a0, a3 + i]
|
MEM[uint32(a1 + i)] = FD_DATA[a0, a3 + i]
|
||||||
FD_OFFSET[a0] = a3 + a2
|
FD_OFFSET[a0] = a3 + a2
|
||||||
|
printf("DEBUG sys_read fd=%d: wrote %d bytes to 0x%X. First 16:", a0, a2, uint32(a1)) > "/dev/stderr"
|
||||||
|
for(k=0; k<16; k++) printf(" %d", MEM[uint32(a1)+k]+0) > "/dev/stderr"
|
||||||
|
printf("\n") > "/dev/stderr"
|
||||||
setreg(10, a2)
|
setreg(10, a2)
|
||||||
}
|
}
|
||||||
} else setreg(10, -9) # -EBADF
|
} else setreg(10, -9) # -EBADF
|
||||||
} else if(callnum == 64) { # sys_write
|
} else if(callnum == 64) { # sys_write
|
||||||
if(a0 == 1 || a0 == 2) {
|
if(a0 == 1 || a0 == 2) {
|
||||||
for(i = 0; i < a2; i++) printf("%c", MEM[uint32(a1 + i)])
|
for(i = 0; i < a2; i++) printf("%c", MEM[uint32(a1 + i)])
|
||||||
|
fflush("")
|
||||||
setreg(10, a2)
|
setreg(10, a2)
|
||||||
} else if(a0 >= 3 && (a0 in FD_PATH) && !(a0 in FD_DIRENT_COUNT)) {
|
} else if(a0 >= 3 && (a0 in FD_PATH) && !(a0 in FD_DIRENT_COUNT)) {
|
||||||
a3 = bw_and(FD_FLAGS[a0], 1024) ? FD_SIZE[a0] : FD_OFFSET[a0] # idx
|
a3 = bw_and(FD_FLAGS[a0], 1024) ? FD_SIZE[a0] : FD_OFFSET[a0] # idx
|
||||||
@@ -440,7 +477,7 @@ function handle_ecall(callnum, a0, a1, a2, a3, a4, a5, i, reclen, cmd, line, ar
|
|||||||
# instruction type executors
|
# instruction type executors
|
||||||
|
|
||||||
function amach_reg_arith(f3, f7, rd, rs1, rs2, r1, r2, ur1, ur2, shamt) {
|
function amach_reg_arith(f3, f7, rd, rs1, rs2, r1, r2, ur1, ur2, shamt) {
|
||||||
r1 = getreg(rs1); r2 = getreg(rs2)
|
r1 = rs1 ? int(REG[rs1]) : 0; r2 = rs2 ? int(REG[rs2]) : 0
|
||||||
ur1 = uint32(r1); ur2 = uint32(r2)
|
ur1 = uint32(r1); ur2 = uint32(r2)
|
||||||
shamt = ur2 % 32
|
shamt = ur2 % 32
|
||||||
|
|
||||||
@@ -449,9 +486,9 @@ function amach_reg_arith(f3, f7, rd, rs1, rs2, r1, r2, ur1, ur2, shamt) {
|
|||||||
else if(f3 == 4 && f7 == 0) setreg(rd, bw_xor(r1, r2))
|
else if(f3 == 4 && f7 == 0) setreg(rd, bw_xor(r1, r2))
|
||||||
else if(f3 == 6 && f7 == 0) setreg(rd, bw_or(r1, r2))
|
else if(f3 == 6 && f7 == 0) setreg(rd, bw_or(r1, r2))
|
||||||
else if(f3 == 7 && f7 == 0) setreg(rd, bw_and(r1, r2))
|
else if(f3 == 7 && f7 == 0) setreg(rd, bw_and(r1, r2))
|
||||||
else if(f3 == 1 && f7 == 0) setreg(rd, (r1 * (2^shamt)) % 4294967296)
|
else if(f3 == 1 && f7 == 0) setreg(rd, (r1 * P2[shamt]) % 4294967296)
|
||||||
else if(f3 == 5 && f7 == 0) setreg(rd, int(ur1 / (2^shamt)))
|
else if(f3 == 5 && f7 == 0) setreg(rd, int(ur1 / P2[shamt]))
|
||||||
else if(f3 == 5 && f7 == 32) setreg(rd, floor(r1 / (2^shamt)))
|
else if(f3 == 5 && f7 == 32) setreg(rd, floor(r1 / P2[shamt]))
|
||||||
else if(f3 == 2 && f7 == 0) setreg(rd, (r1 < r2) ? 1 : 0)
|
else if(f3 == 2 && f7 == 0) setreg(rd, (r1 < r2) ? 1 : 0)
|
||||||
else if(f3 == 3 && f7 == 0) setreg(rd, (ur1 < ur2) ? 1 : 0)
|
else if(f3 == 3 && f7 == 0) setreg(rd, (ur1 < ur2) ? 1 : 0)
|
||||||
else if(f3 == 0 && f7 == 1) setreg(rd, (r1 * r2) % 4294967296)
|
else if(f3 == 0 && f7 == 1) setreg(rd, (r1 * r2) % 4294967296)
|
||||||
@@ -466,13 +503,13 @@ function amach_reg_arith(f3, f7, rd, rs1, rs2, r1, r2, ur1, ur2, shamt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function amach_store(f3, rs1, rs2, immval, r1, r2) {
|
function amach_store(f3, rs1, rs2, immval, r1, r2) {
|
||||||
r1 = getreg(rs1); r2 = getreg(rs2)
|
r1 = rs1 ? int(REG[rs1]) : 0; r2 = rs2 ? int(REG[rs2]) : 0
|
||||||
if(f3 >= 0 && f3 <= 2) write_mem(r1 + immval, r2, 2^f3)
|
if(f3 >= 0 && f3 <= 2) write_mem(r1 + immval, r2, P2[f3])
|
||||||
else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
||||||
}
|
}
|
||||||
|
|
||||||
function amach_branch(f3, rs1, rs2, immval, r1, r2, ur1, ur2, taken) {
|
function amach_branch(f3, rs1, rs2, immval, r1, r2, ur1, ur2, taken) {
|
||||||
r1 = getreg(rs1); r2 = getreg(rs2)
|
r1 = rs1 ? int(REG[rs1]) : 0; r2 = rs2 ? int(REG[rs2]) : 0
|
||||||
ur1 = uint32(r1); ur2 = uint32(r2)
|
ur1 = uint32(r1); ur2 = uint32(r2)
|
||||||
taken = 0
|
taken = 0
|
||||||
if(f3 == 0) taken = (r1 == r2)
|
if(f3 == 0) taken = (r1 == r2)
|
||||||
@@ -486,10 +523,10 @@ function amach_branch(f3, rs1, rs2, immval, r1, r2, ur1, ur2, taken) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function amach_imm(opcode, f3, rd, rs1, immval, r1, ur1, shamt) {
|
function amach_imm(opcode, f3, rd, rs1, immval, r1, ur1, shamt) {
|
||||||
r1 = getreg(rs1); ur1 = uint32(r1)
|
r1 = rs1 ? int(REG[rs1]) : 0; ur1 = uint32(r1)
|
||||||
if(opcode == 3) { # load
|
if(opcode == 3) { # load
|
||||||
if(f3 == 0 || f3 == 1 || f3 == 2 || f3 == 4 || f3 == 5) {
|
if(f3 == 0 || f3 == 1 || f3 == 2 || f3 == 4 || f3 == 5) {
|
||||||
setreg(rd, read_mem(r1 + immval, 2^(f3 % 4), f3 < 4))
|
setreg(rd, read_mem(r1 + immval, P2[f3 % 4], f3 < 4))
|
||||||
} else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
||||||
} else if(opcode == 19) { # 0x13, immediate arithmetic
|
} else if(opcode == 19) { # 0x13, immediate arithmetic
|
||||||
shamt = bw_and(immval, 31)
|
shamt = bw_and(immval, 31)
|
||||||
@@ -497,9 +534,9 @@ function amach_imm(opcode, f3, rd, rs1, immval, r1, ur1, shamt) {
|
|||||||
else if(f3 == 4) setreg(rd, bw_xor(r1, immval))
|
else if(f3 == 4) setreg(rd, bw_xor(r1, immval))
|
||||||
else if(f3 == 6) setreg(rd, bw_or(r1, immval))
|
else if(f3 == 6) setreg(rd, bw_or(r1, immval))
|
||||||
else if(f3 == 7) setreg(rd, bw_and(r1, immval))
|
else if(f3 == 7) setreg(rd, bw_and(r1, immval))
|
||||||
else if(f3 == 1) setreg(rd, (r1 * (2^shamt)) % 4294967296) # slli
|
else if(f3 == 1) setreg(rd, (r1 * P2[shamt]) % 4294967296) # slli
|
||||||
else if(f3 == 5 && immval < 1024) setreg(rd, int(ur1 / (2^shamt))) # srli
|
else if(f3 == 5 && immval < 1024) setreg(rd, int(ur1 / P2[shamt])) # srli
|
||||||
else if(f3 == 5 && immval >= 1024) setreg(rd, floor(r1 / (2^shamt))) # srai
|
else if(f3 == 5 && immval >= 1024) setreg(rd, floor(r1 / P2[shamt])) # srai
|
||||||
else if(f3 == 2) setreg(rd, (r1 < immval) ? 1 : 0)
|
else if(f3 == 2) setreg(rd, (r1 < immval) ? 1 : 0)
|
||||||
else if(f3 == 3) setreg(rd, (ur1 < immval) ? 1 : 0)
|
else if(f3 == 3) setreg(rd, (ur1 < immval) ? 1 : 0)
|
||||||
else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
||||||
@@ -507,7 +544,7 @@ function amach_imm(opcode, f3, rd, rs1, immval, r1, ur1, shamt) {
|
|||||||
setreg(rd, pc)
|
setreg(rd, pc)
|
||||||
pc = r1 + immval
|
pc = r1 + immval
|
||||||
} else if(opcode == 115) { # 0x73, system call / csr
|
} else if(opcode == 115) { # 0x73, system call / csr
|
||||||
if(immval == 0) handle_ecall(getreg(17), getreg(10), getreg(11), getreg(12), getreg(13), getreg(14), getreg(15))
|
if(immval == 0) handle_ecall(REG[17], REG[10], REG[11], REG[12], REG[13], REG[14], REG[15])
|
||||||
else if(immval == 1) trapout(sprintf("EBREAK at 0x%X", pc-4))
|
else if(immval == 1) trapout(sprintf("EBREAK at 0x%X", pc-4))
|
||||||
else trapout(sprintf("Unimplemented external system call at 0x%X", pc-4))
|
else trapout(sprintf("Unimplemented external system call at 0x%X", pc-4))
|
||||||
} else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
||||||
@@ -515,7 +552,7 @@ function amach_imm(opcode, f3, rd, rs1, immval, r1, ur1, shamt) {
|
|||||||
|
|
||||||
# A-extension
|
# A-extension
|
||||||
function amach_atomic(f3, f5, aq, rl, rd, rs1, rs2, r1, r2, val, uval, ur2) {
|
function amach_atomic(f3, f5, aq, rl, rd, rs1, rs2, r1, r2, val, uval, ur2) {
|
||||||
r1 = getreg(rs1); r2 = getreg(rs2)
|
r1 = rs1 ? int(REG[rs1]) : 0; r2 = rs2 ? int(REG[rs2]) : 0
|
||||||
ur2 = uint32(r2)
|
ur2 = uint32(r2)
|
||||||
if(f3 == 2) {
|
if(f3 == 2) {
|
||||||
val = read_word(r1)
|
val = read_word(r1)
|
||||||
@@ -561,33 +598,53 @@ function amach_atomic(f3, f5, aq, rl, rd, rs1, rs2, r1, r2, val, uval, ur2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# C-extension (compressed instructions) handler
|
# C-extension (compressed instructions) handler
|
||||||
function amach_comp(instr, op, f3, b12, r11_7, r9_7, r6_2, r4_2, shamt, imm, base, val) {
|
function amach_comp(instr, addr, op, f3, b12, r11_7, r9_7, r6_2, r4_2, shamt, imm, base, val) {
|
||||||
op = instr % 4
|
if (addr in CACHE_COP) {
|
||||||
f3 = int(instr / 8192) % 8
|
op = CACHE_COP[addr]
|
||||||
b12 = int(instr / 4096) % 2
|
f3 = CACHE_CF3[addr]
|
||||||
r11_7 = int(instr / 128) % 32
|
b12 = CACHE_CB12[addr]
|
||||||
r9_7 = (r11_7 % 8) + 8
|
r11_7 = CACHE_CR11_7[addr]
|
||||||
r6_2 = int(instr / 4) % 32
|
r9_7 = CACHE_CR9_7[addr]
|
||||||
r4_2 = (r6_2 % 8) + 8
|
r6_2 = CACHE_CR6_2[addr]
|
||||||
shamt = r6_2 + b12 * 32
|
r4_2 = CACHE_CR4_2[addr]
|
||||||
|
shamt = CACHE_CSHAMT[addr]
|
||||||
|
} else {
|
||||||
|
op = instr % 4
|
||||||
|
f3 = int(instr / 8192) % 8
|
||||||
|
b12 = int(instr / 4096) % 2
|
||||||
|
r11_7 = int(instr / 128) % 32
|
||||||
|
r9_7 = (r11_7 % 8) + 8
|
||||||
|
r6_2 = int(instr / 4) % 32
|
||||||
|
r4_2 = (r6_2 % 8) + 8
|
||||||
|
shamt = r6_2 + b12 * 32
|
||||||
|
|
||||||
|
CACHE_COP[addr] = op
|
||||||
|
CACHE_CF3[addr] = f3
|
||||||
|
CACHE_CB12[addr] = b12
|
||||||
|
CACHE_CR11_7[addr] = r11_7
|
||||||
|
CACHE_CR9_7[addr] = r9_7
|
||||||
|
CACHE_CR6_2[addr] = r6_2
|
||||||
|
CACHE_CR4_2[addr] = r4_2
|
||||||
|
CACHE_CSHAMT[addr] = shamt
|
||||||
|
}
|
||||||
|
|
||||||
if(op == 0) {
|
if(op == 0) {
|
||||||
if(f3 == 0) { # C.ADDI4SPN
|
if(f3 == 0) { # C.ADDI4SPN
|
||||||
imm = (r11_7 % 16) * 64 + (int(r11_7 / 16) + b12 * 2) * 16 + (int(r6_2 / 8) % 2) * 8 + (int(r6_2 / 16) % 2) * 4
|
imm = (r11_7 % 16) * 64 + (int(r11_7 / 16) + b12 * 2) * 16 + (int(r6_2 / 8) % 2) * 8 + (int(r6_2 / 16) % 2) * 4
|
||||||
if(imm == 0) trapout(sprintf("Illegal instruction C.ADDI4SPN at 0x%X", pc-2))
|
if(imm == 0) trapout(sprintf("Illegal instruction C.ADDI4SPN at 0x%X", pc-2))
|
||||||
setreg(r4_2, getreg(2) + imm)
|
setreg(r4_2, REG[2] + imm)
|
||||||
} else if(f3 == 2) { # C.LW
|
} else if(f3 == 2) { # C.LW
|
||||||
imm = (int(r6_2 / 8) % 2) * 64 + (int(r11_7 / 8) % 4) * 8 + b12 * 32 + (int(r6_2 / 16) % 2) * 4
|
imm = (int(r6_2 / 8) % 2) * 64 + (int(r11_7 / 8) % 4) * 8 + b12 * 32 + (int(r6_2 / 16) % 2) * 4
|
||||||
setreg(r4_2, read_mem(getreg(r9_7) + imm, 4, 1))
|
setreg(r4_2, read_mem((r9_7 ? REG[r9_7] : 0) + imm, 4, 1))
|
||||||
} else if(f3 == 6) { # C.SW
|
} else if(f3 == 6) { # C.SW
|
||||||
imm = (int(r6_2 / 8) % 2) * 64 + (int(r11_7 / 8) % 4) * 8 + b12 * 32 + (int(r6_2 / 16) % 2) * 4
|
imm = (int(r6_2 / 8) % 2) * 64 + (int(r11_7 / 8) % 4) * 8 + b12 * 32 + (int(r6_2 / 16) % 2) * 4
|
||||||
write_mem(getreg(r9_7) + imm, getreg(r4_2), 4)
|
write_mem((r9_7 ? REG[r9_7] : 0) + imm, r4_2 ? REG[r4_2] : 0, 4)
|
||||||
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
||||||
} else if(op == 1) {
|
} else if(op == 1) {
|
||||||
if(f3 == 0) { # C.NOP / C.ADDI
|
if(f3 == 0) { # C.NOP / C.ADDI
|
||||||
imm = r6_2 + b12 * 32
|
imm = r6_2 + b12 * 32
|
||||||
if(imm >= 32) imm -= 64
|
if(imm >= 32) imm -= 64
|
||||||
setreg(r11_7, getreg(r11_7) + imm)
|
setreg(r11_7, (r11_7 ? REG[r11_7] : 0) + imm)
|
||||||
} else if(f3 == 1 || f3 == 5) { # C.JAL / C.J
|
} else if(f3 == 1 || f3 == 5) { # C.JAL / C.J
|
||||||
imm = b12 * 2048 + (int(r11_7 / 2) % 2) * 1024 + (int(r11_7 / 4) % 4) * 256 + (int(r6_2 / 16) % 2) * 128 + (r11_7 % 2) * 64 + (r6_2 % 2) * 32 + (int(r11_7 / 16)) * 16 + (int(r6_2 / 2) % 8) * 2
|
imm = b12 * 2048 + (int(r11_7 / 2) % 2) * 1024 + (int(r11_7 / 4) % 4) * 256 + (int(r6_2 / 16) % 2) * 128 + (r11_7 % 2) * 64 + (r6_2 % 2) * 32 + (int(r11_7 / 16)) * 16 + (int(r6_2 / 2) % 8) * 2
|
||||||
if(imm >= 2048) imm -= 4096
|
if(imm >= 2048) imm -= 4096
|
||||||
@@ -602,7 +659,7 @@ function amach_comp(instr, op, f3, b12, r11_7, r9_7, r6_2, r4_2, shamt, imm, ba
|
|||||||
imm = b12 * 512 + (int(r6_2 / 2) % 4) * 128 + (int(r6_2 / 8) % 2) * 64 + (r6_2 % 2) * 32 + (int(r6_2 / 16) % 2) * 16
|
imm = b12 * 512 + (int(r6_2 / 2) % 4) * 128 + (int(r6_2 / 8) % 2) * 64 + (r6_2 % 2) * 32 + (int(r6_2 / 16) % 2) * 16
|
||||||
if(imm >= 512) imm -= 1024
|
if(imm >= 512) imm -= 1024
|
||||||
if(imm == 0) trapout(sprintf("Illegal instruction C.ADDI16SP at 0x%X", pc-2))
|
if(imm == 0) trapout(sprintf("Illegal instruction C.ADDI16SP at 0x%X", pc-2))
|
||||||
setreg(2, getreg(2) + imm)
|
setreg(2, REG[2] + imm)
|
||||||
} else if(r11_7 != 0) { # C.LUI
|
} else if(r11_7 != 0) { # C.LUI
|
||||||
imm = r6_2 + b12 * 32
|
imm = r6_2 + b12 * 32
|
||||||
if(imm >= 32) imm -= 64
|
if(imm >= 32) imm -= 64
|
||||||
@@ -614,101 +671,133 @@ function amach_comp(instr, op, f3, b12, r11_7, r9_7, r6_2, r4_2, shamt, imm, ba
|
|||||||
val = int(r11_7 / 8) % 4
|
val = int(r11_7 / 8) % 4
|
||||||
if(val == 0) { # C.SRLI
|
if(val == 0) { # C.SRLI
|
||||||
if(shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
if(shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
||||||
imm = getreg(r9_7)
|
imm = r9_7 ? REG[r9_7] : 0
|
||||||
if(imm < 0) imm += 4294967296
|
if(imm < 0) imm += 4294967296
|
||||||
setreg(r9_7, int(imm / (2^shamt)))
|
setreg(r9_7, int(imm / P2[shamt]))
|
||||||
} else if(val == 1) { # C.SRAI
|
} else if(val == 1) { # C.SRAI
|
||||||
if(shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
if(shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
||||||
setreg(r9_7, floor(getreg(r9_7) / (2^shamt)))
|
setreg(r9_7, floor((r9_7 ? REG[r9_7] : 0) / P2[shamt]))
|
||||||
} else if(val == 2) { # C.ANDI
|
} else if(val == 2) { # C.ANDI
|
||||||
imm = r6_2 + b12 * 32
|
imm = r6_2 + b12 * 32
|
||||||
if(imm >= 32) imm -= 64
|
if(imm >= 32) imm -= 64
|
||||||
setreg(r9_7, bw_and(getreg(r9_7), imm))
|
setreg(r9_7, bw_and(r9_7 ? REG[r9_7] : 0, imm))
|
||||||
} else if(val == 3) { # C.SUB, C.XOR, C.OR, C.AND
|
} else if(val == 3) { # C.SUB, C.XOR, C.OR, C.AND
|
||||||
imm = int(r6_2 / 8) % 4
|
imm = int(r6_2 / 8) % 4
|
||||||
if(b12 != 0) trapout(sprintf("Illegal register-register instruction at 0x%X", pc-2))
|
if(b12 != 0) trapout(sprintf("Illegal register-register instruction at 0x%X", pc-2))
|
||||||
if(imm == 0) setreg(r9_7, getreg(r9_7) - getreg(r4_2))
|
r9_val = r9_7 ? REG[r9_7] : 0
|
||||||
else if(imm == 1) setreg(r9_7, bw_xor(getreg(r9_7), getreg(r4_2)))
|
r4_val = r4_2 ? REG[r4_2] : 0
|
||||||
else if(imm == 2) setreg(r9_7, bw_or(getreg(r9_7), getreg(r4_2)))
|
if(imm == 0) setreg(r9_7, r9_val - r4_val)
|
||||||
else if(imm == 3) setreg(r9_7, bw_and(getreg(r9_7), getreg(r4_2)))
|
else if(imm == 1) setreg(r9_7, bw_xor(r9_val, r4_val))
|
||||||
|
else if(imm == 2) setreg(r9_7, bw_or(r9_val, r4_val))
|
||||||
|
else if(imm == 3) setreg(r9_7, bw_and(r9_val, r4_val))
|
||||||
}
|
}
|
||||||
} else if(f3 == 6 || f3 == 7) { # C.BEQZ / C.BNEZ
|
} else if(f3 == 6 || f3 == 7) { # C.BEQZ / C.BNEZ
|
||||||
imm = b12 * 256 + (int(r6_2 / 8) % 4) * 64 + (r6_2 % 2) * 32 + (int(r11_7 / 8) % 4) * 8 + (int(r6_2 / 2) % 4) * 2
|
imm = b12 * 256 + (int(r6_2 / 8) % 4) * 64 + (r6_2 % 2) * 32 + (int(r11_7 / 8) % 4) * 8 + (int(r6_2 / 2) % 4) * 2
|
||||||
if(imm >= 256) imm -= 512
|
if(imm >= 256) imm -= 512
|
||||||
val = (f3 == 6) ? (getreg(r9_7) == 0) : (getreg(r9_7) != 0)
|
val = (f3 == 6) ? ((r9_7 ? REG[r9_7] : 0) == 0) : ((r9_7 ? REG[r9_7] : 0) != 0)
|
||||||
pc = val ? (pc - 2) + imm : pc
|
pc = val ? (pc - 2) + imm : pc
|
||||||
}
|
}
|
||||||
} else if(op == 2) {
|
} else if(op == 2) {
|
||||||
if(f3 == 0) { # C.SLLI
|
if(f3 == 0) { # C.SLLI
|
||||||
if(shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
if(shamt >= 32) trapout(sprintf("Illegal shift amount %d at 0x%X", shamt, pc-2))
|
||||||
if(r11_7 != 0) {
|
if(r11_7 != 0) {
|
||||||
setreg(r11_7, (getreg(r11_7) * (2^shamt)) % 4294967296)
|
setreg(r11_7, (REG[r11_7] * P2[shamt]) % 4294967296)
|
||||||
}
|
}
|
||||||
} else if(f3 == 2) { # C.LWSP
|
} else if(f3 == 2) { # C.LWSP
|
||||||
if(r11_7 == 0) trapout(sprintf("Illegal instruction C.LWSP with rd=0 at 0x%X", pc-2))
|
if(r11_7 == 0) trapout(sprintf("Illegal instruction C.LWSP with rd=0 at 0x%X", pc-2))
|
||||||
imm = (r6_2 % 4) * 64 + b12 * 32 + (int(r6_2 / 4) % 8) * 4
|
imm = (r6_2 % 4) * 64 + b12 * 32 + (int(r6_2 / 4) % 8) * 4
|
||||||
setreg(r11_7, read_mem(getreg(2) + imm, 4, 1))
|
setreg(r11_7, read_mem(REG[2] + imm, 4, 1))
|
||||||
} else if(f3 == 4) { # C.JR, C.MV, C.JALR, C.ADD
|
} else if(f3 == 4) { # C.JR, C.MV, C.JALR, C.ADD
|
||||||
if(b12 == 0) {
|
if(b12 == 0) {
|
||||||
if(r6_2 == 0) { # C.JR
|
if(r6_2 == 0) { # C.JR
|
||||||
if(r11_7 == 0) trapout(sprintf("Illegal instruction C.JR with rs1=0 at 0x%X", pc-2))
|
if(r11_7 == 0) trapout(sprintf("Illegal instruction C.JR with rs1=0 at 0x%X", pc-2))
|
||||||
pc = getreg(r11_7)
|
pc = r11_7 ? REG[r11_7] : 0
|
||||||
} else setreg(r11_7, getreg(r6_2)) # C.MV
|
} else setreg(r11_7, r6_2 ? REG[r6_2] : 0) # C.MV
|
||||||
} else {
|
} else {
|
||||||
if(r6_2 == 0) {
|
if(r6_2 == 0) {
|
||||||
if(r11_7 == 0) trapout(sprintf("EBREAK at 0x%X", pc-2)) # C.EBREAK
|
if(r11_7 == 0) trapout(sprintf("EBREAK at 0x%X", pc-2)) # C.EBREAK
|
||||||
else { # C.JALR
|
else { # C.JALR
|
||||||
imm = getreg(r11_7)
|
imm = r11_7 ? REG[r11_7] : 0
|
||||||
setreg(1, pc)
|
setreg(1, pc)
|
||||||
pc = imm
|
pc = imm
|
||||||
}
|
}
|
||||||
} else setreg(r11_7, getreg(r11_7) + getreg(r6_2)) # C.ADD
|
} else setreg(r11_7, (r11_7 ? REG[r11_7] : 0) + (r6_2 ? REG[r6_2] : 0)) # C.ADD
|
||||||
}
|
}
|
||||||
} else if(f3 == 6) { # C.SWSP
|
} else if(f3 == 6) { # C.SWSP
|
||||||
imm = (r11_7 % 4) * 64 + int(r11_7 / 4) * 4 + b12 * 32
|
imm = (r11_7 % 4) * 64 + int(r11_7 / 4) * 4 + b12 * 32
|
||||||
write_mem(getreg(2) + imm, getreg(r6_2), 4)
|
write_mem(REG[2] + imm, r6_2 ? REG[r6_2] : 0, 4)
|
||||||
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
||||||
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-2))
|
||||||
}
|
}
|
||||||
|
|
||||||
# main instruction decoding and execution routine
|
# main instruction decoding and execution routine
|
||||||
function amach_exec(instr, opcode, rd, rs1, rs2, imm, funct3, funct7) {
|
function amach_exec(instr, addr, opcode, rd, rs1, rs2, imm, funct3, funct7) {
|
||||||
if((instr % 4) != 3) {
|
if((instr % 4) != 3) {
|
||||||
amach_comp(instr)
|
amach_comp(instr, addr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
opcode = instr % 128
|
if (addr in CACHE_OPCODE) {
|
||||||
instr = int(instr / 128)
|
opcode = CACHE_OPCODE[addr]
|
||||||
rd = instr % 32
|
rd = CACHE_RD[addr]
|
||||||
imm = int(instr / 32)
|
rs1 = CACHE_RS1[addr]
|
||||||
funct3 = imm % 8
|
rs2 = CACHE_RS2[addr]
|
||||||
rs1 = int(imm / 8) % 32
|
imm = CACHE_IMM[addr]
|
||||||
rs2 = int(imm / 256) % 32
|
funct3 = CACHE_F3[addr]
|
||||||
funct7 = int(imm / 8192)
|
funct7 = CACHE_F7[addr]
|
||||||
|
} else {
|
||||||
|
opcode = instr % 128
|
||||||
|
instr = int(instr / 128)
|
||||||
|
rd = instr % 32
|
||||||
|
imm = int(instr / 32)
|
||||||
|
funct3 = imm % 8
|
||||||
|
rs1 = int(imm / 8) % 32
|
||||||
|
rs2 = int(imm / 256) % 32
|
||||||
|
funct7 = int(imm / 8192)
|
||||||
|
|
||||||
|
# Reconstruct/cache final immediate values for caching
|
||||||
|
if(opcode == 3 || opcode == 19 || opcode == 103 || opcode == 115) {
|
||||||
|
imm = imm_sign_ex(rs2 + funct7 * 32)
|
||||||
|
} else if(opcode == 35) {
|
||||||
|
imm = imm_sign_ex(rd + funct7 * 32)
|
||||||
|
} else if(opcode == 99) {
|
||||||
|
imm = rd + (funct7 % 64) * 32 + (rd % 2) * 2047 + int(funct7 / 64) * 4096
|
||||||
|
imm = imm_sign_ex_b(imm)
|
||||||
|
} else if(opcode == 111) {
|
||||||
|
imm_10_1 = int(rs2 / 2) + (funct7 % 64) * 16
|
||||||
|
imm_19_12 = funct3 + rs1 * 8
|
||||||
|
imm = imm_10_1 * 2 + (rs2 % 2) * 2048 + imm_19_12 * 4096 + int(funct7 / 64) * 1048576
|
||||||
|
if(imm >= 1048576) imm -= 2097152
|
||||||
|
} else if(opcode == 55 || opcode == 23) {
|
||||||
|
imm = imm * 4096
|
||||||
|
}
|
||||||
|
|
||||||
|
CACHE_OPCODE[addr] = opcode
|
||||||
|
CACHE_RD[addr] = rd
|
||||||
|
CACHE_RS1[addr] = rs1
|
||||||
|
CACHE_RS2[addr] = rs2
|
||||||
|
CACHE_IMM[addr] = imm
|
||||||
|
CACHE_F3[addr] = funct3
|
||||||
|
CACHE_F7[addr] = funct7
|
||||||
|
}
|
||||||
|
|
||||||
if(opcode == 51) { # 0x33, register arithmetic, type R
|
if(opcode == 51) { # 0x33, register arithmetic, type R
|
||||||
amach_reg_arith(funct3, funct7, rd, rs1, rs2)
|
amach_reg_arith(funct3, funct7, rd, rs1, rs2)
|
||||||
} else if(opcode == 47) { # 0x2f, atomic operations, type R
|
} else if(opcode == 47) { # 0x2f, atomic operations, type R
|
||||||
amach_atomic(funct3, int(funct7 / 4), int(funct7 / 2) % 2, funct7 % 2, rd, rs1, rs2)
|
amach_atomic(funct3, int(funct7 / 4), int(funct7 / 2) % 2, funct7 % 2, rd, rs1, rs2)
|
||||||
} else if(opcode == 3 || opcode == 19 || opcode == 103 || opcode == 115) { # type I
|
} else if(opcode == 3 || opcode == 19 || opcode == 103 || opcode == 115) { # type I
|
||||||
amach_imm(opcode, funct3, rd, rs1, imm_sign_ex(rs2 + funct7 * 32))
|
amach_imm(opcode, funct3, rd, rs1, imm)
|
||||||
} else if(opcode == 35) { # 0x23, store, type S
|
} else if(opcode == 35) { # 0x23, store, type S
|
||||||
amach_store(funct3, rs1, rs2, imm_sign_ex(rd + funct7 * 32))
|
amach_store(funct3, rs1, rs2, imm)
|
||||||
} else if(opcode == 99) { # 0x63, branch, type B
|
} else if(opcode == 99) { # 0x63, branch, type B
|
||||||
imm = rd + (funct7 % 64) * 32 + (rd % 2) * 2047 + int(funct7 / 64) * 4096
|
|
||||||
pc -= 4
|
pc -= 4
|
||||||
amach_branch(funct3, rs1, rs2, imm_sign_ex_b(imm))
|
amach_branch(funct3, rs1, rs2, imm)
|
||||||
} else if(opcode == 111) { # 0x6F, JAL, type J
|
} else if(opcode == 111) { # 0x6F, JAL, type J
|
||||||
setreg(rd, pc)
|
setreg(rd, pc)
|
||||||
imm_10_1 = int(rs2 / 2) + (funct7 % 64) * 16
|
|
||||||
imm_19_12 = funct3 + rs1 * 8
|
|
||||||
imm = imm_10_1 * 2 + (rs2 % 2) * 2048 + imm_19_12 * 4096 + int(funct7 / 64) * 1048576
|
|
||||||
if(imm >= 1048576) imm -= 2097152
|
|
||||||
pc += imm - 4
|
pc += imm - 4
|
||||||
} else if(opcode == 55) { # 0x37, LUI, type U
|
} else if(opcode == 55) { # 0x37, LUI, type U
|
||||||
setreg(rd, imm * 4096)
|
setreg(rd, imm)
|
||||||
} else if(opcode == 23) { # 0x17, AUIPC, type U
|
} else if(opcode == 23) { # 0x17, AUIPC, type U
|
||||||
setreg(rd, imm * 4096 + pc - 4)
|
setreg(rd, imm + pc - 4)
|
||||||
} else if(opcode == 15) { # 0x0F, FENCE, type I / no-op
|
} else if(opcode == 15) { # 0x0F, FENCE, type I / no-op
|
||||||
} else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
} else trapout(sprintf("Illegal instruction at 0x%X", pc-4))
|
||||||
}
|
}
|
||||||
@@ -726,6 +815,8 @@ BEGIN {
|
|||||||
LAST_SEC = -1
|
LAST_SEC = -1
|
||||||
VIRT_NSEC = 0
|
VIRT_NSEC = 0
|
||||||
srand()
|
srand()
|
||||||
|
STDIN_BUF = ""
|
||||||
|
for(i=0; i<=32; i++) P2[i] = 2^i
|
||||||
}
|
}
|
||||||
|
|
||||||
# Decimal memory collection section
|
# Decimal memory collection section
|
||||||
@@ -789,7 +880,7 @@ END {
|
|||||||
args[1] = "amach"
|
args[1] = "amach"
|
||||||
}
|
}
|
||||||
|
|
||||||
sp = getreg(2)
|
sp = REG[2]
|
||||||
for(i = n; i >= 1; i--) {
|
for(i = n; i >= 1; i--) {
|
||||||
len = length(args[i])
|
len = length(args[i])
|
||||||
sp = sp - (len + 1)
|
sp = sp - (len + 1)
|
||||||
@@ -812,11 +903,24 @@ END {
|
|||||||
|
|
||||||
memsize = pc - LVA
|
memsize = pc - LVA
|
||||||
pc = LVA
|
pc = LVA
|
||||||
|
ic = 0
|
||||||
while(pc > -1) {
|
while(pc > -1) {
|
||||||
instr = MEM[pc++] + 256 * MEM[pc++]
|
ic++
|
||||||
if((instr % 4) == 3) # full instruction
|
instr_pc = pc
|
||||||
instr += 65536 * MEM[pc++] + 16777216 * MEM[pc++]
|
if (instr_pc in CACHE_INSTR) {
|
||||||
amach_exec(instr) # decode and execute
|
instr = CACHE_INSTR[instr_pc]
|
||||||
|
pc += CACHE_LEN[instr_pc]
|
||||||
|
} else {
|
||||||
|
instr = MEM[pc++] + 256 * MEM[pc++]
|
||||||
|
if((instr % 4) == 3) { # full instruction
|
||||||
|
instr += 65536 * MEM[pc++] + 16777216 * MEM[pc++]
|
||||||
|
CACHE_LEN[instr_pc] = 4
|
||||||
|
} else {
|
||||||
|
CACHE_LEN[instr_pc] = 2
|
||||||
|
}
|
||||||
|
CACHE_INSTR[instr_pc] = instr
|
||||||
|
}
|
||||||
|
amach_exec(instr, instr_pc) # decode and execute
|
||||||
}
|
}
|
||||||
for(fd in FD_PATH) if(FD_DIRTY[fd]) write_fd_to_file(fd)
|
for(fd in FD_PATH) if(FD_DIRTY[fd]) write_fd_to_file(fd)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user