@@ -41,3 +41,192 @@ amoadd.d:
4141 XReg virtual_address = X[rs1];
4242
4343 X[rd] = amo<64>(virtual_address, X[rs2], AmoOperation::Add, aq, rl, $encoding);
44+
45+
46+
47+ sail() : |
48+ {
49+ if extension("A") then {
50+ /* Get the address, X(rs1) (no offset).
51+ * Some extensions perform additional checks on address validity.
52+ */
53+ match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) {
54+ Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
55+ Ext_DataAddr_OK(vaddr) => {
56+ match translateAddr(vaddr, ReadWrite(Data, Data)) {
57+ TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
58+ TR_Address(addr, _) => {
59+ let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) {
60+ (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true),
61+ (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true),
62+ (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true),
63+ (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true),
64+ _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width")
65+ };
66+ let is_unsigned : bool = match op {
67+ AMOMINU => true,
68+ AMOMAXU => true,
69+ _ => false
70+ };
71+ let rs2_val : xlenbits = match width {
72+ BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]),
73+ HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]),
74+ WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]),
75+ DOUBLE => X(rs2)
76+ };
77+ match (eares) {
78+ MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
79+ MemValue(_) => {
80+ let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) {
81+ (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)),
82+ (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)),
83+ (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)),
84+ (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)),
85+ _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width")
86+ };
87+ match (mval) {
88+ MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
89+ MemValue(loaded) => {
90+ let result : xlenbits =
91+ match op {
92+ AMOSWAP => rs2_val,
93+ AMOADD => rs2_val + loaded,
94+ AMOXOR => rs2_val ^ loaded,
95+ AMOAND => rs2_val & loaded,
96+ AMOOR => rs2_val | loaded,
97+
98+ /* These operations convert bitvectors to integer values using [un]signed,
99+ * and back using to_bits().
100+ */
101+ AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))),
102+ AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))),
103+ AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))),
104+ AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded)))
105+ };
106+ let rval : xlenbits = match width {
107+ BYTE => sign_extend(loaded[7..0]),
108+ HALF => sign_extend(loaded[15..0]),
109+ WORD => sign_extend(loaded[31..0]),
110+ DOUBLE => loaded
111+ };
112+ let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) {
113+ (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true),
114+ (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true),
115+ (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true),
116+ (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true),
117+ _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width")
118+ };
119+ match (wval) {
120+ MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS },
121+ MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") },
122+ MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }
123+ }
124+ }
125+ }
126+ }
127+ }
128+ }
129+ }
130+ }
131+ }
132+ } else {
133+ handle_illegal();
134+ RETIRE_FAIL
135+ }
136+ }
137+
138+
139+
140+
141+ sail() : |
142+ {
143+ if extension("A") then {
144+ /* Get the address, X(rs1) (no offset).
145+ * Some extensions perform additional checks on address validity.
146+ */
147+ match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) {
148+ Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL },
149+ Ext_DataAddr_OK(vaddr) => {
150+ match translateAddr(vaddr, ReadWrite(Data, Data)) {
151+ TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
152+ TR_Address(addr, _) => {
153+ let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) {
154+ (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true),
155+ (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true),
156+ (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true),
157+ (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true),
158+ _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width")
159+ };
160+ let is_unsigned : bool = match op {
161+ AMOMINU => true,
162+ AMOMAXU => true,
163+ _ => false
164+ };
165+ let rs2_val : xlenbits = match width {
166+ BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]),
167+ HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]),
168+ WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]),
169+ DOUBLE => X(rs2)
170+ };
171+ match (eares) {
172+ MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
173+ MemValue(_) => {
174+ let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) {
175+ (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)),
176+ (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)),
177+ (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)),
178+ (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)),
179+ _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width")
180+ };
181+ match (mval) {
182+ MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL },
183+ MemValue(loaded) => {
184+ let result : xlenbits =
185+ match op {
186+ AMOSWAP => rs2_val,
187+ AMOADD => rs2_val + loaded,
188+ AMOXOR => rs2_val ^ loaded,
189+ AMOAND => rs2_val & loaded,
190+ AMOOR => rs2_val | loaded,
191+
192+ /* These operations convert bitvectors to integer values using [un]signed,
193+ * and back using to_bits().
194+ */
195+ AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))),
196+ AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))),
197+ AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))),
198+ AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded)))
199+ };
200+ let rval : xlenbits = match width {
201+ BYTE => sign_extend(loaded[7..0]),
202+ HALF => sign_extend(loaded[15..0]),
203+ WORD => sign_extend(loaded[31..0]),
204+ DOUBLE => loaded
205+ };
206+ let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) {
207+ (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true),
208+ (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true),
209+ (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true),
210+ (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true),
211+ _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width")
212+ };
213+ match (wval) {
214+ MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS },
215+ MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") },
216+ MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }
217+ }
218+ }
219+ }
220+ }
221+ }
222+ }
223+ }
224+ }
225+ }
226+ } else {
227+ handle_illegal();
228+ RETIRE_FAIL
229+ }
230+ }
231+
232+
0 commit comments