diff --git a/src/frontend/frontend.sv b/src/frontend/frontend.sv
index b9104b92b1e952984a893dcb4d8211b2a083263c..6178aab4cdded77bc47dcfe7c9150a6c9191d165 100644
--- a/src/frontend/frontend.sv
+++ b/src/frontend/frontend.sv
@@ -136,11 +136,11 @@ module frontend import ariane_pkg::*; #(
       // unconditional jumps with known target -> immediately resolved
       assign is_jump[i] = instruction_valid[i] & (rvi_jump[i] | rvc_jump[i]);
       // unconditional jumps with unknown target -> BTB
-      assign is_jalr[i] = instruction_valid[i] & ~is_return[i] & ~is_call[i] & (rvi_jalr[i] | rvc_jalr[i] | rvc_jr[i]);
+      assign is_jalr[i] = instruction_valid[i] & (rvi_jalr[i] | rvc_jalr[i] | rvc_jr[i]);
     end
 
     logic should_stall;
-    assign should_stall = (stalling_q | (|is_branch) | (|is_return) | (|is_jalr)) & (!resolved_branch_i.valid);
+    assign should_stall = (stalling_q | (|is_branch) | (|is_jalr)) & (!resolved_branch_i.valid || (resolved_branch_i.cf_type == Jump));
 
     // taken/not taken
     always_comb begin
@@ -150,15 +150,19 @@ module frontend import ariane_pkg::*; #(
       predict_address = '0;
       bp_valid = 1'b0;
 
-      if (!should_stall) begin
+      if (replay) begin
+         stalling_d = 1'b0;
+      end else if (!stalling_q || (resolved_branch_i.valid && resolved_branch_i.cf_type != Jump)) begin
          stalling_d = 1'b0;
 
          for (int unsigned i = 0; i < INSTR_PER_FETCH; i++) begin
-            unique case ({is_branch[i] | is_return[i] | is_jalr[i], is_jump[i]})
+            cf_type[i] = ariane_pkg::NoCF;
+
+            unique case ({is_branch[i] | is_jalr[i], is_jump[i]})
               2'b00:;
               2'b01: begin
                  if (!(|taken_rvi_cf) && !(|taken_rvc_cf))
-                   predict_address = addr[i] + (taken_rvc_cf[i] ? rvc_imm[i] : rvi_imm[i]);
+                   predict_address = addr[i] + (rvc_jump[i] ? rvc_imm[i] : rvi_imm[i]);
 
                  taken_rvi_cf[i] = rvi_jump[i];
                  taken_rvc_cf[i] = rvc_jump[i];
@@ -166,6 +170,9 @@ module frontend import ariane_pkg::*; #(
                  bp_valid = 1'b1;
               end
               2'b10: begin
+                 if (!(|taken_rvi_cf) && !(|taken_rvc_cf))
+                   predict_address = addr[i] + 'h4;
+
                  taken_rvi_cf[i] = 1'b1;
                  taken_rvc_cf[i] = 1'b1;
                  bp_valid = 1'b1;
@@ -180,13 +187,13 @@ module frontend import ariane_pkg::*; #(
     assign is_mispredict = resolved_branch_i.valid & resolved_branch_i.is_mispredict;
 
     // Cache interface
-    assign icache_dreq_o.req = instr_queue_ready & (!should_stall);
-    assign if_ready = icache_dreq_i.ready & instr_queue_ready;
+    assign icache_dreq_o.req = instr_queue_ready & (!should_stall | replay);
+    assign if_ready = icache_dreq_i.ready & instr_queue_ready & (!should_stall);
     // We need to flush the cache pipeline if:
     // 1. We mispredicted
     // 2. Want to flush the whole processor front-end
     // 3. Need to replay an instruction because the fetch-fifo was full
