--- 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 a4ad239..539fc31 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 d1d282a..28675a8 100755 --- a/tests/arm-asm-testsuite.sh +++ b/tests/arm-asm-testsuite.sh @@ -107,6 +107,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 @@ -115,7 +119,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 mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel