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