@@ -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,122 @@ 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
+ // clang-format off
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
+ TABLE_TYPE jump_table [] = {
799
+ // 000 001 010 011 100 101 110 111
800
+ OP (load ), OP (load_fp ), OP (unimp ), OP (misc_mem ), OP (op_imm ), OP (auipc ), OP (unimp ), OP (unimp ), // 00
801
+ OP (store ), OP (store_fp ), OP (unimp ), OP (amo ), OP (op ), OP (lui ), OP (unimp ), OP (unimp ), // 01
802
+ OP (madd ), OP (msub ), OP (nmsub ), OP (nmadd ), OP (fp ), OP (unimp ), OP (unimp ), OP (unimp ), // 10
803
+ OP (branch ), OP (jalr ), OP (unimp ), OP (jal ), OP (system ), OP (unimp ), OP (unimp ), OP (unimp ), // 11
804
+ };
805
+ // clang-format on
806
+
807
+ #ifdef ENABLE_COMPUTED_GOTO
808
+ #define DISPATCH () \
809
+ { \
810
+ if (rv->csr_cycle >= cycles_target || rv->halt) \
811
+ goto exit; \
812
+ /* fetch the next instruction */ \
813
+ inst = rv -> io .mem_ifetch (rv , rv -> PC ); \
814
+ /* standard uncompressed instruction */ \
815
+ if ((inst & 3 ) == 3 ) { \
816
+ index = (inst & INST_6_2 ) >> 2 ; \
817
+ goto * jump_table [index ]; \
818
+ } else { \
819
+ /* TODO: compressed instruction*/ \
820
+ assert (!"Unreachable" ); \
821
+ } \
822
+ }
823
+
824
+ #define EXEC (instr ) \
825
+ { \
826
+ /* dispatch this opcode */ \
827
+ if (!op_##instr(rv, inst)) \
828
+ goto exit; \
829
+ /* increment the cycles csr*/ \
830
+ rv ->csr_cycle++; \
831
+ }
832
+ // clang-format off
833
+ #define TARGET (instr ) \
834
+ op_##instr : \
835
+ EXEC(instr); \
836
+ DISPATCH();
837
+ // clang-format on
838
+
839
+ DISPATCH ();
840
+
841
+ // main loop
842
+ TARGET (load )
843
+ TARGET (op_imm )
844
+ TARGET (auipc )
845
+ TARGET (store )
846
+ TARGET (op )
847
+ TARGET (lui )
848
+ TARGET (branch )
849
+ TARGET (jalr )
850
+ TARGET (jal )
851
+ TARGET (system )
852
+ #ifdef ENABLE_Zifencei
853
+ TARGET (misc_mem )
854
+ #endif
855
+ #ifdef ENABLE_RV32A
856
+ TARGET (amo )
857
+ #endif
858
+ TARGET (unimp )
859
+
860
+ exit :
861
+ return ;
791
862
863
+ #undef DISPATCH
864
+ #undef EXEC
865
+ #undef TARGET
866
+ #else // ENABLE_COMPUTED_GOTO = 0
792
867
while (rv - > csr_cycle < cycles_target && !rv - > halt ) {
793
868
// fetch the next instruction
794
- const uint32_t inst = rv -> io .mem_ifetch (rv , rv -> PC );
869
+ inst = rv -> io .mem_ifetch (rv , rv -> PC );
795
870
796
871
// standard uncompressed instruction
797
872
if ((inst & 3 ) == 3 ) {
798
- const uint32_t index = (inst & INST_6_2 ) >> 2 ;
873
+ index = (inst & INST_6_2 ) >> 2 ;
799
874
800
- // dispatch this opcode
801
- const opcode_t op = opcodes [index ];
875
+ // dispatch this opcode
876
+ TABLE_TYPE op = jump_table [index ];
802
877
assert (op );
803
878
if (!op (rv , inst ))
804
879
break ;
@@ -810,6 +885,7 @@ void rv_step(struct riscv_t *rv, int32_t cycles)
810
885
assert (!"Unreachable" );
811
886
}
812
887
}
888
+ #endif // ENABLE_COMPUTED_GOTO
813
889
}
814
890
815
891
riscv_user_t rv_userdata (struct riscv_t * rv )
0 commit comments