History

Implement some RV64F/D instructions

This patch implements some instructions required by musl 1.1.24.

Aleksi Hannula committed 11 months ago

Commit 06e24e71 parent 3c631fd2 files · +155 −2Browse files

Unified · Split

2 files
  1. riscv64-asm.c +142 −2
  2. riscv64-tok.h +13 −0
riscv64-asm.c+142−2
@@ -63,6 +63,9 @@ static void asm_emit_opcode(uint32_t opcode); · 62 unmodified lines
6363 static void asm_emit_r(int token, uint32_t opcode, const Operand *rd, const Operand *rs1, const Operand *rs2);
6464 static void asm_emit_s(int token, uint32_t opcode, const Operand *rs1, const Operand *rs2, const Operand *imm);
6565 static 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);
6669 ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
6770 static void asm_nullary_opcode(TCCState *s1, int token);
6871 ST_FUNC void asm_opcode(TCCState *s1, int token);
@@ -587,6 +590,14 @@ static void asm_binary_opcode(TCCState* s1, int token) · 518 unmodified lines
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) · 89 unmodified lines
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 · 21 unmodified lines
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 */
713800 static 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) · 374 unmodified lines
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+
10971222 static 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) · 171 unmodified lines
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) · 72 unmodified lines
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) · 84 unmodified lines
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) · 109 unmodified lines
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) · 7 unmodified lines
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;
riscv64-tok.h+13−0
@@ -266,6 +266,19 @@ · 265 unmodified lines
266266 DEF_ASM(remw)
267267 DEF_ASM(remuw)
268268
269+/* "F"/"D" Extension for Single/Double-Precision Floating Point Arithmetic, V2.2 */
270+ /* enough implemented for musl */
271+ DEF_ASM_WITH_SUFFIX(fsgnj, s)
272+ DEF_ASM_WITH_SUFFIX(fsgnj, d)
273+ DEF_ASM_WITH_SUFFIX(fmadd, s)
274+ DEF_ASM_WITH_SUFFIX(fmadd, d)
275+ DEF_ASM_WITH_SUFFIX(fmax, s)
276+ DEF_ASM_WITH_SUFFIX(fmax, d)
277+ DEF_ASM_WITH_SUFFIX(fmin, s)
278+ DEF_ASM_WITH_SUFFIX(fmin, d)
279+ DEF_ASM_WITH_SUFFIX(fsqrt, s)
280+ DEF_ASM_WITH_SUFFIX(fsqrt, d)
281+
269282 /* "C" Extension for Compressed Instructions, V2.0 */
270283 DEF_ASM_WITH_SUFFIX(c, nop)
271284 /* Loads */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t