52
52
53
53
static void rv_exception_default_handler (struct riscv_t * rv )
54
54
{
55
- rv -> csr_mepc += rv -> insn_len ;
55
+ struct rv_insn_t * ir = queue_current (& rv -> block );
56
+ rv -> csr_mepc += ir -> insn_len ;
56
57
rv -> PC = rv -> csr_mepc ; /* mret */
57
58
}
58
59
@@ -256,7 +257,7 @@ static bool insn_is_misaligned(uint32_t pc)
256
257
);
257
258
}
258
259
259
- static bool rv_emulate (struct riscv_t * rv , struct rv_insn_t * ir )
260
+ static bool emulate (struct riscv_t * rv , struct rv_insn_t * ir )
260
261
{
261
262
switch (ir -> opcode ) {
262
263
/* RV32I Base Instruction Set */
@@ -286,7 +287,7 @@ static bool rv_emulate(struct riscv_t *rv, struct rv_insn_t *ir)
286
287
rv -> PC += ir -> imm ;
287
288
/* link with return address */
288
289
if (ir -> rd )
289
- rv -> X [ir -> rd ] = pc + rv -> insn_len ;
290
+ rv -> X [ir -> rd ] = pc + ir -> insn_len ;
290
291
/* check instruction misaligned */
291
292
if (insn_is_misaligned (rv -> PC )) {
292
293
rv_except_insn_misaligned (rv , pc );
@@ -308,7 +309,7 @@ static bool rv_emulate(struct riscv_t *rv, struct rv_insn_t *ir)
308
309
rv -> PC = (rv -> X [ir -> rs1 ] + ir -> imm ) & ~1U ;
309
310
/* link */
310
311
if (ir -> rd )
311
- rv -> X [ir -> rd ] = pc + rv -> insn_len ;
312
+ rv -> X [ir -> rd ] = pc + ir -> insn_len ;
312
313
/* check instruction misaligned */
313
314
if (insn_is_misaligned (rv -> PC )) {
314
315
rv_except_insn_misaligned (rv , pc );
@@ -963,7 +964,7 @@ static bool rv_emulate(struct riscv_t *rv, struct rv_insn_t *ir)
963
964
rv -> X [ir -> rd ] += (int16_t ) ir -> imm ;
964
965
break ;
965
966
case rv_insn_cjal :
966
- rv -> X [1 ] = rv -> PC + rv -> insn_len ;
967
+ rv -> X [1 ] = rv -> PC + ir -> insn_len ;
967
968
rv -> PC += ir -> imm ;
968
969
if (rv -> PC & 0x1 ) {
969
970
rv_except_insn_misaligned (rv , rv -> PC );
@@ -1055,11 +1056,11 @@ static bool rv_emulate(struct riscv_t *rv, struct rv_insn_t *ir)
1055
1056
* the value in register rs1' is zero. It expands to beq rs1', x0,
1056
1057
* offset[8:1].
1057
1058
*/
1058
- rv -> PC += (!rv -> X [ir -> rs1 ]) ? (uint32_t ) ir -> imm : rv -> insn_len ;
1059
+ rv -> PC += (!rv -> X [ir -> rs1 ]) ? (uint32_t ) ir -> imm : ir -> insn_len ;
1059
1060
/* can branch */
1060
1061
return true;
1061
1062
case rv_insn_cbnez : /* C.BEQZ */
1062
- rv -> PC += (rv -> X [ir -> rs1 ]) ? (uint32_t ) ir -> imm : rv -> insn_len ;
1063
+ rv -> PC += (rv -> X [ir -> rs1 ]) ? (uint32_t ) ir -> imm : ir -> insn_len ;
1063
1064
/* can branch */
1064
1065
return true;
1065
1066
case rv_insn_cslli : /* C.SLLI */
@@ -1093,7 +1094,7 @@ static bool rv_emulate(struct riscv_t *rv, struct rv_insn_t *ir)
1093
1094
case rv_insn_cjalr : { /* C.JALR */
1094
1095
/* Unconditional jump and store PC+2 to ra */
1095
1096
const int32_t jump_to = rv -> X [ir -> rs1 ];
1096
- rv -> X [rv_reg_ra ] = rv -> PC + rv -> insn_len ;
1097
+ rv -> X [rv_reg_ra ] = rv -> PC + ir -> insn_len ;
1097
1098
rv -> PC = jump_to ;
1098
1099
if (rv -> PC & 0x1 ) {
1099
1100
rv_except_insn_misaligned (rv , rv -> PC );
@@ -1125,37 +1126,100 @@ static bool rv_emulate(struct riscv_t *rv, struct rv_insn_t *ir)
1125
1126
}
1126
1127
1127
1128
/* step over instruction */
1128
- rv -> PC += rv -> insn_len ;
1129
+ rv -> PC += ir -> insn_len ;
1129
1130
return true;
1130
1131
}
1131
1132
1132
- void rv_step (struct riscv_t * rv , int32_t cycles )
1133
+ static bool emulate_block (struct riscv_t * rv , block_t * block )
1133
1134
{
1134
- assert (rv );
1135
- uint32_t insn ;
1136
- struct rv_insn_t ir ;
1137
- const uint64_t cycles_target = rv -> csr_cycle + cycles ;
1138
-
1139
- while (rv -> csr_cycle < cycles_target && !rv -> halt ) {
1135
+ /* execute the block */
1136
+ while (!block_is_empty (block )) {
1140
1137
/* enforce zero register */
1141
1138
rv -> X [rv_reg_zero ] = 0 ;
1142
1139
1140
+ /* execute the instruction */
1141
+ if (!emulate (rv , queue_current (& rv -> block )))
1142
+ return false;
1143
+
1144
+ queue_dequeue (block );
1145
+
1146
+ /* increment the cycles csr */
1147
+ rv -> csr_cycle ++ ;
1148
+ }
1149
+ return true;
1150
+ }
1151
+
1152
+ static bool insn_is_branch (uint8_t opcode )
1153
+ {
1154
+ switch (opcode ) {
1155
+ case rv_insn_jal :
1156
+ case rv_insn_jalr :
1157
+ case rv_insn_beq :
1158
+ case rv_insn_bne :
1159
+ case rv_insn_blt :
1160
+ case rv_insn_bge :
1161
+ case rv_insn_bltu :
1162
+ case rv_insn_bgeu :
1163
+ case rv_insn_ecall :
1164
+ case rv_insn_ebreak :
1165
+ case rv_insn_mret :
1166
+ #if RV32_HAS (EXT_C )
1167
+ case rv_insn_cj :
1168
+ case rv_insn_cjr :
1169
+ case rv_insn_cjal :
1170
+ case rv_insn_cjalr :
1171
+ case rv_insn_cbeqz :
1172
+ case rv_insn_cbnez :
1173
+ case rv_insn_cebreak :
1174
+ #endif
1175
+ #if RV32_HAS (Zifencei )
1176
+ case rv_insn_fencei :
1177
+ #endif
1178
+ return true;
1179
+ }
1180
+ return false;
1181
+ }
1182
+
1183
+ static void translate_block (struct riscv_t * rv , block_t * block )
1184
+ {
1185
+ /* translate the basic block */
1186
+ uint32_t pc = rv -> PC ;
1187
+ block -> front = 0 ;
1188
+ block -> rear = 0 ;
1189
+ while (!block_is_full (block )) {
1190
+ struct rv_insn_t * ir = queue_enqueue (block );
1191
+ memset (ir , 0 , sizeof (struct rv_insn_t ));
1192
+
1143
1193
/* fetch the next instruction */
1144
- insn = rv -> io .mem_ifetch (rv , rv -> PC );
1145
- memset (& ir , 0 , sizeof (struct rv_insn_t ));
1194
+ const uint32_t insn = rv -> io .mem_ifetch (rv , pc );
1146
1195
1147
1196
/* decode the instruction */
1148
- if (!rv_decode (& ir , insn , & rv -> insn_len )) {
1197
+ if (!rv_decode (ir , insn )) {
1149
1198
rv_except_illegal_insn (rv , insn );
1150
1199
break ;
1151
1200
}
1152
1201
1153
- /* execute the instruciton */
1154
- if (! rv_emulate ( rv , & ir ))
1202
+ /* stop on branch */
1203
+ if (insn_is_branch ( ir -> opcode ))
1155
1204
break ;
1156
1205
1157
- /* increment the cycles csr */
1158
- rv -> csr_cycle ++ ;
1206
+ /* compute next pc */
1207
+ pc += ir -> insn_len ;
1208
+ }
1209
+ }
1210
+
1211
+ void rv_step (struct riscv_t * rv , int32_t cycles )
1212
+ {
1213
+ assert (rv );
1214
+ const uint64_t cycles_target = rv -> csr_cycle + cycles ;
1215
+
1216
+ while (rv -> csr_cycle < cycles_target && !rv -> halt ) {
1217
+ /* translate basic block */
1218
+ translate_block (rv , & rv -> block );
1219
+
1220
+ /* execute the block */
1221
+ if (!emulate_block (rv , & rv -> block ))
1222
+ break ;
1159
1223
}
1160
1224
}
1161
1225
@@ -1213,6 +1277,10 @@ struct riscv_t *rv_create(const struct riscv_io_t *io, riscv_user_t userdata)
1213
1277
/* copy over the userdata */
1214
1278
rv -> userdata = userdata ;
1215
1279
1280
+ /* place a new queue */
1281
+ if (!block_init (& rv -> block , 10 ))
1282
+ return NULL ;
1283
+
1216
1284
/* reset */
1217
1285
rv_reset (rv , 0U );
1218
1286
@@ -1232,6 +1300,7 @@ bool rv_has_halted(struct riscv_t *rv)
1232
1300
void rv_delete (struct riscv_t * rv )
1233
1301
{
1234
1302
assert (rv );
1303
+ block_free (& rv -> block );
1235
1304
free (rv );
1236
1305
}
1237
1306
@@ -1242,7 +1311,6 @@ void rv_reset(struct riscv_t *rv, riscv_word_t pc)
1242
1311
1243
1312
/* set the reset address */
1244
1313
rv -> PC = pc ;
1245
- rv -> insn_len = INSN_UNKNOWN ;
1246
1314
1247
1315
/* set the default stack pointer */
1248
1316
rv -> X [rv_reg_sp ] = DEFAULT_STACK_ADDR ;
0 commit comments