From b495959e4babed8a0d90000166fa9471b051ddaa Mon Sep 17 00:00:00 2001 From: Danny Milosavljevic Date: Sat, 26 Dec 2020 16:43:01 +0100 Subject: [PATCH] arm-asm: Add push, pop Also edited tcctok.h to not redefine push, pop --- arm-asm.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ arm-tok.h | 5 +++++ tcctok.h | 2 +- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/arm-asm.c b/arm-asm.c index aa377092..d79bf589 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -171,6 +171,61 @@ static void asm_nullary_opcode(int token) } } +static void asm_block_data_transfer_opcode(TCCState *s1, int token) +{ + uint32_t opcode; + int op0_exclam; + Operand ops[2]; + int nb_ops = 1; + parse_operand(s1, &ops[0]); + if (tok == '!') { + op0_exclam = 1; + next(); // skip '!' + } + if (tok == ',') { + next(); // skip comma + parse_operand(s1, &ops[1]); + ++nb_ops; + } + if (nb_ops < 1) { + expect("at least one operand"); + return; + } else if (ops[nb_ops - 1].type != OP_REGSET32) { + expect("(last operand) register list"); + return; + } + + // block data transfer: 1 0 0 P U S W L << 20 (general case): + // operands: + // Rn: bits 19...16 base register + // Register List: bits 15...0 + + switch (ARM_INSTRUCTION_GROUP(token)) { + case TOK_ASM_pusheq: // TODO: Optimize 1-register case to: str ?, [sp, #-4]! + // Instruction: 1 I=0 P=1 U=0 S=0 W=1 L=0 << 20, op 1101 + // operands: + // Rn: base register + // Register List: bits 15...0 + if (nb_ops != 1) + expect("exactly one operand"); + else + asm_emit_opcode(token, (0x92d << 16) | ops[0].regset); // TODO: base register ? + break; + case TOK_ASM_popeq: // TODO: Optimize 1-register case to: ldr ?, [sp], #4 + // Instruction: 1 I=0 P=0 U=1 S=0 W=0 L=1 << 20, op 1101 + // operands: + // Rn: base register + // Register List: bits 15...0 + if (nb_ops != 1) + expect("exactly one operand"); + else + asm_emit_opcode(token, (0x8bd << 16) | ops[0].regset); // TODO: base register ? + break; + default: + expect("block data transfer instruction"); + } +} + ST_FUNC void asm_opcode(TCCState *s1, int token) { while (token == TOK_LINEFEED) { @@ -185,6 +240,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) } switch (ARM_INSTRUCTION_GROUP(token)) { + case TOK_ASM_pusheq: + case TOK_ASM_popeq: + return asm_block_data_transfer_opcode(s1, token); case TOK_ASM_nopeq: case TOK_ASM_wfeeq: case TOK_ASM_wfieq: diff --git a/arm-tok.h b/arm-tok.h index 6d9c5962..82cb3dd9 100644 --- a/arm-tok.h +++ b/arm-tok.h @@ -54,3 +54,8 @@ DEF_ASM_CONDED(nop) DEF_ASM_CONDED(wfe) DEF_ASM_CONDED(wfi) + + /* instruction macros */ + + DEF_ASM_CONDED(push) + DEF_ASM_CONDED(pop) diff --git a/tcctok.h b/tcctok.h index aeac1cd5..4d2ce18a 100644 --- a/tcctok.h +++ b/tcctok.h @@ -171,7 +171,7 @@ /* pragma */ DEF(TOK_pack, "pack") -#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) +#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_ARM) /* already defined for assembler */ DEF(TOK_ASM_push, "push") DEF(TOK_ASM_pop, "pop")