[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Tinycc-devel] [PATCH 7/8] arm-asm: Add vmla, vmls, vnmls, vnmla, vmul,
From: |
Danny Milosavljevic |
Subject: |
[Tinycc-devel] [PATCH 7/8] arm-asm: Add vmla, vmls, vnmls, vnmla, vmul, vnmul, vadd, vsub, vdiv |
Date: |
Thu, 14 Jan 2021 23:22:26 +0100 |
---
arm-asm.c | 170 ++++++++++++++++++++++++++++++++++++-
arm-tok.h | 10 +++
tests/arm-asm-testsuite.sh | 6 +-
3 files changed, 184 insertions(+), 2 deletions(-)
diff --git a/arm-asm.c b/arm-asm.c
index 7e59ad7..c12e3a5 100644
--- a/arm-asm.c
+++ b/arm-asm.c
@@ -1462,7 +1462,6 @@ static int asm_parse_vfp_regvar(int t, int
double_precision)
return -1;
}
-
static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int
token)
{
Operand ops[3];
@@ -1532,6 +1531,164 @@ static void
asm_floating_point_single_data_transfer_opcode(TCCState *s1, int tok
expect("floating point data transfer instruction");
}
}
+
+static void asm_floating_point_data_processing_opcode(TCCState *s1, int token)
{
+ uint8_t coprocessor = 0;
+ uint8_t opcode1 = 0;
+ uint8_t opcode2 = 0; // (0 || 2) | register selection
+ uint8_t registers[3];
+ uint8_t nb_registers = 0;
+ int has_register_1 = 1;
+ int reg;
+
+/* TODO:
+ Instruction opcode opcode2 Reason
+ =============================================================
+ - 1?00 ?1? Undefined
+ VFNMS 1?01 ?0? Must be unconditional
+ VFNMA 1?01 ?1? Must be unconditional
+ VFMA 1?10 ?0? Must be unconditional
+ VFMS 1?10 ?1? Must be unconditional
+ VMOV Fd, const 1?11 ?0? Needs fixed-point arithmetic
+
+ VABS Nope Completely different encoding
+ VSQRT Nope Completely different encoding
+
+ VCMP{E}
+ >VCMP with 0
+
+ VCVT*
+
+ VMOV Fd, Fm
+ VMOV Sn, Rd
+ VMOV Rd, Sn
+ VMOV Sn, Sm, Rd, Rn
+ VMOV Rd, Rn, Sn, Sm
+ VMOV Dm, Rd, Rn
+ VMOV Rd, Rn, Dm
+ VMOV Dn[0], Rd
+ VMOV Rd, Dn[0]
+ VMOV Dn[1], Rd
+ VMOV Rd, Dn[1]
+
+ VMSR <sysreg>, Rd
+ VMRS Rd, <sysreg>
+ VMRS APSR_nzcv, FPSCR
+
+ VLDR Fd, <label>
+ VSTR Fd, <label>
+
+ VPUSH <regs>
+ VLDM Rn{!}, <regs>
+ VLDMDB Rn!, <regs>
+ VSTM Rn{!}, <regs>
+ VSTMDB Rn!, <regs>
+ VPOP <regs>
+*/
+
+ for (nb_registers = 0; nb_registers < 3; ) {
+ if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {
+ if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {
+ registers[nb_registers] = reg;
+ next();
+ } else {
+ expect("'s<number>'");
+ return;
+ }
+ } else if (coprocessor == CP_DOUBLE_PRECISION_FLOAT) {
+ if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {
+ registers[nb_registers] = reg;
+ next();
+ } else {
+ expect("'d<number>'");
+ return;
+ }
+ } else if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) {
+ coprocessor = CP_SINGLE_PRECISION_FLOAT;
+ registers[nb_registers] = reg;
+ next();
+ } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) {
+ coprocessor = CP_DOUBLE_PRECISION_FLOAT;
+ registers[nb_registers] = reg;
+ next();
+ } else
+ tcc_internal_error("unknown coprocessor");
+ ++nb_registers;
+ if (tok == ',')
+ next();
+ else
+ break;
+ }
+ if (nb_registers == 2) { // implicit
+ registers[2] = registers[1];
+ registers[1] = registers[0];
+ nb_registers = 3;
+ }
+ if (nb_registers < 3) {
+ tcc_error("Not enough operands for '%s' (%u)", get_tok_str(token,
NULL), nb_registers);
+ return;
+ }
+
+ switch (ARM_INSTRUCTION_GROUP(token)) {
+ case TOK_ASM_vmlaeq:
+ opcode1 = 0;
+ opcode2 = 0;
+ break;
+ case TOK_ASM_vmlseq:
+ opcode1 = 0;
+ opcode2 = 2;
+ break;
+ case TOK_ASM_vnmlseq:
+ opcode1 = 1;
+ opcode2 = 0;
+ break;
+ case TOK_ASM_vnmlaeq:
+ opcode1 = 1;
+ opcode2 = 2;
+ break;
+ case TOK_ASM_vmuleq:
+ opcode1 = 2;
+ opcode2 = 0;
+ break;
+ case TOK_ASM_vnmuleq:
+ opcode1 = 2;
+ opcode2 = 2;
+ break;
+ case TOK_ASM_vaddeq:
+ opcode1 = 3;
+ opcode2 = 0;
+ break;
+ case TOK_ASM_vsubeq:
+ opcode1 = 3;
+ opcode2 = 2;
+ break;
+ case TOK_ASM_vdiveq:
+ opcode1 = 8;
+ opcode2 = 0;
+ break;
+ default:
+ expect("known floating point instruction");
+ return;
+ }
+
+ if (coprocessor == CP_SINGLE_PRECISION_FLOAT) {
+ if (registers[2] & 1)
+ opcode2 |= 1;
+ registers[2] >>= 1;
+
+ if (has_register_1) {
+ if (registers[1] & 1)
+ opcode2 |= 4;
+ registers[1] >>= 1;
+ }
+
+ if (registers[0] & 1)
+ opcode1 |= 4;
+ registers[0] >>= 1;
+ }
+
+ asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor,
opcode1, registers[0], registers[1], registers[2], opcode2, 0);
+}
#endif
static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)
@@ -1879,6 +2036,17 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_vldreq:
case TOK_ASM_vstreq:
return asm_floating_point_single_data_transfer_opcode(s1, token);
+
+ case TOK_ASM_vmlaeq:
+ case TOK_ASM_vmlseq:
+ case TOK_ASM_vnmlseq:
+ case TOK_ASM_vnmlaeq:
+ case TOK_ASM_vmuleq:
+ case TOK_ASM_vnmuleq:
+ case TOK_ASM_vaddeq:
+ case TOK_ASM_vsubeq:
+ case TOK_ASM_vdiveq:
+ return asm_floating_point_data_processing_opcode(s1, token);
#endif
default:
diff --git a/arm-tok.h b/arm-tok.h
index 3dc3ea0..6adbc68 100644
--- a/arm-tok.h
+++ b/arm-tok.h
@@ -284,3 +284,13 @@
DEF_ASM_CONDED(vldr)
DEF_ASM_CONDED(vstr)
+
+ DEF_ASM_CONDED(vmla)
+ DEF_ASM_CONDED(vmls)
+ DEF_ASM_CONDED(vnmls)
+ DEF_ASM_CONDED(vnmla)
+ DEF_ASM_CONDED(vmul)
+ DEF_ASM_CONDED(vnmul)
+ DEF_ASM_CONDED(vadd)
+ DEF_ASM_CONDED(vsub)
+ DEF_ASM_CONDED(vdiv)
diff --git a/tests/arm-asm-testsuite.sh b/tests/arm-asm-testsuite.sh
index 1a76a2d..b19c80b 100755
--- a/tests/arm-asm-testsuite.sh
+++ b/tests/arm-asm-testsuite.sh
@@ -103,6 +103,10 @@ do
"s2, [r3, #-4]" \
"s2, [r3, #0x45]" \
"s2, [r3, #-0x45]" \
+ "s2, s3, s4" \
+ "s2, s3" \
+ "d2, d3, d4" \
+ "d2, d3" \
""
do
#echo ".syntax unified" > a.s
@@ -111,7 +115,7 @@ do
tcc_object="${state}/tcc-$s $args.o"
expected="${state}/expected-$s $args"
got="${state}/got-$s $args"
- if echo "$s $args" | "${CROSS_COMPILE}as" -mlittle-endian -o
"${as_object}" - 2>"${err}"
+ if echo "$s $args" | "${CROSS_COMPILE}as" -mlittle-endian
-mfpu=vfp -o "${as_object}" - 2>"${err}" || echo "$s.f32 $args" |
"${CROSS_COMPILE}as" -mlittle-endian -mfpu=vfp -o "${as_object}" - 2>"${err}"
|| echo "$s.f64 $args" | "${CROSS_COMPILE}as" -mlittle-endian -mfpu=vfp -o
"${as_object}" - 2>"${err}"
then
cat "${err}"
rm -f "${err}"
- [Tinycc-devel] [PATCH 0/8] Implement ARM VFP in ARM inline assembler, Danny Milosavljevic, 2021/01/14
- [Tinycc-devel] [PATCH 4/8] arm-asm: Add ldc, ldcl, stc, stcl, Danny Milosavljevic, 2021/01/14
- [Tinycc-devel] [PATCH 1/8] arm-asm: Add cdp, Danny Milosavljevic, 2021/01/14
- [Tinycc-devel] [PATCH 3/8] arm-asm: Add mcr, mrc, Danny Milosavljevic, 2021/01/14
- [Tinycc-devel] [PATCH 5/8] arm-asm: Add ldc2, ldc2l, stc2, stc2l, Danny Milosavljevic, 2021/01/14
- [Tinycc-devel] [PATCH 8/8] arm-asm: Add vneg, vabs, vsqrt, vcmp, vcmpe, Danny Milosavljevic, 2021/01/14
- [Tinycc-devel] [PATCH 2/8] arm-asm: Add cdp2, Danny Milosavljevic, 2021/01/14
- [Tinycc-devel] [PATCH 7/8] arm-asm: Add vmla, vmls, vnmls, vnmla, vmul, vnmul, vadd, vsub, vdiv,
Danny Milosavljevic <=
- [Tinycc-devel] [PATCH 6/8] arm-asm: Add vldr, vstr., Danny Milosavljevic, 2021/01/14