@@ -270,10 +270,6 @@ enum {
270270 rv->X[rv_reg_zero] = 0; \
271271 code; \
272272 rv->csr_cycle++; \
273- if (__rv_insn_##inst##_canbranch) { \
274- /* can branch */ \
275- return true; \
276- } \
277273 nextop: \
278274 rv->PC += ir->insn_len; \
279275 if (ir->tailcall) \
@@ -319,6 +315,7 @@ RVOP(jal, {
319315 rv_except_insn_misaligned (rv , pc );
320316 return false;
321317 }
318+ return true;
322319})
323320
324321/*The indirect jump instruction JALR uses the I-type encoding. The
@@ -341,90 +338,133 @@ RVOP(jalr, {
341338 rv_except_insn_misaligned (rv , pc );
342339 return false;
343340 }
341+ return true;
344342})
345343
346344/* BEQ: Branch if Equal */
347345RVOP (beq , {
348346 const uint32_t pc = rv -> PC ;
349- if (rv -> X [ir -> rs1 ] != rv -> X [ir -> rs2 ])
350- goto nextop ;
347+ if (rv -> X [ir -> rs1 ] != rv -> X [ir -> rs2 ]) {
348+ if (!ir -> branch_untaken )
349+ goto nextop ;
350+ rv -> PC += ir -> insn_len ;
351+ return ir -> branch_untaken -> impl (rv , ir -> branch_untaken );
352+ }
351353 rv -> PC += ir -> imm ;
352354 /* check instruction misaligned */
353355 if (unlikely (insn_is_misaligned (rv -> PC ))) {
354356 rv -> compressed = false;
355357 rv_except_insn_misaligned (rv , pc );
356358 return false;
357359 }
360+ if (ir -> branch_taken )
361+ return ir -> branch_taken -> impl (rv , ir -> branch_taken );
362+ return true;
358363})
359364
360365/* BNE: Branch if Not Equal */
361366RVOP (bne , {
362367 const uint32_t pc = rv -> PC ;
363- if (rv -> X [ir -> rs1 ] == rv -> X [ir -> rs2 ])
364- goto nextop ;
368+ if (rv -> X [ir -> rs1 ] == rv -> X [ir -> rs2 ]) {
369+ if (!ir -> branch_untaken )
370+ goto nextop ;
371+ rv -> PC += ir -> insn_len ;
372+ return ir -> branch_untaken -> impl (rv , ir -> branch_untaken );
373+ }
365374 rv -> PC += ir -> imm ;
366375 /* check instruction misaligned */
367376 if (unlikely (insn_is_misaligned (rv -> PC ))) {
368377 rv -> compressed = false;
369378 rv_except_insn_misaligned (rv , pc );
370379 return false;
371380 }
381+ if (ir -> branch_taken )
382+ return ir -> branch_taken -> impl (rv , ir -> branch_taken );
383+ return true;
372384})
373385
374386/* BLT: Branch if Less Than */
375387RVOP (blt , {
376388 const uint32_t pc = rv -> PC ;
377- if ((int32_t ) rv -> X [ir -> rs1 ] >= (int32_t ) rv -> X [ir -> rs2 ])
378- goto nextop ;
389+ if ((int32_t ) rv -> X [ir -> rs1 ] >= (int32_t ) rv -> X [ir -> rs2 ]) {
390+ if (!ir -> branch_untaken )
391+ goto nextop ;
392+ rv -> PC += ir -> insn_len ;
393+ return ir -> branch_untaken -> impl (rv , ir -> branch_untaken );
394+ }
379395 rv -> PC += ir -> imm ;
380396 /* check instruction misaligned */
381397 if (unlikely (insn_is_misaligned (rv -> PC ))) {
382398 rv -> compressed = false;
383399 rv_except_insn_misaligned (rv , pc );
384400 return false;
385401 }
402+ if (ir -> branch_taken )
403+ return ir -> branch_taken -> impl (rv , ir -> branch_taken );
404+ return true;
386405})
387406
388407/* BGE: Branch if Greater Than */
389408RVOP (bge , {
390409 const uint32_t pc = rv -> PC ;
391- if ((int32_t ) rv -> X [ir -> rs1 ] < (int32_t ) rv -> X [ir -> rs2 ])
392- goto nextop ;
410+ if ((int32_t ) rv -> X [ir -> rs1 ] < (int32_t ) rv -> X [ir -> rs2 ]) {
411+ if (!ir -> branch_untaken )
412+ goto nextop ;
413+ rv -> PC += ir -> insn_len ;
414+ return ir -> branch_untaken -> impl (rv , ir -> branch_untaken );
415+ }
393416 rv -> PC += ir -> imm ;
394417 /* check instruction misaligned */
395418 if (unlikely (insn_is_misaligned (rv -> PC ))) {
396419 rv -> compressed = false;
397420 rv_except_insn_misaligned (rv , pc );
398421 return false;
399422 }
423+ if (ir -> branch_taken )
424+ return ir -> branch_taken -> impl (rv , ir -> branch_taken );
425+ return true;
400426})
401427
402428/* BLTU: Branch if Less Than Unsigned */
403429RVOP (bltu , {
404430 const uint32_t pc = rv -> PC ;
405- if (rv -> X [ir -> rs1 ] >= rv -> X [ir -> rs2 ])
406- goto nextop ;
431+ if (rv -> X [ir -> rs1 ] >= rv -> X [ir -> rs2 ]) {
432+ if (!ir -> branch_untaken )
433+ goto nextop ;
434+ rv -> PC += ir -> insn_len ;
435+ return ir -> branch_untaken -> impl (rv , ir -> branch_untaken );
436+ }
407437 rv -> PC += ir -> imm ;
408438 /* check instruction misaligned */
409439 if (unlikely (insn_is_misaligned (rv -> PC ))) {
410440 rv -> compressed = false;
411441 rv_except_insn_misaligned (rv , pc );
412442 return false;
413443 }
444+ if (ir -> branch_taken )
445+ return ir -> branch_taken -> impl (rv , ir -> branch_taken );
446+ return true;
414447})
415448
416449/* BGEU: Branch if Greater Than Unsigned */
417450RVOP (bgeu , {
418451 const uint32_t pc = rv -> PC ;
419- if (rv -> X [ir -> rs1 ] < rv -> X [ir -> rs2 ])
420- goto nextop ;
452+ if (rv -> X [ir -> rs1 ] < rv -> X [ir -> rs2 ]) {
453+ if (!ir -> branch_untaken )
454+ goto nextop ;
455+ rv -> PC += ir -> insn_len ;
456+ return ir -> branch_untaken -> impl (rv , ir -> branch_untaken );
457+ }
421458 rv -> PC += ir -> imm ;
422459 /* check instruction misaligned */
423460 if (unlikely (insn_is_misaligned (rv -> PC ))) {
424461 rv -> compressed = false;
425462 rv_except_insn_misaligned (rv , pc );
426463 return false;
427464 }
465+ if (ir -> branch_taken )
466+ return ir -> branch_taken -> impl (rv , ir -> branch_taken );
467+ return true;
428468})
429469
430470/* LB: Load Byte */
@@ -583,12 +623,14 @@ RVOP(and, { rv->X[ir->rd] = rv->X[ir->rs1] & rv->X[ir->rs2]; })
583623RVOP (ecall , {
584624 rv -> compressed = false;
585625 rv -> io .on_ecall (rv );
626+ return true;
586627})
587628
588629/* EBREAK: Environment Break */
589630RVOP (ebreak , {
590631 rv -> compressed = false;
591632 rv -> io .on_ebreak (rv );
633+ return true;
592634})
593635
594636/* WFI: Wait for Interrupt */
@@ -616,12 +658,16 @@ RVOP(hret, {
616658})
617659
618660/* MRET: return from traps in U-mode */
619- RVOP (mret , { rv -> PC = rv -> csr_mepc ; })
661+ RVOP (mret , {
662+ rv -> PC = rv -> csr_mepc ;
663+ return true;
664+ })
620665
621666#if RV32_HAS (Zifencei ) /* RV32 Zifencei Standard Extension */
622667RVOP (fencei , {
623668 rv -> PC += ir -> insn_len ;
624669 /* FIXME: fill real implementations */
670+ return true;
625671})
626672#endif
627673
@@ -1085,6 +1131,7 @@ RVOP(cjal, {
10851131 rv_except_insn_misaligned (rv , rv -> PC );
10861132 return false;
10871133 }
1134+ return true;
10881135})
10891136
10901137/* C.LI loads the sign-extended 6-bit immediate, imm, into register rd.
@@ -1156,6 +1203,7 @@ RVOP(cj, {
11561203 rv_except_insn_misaligned (rv , rv -> PC );
11571204 return false;
11581205 }
1206+ return true;
11591207})
11601208
11611209/* C.BEQZ performs conditional control transfers. The offset is
@@ -1164,11 +1212,32 @@ RVOP(cj, {
11641212 * the value in register rs1' is zero. It expands to beq rs1', x0,
11651213 * offset[8:1].
11661214 */
1167- RVOP (cbeqz ,
1168- { rv -> PC += (!rv -> X [ir -> rs1 ]) ? (uint32_t ) ir -> imm : ir -> insn_len ; })
1215+ RVOP (cbeqz , {
1216+ if (rv -> X [ir -> rs1 ]) {
1217+ if (!ir -> branch_untaken )
1218+ goto nextop ;
1219+ rv -> PC += ir -> insn_len ;
1220+ return ir -> branch_untaken -> impl (rv , ir -> branch_untaken );
1221+ }
1222+ rv -> PC += (uint32_t ) ir -> imm ;
1223+ if (ir -> branch_taken )
1224+ return ir -> branch_taken -> impl (rv , ir -> branch_taken );
1225+ return true;
1226+ })
11691227
11701228/* C.BEQZ */
1171- RVOP (cbnez , { rv -> PC += (rv -> X [ir -> rs1 ]) ? (uint32_t ) ir -> imm : ir -> insn_len ; })
1229+ RVOP (cbnez , {
1230+ if (!rv -> X [ir -> rs1 ]) {
1231+ if (!ir -> branch_untaken )
1232+ goto nextop ;
1233+ rv -> PC += ir -> insn_len ;
1234+ return ir -> branch_untaken -> impl (rv , ir -> branch_untaken );
1235+ }
1236+ rv -> PC += (uint32_t ) ir -> imm ;
1237+ if (ir -> branch_taken )
1238+ return ir -> branch_taken -> impl (rv , ir -> branch_taken );
1239+ return true;
1240+ })
11721241
11731242/* C.SLLI is a CI-format instruction that performs a logical left shift
11741243 * of the value in register rd then writes the result to rd. The shift
@@ -1189,7 +1258,10 @@ RVOP(clwsp, {
11891258})
11901259
11911260/* C.JR */
1192- RVOP (cjr , { rv -> PC = rv -> X [ir -> rs1 ]; })
1261+ RVOP (cjr , {
1262+ rv -> PC = rv -> X [ir -> rs1 ];
1263+ return true;
1264+ })
11931265
11941266/* C.MV */
11951267RVOP (cmv , { rv -> X [ir -> rd ] = rv -> X [ir -> rs2 ]; })
@@ -1198,6 +1270,7 @@ RVOP(cmv, { rv->X[ir->rd] = rv->X[ir->rs2]; })
11981270RVOP (cebreak , {
11991271 rv -> compressed = true;
12001272 rv -> io .on_ebreak (rv );
1273+ return true;
12011274})
12021275
12031276/* C.JALR */
@@ -1211,6 +1284,7 @@ RVOP(cjalr, {
12111284 rv_except_insn_misaligned (rv , rv -> PC );
12121285 return false;
12131286 }
1287+ return true;
12141288})
12151289
12161290/* C.ADD adds the values in registers rd and rs2 and writes the
@@ -1340,6 +1414,30 @@ static void block_translate(riscv_t *rv, block_t *block)
13401414 block -> ir [block -> n_insn - 1 ].tailcall = true;
13411415}
13421416
1417+ static void extend_block (riscv_t * rv , block_t * block )
1418+ {
1419+ rv_insn_t * last_ir = block -> ir + block -> n_insn - 1 ;
1420+ if (last_ir -> branch_taken && last_ir -> branch_untaken )
1421+ return ;
1422+ /* calculate the PC of taken and untaken branches to find block */
1423+ uint32_t taken_pc = block -> pc_end - last_ir -> insn_len + last_ir -> imm ,
1424+ not_taken_pc = block -> pc_end ;
1425+
1426+ block_map_t * map = & rv -> block_map ;
1427+ block_t * next ;
1428+
1429+ /* check the branch_taken/branch_untaken pointer has been assigned and the
1430+ * first basic block in the path of the taken/untaken branches exists or
1431+ * not. If either of these conditions is not met, it will not be possible to
1432+ * extend the path of the taken/untaken branches for basic block.
1433+ */
1434+ if (!last_ir -> branch_taken && (next = block_find (map , taken_pc )))
1435+ last_ir -> branch_taken = next -> ir ;
1436+
1437+ if (!last_ir -> branch_untaken && (next = block_find (map , not_taken_pc )))
1438+ last_ir -> branch_untaken = next -> ir ;
1439+ }
1440+
13431441static block_t * block_find_or_translate (riscv_t * rv , block_t * prev )
13441442{
13451443 block_map_t * map = & rv -> block_map ;
@@ -1368,7 +1466,9 @@ static block_t *block_find_or_translate(riscv_t *rv, block_t *prev)
13681466 */
13691467 if (prev )
13701468 prev -> predict = next ;
1371- }
1469+ } else
1470+ extend_block (rv , next );
1471+
13721472
13731473 return next ;
13741474}
0 commit comments