From 036a7fe7d41c514fdd480d2298a9d6b353966e1f Mon Sep 17 00:00:00 2001 From: Danny Milosavljevic Date: Tue, 12 Jan 2021 23:43:54 +0100 Subject: [PATCH] arm-asm: Add cdp Also add p0...p15 (coprocessors), c0...c15 (coprocessor register aliases) --- arm-asm.c | 77 ++++++++++++++++++++++++++++++++++++++ arm-tok.h | 40 ++++++++++++++++++++ tests/arm-asm-testsuite.sh | 1 + 3 files changed, 118 insertions(+) diff --git a/arm-asm.c b/arm-asm.c index edfbab3d..a2f38bc0 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -165,6 +165,26 @@ static void asm_emit_opcode(int token, uint32_t opcode) { gen_le32((condition_code_of_token(token) << 28) | opcode); } +static void asm_emit_coprocessor_opcode(uint32_t high_nibble, uint8_t cp_number, uint8_t cp_opcode, uint8_t cp_destination_register, uint8_t cp_n_operand_register, uint8_t cp_m_operand_register, uint8_t cp_opcode2, int inter_processor_transfer) +{ + uint32_t opcode = 0xe000000; + if (inter_processor_transfer) + opcode |= 1 << 4; + //assert(cp_opcode < 16); + opcode |= cp_opcode << 20; + //assert(cp_n_operand_register < 16); + opcode |= cp_n_operand_register << 16; + //assert(cp_destination_register < 16); + opcode |= cp_destination_register << 12; + //assert(cp_number < 16); + opcode |= cp_number << 8; + //assert(cp_information < 8); + opcode |= cp_opcode2 << 5; + //assert(cp_m_operand_register < 16); + opcode |= cp_m_operand_register; + gen_le32((high_nibble << 28) | opcode); +} + static void asm_nullary_opcode(int token) { switch (ARM_INSTRUCTION_GROUP(token)) { @@ -309,6 +329,60 @@ static void asm_binary_opcode(TCCState *s1, int token) } } +static void asm_coprocessor_opcode(TCCState *s1, int token) { + uint8_t coprocessor; + Operand opcode1; + Operand opcode2; + uint8_t registers[3]; + unsigned int i; + + if (tok >= TOK_ASM_p0 && tok <= TOK_ASM_p15) { + coprocessor = tok - TOK_ASM_p0; + next(); + } else { + expect("'p'"); + return; + } + + if (tok == ',') + next(); + else + expect("','"); + + parse_operand(s1, &opcode1); + if (opcode1.type != OP_IM8 || opcode1.e.v > 15) { + tcc_error("opcode1 of instruction '%s' must be an immediate value between 0 and 15", get_tok_str(token, NULL)); + return; + } + + for (i = 0; i < 3; ++i) { + if (tok == ',') + next(); + else + expect("','"); + if (tok >= TOK_ASM_c0 && tok <= TOK_ASM_c15) { + registers[i] = tok - TOK_ASM_c0; + next(); + } else { + expect("'c"); + return; + } + } + if (tok == ',') { + next(); + parse_operand(s1, &opcode2); + } else { + opcode2.type = OP_IM8; + opcode2.e.v = 0; + } + if (opcode2.type != OP_IM8 || opcode2.e.v > 15) { + tcc_error("opcode2 of instruction '%s' must be an immediate value between 0 and 15", get_tok_str(token, NULL)); + return; + } + + asm_emit_coprocessor_opcode(condition_code_of_token(token), coprocessor, opcode1.e.v, registers[0], registers[1], registers[2], opcode2.e.v, 0); +} + /* data processing and single data transfer instructions only */ #define ENCODE_RN(register_index) ((register_index) << 16) #define ENCODE_RD(register_index) ((register_index) << 12) @@ -1468,6 +1542,9 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) case TOK_ASM_umlaleq: case TOK_ASM_umlalseq: return asm_long_multiplication_opcode(s1, token); + + case TOK_ASM_cdpeq: + return asm_coprocessor_opcode(s1, token); default: expect("known instruction"); } diff --git a/arm-tok.h b/arm-tok.h index f73add14..f6cad277 100644 --- a/arm-tok.h +++ b/arm-tok.h @@ -28,6 +28,44 @@ DEF_ASM(lr) /* alias for r14 */ DEF_ASM(pc) /* alias for r15 */ + /* coprocessors */ + + DEF_ASM(p0) + DEF_ASM(p1) + DEF_ASM(p2) + DEF_ASM(p3) + DEF_ASM(p4) + DEF_ASM(p5) + DEF_ASM(p6) + DEF_ASM(p7) + DEF_ASM(p8) + DEF_ASM(p9) + DEF_ASM(p10) + DEF_ASM(p11) + DEF_ASM(p12) + DEF_ASM(p13) + DEF_ASM(p14) + DEF_ASM(p15) + + /* coprocessor registers */ + + DEF_ASM(c0) + DEF_ASM(c1) + DEF_ASM(c2) + DEF_ASM(c3) + DEF_ASM(c4) + DEF_ASM(c5) + DEF_ASM(c6) + DEF_ASM(c7) + DEF_ASM(c8) + DEF_ASM(c9) + DEF_ASM(c10) + DEF_ASM(c11) + DEF_ASM(c12) + DEF_ASM(c13) + DEF_ASM(c14) + DEF_ASM(c15) + /* data processing directives */ DEF_ASM(asl) @@ -170,3 +208,5 @@ DEF_ASM_CONDED(rors) DEF_ASM_CONDED(rrx) DEF_ASM_CONDED(rrxs) + + DEF_ASM_CONDED(cdp) diff --git a/tests/arm-asm-testsuite.sh b/tests/arm-asm-testsuite.sh index 9ba785b5..0b55e560 100755 --- a/tests/arm-asm-testsuite.sh +++ b/tests/arm-asm-testsuite.sh @@ -89,6 +89,7 @@ do "r4, #0x0201" \ "r4, #0xFFFFFF00" \ "r2, #-4" \ + "p10, #7, c2, c0, c1, #4" \ "#4" \ "#-4" \ ""