-    assign icache_dreq_o.kill_s1 = is_mispredict | flush_i | replay;
+    assign icache_dreq_o.kill_s1 = is_mispredict | flush_i;
     // if we have a valid branch-prediction we need to only kill the last cache request
     // also if we killed the first stage we also need to kill the second stage (inclusive flush)
     assign icache_dreq_o.kill_s2 = icache_dreq_o.kill_s1 | bp_valid;
@@ -220,35 +227,33 @@ module frontend import ariane_pkg::*; #(
         npc_d            = npc_q;
       end
 
-      if (!should_stall) begin
-         // 0. Branch Prediction
-         if (bp_valid) begin
-            fetch_address = predict_address;
-            npc_d = predict_address;
-         end
-         // 1. Default assignment
-         if (if_ready) npc_d = {fetch_address[riscv::VLEN-1:2], 2'b0}  + 'h4;
-         // 2. Replay instruction fetch
-         if (replay) npc_d = replay_addr;
-         // 3. Control flow change request
-         if (is_mispredict) npc_d = resolved_branch_i.target_address;
-         // 4. Return from environment call
-         if (eret_i) npc_d = epc_i;
-         // 5. Exception/Interrupt
-         if (ex_valid_i) npc_d = trap_vector_base_i;
-         // 6. Pipeline Flush because of CSR side effects
-         // On a pipeline flush start fetching from the next address
-         // of the instruction in the commit stage
-         // we came here from a flush request of a CSR instruction or AMO,
-         // as CSR or AMO instructions do not exist in a compressed form
-         // we can unconditionally do PC + 4 here
-         // TODO(zarubaf) This adder can at least be merged with the one in the csr_regfile stage
-         if (set_pc_commit_i) npc_d = pc_commit_i + {{riscv::VLEN-3{1'b0}}, 3'b100};
-         // 7. Debug
-         // enter debug on a hard-coded base-address
-         if (set_debug_pc_i) npc_d = ArianeCfg.DmBaseAddress[riscv::VLEN-1:0] + dm::HaltAddress[riscv::VLEN-1:0];
-         icache_dreq_o.vaddr = fetch_address;
+      // 0. Branch Prediction
+      if (bp_valid) begin
+         fetch_address = predict_address;
+         npc_d = predict_address;
       end
+      // 1. Default assignment
+      if (if_ready) npc_d = {fetch_address[riscv::VLEN-1:2], 2'b0}  + 'h4;
+      // 2. Replay instruction fetch
+      if (replay) npc_d = replay_addr;
+      // 3. Control flow change request
+      if (is_mispredict) npc_d = resolved_branch_i.target_address;
+      // 4. Return from environment call
+      if (eret_i) npc_d = epc_i;
+      // 5. Exception/Interrupt
+      if (ex_valid_i) npc_d = trap_vector_base_i;
+      // 6. Pipeline Flush because of CSR side effects
+      // On a pipeline flush start fetching from the next address
+      // of the instruction in the commit stage
+      // we came here from a flush request of a CSR instruction or AMO,
+      // as CSR or AMO instructions do not exist in a compressed form
+      // we can unconditionally do PC + 4 here
+      // TODO(zarubaf) This adder can at least be merged with the one in the csr_regfile stage
+      if (set_pc_commit_i) npc_d = pc_commit_i + {{riscv::VLEN-3{1'b0}}, 3'b100};
+      // 7. Debug
+      // enter debug on a hard-coded base-address
+      if (set_debug_pc_i) npc_d = ArianeCfg.DmBaseAddress[riscv::VLEN-1:0] + dm::HaltAddress[riscv::VLEN-1:0];
+      icache_dreq_o.vaddr = fetch_address;
     end
 
     logic [FETCH_WIDTH-1:0] icache_data;
@@ -281,7 +286,11 @@ module frontend import ariane_pkg::*; #(
           end else icache_ex_valid_q <= ariane_pkg::FE_NONE;
           // save the uppermost prediction
         end
-        stalling_q           <= stalling_d;
+
+        if (flush_i)
+          stalling_q         <= 1'b0;
+        else
+          stalling_q         <= stalling_d;
       end
     end