[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Tinycc-devel] [PATCH] arm-asm: Add vpush, vpop, vldm, vldmia, vldmdb, v
From: |
Danny Milosavljevic |
Subject: |
[Tinycc-devel] [PATCH] arm-asm: Add vpush, vpop, vldm, vldmia, vldmdb, vstm, vstmia, vstmdb |
Date: |
Thu, 21 Jan 2021 22:40:03 +0100 |
---
arm-asm.c | 123 +++++++++++++++++++++++++++++++++++++
arm-tok.h | 9 +++
tests/arm-asm-testsuite.sh | 12 ++++
3 files changed, 144 insertions(+)
diff --git a/arm-asm.c b/arm-asm.c
index e039fa9..47cf066 100644
--- a/arm-asm.c
+++ b/arm-asm.c
@@ -1533,6 +1533,119 @@ static void
asm_floating_point_single_data_transfer_opcode(TCCState *s1, int tok
expect("floating point data transfer instruction");
}
}
+
+static void asm_floating_point_block_data_transfer_opcode(TCCState *s1, int
token)
+{
+ uint8_t coprocessor = 0;
+ int first_regset_register;
+ int last_regset_register;
+ uint8_t regset_item_count;
+ uint8_t extra_register_bit = 0;
+ int op0_exclam = 0;
+ int load = 0;
+ int preincrement = 0;
+ Operand ops[1];
+ Operand offset;
+ switch (ARM_INSTRUCTION_GROUP(token)) {
+ case TOK_ASM_vpusheq:
+ case TOK_ASM_vpopeq:
+ ops[0].type = OP_REG32;
+ ops[0].reg = 13; // sp
+ op0_exclam = 1;
+ break;
+ default:
+ parse_operand(s1, &ops[0]);
+ if (tok == '!') {
+ op0_exclam = 1;
+ next(); // skip '!'
+ }
+ if (tok == ',')
+ next(); // skip comma
+ else {
+ expect("','");
+ return;
+ }
+ }
+
+ if (tok != '{') {
+ expect("'{'");
+ return;
+ }
+ next(); // skip '{'
+ first_regset_register = asm_parse_vfp_regvar(tok, 1);
+ if ((first_regset_register = asm_parse_vfp_regvar(tok, 1)) != -1) {
+ coprocessor = CP_DOUBLE_PRECISION_FLOAT;
+ next();
+ } else if ((first_regset_register = asm_parse_vfp_regvar(tok, 0)) != -1) {
+ coprocessor = CP_SINGLE_PRECISION_FLOAT;
+ next();
+ } else {
+ expect("floating-point register");
+ return;
+ }
+
+ if (tok == '-') {
+ next();
+ if ((last_regset_register = asm_parse_vfp_regvar(tok, coprocessor ==
CP_DOUBLE_PRECISION_FLOAT)) != -1)
+ next();
+ else {
+ expect("floating-point register");
+ return;
+ }
+ } else
+ last_regset_register = first_regset_register;
+
+ if (last_regset_register < first_regset_register) {
+ tcc_error("registers will be processed in ascending order by
hardware--but are not specified in ascending order here");
+ return;
+ }
+ if (tok != '}') {
+ expect("'}'");
+ return;
+ }
+ next(); // skip '}'
+
+ // Note: 0 (one down) is not implemented by us regardless.
+ regset_item_count = last_regset_register - first_regset_register + 1;
+ if (coprocessor == CP_DOUBLE_PRECISION_FLOAT)
+ regset_item_count <<= 1;
+ else {
+ extra_register_bit = first_regset_register & 1;
+ first_regset_register >>= 1;
+ }
+ offset.type = OP_IM8;
+ offset.e.v = regset_item_count << 2;
+ switch (ARM_INSTRUCTION_GROUP(token)) {
+ case TOK_ASM_vstmeq: // post-increment store
+ case TOK_ASM_vstmiaeq: // post-increment store
+ break;
+ case TOK_ASM_vpopeq:
+ case TOK_ASM_vldmeq: // post-increment load
+ case TOK_ASM_vldmiaeq: // post-increment load
+ load = 1;
+ break;
+ case TOK_ASM_vldmdbeq: // pre-decrement load
+ load = 1;
+ /* fallthrough */
+ case TOK_ASM_vpusheq:
+ case TOK_ASM_vstmdbeq: // pre-decrement store
+ offset.type = OP_IM8N;
+ offset.e.v = -offset.e.v;
+ preincrement = 1;
+ break;
+ default:
+ expect("floating point block data transfer instruction");
+ return;
+ }
+ if (ops[0].type != OP_REG32)
+ expect("(first operand) register");
+ else if (ops[0].reg == 15)
+ tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token,
NULL));
+ else if (!op0_exclam && ARM_INSTRUCTION_GROUP(token) != TOK_ASM_vldmeq &&
ARM_INSTRUCTION_GROUP(token) != TOK_ASM_vldmiaeq &&
ARM_INSTRUCTION_GROUP(token) != TOK_ASM_vstmeq && ARM_INSTRUCTION_GROUP(token)
!= TOK_ASM_vstmiaeq)
+ tcc_error("first operand of '%s' should have an exclamation mark",
get_tok_str(token, NULL));
+ else
+ asm_emit_coprocessor_data_transfer(condition_code_of_token(token),
coprocessor, first_regset_register, &ops[0], &offset, 0, preincrement,
op0_exclam, extra_register_bit, load);
+}
#endif
static void asm_misc_single_data_transfer_opcode(TCCState *s1, int token)
@@ -1896,6 +2009,16 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_vstreq:
asm_floating_point_single_data_transfer_opcode(s1, token);
return;
+
+ case TOK_ASM_vpusheq:
+ case TOK_ASM_vpopeq:
+ case TOK_ASM_vldmeq:
+ case TOK_ASM_vldmiaeq:
+ case TOK_ASM_vldmdbeq:
+ case TOK_ASM_vstmeq:
+ case TOK_ASM_vstmiaeq:
+ case TOK_ASM_vstmdbeq:
+ return asm_floating_point_block_data_transfer_opcode(s1, token);
#endif
default:
diff --git a/arm-tok.h b/arm-tok.h
index 3dc3ea0..cd45a01 100644
--- a/arm-tok.h
+++ b/arm-tok.h
@@ -284,3 +284,12 @@
DEF_ASM_CONDED(vldr)
DEF_ASM_CONDED(vstr)
+
+ DEF_ASM_CONDED(vpush)
+ DEF_ASM_CONDED(vpop)
+ DEF_ASM_CONDED(vldm)
+ DEF_ASM_CONDED(vldmia)
+ DEF_ASM_CONDED(vldmdb)
+ DEF_ASM_CONDED(vstm)
+ DEF_ASM_CONDED(vstmia)
+ DEF_ASM_CONDED(vstmdb)
diff --git a/tests/arm-asm-testsuite.sh b/tests/arm-asm-testsuite.sh
index 3d41f7e..4e27863 100755
--- a/tests/arm-asm-testsuite.sh
+++ b/tests/arm-asm-testsuite.sh
@@ -120,6 +120,18 @@ do
"s2, [r3, #-4]" \
"s2, [r3, #0x45]" \
"s2, [r3, #-0x45]" \
+ "r1, {d3-d4}" \
+ "r1!, {d3-d4}" \
+ "r2, {d4-d15}" \
+ "r3!, {d4-d15}" \
+ "r3!, {d4}" \
+ "r2, {s4-s31}" \
+ "r3!, {s4}" \
+ "{d3-d4}" \
+ "{d4-d15}" \
+ "{d4}" \
+ "{s4-s31}" \
+ "{s4}" \
""
do
#echo ".syntax unified" > a.s
--
2.29.2
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Tinycc-devel] [PATCH] arm-asm: Add vpush, vpop, vldm, vldmia, vldmdb, vstm, vstmia, vstmdb,
Danny Milosavljevic <=