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
63static void asm_emit_r(int token, uint32_t opcode, const Operand *rd, const Operand *rs1, const Operand *rs2);63static void asm_emit_r(int token, uint32_t opcode, const Operand *rd, const Operand *rs1, const Operand *rs2);
64static void asm_emit_s(int token, uint32_t opcode, const Operand *rs1, const Operand *rs2, const Operand *imm);64static void asm_emit_s(int token, uint32_t opcode, const Operand *rs1, const Operand *rs2, const Operand *imm);
65static void asm_emit_u(int token, uint32_t opcode, const Operand *rd, const Operand *rs2);65static void asm_emit_u(int token, uint32_t opcode, const Operand *rd, const Operand *rs2);
66static void asm_emit_f(int token, uint32_t opcode, const Operand *rd, const Operand *rs1, const Operand *rs2);
67static void asm_emit_fb(int token, uint32_t opcode, const Operand *rd, const Operand *rs);
68static void asm_emit_fq(int token, uint32_t opcode, const Operand *rd, const Operand *rs1, const Operand *rs2, const Operand *rs3);
66ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);69ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
67static void asm_nullary_opcode(TCCState *s1, int token);70static void asm_nullary_opcode(TCCState *s1, int token);
68ST_FUNC void asm_opcode(TCCState *s1, int token);71ST_FUNC void asm_opcode(TCCState *s1, int token);
@@ -587,6 +590,14 @@ static void asm_binary_opcode(TCCState* s1, int token) · 518 unmodified lines
587 asm_emit_css(token, 2 | (5 << 13), ops, ops + 1);590 asm_emit_css(token, 2 | (5 << 13), ops, ops + 1);
588 return;591 return;
589 592
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
590 /* pseudoinstructions */601 /* pseudoinstructions */
591 /* rd, sym */602 /* rd, sym */
592 case TOK_ASM_la:603 case TOK_ASM_la:
@@ -682,6 +693,15 @@ static void asm_binary_opcode(TCCState* s1, int token) · 89 unmodified lines
682 asm_emit_r(token, (0xC << 2) | 3 | (2 << 12), &ops[0], &zero, &ops[1]);693 asm_emit_r(token, (0xC << 2) | 3 | (2 << 12), &ops[0], &zero, &ops[1]);
683 return;694 return;
684 695
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
685 default:705 default:
686 expect("binary instruction");706 expect("binary instruction");
687 }707 }
@@ -709,6 +729,73 @@ static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Oper · 21 unmodified lines
709 gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));729 gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));
710}730}
711 731
732/* caller: Add rounding mode, fmt, funct5 to opcode */
733static 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 */
755static 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 */
774static 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
712/* caller: Add funct3 into opcode */799/* caller: Add funct3 into opcode */
713static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)800static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
714{801{
@@ -1089,11 +1176,49 @@ static void asm_ternary_opcode(TCCState *s1, int token) · 374 unmodified lines
1089 asm_emit_cs(token, 6 << 13, ops, ops + 1, ops + 2);1176 asm_emit_cs(token, 6 << 13, ops, ops + 1, ops + 2);
1090 return;1177 return;
1091 1178
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
1092 default:1199 default:
1093 expect("ternary instruction");1200 expect("ternary instruction");
1094 }1201 }
1095}1202}
1096 1203
1204static 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
1097static void asm_atomic_opcode(TCCState *s1, int token)1222static void asm_atomic_opcode(TCCState *s1, int token)
1098{1223{
1099 Operand ops[3];1224 Operand ops[3];
@@ -1271,6 +1396,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 171 unmodified lines
1271 1396
1272 case TOK_ASM_lui:1397 case TOK_ASM_lui:
1273 case TOK_ASM_auipc:1398 case TOK_ASM_auipc:
1399 case TOK_ASM_fsqrt_s:
1400 case TOK_ASM_fsqrt_d:
1274 asm_binary_opcode(s1, token);1401 asm_binary_opcode(s1, token);
1275 return;1402 return;
1276 1403
@@ -1349,8 +1476,19 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 72 unmodified lines
1349 case TOK_ASM_csrrsi:1476 case TOK_ASM_csrrsi:
1350 case TOK_ASM_csrrw:1477 case TOK_ASM_csrrw:
1351 case TOK_ASM_csrrwi:1478 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:
1352 asm_ternary_opcode(s1, token);1486 asm_ternary_opcode(s1, token);
1353 return;1487 return;
1488 case TOK_ASM_fmadd_d:
1489 case TOK_ASM_fmadd_s:
1490 asm_quaternary_opcode(s1, token);
1491 return;
1354 1492
1355 /* Branches */1493 /* Branches */
1356 case TOK_ASM_beq:1494 case TOK_ASM_beq:
@@ -1441,6 +1579,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 84 unmodified lines
1441 case TOK_ASM_not:1579 case TOK_ASM_not:
1442 case TOK_ASM_neg:1580 case TOK_ASM_neg:
1443 case TOK_ASM_negw:1581 case TOK_ASM_negw:
1582 case TOK_ASM_fabs_s:
1583 case TOK_ASM_fabs_d:
1444 asm_binary_opcode(s1, token);1584 asm_binary_opcode(s1, token);
1445 return;1585 return;
1446 1586
@@ -1556,7 +1696,7 @@ ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier) · 109 unmodified lines
1556 if ((sv->type.t & VT_BTYPE) == VT_FLOAT ||1696 if ((sv->type.t & VT_BTYPE) == VT_FLOAT ||
1557 (sv->type.t & VT_BTYPE) == VT_DOUBLE) {1697 (sv->type.t & VT_BTYPE) == VT_DOUBLE) {
1558 /* floating point register */1698 /* floating point register */
1559 reg = TOK_ASM_f0 + reg;1699 reg = TOK_ASM_f0 + REG_VALUE(reg);
1560 } else {1700 } else {
1561 /* general purpose register */1701 /* general purpose register */
1562 reg = TOK_ASM_x0 + reg;1702 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
1570 if ((sv->type.t & VT_BTYPE) == VT_FLOAT ||1710 if ((sv->type.t & VT_BTYPE) == VT_FLOAT ||
1571 (sv->type.t & VT_BTYPE) == VT_DOUBLE) {1711 (sv->type.t & VT_BTYPE) == VT_DOUBLE) {
1572 /* floating point register */1712 /* floating point register */
1573 reg = TOK_ASM_f0 + reg;1713 reg = TOK_ASM_f0 + REG_VALUE(reg);
1574 } else {1714 } else {
1575 /* general purpose register */1715 /* general purpose register */
1576 reg = TOK_ASM_x0 + reg;1716 reg = TOK_ASM_x0 + reg;
riscv64-tok.h+13−0
@@ -266,6 +266,19 @@ · 265 unmodified lines
266 DEF_ASM(remw)266 DEF_ASM(remw)
267 DEF_ASM(remuw)267 DEF_ASM(remuw)
268 268
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
269/* "C" Extension for Compressed Instructions, V2.0 */282/* "C" Extension for Compressed Instructions, V2.0 */
270 DEF_ASM_WITH_SUFFIX(c, nop)283 DEF_ASM_WITH_SUFFIX(c, nop)
271/* Loads */284/* 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