[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Tinycc-devel] [PATCH 2/3] arm-asm: Add ldrex, ldrexb, strex, strexb
From: |
Danny Milosavljevic |
Subject: |
[Tinycc-devel] [PATCH 2/3] arm-asm: Add ldrex, ldrexb, strex, strexb |
Date: |
Tue, 5 Jan 2021 01:06:39 +0100 |
---
arm-asm.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
arm-tok.h | 4 ++++
2 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/arm-asm.c b/arm-asm.c
index 27f396b..5b64fa6 100644
--- a/arm-asm.c
+++ b/arm-asm.c
@@ -939,10 +939,11 @@ static void asm_long_multiplication_opcode(TCCState *s1,
int token)
static void asm_single_data_transfer_opcode(TCCState *s1, int token)
{
Operand ops[3];
+ Operand strex_operand;
int exclam = 0;
int closed_bracket = 0;
int op2_minus = 0;
- uint32_t opcode = 1 << 26;
+ uint32_t opcode = 0;
// Note: ldr r0, [r4, #4] ; simple offset: r0 = *(int*)(r4+4); r4
unchanged
// Note: ldr r0, [r4, #4]! ; pre-indexed: r0 = *(int*)(r4+4); r4 = r4+4
// Note: ldr r0, [r4], #4 ; post-indexed: r0 = *(int*)(r4+0); r4 = r4+4
@@ -955,9 +956,25 @@ static void asm_single_data_transfer_opcode(TCCState *s1,
int token)
return;
}
if (tok != ',')
- expect("two arguments");
+ expect("at least two arguments");
else
next(); // skip ','
+
+ switch (ARM_INSTRUCTION_GROUP(token)) {
+ case TOK_ASM_strexbeq:
+ case TOK_ASM_strexeq:
+ parse_operand(s1, &strex_operand);
+ if (strex_operand.type != OP_REG32) {
+ expect("register");
+ return;
+ }
+ if (tok != ',')
+ expect("at least three arguments");
+ else
+ next(); // skip ','
+ break;
+ }
+
if (tok != '[')
expect("'['");
else
@@ -1039,6 +1056,7 @@ static void asm_single_data_transfer_opcode(TCCState *s1,
int token)
opcode |= 1 << 22; // B
/* fallthrough */
case TOK_ASM_streq:
+ opcode |= 1 << 26; // Load/Store
asm_emit_opcode(token, opcode);
break;
case TOK_ASM_ldrbeq:
@@ -1046,6 +1064,47 @@ static void asm_single_data_transfer_opcode(TCCState
*s1, int token)
/* fallthrough */
case TOK_ASM_ldreq:
opcode |= 1 << 20; // L
+ opcode |= 1 << 26; // Load/Store
+ asm_emit_opcode(token, opcode);
+ break;
+ case TOK_ASM_strexbeq:
+ opcode |= 1 << 22; // B
+ /* fallthrough */
+ case TOK_ASM_strexeq:
+ if (opcode & 0xFFF) {
+ tcc_error("offset not allowed with 'strex'");
+ return;
+ } else if (opcode & ENCODE_IMMEDIATE_FLAG) { // if set, it means it's
NOT immediate
+ tcc_error("offset not allowed with 'strex'");
+ return;
+ }
+ if ((opcode & (1 << 24)) == 0) { // add offset after transfer
+ tcc_error("adding offset after transfer not allowed with 'strex'");
+ return;
+ }
+
+ opcode |= 0xf90;
+ opcode |= strex_operand.reg;
+ asm_emit_opcode(token, opcode);
+ break;
+ case TOK_ASM_ldrexbeq:
+ opcode |= 1 << 22; // B
+ /* fallthrough */
+ case TOK_ASM_ldrexeq:
+ if (opcode & 0xFFF) {
+ tcc_error("offset not allowed with 'ldrex'");
+ return;
+ } else if (opcode & ENCODE_IMMEDIATE_FLAG) { // if set, it means it's
NOT immediate
+ tcc_error("offset not allowed with 'ldrex'");
+ return;
+ }
+ if ((opcode & (1 << 24)) == 0) { // add offset after transfer
+ tcc_error("adding offset after transfer not allowed with 'ldrex'");
+ return;
+ }
+ opcode |= 1 << 20; // L
+ opcode |= 0x00f;
+ opcode |= 0xf90;
asm_emit_opcode(token, opcode);
break;
default:
@@ -1163,6 +1222,10 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
case TOK_ASM_ldrbeq:
case TOK_ASM_streq:
case TOK_ASM_strbeq:
+ case TOK_ASM_ldrexeq:
+ case TOK_ASM_ldrexbeq:
+ case TOK_ASM_strexeq:
+ case TOK_ASM_strexbeq:
return asm_single_data_transfer_opcode(s1, token);
case TOK_ASM_andeq:
diff --git a/arm-tok.h b/arm-tok.h
index 7c1a202..be927cc 100644
--- a/arm-tok.h
+++ b/arm-tok.h
@@ -93,6 +93,10 @@
DEF_ASM_CONDED(ldrb)
DEF_ASM_CONDED(str)
DEF_ASM_CONDED(strb)
+ DEF_ASM_CONDED(ldrex)
+ DEF_ASM_CONDED(ldrexb)
+ DEF_ASM_CONDED(strex)
+ DEF_ASM_CONDED(strexb)
DEF_ASM_CONDED(stmda)
DEF_ASM_CONDED(ldmda)