arm-asm: Add vldr, vstr

Also add s0...s31, d0...d15
This commit is contained in:
Danny Milosavljevic 2021-01-14 13:23:11 +01:00
parent 31dde11ad5
commit cdbb55396c
No known key found for this signature in database
GPG key ID: E71A35542C30BAA5
3 changed files with 169 additions and 1 deletions

View file

@ -1444,6 +1444,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) static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)
{ {
Operand ops[3]; Operand ops[3];
@ -1785,6 +1876,12 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_stcleq: case TOK_ASM_stcleq:
return asm_coprocessor_data_transfer_opcode(s1, token); 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: default:
expect("known instruction"); expect("known instruction");
} }

View file

@ -66,6 +66,60 @@
DEF_ASM(c14) DEF_ASM(c14)
DEF_ASM(c15) 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 */ /* data processing directives */
DEF_ASM(asl) DEF_ASM(asl)
@ -225,3 +279,8 @@
DEF_ASM_CONDED(cdp) DEF_ASM_CONDED(cdp)
DEF_ASM_CONDED(mcr) DEF_ASM_CONDED(mcr)
DEF_ASM_CONDED(mrc) DEF_ASM_CONDED(mrc)
// Floating point high-level instructions
DEF_ASM_CONDED(vldr)
DEF_ASM_CONDED(vstr)

View file

@ -5,8 +5,14 @@ set -e
# Note: "{r3}" is definitely different--but would complicate the assembler. # Note: "{r3}" is definitely different--but would complicate the assembler.
state="`mktemp -d`" 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 do
# If VFP is disabled, skip VFP tests.
if [ "${s#v}" != "${s}" ] && ! grep -q "CONFIG_arm_vfp=yes" ../config.mak
then
echo "note: skipping VFP instruction: $s (because VFP is disabled)">&2
continue
fi
ok=0 ok=0
for args in "r3, r4, r5, r6" \ for args in "r3, r4, r5, r6" \
"r3, r4, r5" \ "r3, r4, r5" \
@ -103,6 +109,12 @@ do
"p5, c2, [r3, #-4]" \ "p5, c2, [r3, #-4]" \
"p5, c2, [r3, #0x45]" \ "p5, c2, [r3, #0x45]" \
"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 do
#echo ".syntax unified" > a.s #echo ".syntax unified" > a.s