Also add s0...s31, d0...d15 --- arm-asm.c | 105 ++++++++++++++++++++++++++++++++++++- arm-tok.h | 59 +++++++++++++++++++++ tests/arm-asm-testsuite.sh | 8 ++- 3 files changed, 169 insertions(+), 3 deletions(-)
diff --git a/arm-asm.c b/arm-asm.c index 3591651..7e59ad7 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -1289,11 +1289,11 @@ static void asm_emit_coprocessor_data_transfer(uint32_t high_nibble, uint8_t cp_ if (writeback) opcode |= 1 << 21; // write offset back into register - if (offset->type == OP_IM8 || offset->type == OP_IM8N) { + if (offset->type == OP_IM8 || offset->type == OP_IM8N || offset->type == OP_IM32) { int v = offset->e.v; if (offset_minus) tcc_error("minus before '#' not supported for immediate values"); - if (offset->type == OP_IM8N) + if (offset->type == OP_IM8N || v < 0) v = -v; else opcode |= 1 << 23; // up @@ -1302,6 +1302,10 @@ static void asm_emit_coprocessor_data_transfer(uint32_t high_nibble, uint8_t cp_ return; } v >>= 2; + if (v > 255) { + tcc_error("immediate offset must be between -1020 and 1020"); + return; + } opcode |= v; } else if (offset->type == OP_REG32) { if (!offset_minus) @@ -1439,6 +1443,97 @@ static void asm_coprocessor_data_transfer_opcode(TCCState *s1, int token) } } +#if defined(TCC_ARM_VFP) +#define CP_SINGLE_PRECISION_FLOAT 10 +#define CP_DOUBLE_PRECISION_FLOAT 11 + +/* Read the VFP register referred to by T. + If OK, returns its number. + If not OK, returns -1. */ +static int asm_parse_vfp_regvar(int t, int double_precision) +{ + if (double_precision) { + if (t >= TOK_ASM_d0 && t <= TOK_ASM_d15) + return t - TOK_ASM_d0; + } else { + if (t >= TOK_ASM_s0 && t <= TOK_ASM_s31) + return t - TOK_ASM_s0; + } + return -1; +} + + +static void asm_floating_point_single_data_transfer_opcode(TCCState *s1, int token) +{ + Operand ops[3]; + uint8_t coprocessor = 0; + uint8_t coprocessor_destination_register = 0; + int long_transfer = 0; + int reg; + // Note: vldr p1, c0, [r4, #4] ; simple offset: r0 = *(int*)(r4+4); r4 unchanged + // Note: Not allowed: vldr p2, c0, [r4, #4]! ; pre-indexed: r0 = *(int*)(r4+4); r4 = r4+4 + // Note: Not allowed: vldr p3, c0, [r4], #4 ; post-indexed: r0 = *(int*)(r4+0); r4 = r4+4 + + if ((reg = asm_parse_vfp_regvar(tok, 0)) != -1) { + coprocessor = CP_SINGLE_PRECISION_FLOAT; + coprocessor_destination_register = reg; + long_transfer = coprocessor_destination_register & 1; + coprocessor_destination_register >>= 1; + next(); + } else if ((reg = asm_parse_vfp_regvar(tok, 1)) != -1) { + coprocessor = CP_DOUBLE_PRECISION_FLOAT; + coprocessor_destination_register = reg; + next(); + } else { + expect("floating point register"); + return; + } + + if (tok == ',') + next(); + else + expect("','"); + + if (tok != '[') + expect("'['"); + else + next(); // skip '[' + + parse_operand(s1, &ops[1]); + if (ops[1].type != OP_REG32) { + expect("(first source operand) register"); + return; + } + if (tok == ',') { + next(); // skip ',' + parse_operand(s1, &ops[2]); + if (ops[2].type != OP_IM8 && ops[2].type != OP_IM8N) { + expect("immediate offset"); + return; + } + } else { + // end of input expression in brackets--assume 0 offset + ops[2].type = OP_IM8; + ops[2].e.v = 0; + } + if (tok != ']') + expect("']'"); + else + next(); // skip ']' + + switch (ARM_INSTRUCTION_GROUP(token)) { + case TOK_ASM_vldreq: + asm_emit_coprocessor_data_transfer(condition_code_of_token(token), coprocessor, coprocessor_destination_register, &ops[1], &ops[2], 0, 1, 0, long_transfer, 1); + break; + case TOK_ASM_vstreq: + asm_emit_coprocessor_data_transfer(condition_code_of_token(token), coprocessor, coprocessor_destination_register, &ops[1], &ops[2], 0, 1, 0, long_transfer, 0); + break; + default: + expect("floating point data transfer instruction"); + } +} +#endif + static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token) { Operand ops[3]; @@ -1780,6 +1875,12 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) case TOK_ASM_stcleq: return asm_coprocessor_data_transfer_opcode(s1, token); +#if defined(TCC_ARM_VFP) + case TOK_ASM_vldreq: + case TOK_ASM_vstreq: + return asm_floating_point_single_data_transfer_opcode(s1, token); +#endif + default: expect("known instruction"); } diff --git a/arm-tok.h b/arm-tok.h index 28794e2..3dc3ea0 100644 --- a/arm-tok.h +++ b/arm-tok.h @@ -66,6 +66,60 @@ DEF_ASM(c14) DEF_ASM(c15) + /* single-precision VFP registers */ + + DEF_ASM(s0) + DEF_ASM(s1) + DEF_ASM(s2) + DEF_ASM(s3) + DEF_ASM(s4) + DEF_ASM(s5) + DEF_ASM(s6) + DEF_ASM(s7) + DEF_ASM(s8) + DEF_ASM(s9) + DEF_ASM(s10) + DEF_ASM(s11) + DEF_ASM(s12) + DEF_ASM(s13) + DEF_ASM(s14) + DEF_ASM(s15) + DEF_ASM(s16) + DEF_ASM(s17) + DEF_ASM(s18) + DEF_ASM(s19) + DEF_ASM(s20) + DEF_ASM(s21) + DEF_ASM(s22) + DEF_ASM(s23) + DEF_ASM(s24) + DEF_ASM(s25) + DEF_ASM(s26) + DEF_ASM(s27) + DEF_ASM(s28) + DEF_ASM(s29) + DEF_ASM(s30) + DEF_ASM(s31) + + /* double-precision VFP registers */ + + DEF_ASM(d0) + DEF_ASM(d1) + DEF_ASM(d2) + DEF_ASM(d3) + DEF_ASM(d4) + DEF_ASM(d5) + DEF_ASM(d6) + DEF_ASM(d7) + DEF_ASM(d8) + DEF_ASM(d9) + DEF_ASM(d10) + DEF_ASM(d11) + DEF_ASM(d12) + DEF_ASM(d13) + DEF_ASM(d14) + DEF_ASM(d15) + /* data processing directives */ DEF_ASM(asl) @@ -225,3 +279,8 @@ DEF_ASM_CONDED(cdp) DEF_ASM_CONDED(mcr) DEF_ASM_CONDED(mrc) + + // Floating point high-level instructions + + DEF_ASM_CONDED(vldr) + DEF_ASM_CONDED(vstr) diff --git a/tests/arm-asm-testsuite.sh b/tests/arm-asm-testsuite.sh index 4995c4c..1a76a2d 100755 --- a/tests/arm-asm-testsuite.sh +++ b/tests/arm-asm-testsuite.sh @@ -5,7 +5,7 @@ set -e # Note: "{r3}" is definitely different--but would complicate the assembler. state="`mktemp -d`" -cat ../arm-tok.h |grep DEF_ASM |grep -v 'not useful' |grep -v '#define' |grep -v '/[*]' |sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;' | egrep -v '^((r|c|p)[0-9]+|fp|ip|sp|lr|pc|asl)$' | while read s +cat ../arm-tok.h |grep DEF_ASM |grep -v 'not useful' |grep -v '#define' |grep -v '/[*]' |sed -e 's;^[ ]*DEF_ASM[^(]*(\(.*\)).*$;\1;' | egrep -v '^((r|c|p|s|d)[0-9]+|fp|ip|sp|lr|pc|asl)$' | while read s do ok=0 for args in "r3, r4, r5, r6" \ @@ -97,6 +97,12 @@ do "p5, c2, [r3, #-4]" \ "p5, c2, [r3, #0x45]" \ "p5, c2, [r3, #-0x45]" \ + "s2, [r3]" \ + "s3, [r4]" \ + "s2, [r3, #4]" \ + "s2, [r3, #-4]" \ + "s2, [r3, #0x45]" \ + "s2, [r3, #-0x45]" \ "" do #echo ".syntax unified" > a.s _______________________________________________ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel