@@ -138,7 +138,7 @@ static bool op_misc_mem(struct riscv_t *rv, uint32_t inst UNUSED)
138
138
return true;
139
139
}
140
140
#else
141
- #define op_misc_mem NULL
141
+ #define op_misc_mem OP_UNIMP
142
142
#endif // ENABLE_Zifencei
143
143
144
144
static bool op_op_imm (struct riscv_t * rv , uint32_t inst )
@@ -758,47 +758,124 @@ static bool op_amo(struct riscv_t *rv, uint32_t inst)
758
758
return true;
759
759
}
760
760
#else
761
- #define op_amo NULL
761
+ #define op_amo OP_UNIMP
762
762
#endif // ENABLE_RV32A
763
763
764
764
/* No RV32F support */
765
- #define op_load_fp NULL
766
- #define op_store_fp NULL
767
- #define op_fp NULL
768
- #define op_madd NULL
769
- #define op_msub NULL
770
- #define op_nmsub NULL
771
- #define op_nmadd NULL
765
+ #define op_load_fp OP_UNIMP
766
+ #define op_store_fp OP_UNIMP
767
+ #define op_fp OP_UNIMP
768
+ #define op_madd OP_UNIMP
769
+ #define op_msub OP_UNIMP
770
+ #define op_nmsub OP_UNIMP
771
+ #define op_nmadd OP_UNIMP
772
+
773
+ // handler for all unimplemented opcodes
774
+ static bool op_unimp (struct riscv_t * rv , uint32_t inst UNUSED )
775
+ {
776
+ rv_except_illegal_inst (rv );
777
+ return false;
778
+ }
772
779
773
780
// opcode handler type
774
781
typedef bool (* opcode_t )(struct riscv_t * rv , uint32_t inst );
775
782
776
- // clang-format off
777
- // opcode dispatch table
778
- static const opcode_t opcodes [] = {
779
- // 000 001 010 011 100 101 110 111
780
- op_load , op_load_fp , NULL , op_misc_mem , op_op_imm , op_auipc , NULL , NULL , // 00
781
- op_store , op_store_fp , NULL , op_amo , op_op , op_lui , NULL , NULL , // 01
782
- op_madd , op_msub , op_nmsub , op_nmadd , op_fp , NULL , NULL , NULL , // 10
783
- op_branch , op_jalr , NULL , op_jal , op_system , NULL , NULL , NULL , // 11
784
- };
785
- // clang-format on
786
-
787
783
void rv_step (struct riscv_t * rv , int32_t cycles )
788
784
{
789
785
assert (rv );
790
786
const uint64_t cycles_target = rv -> csr_cycle + cycles ;
787
+ uint32_t inst , index ;
788
+
789
+ #define OP_UNIMP op_unimp
790
+ #ifdef ENABLE_COMPUTED_GOTO
791
+ #define OP (instr ) &&op_##instr
792
+ #define TABLE_TYPE const void *
793
+ #else
794
+ #define OP (instr ) op_##instr
795
+ #define TABLE_TYPE const opcode_t
796
+ #endif
797
+
798
+ // clang-format off
799
+ TABLE_TYPE jump_table [] = {
800
+ // 000 001 010 011 100 101 110 111
801
+ OP (load ), OP (load_fp ), OP (unimp ), OP (misc_mem ), OP (op_imm ), OP (auipc ), OP (unimp ), OP (unimp ), // 00
802
+ OP (store ), OP (store_fp ), OP (unimp ), OP (amo ), OP (op ), OP (lui ), OP (unimp ), OP (unimp ), // 01
803
+ OP (madd ), OP (msub ), OP (nmsub ), OP (nmadd ), OP (fp ), OP (unimp ), OP (unimp ), OP (unimp ), // 10
804
+ OP (branch ), OP (jalr ), OP (unimp ), OP (jal ), OP (system ), OP (unimp ), OP (unimp ), OP (unimp ), // 11
805
+ };
806
+ // clang-format on
807
+
808
+ #ifdef ENABLE_COMPUTED_GOTO
809
+ #define DISPATCH () \
810
+ { \
811
+ if (rv->csr_cycle >= cycles_target || rv->halt) \
812
+ goto exit; \
813
+ else { \
814
+ /* fetch the next instruction */ \
815
+ inst = rv -> io .mem_ifetch (rv , rv -> PC ); \
816
+ /* standard uncompressed instruction */ \
817
+ if ((inst & 3 ) == 3 ) { \
818
+ index = (inst & INST_6_2 ) >> 2 ; \
819
+ goto * jump_table [index ]; \
820
+ } else { \
821
+ /* TODO: compressed instruction*/ \
822
+ assert (!"Unreachable" ); \
823
+ } \
824
+ } \
825
+ }
826
+
827
+ #define EXEC (instr ) \
828
+ { \
829
+ /* dispatch this opcode */ \
830
+ if (!op_##instr(rv, inst)) \
831
+ goto exit; \
832
+ /* increment the cycles csr*/ \
833
+ rv ->csr_cycle++; \
834
+ }
835
+
836
+ #define TARGET (instr ) \
837
+ op_##instr : \
838
+ EXEC(instr); \
839
+ DISPATCH();
840
+
841
+ DISPATCH ();
842
+
843
+ // main loop
844
+ TARGET (load )
845
+ TARGET (op_imm )
846
+ TARGET (auipc )
847
+ TARGET (store )
848
+ TARGET (op )
849
+ TARGET (lui )
850
+ TARGET (branch )
851
+ TARGET (jalr )
852
+ TARGET (jal )
853
+ TARGET (system )
854
+ #ifdef ENABLE_Zifencei
855
+ TARGET (misc_mem )
856
+ #endif
857
+ #ifdef ENABLE_RV32A
858
+ TARGET (amo )
859
+ #endif
860
+ TARGET (unimp )
861
+
862
+ exit :
863
+ return ;
791
864
865
+ #undef DISPATCH
866
+ #undef EXEC
867
+ #undef TARGET
868
+ #else // ENABLE_COMPUTED_GOTO = 0
792
869
while (rv - > csr_cycle < cycles_target && !rv - > halt ) {
793
870
// fetch the next instruction
794
- const uint32_t inst = rv -> io .mem_ifetch (rv , rv -> PC );
871
+ inst = rv -> io .mem_ifetch (rv , rv -> PC );
795
872
796
873
// standard uncompressed instruction
797
874
if ((inst & 3 ) == 3 ) {
798
- const uint32_t index = (inst & INST_6_2 ) >> 2 ;
875
+ index = (inst & INST_6_2 ) >> 2 ;
799
876
800
- // dispatch this opcode
801
- const opcode_t op = opcodes [index ];
877
+ // dispatch this opcode
878
+ TABLE_TYPE op = jump_table [index ];
802
879
assert (op );
803
880
if (!op (rv , inst ))
804
881
break ;
@@ -810,6 +887,7 @@ void rv_step(struct riscv_t *rv, int32_t cycles)
810
887
assert (!"Unreachable" );
811
888
}
812
889
}
890
+ #endif // ENABLE_COMPUTED_GOTO
813
891
}
814
892
815
893
riscv_user_t rv_userdata (struct riscv_t * rv )
0 commit comments