Repository navigation
Expand file tree
/
Copy pathriscv_utils.py
More file actions
135 lines (108 loc) · 3.24 KB
/
Copy pathriscv_utils.py
File metadata and controls
135 lines (108 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
MASK32 = 0xFFFFFFFF
SIGN32 = 0x80000000
INT32_MIN = -0x80000000
LOAD_BYTE = 0
LOAD_HALFWORD = 1
LOAD_WORD = 2
LOAD_DOUBLEWORD = 3
LOAD_BYTE_UNSIGNED = 4
LOAD_HALFWORD_UNSIGNED = 5
_DATA_TYPE_SIZES = {
LOAD_BYTE: 1,
LOAD_HALFWORD: 2,
LOAD_WORD: 4,
LOAD_DOUBLEWORD: 8,
LOAD_BYTE_UNSIGNED: 1,
LOAD_HALFWORD_UNSIGNED: 2,
}
_DATA_TYPE_NAMES = {
LOAD_BYTE: "byte",
LOAD_HALFWORD: "halfword",
LOAD_WORD: "word",
LOAD_DOUBLEWORD: "doubleword",
LOAD_BYTE_UNSIGNED: "unsigned byte",
LOAD_HALFWORD_UNSIGNED: "unsigned halfword",
}
def u32(value):
return value & MASK32
def s32(value):
value = u32(value)
if value & SIGN32:
return value - (1 << 32)
return value
def sign_extend(value, bits):
sign_bit = 1 << (bits - 1)
value &= (1 << bits) - 1
return (value ^ sign_bit) - sign_bit
def shift_amount(value):
return value & 0x1F
def riscv_div(dividend, divisor):
dividend = s32(dividend)
divisor = s32(divisor)
if divisor == 0:
return MASK32
if dividend == INT32_MIN and divisor == -1:
return u32(dividend)
quotient = abs(dividend) // abs(divisor)
if (dividend < 0) ^ (divisor < 0):
quotient = -quotient
return u32(quotient)
def riscv_rem(dividend, divisor):
dividend = s32(dividend)
divisor = s32(divisor)
if divisor == 0:
return u32(dividend)
if dividend == INT32_MIN and divisor == -1:
return 0
remainder = abs(dividend) % abs(divisor)
if dividend < 0:
remainder = -remainder
return u32(remainder)
def branch_taken(funct3, rs1, rs2):
if funct3 == 0:
return u32(rs1) == u32(rs2)
if funct3 == 1:
return u32(rs1) != u32(rs2)
if funct3 == 4:
return s32(rs1) < s32(rs2)
if funct3 == 5:
return s32(rs1) >= s32(rs2)
if funct3 == 6:
return u32(rs1) < u32(rs2)
if funct3 == 7:
return u32(rs1) >= u32(rs2)
raise ValueError(f"Unsupported branch funct3: {funct3}")
def data_type_size(data_type):
try:
return _DATA_TYPE_SIZES[data_type]
except KeyError as exc:
raise ValueError(f"Unsupported memory data type: {data_type}") from exc
def data_type_name(data_type):
try:
return _DATA_TYPE_NAMES[data_type]
except KeyError as exc:
raise ValueError(f"Unsupported memory data type: {data_type}") from exc
def load_extend(data_type, value):
if data_type == LOAD_BYTE:
return u32(sign_extend(value, 8))
if data_type == LOAD_HALFWORD:
return u32(sign_extend(value, 16))
if data_type == LOAD_WORD:
return u32(value)
if data_type == LOAD_DOUBLEWORD:
return value & ((1 << 64) - 1)
if data_type == LOAD_BYTE_UNSIGNED:
return value & 0xFF
if data_type == LOAD_HALFWORD_UNSIGNED:
return value & 0xFFFF
raise ValueError(f"Unsupported memory data type: {data_type}")
def mask_store_value(data_type, value):
if data_type == LOAD_BYTE:
return value & 0xFF
if data_type == LOAD_HALFWORD:
return value & 0xFFFF
if data_type == LOAD_WORD:
return value & MASK32
if data_type == LOAD_DOUBLEWORD:
return value & ((1 << 64) - 1)
raise ValueError(f"Unsupported store data type: {data_type}")