@@ -63,6 +63,9 @@ static void asm_emit_opcode(uint32_t opcode);
6363static void asm_emit_r (int token , uint32_t opcode , const Operand * rd , const Operand * rs1 , const Operand * rs2 );
6464static void asm_emit_s (int token , uint32_t opcode , const Operand * rs1 , const Operand * rs2 , const Operand * imm );
6565static void asm_emit_u (int token , uint32_t opcode , const Operand * rd , const Operand * rs2 );
66+ static void asm_emit_f (int token , uint32_t opcode , const Operand * rd , const Operand * rs1 , const Operand * rs2 );
67+ static void asm_emit_fb (int token , uint32_t opcode , const Operand * rd , const Operand * rs );
68+ static void asm_emit_fq (int token , uint32_t opcode , const Operand * rd , const Operand * rs1 , const Operand * rs2 , const Operand * rs3 );
6669ST_FUNC void asm_gen_code (ASMOperand * operands , int nb_operands , int nb_outputs , int is_output , uint8_t * clobber_regs , int out_reg );
6770static void asm_nullary_opcode (TCCState * s1 , int token );
6871ST_FUNC void asm_opcode (TCCState * s1 , int token );
@@ -587,6 +590,14 @@ static void asm_binary_opcode(TCCState* s1, int token)
587590 asm_emit_css (token , 2 | (5 << 13 ), ops , ops + 1 );
588591 return ;
589592
593+ /* F/D extension */
594+ case TOK_ASM_fsqrt_d :
595+ asm_emit_fb (token , 0x53 | (11 << 27 ) | (1 << 25 ) | (7 << 12 ), ops , ops + 1 );
596+ return ;
597+ case TOK_ASM_fsqrt_s :
598+ asm_emit_fb (token , 0x53 | (11 << 27 ) | (0 << 25 ) | (7 << 12 ), ops , ops + 1 );
599+ return ;
600+
590601 /* pseudoinstructions */
591602 /* rd, sym */
592603 case TOK_ASM_la :
@@ -682,6 +693,15 @@ static void asm_binary_opcode(TCCState* s1, int token)
682693 asm_emit_r (token , (0xC << 2 ) | 3 | (2 << 12 ), & ops [0 ], & zero , & ops [1 ]);
683694 return ;
684695
696+ case TOK_ASM_fabs_d :
697+ /* fsgnjx.d rd, rs, rs */
698+ asm_emit_f (token , 0x53 | (4 << 27 ) | (1 << 25 ) | (2 << 12 ), & ops [0 ], & ops [1 ], & ops [1 ]);
699+ return ;
700+ case TOK_ASM_fabs_s :
701+ /* fsgnjx.s rd, rs, rs */
702+ asm_emit_f (token , 0x53 | (4 << 27 ) | (0 << 25 ) | (2 << 12 ), & ops [0 ], & ops [1 ], & ops [1 ]);
703+ return ;
704+
685705 default :
686706 expect ("binary instruction" );
687707 }
@@ -709,6 +729,73 @@ static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Oper
709729 gen_le32 (opcode | ENCODE_RD (rd -> reg ) | ENCODE_RS1 (rs1 -> reg ) | ENCODE_RS2 (rs2 -> reg ));
710730}
711731
732+ /* caller: Add rounding mode, fmt, funct5 to opcode */
733+ static void asm_emit_f (int token , uint32_t opcode , const Operand * rd , const Operand * rs1 , const Operand * rs2 )
734+ {
735+ if (rd -> type != OP_REG || !REG_IS_FLOAT (rd -> reg )) {
736+ tcc_error ("'%s': Expected destination operand that is a floating-point register" , get_tok_str (token , NULL ));
737+ }
738+ if (rs1 -> type != OP_REG || !REG_IS_FLOAT (rs1 -> reg )) {
739+ tcc_error ("'%s': Expected first source operand that is a floating-point register" , get_tok_str (token , NULL ));
740+ }
741+ if (rs2 -> type != OP_REG || !REG_IS_FLOAT (rs2 -> reg )) {
742+ tcc_error ("'%s': Expected second source operand that is a floating-point register" , get_tok_str (token , NULL ));
743+ }
744+ /* F-type instruction:
745+ 31...27 funct5
746+ 26...25 fmt
747+ 24...20 rs2
748+ 19...15 rs1
749+ 14...12 rm
750+ 11...7 rd
751+ 6...0 opcode = OP-FP */
752+ gen_le32 (opcode | ENCODE_RD (rd -> reg ) | ENCODE_RS1 (rs1 -> reg ) | ENCODE_RS2 (rs2 -> reg ));
753+ }
754+ /* caller: Add rounding mode, fmt, funct5 to opcode */
755+ static void asm_emit_fb (int token , uint32_t opcode , const Operand * rd , const Operand * rs )
756+ {
757+ if (rd -> type != OP_REG || !REG_IS_FLOAT (rd -> reg )) {
758+ tcc_error ("'%s': Expected destination operand that is a floating-point register" , get_tok_str (token , NULL ));
759+ }
760+ if (rs -> type != OP_REG || !REG_IS_FLOAT (rs -> reg )) {
761+ tcc_error ("'%s': Expected source operand that is a floating-point register" , get_tok_str (token , NULL ));
762+ }
763+ /* F-type instruction:
764+ 31...27 funct5
765+ 26...25 fmt
766+ 24...20 rs2 = 0
767+ 19...15 rs1 = rs
768+ 14...12 rm
769+ 11...7 rd
770+ 6...0 opcode = OP-FP */
771+ gen_le32 (opcode | ENCODE_RD (rd -> reg ) | ENCODE_RS1 (rs -> reg ) | ENCODE_RS2 (0 ));
772+ }
773+ /* caller: Add rounding mode, fmt to opcode */
774+ static void asm_emit_fq (int token , uint32_t opcode , const Operand * rd , const Operand * rs1 , const Operand * rs2 , const Operand * rs3 )
775+ {
776+ if (rd -> type != OP_REG || !REG_IS_FLOAT (rd -> reg )) {
777+ tcc_error ("'%s': Expected destination operand that is a floating-point register" , get_tok_str (token , NULL ));
778+ }
779+ if (rs1 -> type != OP_REG || !REG_IS_FLOAT (rs1 -> reg )) {
780+ tcc_error ("'%s': Expected first source operand that is a floating-point register" , get_tok_str (token , NULL ));
781+ }
782+ if (rs2 -> type != OP_REG || !REG_IS_FLOAT (rs2 -> reg )) {
783+ tcc_error ("'%s': Expected second source operand that is a floating-point register" , get_tok_str (token , NULL ));
784+ }
785+ if (rs3 -> type != OP_REG || !REG_IS_FLOAT (rs3 -> reg )) {
786+ tcc_error ("'%s': Expected third source operand that is a floating-point register" , get_tok_str (token , NULL ));
787+ }
788+ /* F-type instruction:
789+ 31...27 rs3
790+ 26...25 fmt
791+ 24...20 rs2
792+ 19...15 rs1
793+ 14...12 rm
794+ 11...7 rd
795+ 6...0 opcode */
796+ gen_le32 (opcode | ENCODE_RD (rd -> reg ) | ENCODE_RS1 (rs1 -> reg ) | ENCODE_RS2 (rs2 -> reg ) | (REG_VALUE (rs3 -> reg ) << 27 ));
797+ }
798+
712799/* caller: Add funct3 into opcode */
713800static void asm_emit_i (int token , uint32_t opcode , const Operand * rd , const Operand * rs1 , const Operand * rs2 )
714801{
@@ -1089,11 +1176,49 @@ static void asm_ternary_opcode(TCCState *s1, int token)
10891176 asm_emit_cs (token , 6 << 13 , ops , ops + 1 , ops + 2 );
10901177 return ;
10911178
1179+ /* F/D extension */
1180+ case TOK_ASM_fsgnj_d :
1181+ asm_emit_f (token , 0x53 | (4 << 27 ) | (1 << 25 ) | (0 << 12 ), ops , ops + 1 , ops + 2 );
1182+ return ;
1183+ case TOK_ASM_fsgnj_s :
1184+ asm_emit_f (token , 0x53 | (4 << 27 ) | (0 << 25 ) | (0 << 12 ), ops , ops + 1 , ops + 2 );
1185+ return ;
1186+ case TOK_ASM_fmax_d :
1187+ asm_emit_f (token , 0x53 | (5 << 27 ) | (1 << 25 ) | (1 << 12 ), ops , ops + 1 , ops + 2 );
1188+ return ;
1189+ case TOK_ASM_fmax_s :
1190+ asm_emit_f (token , 0x53 | (5 << 27 ) | (0 << 25 ) | (1 << 12 ), ops , ops + 1 , ops + 2 );
1191+ return ;
1192+ case TOK_ASM_fmin_d :
1193+ asm_emit_f (token , 0x53 | (5 << 27 ) | (1 << 25 ) | (0 << 12 ), ops , ops + 1 , ops + 2 );
1194+ return ;
1195+ case TOK_ASM_fmin_s :
1196+ asm_emit_f (token , 0x53 | (5 << 27 ) | (0 << 25 ) | (0 << 12 ), ops , ops + 1 , ops + 2 );
1197+ return ;
1198+
10921199 default :
10931200 expect ("ternary instruction" );
10941201 }
10951202}
10961203
1204+ static void asm_quaternary_opcode (TCCState * s1 , int token )
1205+ {
1206+ Operand ops [4 ];
1207+ parse_operands (s1 , & ops [0 ], 4 );
1208+
1209+ switch (token ) {
1210+ case TOK_ASM_fmadd_d :
1211+ asm_emit_fq (token , 0x43 | (1 << 25 ) | (7 << 12 ), ops , ops + 1 , ops + 2 , ops + 3 );
1212+ return ;
1213+ case TOK_ASM_fmadd_s :
1214+ asm_emit_fq (token , 0x43 | (0 << 25 ) | (7 << 12 ), ops , ops + 1 , ops + 2 , ops + 3 );
1215+ return ;
1216+
1217+ default :
1218+ expect ("quaternary instruction" );
1219+ }
1220+ }
1221+
10971222static void asm_atomic_opcode (TCCState * s1 , int token )
10981223{
10991224 Operand ops [3 ];
@@ -1271,6 +1396,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
12711396
12721397 case TOK_ASM_lui :
12731398 case TOK_ASM_auipc :
1399+ case TOK_ASM_fsqrt_s :
1400+ case TOK_ASM_fsqrt_d :
12741401 asm_binary_opcode (s1 , token );
12751402 return ;
12761403
@@ -1349,8 +1476,19 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
13491476 case TOK_ASM_csrrsi :
13501477 case TOK_ASM_csrrw :
13511478 case TOK_ASM_csrrwi :
1479+ /* F/D extension */
1480+ case TOK_ASM_fsgnj_d :
1481+ case TOK_ASM_fsgnj_s :
1482+ case TOK_ASM_fmax_s :
1483+ case TOK_ASM_fmax_d :
1484+ case TOK_ASM_fmin_s :
1485+ case TOK_ASM_fmin_d :
13521486 asm_ternary_opcode (s1 , token );
13531487 return ;
1488+ case TOK_ASM_fmadd_d :
1489+ case TOK_ASM_fmadd_s :
1490+ asm_quaternary_opcode (s1 , token );
1491+ return ;
13541492
13551493 /* Branches */
13561494 case TOK_ASM_beq :
@@ -1441,6 +1579,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
14411579 case TOK_ASM_not :
14421580 case TOK_ASM_neg :
14431581 case TOK_ASM_negw :
1582+ case TOK_ASM_fabs_s :
1583+ case TOK_ASM_fabs_d :
14441584 asm_binary_opcode (s1 , token );
14451585 return ;
14461586
@@ -1556,7 +1696,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
15561696 if ((sv -> type .t & VT_BTYPE ) == VT_FLOAT ||
15571697 (sv -> type .t & VT_BTYPE ) == VT_DOUBLE ) {
15581698 /* floating point register */
1559- reg = TOK_ASM_f0 + reg ;
1699+ reg = TOK_ASM_f0 + REG_VALUE ( reg ) ;
15601700 } else {
15611701 /* general purpose register */
15621702 reg = TOK_ASM_x0 + reg ;
@@ -1570,7 +1710,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
15701710 if ((sv -> type .t & VT_BTYPE ) == VT_FLOAT ||
15711711 (sv -> type .t & VT_BTYPE ) == VT_DOUBLE ) {
15721712 /* floating point register */
1573- reg = TOK_ASM_f0 + reg ;
1713+ reg = TOK_ASM_f0 + REG_VALUE ( reg ) ;
15741714 } else {
15751715 /* general purpose register */
15761716 reg = TOK_ASM_x0 + reg ;
0 commit comments