@@ -196,7 +196,6 @@ typedef enum {
196196 CALL_R , // Opcode Register
197197 CALL_RL , // Opcode Register, Label
198198 CALL_N , // Opcode
199- CALL_I , // Opcode Immediate
200199 CALL_RII , // Opcode Register, Register, Immediate
201200 CALL_RIR , // Opcode Register, Immediate(Register)
202201 CALL_COUNT
@@ -210,7 +209,6 @@ typedef enum {
210209#define U (1 << 2) // Unsigned immediate
211210#define Z (1 << 3) // Non-zero
212211
213- typedef void (* call_l_t )(asm_rv32_t * state , mp_uint_t label_index );
214212typedef void (* call_ri_t )(asm_rv32_t * state , mp_uint_t rd , mp_int_t immediate );
215213typedef void (* call_rri_t )(asm_rv32_t * state , mp_uint_t rd , mp_uint_t rs1 , mp_int_t immediate );
216214typedef void (* call_rii_t )(asm_rv32_t * state , mp_uint_t rd , mp_uint_t immediate1 , mp_int_t immediate2 );
@@ -439,8 +437,7 @@ static bool validate_integer(mp_uint_t value, mp_uint_t mask, mp_uint_t flags) {
439437#define ET_WRONG_ARGUMENTS_COUNT MP_ERROR_TEXT("opcode '%q': expecting %d arguments")
440438#define ET_OUT_OF_RANGE MP_ERROR_TEXT("opcode '%q' argument %d: out of range")
441439
442- static bool validate_argument (emit_inline_asm_t * emit , qstr opcode_qstr ,
443- const opcode_t * opcode , mp_parse_node_t node , mp_uint_t node_index ) {
440+ static bool serialise_argument (emit_inline_asm_t * emit , const opcode_t * opcode , mp_parse_node_t node , mp_uint_t node_index , mp_uint_t * serialised ) {
444441 assert ((node_index < 3 ) && "Invalid argument node number." );
445442
446443 uint32_t kind = 0 ;
@@ -470,29 +467,31 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr,
470467 break ;
471468 }
472469
470+ mp_uint_t serialised_value = 0 ;
471+
473472 switch (kind & 0x03 ) {
474473 case N :
475474 assert (mask == OPCODE_MASKS [MASK_NOT_USED ] && "Invalid mask index for missing operand." );
476- return true ;
475+ break ;
477476
478477 case R : {
479478 mp_uint_t register_index ;
480479 if (!parse_register_node (node , & register_index , false)) {
481480 emit_inline_rv32_error_exc (emit ,
482481 mp_obj_new_exception_msg_varg (& mp_type_SyntaxError ,
483- ET_WRONG_ARGUMENT_KIND , opcode_qstr , node_index + 1 , MP_QSTR_register ));
482+ ET_WRONG_ARGUMENT_KIND , opcode -> qstring , node_index + 1 , MP_QSTR_register ));
484483 return false;
485484 }
486485
487486 if ((mask & (1U << register_index )) == 0 ) {
488487 emit_inline_rv32_error_exc (emit ,
489488 mp_obj_new_exception_msg_varg (& mp_type_SyntaxError ,
490489 MP_ERROR_TEXT ("opcode '%q' argument %d: unknown register" ),
491- opcode_qstr , node_index + 1 ));
490+ opcode -> qstring , node_index + 1 ));
492491 return false;
493492 }
494493
495- return true ;
494+ serialised_value = ( kind & C ) ? RV32_MAP_IN_C_REGISTER_WINDOW ( register_index ) : register_index ;
496495 }
497496 break ;
498497
@@ -501,7 +500,7 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr,
501500 if (!mp_parse_node_get_int_maybe (node , & object )) {
502501 emit_inline_rv32_error_exc (emit ,
503502 mp_obj_new_exception_msg_varg (& mp_type_SyntaxError ,
504- ET_WRONG_ARGUMENT_KIND , opcode_qstr , node_index + 1 , MP_QSTR_integer ));
503+ ET_WRONG_ARGUMENT_KIND , opcode -> qstring , node_index + 1 , MP_QSTR_integer ));
505504 return false;
506505 }
507506
@@ -520,15 +519,15 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr,
520519 goto zero_immediate ;
521520 }
522521
523- return true ;
522+ serialised_value = immediate ;
524523 }
525524 break ;
526525
527526 case L : {
528527 if (!MP_PARSE_NODE_IS_ID (node )) {
529528 emit_inline_rv32_error_exc (emit ,
530529 mp_obj_new_exception_msg_varg (& mp_type_SyntaxError ,
531- ET_WRONG_ARGUMENT_KIND , opcode_qstr , node_index + 1 , MP_QSTR_label ));
530+ ET_WRONG_ARGUMENT_KIND , opcode -> qstring , node_index + 1 , MP_QSTR_label ));
532531 return false;
533532 }
534533
@@ -538,7 +537,7 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr,
538537 emit_inline_rv32_error_exc (emit ,
539538 mp_obj_new_exception_msg_varg (& mp_type_SyntaxError ,
540539 MP_ERROR_TEXT ("opcode '%q' argument %d: undefined label '%q'" ),
541- opcode_qstr , node_index + 1 , qstring ));
540+ opcode -> qstring , node_index + 1 , qstring ));
542541 return false;
543542 }
544543
@@ -552,27 +551,33 @@ static bool validate_argument(emit_inline_asm_t *emit, qstr opcode_qstr,
552551 goto out_of_range ;
553552 }
554553 }
555- return true;
554+
555+ serialised_value = displacement ;
556556 }
557557 break ;
558558
559559 default :
560560 assert (!"Unknown argument kind" );
561+ MP_UNREACHABLE ;
561562 break ;
562563 }
563564
564- return false;
565+ if (serialised != NULL ) {
566+ * serialised = serialised_value ;
567+ }
568+
569+ return true;
565570
566571out_of_range :
567572 emit_inline_rv32_error_exc (emit ,
568- mp_obj_new_exception_msg_varg (& mp_type_SyntaxError , ET_OUT_OF_RANGE , opcode_qstr , node_index + 1 ));
573+ mp_obj_new_exception_msg_varg (& mp_type_SyntaxError , ET_OUT_OF_RANGE , opcode -> qstring , node_index + 1 ));
569574 return false;
570575
571576zero_immediate :
572577 emit_inline_rv32_error_exc (emit ,
573578 mp_obj_new_exception_msg_varg (& mp_type_SyntaxError ,
574579 MP_ERROR_TEXT ("opcode '%q' argument %d: must not be zero" ),
575- opcode_qstr , node_index + 1 ));
580+ opcode -> qstring , node_index + 1 ));
576581 return false;
577582}
578583
@@ -618,14 +623,14 @@ static bool parse_register_offset_node(emit_inline_asm_t *emit, qstr opcode_qstr
618623 return false;
619624 }
620625 } else {
621- if (!validate_argument (emit , opcode_qstr , opcode_data , node_struct -> nodes [0 ], 1 )) {
626+ if (!serialise_argument (emit , opcode_data , node_struct -> nodes [0 ], 1 , NULL )) {
622627 return false;
623628 }
624629 }
625630
626631 * offset_node = node_struct -> nodes [0 ];
627632 node_struct = (mp_parse_node_struct_t * )node_struct -> nodes [1 ];
628- if (!validate_argument (emit , opcode_qstr , opcode_data , node_struct -> nodes [0 ], 2 )) {
633+ if (!serialise_argument (emit , opcode_data , node_struct -> nodes [0 ], 2 , NULL )) {
629634 return false;
630635 }
631636 * register_node = node_struct -> nodes [0 ];
@@ -638,115 +643,58 @@ static bool parse_register_offset_node(emit_inline_asm_t *emit, qstr opcode_qstr
638643 return false;
639644}
640645
641- static void handle_opcode (emit_inline_asm_t * emit , qstr opcode , const opcode_t * opcode_data , mp_parse_node_t * arguments ) {
642- mp_uint_t rd = 0 ;
643- mp_uint_t rs1 = 0 ;
644- mp_uint_t rs2 = 0 ;
645-
646+ static void handle_opcode (emit_inline_asm_t * emit , const opcode_t * opcode_data , mp_uint_t * arguments ) {
646647 switch (opcode_data -> calling_convention ) {
647- case CALL_RRR : {
648- parse_register_node (arguments [0 ], & rd , opcode_data -> argument1_kind & C );
649- parse_register_node (arguments [1 ], & rs1 , opcode_data -> argument2_kind & C );
650- parse_register_node (arguments [2 ], & rs2 , opcode_data -> argument3_kind & C );
651- ((call_rrr_t )opcode_data -> emitter )(& emit -> as , rd , rs1 , rs2 );
648+ case CALL_RRR :
649+ ((call_rrr_t )opcode_data -> emitter )(& emit -> as , arguments [0 ], arguments [1 ], arguments [2 ]);
652650 break ;
653- }
654651
655- case CALL_RR : {
656- parse_register_node (arguments [0 ], & rd , opcode_data -> argument1_kind & C );
657- parse_register_node (arguments [1 ], & rs1 , opcode_data -> argument2_kind & C );
658- ((call_rr_t )opcode_data -> emitter )(& emit -> as , rd , rs1 );
652+ case CALL_RR :
653+ ((call_rr_t )opcode_data -> emitter )(& emit -> as , arguments [0 ], arguments [1 ]);
659654 break ;
660- }
661655
662- case CALL_RRI : {
663- parse_register_node (arguments [0 ], & rd , opcode_data -> argument1_kind & C );
664- parse_register_node (arguments [1 ], & rs1 , opcode_data -> argument2_kind & C );
665- mp_obj_t object ;
666- mp_parse_node_get_int_maybe (arguments [2 ], & object );
667- mp_uint_t immediate = mp_obj_get_int_truncated (object ) << opcode_data -> argument3_shift ;
668- ((call_rri_t )opcode_data -> emitter )(& emit -> as , rd , rs1 , immediate );
656+ case CALL_RRI :
657+ ((call_rri_t )opcode_data -> emitter )(& emit -> as , arguments [0 ], arguments [1 ], arguments [2 ]);
669658 break ;
670- }
671659
672- case CALL_RI : {
673- parse_register_node (arguments [0 ], & rd , opcode_data -> argument1_kind & C );
674- mp_obj_t object ;
675- mp_parse_node_get_int_maybe (arguments [1 ], & object );
676- mp_uint_t immediate = mp_obj_get_int_truncated (object ) << opcode_data -> argument2_shift ;
677- ((call_ri_t )opcode_data -> emitter )(& emit -> as , rd , immediate );
660+ case CALL_RI :
661+ ((call_ri_t )opcode_data -> emitter )(& emit -> as , arguments [0 ], arguments [1 ]);
678662 break ;
679- }
680663
681- case CALL_R : {
682- parse_register_node (arguments [0 ], & rd , opcode_data -> argument1_kind & C );
683- ((call_r_t )opcode_data -> emitter )(& emit -> as , rd );
664+ case CALL_R :
665+ ((call_r_t )opcode_data -> emitter )(& emit -> as , arguments [0 ]);
684666 break ;
685- }
686667
687- case CALL_RRL : {
688- parse_register_node (arguments [0 ], & rd , opcode_data -> argument1_kind & C );
689- parse_register_node (arguments [1 ], & rs1 , opcode_data -> argument2_kind & C );
690- qstr qstring ;
691- mp_uint_t label_index = lookup_label (emit , arguments [2 ], & qstring );
692- ptrdiff_t displacement = label_code_offset (emit , label_index );
693- ((call_rri_t )opcode_data -> emitter )(& emit -> as , rd , rs1 , displacement );
668+ case CALL_RRL :
669+ ((call_rri_t )opcode_data -> emitter )(& emit -> as , arguments [0 ], arguments [1 ], (ptrdiff_t )arguments [2 ]);
694670 break ;
695- }
696671
697- case CALL_RL : {
698- parse_register_node (arguments [0 ], & rd , opcode_data -> argument1_kind & C );
699- qstr qstring ;
700- mp_uint_t label_index = lookup_label (emit , arguments [1 ], & qstring );
701- ptrdiff_t displacement = label_code_offset (emit , label_index );
702- ((call_ri_t )opcode_data -> emitter )(& emit -> as , rd , displacement );
672+ case CALL_RL :
673+ ((call_ri_t )opcode_data -> emitter )(& emit -> as , arguments [0 ], (ptrdiff_t )arguments [1 ]);
703674 break ;
704- }
705675
706- case CALL_L : {
707- qstr qstring ;
708- mp_uint_t label_index = lookup_label (emit , arguments [0 ], & qstring );
709- ptrdiff_t displacement = label_code_offset (emit , label_index );
710- ((call_i_t )opcode_data -> emitter )(& emit -> as , displacement );
676+ case CALL_L :
677+ ((call_i_t )opcode_data -> emitter )(& emit -> as , (ptrdiff_t )arguments [0 ]);
711678 break ;
712- }
713679
714680 case CALL_N :
715681 ((call_n_t )opcode_data -> emitter )(& emit -> as );
716682 break ;
717683
718- case CALL_I : {
719- mp_obj_t object ;
720- mp_parse_node_get_int_maybe (arguments [0 ], & object );
721- mp_uint_t immediate = mp_obj_get_int_truncated (object ) << opcode_data -> argument1_shift ;
722- ((call_i_t )opcode_data -> emitter )(& emit -> as , immediate );
723- break ;
724- }
725-
726- case CALL_RII : {
727- parse_register_node (arguments [0 ], & rd , opcode_data -> argument1_kind & C );
728- mp_obj_t object ;
729- mp_parse_node_get_int_maybe (arguments [1 ], & object );
730- mp_uint_t immediate1 = mp_obj_get_int_truncated (object ) << opcode_data -> argument2_shift ;
731- mp_parse_node_get_int_maybe (arguments [2 ], & object );
732- mp_uint_t immediate2 = mp_obj_get_int_truncated (object ) << opcode_data -> argument3_shift ;
733- ((call_rii_t )opcode_data -> emitter )(& emit -> as , rd , immediate1 , immediate2 );
734- break ;
735- }
736-
737- case CALL_RIR :
738- assert (!"Should not get here." );
684+ case CALL_RII :
685+ ((call_rii_t )opcode_data -> emitter )(& emit -> as , arguments [0 ], arguments [1 ], arguments [2 ]);
739686 break ;
740687
741688 default :
742689 assert (!"Unhandled call convention." );
690+ MP_UNREACHABLE ;
743691 break ;
744692 }
745693}
746694
747695static bool handle_load_store_opcode_with_offset (emit_inline_asm_t * emit , qstr opcode , const opcode_t * opcode_data , mp_parse_node_t * argument_nodes ) {
748696 mp_parse_node_t nodes [3 ] = {0 };
749- if (!validate_argument (emit , opcode , opcode_data , argument_nodes [0 ], 0 )) {
697+ if (!serialise_argument (emit , opcode_data , argument_nodes [0 ], 0 , NULL )) {
750698 return false;
751699 }
752700 nodes [0 ] = argument_nodes [0 ];
@@ -806,16 +754,17 @@ static void emit_inline_rv32_opcode(emit_inline_asm_t *emit, qstr opcode, mp_uin
806754 ET_WRONG_ARGUMENTS_COUNT , opcode , opcode_data -> arguments_count ));
807755 return ;
808756 }
809- if (opcode_data -> arguments_count >= 1 && !validate_argument (emit , opcode , opcode_data , argument_nodes [0 ], 0 )) {
757+ mp_uint_t serialised_arguments [3 ] = { 0 };
758+ if (opcode_data -> arguments_count >= 1 && !serialise_argument (emit , opcode_data , argument_nodes [0 ], 0 , & serialised_arguments [0 ])) {
810759 return ;
811760 }
812- if (opcode_data -> arguments_count >= 2 && !validate_argument (emit , opcode , opcode_data , argument_nodes [1 ], 1 )) {
761+ if (opcode_data -> arguments_count >= 2 && !serialise_argument (emit , opcode_data , argument_nodes [1 ], 1 , & serialised_arg
4861
uments [ 1 ] )) {
813762 return ;
814763 }
815- if (opcode_data -> arguments_count >= 3 && !validate_argument (emit , opcode , opcode_data , argument_nodes [2 ], 2 )) {
764+ if (opcode_data -> arguments_count >= 3 && !serialise_argument (emit , opcode_data , argument_nodes [2 ], 2 , & serialised_arguments [ 2 ] )) {
816765 return ;
817766 }
818- handle_opcode (emit , opcode , opcode_data , argument_nodes );
767+ handle_opcode (emit , opcode_data , serialised_arguments );
819768 return ;
820769 }
821770
0 commit comments