This patchset improves the ARM inline assembler I posted earlier.
(Please apply it on top of the patchset I posted earlier--it does not replace it) First, I add support for the barrel shifter--supporting specifying both modifiers for the old ARM instructions and also the new ARM shift instructions. I add ROR support for sxtb, sxth, uxtb, uxth. I add some warnings and errors for some cases that are not supported by ARM hardware. Danny Milosavljevic (9): arm-asm: Add lsl, lsr, asr, ror, rrx arm-asm: For data processing instructions, support shifts and rotations. arm-asm: Support rotation for sxtb, sxth, uxtb, uxth arm-asm: Warn if regset registers are not specified in ascending order arm-asm: Add error case in asm_multiplication_opcode arm-asm: Raise an error if asm_binary_opcode is used with PC as operand arm-asm: Print a warning if asm_binary_opcode is used with SP as operand arm-asm: Raise error if more than two operands are specified on mov, mvn, cmp, cmn, tst, teq arm-asm: Raise error if asm_data_processing_opcode and asm_shift_opcode try to use PC for register-controlled shifts arm-asm.c | 322 +++++++++++++++++++++++++++++++++++++++++++++++++----- arm-tok.h | 15 +++ 2 files changed, 312 insertions(+), 25 deletions(-) _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
---
arm-asm.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ arm-tok.h | 11 ++++ 2 files changed, 173 insertions(+) diff --git a/arm-asm.c b/arm-asm.c index ce3ac80..6dc24c0 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -248,6 +248,14 @@ static void asm_binary_opcode(TCCState *s1, int token) Note: For single data transfer instructions, "0" means immediate. */ #define ENCODE_IMMEDIATE_FLAG (1 << 25) +#define ENCODE_BARREL_SHIFTER_SHIFT_BY_REGISTER (1 << 4) +#define ENCODE_BARREL_SHIFTER_MODE_LSL (0 << 5) +#define ENCODE_BARREL_SHIFTER_MODE_LSR (1 << 5) +#define ENCODE_BARREL_SHIFTER_MODE_ASR (2 << 5) +#define ENCODE_BARREL_SHIFTER_MODE_ROR (3 << 5) +#define ENCODE_BARREL_SHIFTER_REGISTER(register_index) ((register_index) << 8) +#define ENCODE_BARREL_SHIFTER_IMMEDIATE(value) ((value) << 7) + static void asm_block_data_transfer_opcode(TCCState *s1, int token) { uint32_t opcode; @@ -355,6 +363,52 @@ static void asm_block_data_transfer_opcode(TCCState *s1, int token) } } +static uint32_t asm_encode_rotation(Operand* rotation) +{ + uint64_t amount; + switch (rotation->type) { + case OP_REG32: + tcc_error("cannot rotate immediate value by register"); + return 0; + case OP_IM8: + amount = rotation->e.v; + if (amount >= 0 && amount < 32 && (amount & 1) == 0) + return (amount >> 1) << 8; + else + tcc_error("rotating is only possible by a multiple of 2"); + break; + default: + tcc_error("unknown rotation amount"); + return 0; + } +} + +static uint32_t asm_encode_shift(Operand* shift) +{ + uint64_t amount; + uint32_t operands = 0; + switch (shift->type) { + case OP_REG32: + if (shift->reg == 15) + tcc_error("r15 cannot be used as a shift count"); + else { + operands = ENCODE_BARREL_SHIFTER_SHIFT_BY_REGISTER; + operands |= ENCODE_BARREL_SHIFTER_REGISTER(shift->reg); + } + break; + case OP_IM8: + amount = shift->e.v; + if (amount > 0 && amount < 32) + operands = ENCODE_BARREL_SHIFTER_IMMEDIATE(amount); + else + tcc_error("shift count out of range"); + break; + default: + tcc_error("unknown shift amount"); + } + return operands; +} + static void asm_data_processing_opcode(TCCState *s1, int token) { Operand ops[3]; @@ -486,6 +540,102 @@ static void asm_data_processing_opcode(TCCState *s1, int token) } } +static void asm_shift_opcode(TCCState *s1, int token) +{ + Operand ops[3]; + int nb_ops; + uint32_t opcode = 0xd << 21; // MOV + uint32_t operands = 0; + + for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) { + parse_operand(s1, &ops[nb_ops]); + if (tok != ',') { + ++nb_ops; + break; + } + next(); // skip ',' + } + if (nb_ops < 2) { + expect("at least two operands"); + return; + } + + if (ops[0].type != OP_REG32) + expect("(destination operand) register"); + else + operands |= ENCODE_RD(ops[0].reg); + + if (nb_ops == 2) { + switch (ARM_INSTRUCTION_GROUP(token)) { + case TOK_ASM_rrxseq: + opcode |= ENCODE_SET_CONDITION_CODES; + /* fallthrough */ + case TOK_ASM_rrxeq: + if (ops[1].type == OP_REG32) { + operands |= ops[1].reg; + operands |= ENCODE_BARREL_SHIFTER_MODE_ROR; + asm_emit_opcode(token, opcode | operands); + } else + tcc_error("(first source operand) register"); + return; + default: + memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2] + memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit + nb_ops = 3; + } + } + if (nb_ops != 3) { + expect("two or three operands"); + return; + } + + switch (ops[1].type) { + case OP_REG32: + operands |= ops[1].reg; + break; + case OP_IM8: + operands |= ENCODE_IMMEDIATE_FLAG; + operands |= ops[1].e.v; + break; + } + + if (operands & ENCODE_IMMEDIATE_FLAG) + operands |= asm_encode_rotation(&ops[2]); + else + operands |= asm_encode_shift(&ops[2]); + + switch (ARM_INSTRUCTION_GROUP(token)) { + case TOK_ASM_lslseq: + opcode |= ENCODE_SET_CONDITION_CODES; + /* fallthrough */ + case TOK_ASM_lsleq: + operands |= ENCODE_BARREL_SHIFTER_MODE_LSL; + break; + case TOK_ASM_lsrseq: + opcode |= ENCODE_SET_CONDITION_CODES; + /* fallthrough */ + case TOK_ASM_lsreq: + operands |= ENCODE_BARREL_SHIFTER_MODE_LSR; + break; + case TOK_ASM_asrseq: + opcode |= ENCODE_SET_CONDITION_CODES; + /* fallthrough */ + case TOK_ASM_asreq: + operands |= ENCODE_BARREL_SHIFTER_MODE_ASR; + break; + case TOK_ASM_rorseq: + opcode |= ENCODE_SET_CONDITION_CODES; + /* fallthrough */ + case TOK_ASM_roreq: + operands |= ENCODE_BARREL_SHIFTER_MODE_ROR; + break; + default: + expect("shift instruction"); + return; + } + asm_emit_opcode(token, opcode | operands); +} + static void asm_multiplication_opcode(TCCState *s1, int token) { Operand ops[4]; @@ -902,6 +1052,18 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) case TOK_ASM_mvnseq: return asm_data_processing_opcode(s1, token); + case TOK_ASM_lsleq: + case TOK_ASM_lslseq: + case TOK_ASM_lsreq: + case TOK_ASM_lsrseq: + case TOK_ASM_asreq: + case TOK_ASM_asrseq: + case TOK_ASM_roreq: + case TOK_ASM_rorseq: + case TOK_ASM_rrxseq: + case TOK_ASM_rrxeq: + return asm_shift_opcode(s1, token); + case TOK_ASM_muleq: case TOK_ASM_mulseq: case TOK_ASM_mlaeq: diff --git a/arm-tok.h b/arm-tok.h index 2f1798b..a1fb158 100644 --- a/arm-tok.h +++ b/arm-tok.h @@ -145,3 +145,14 @@ DEF_ASM_CONDED(bics) DEF_ASM_CONDED(mvn) DEF_ASM_CONDED(mvns) + + DEF_ASM_CONDED(lsl) + DEF_ASM_CONDED(lsls) + DEF_ASM_CONDED(lsr) + DEF_ASM_CONDED(lsrs) + DEF_ASM_CONDED(asr) + DEF_ASM_CONDED(asrs) + DEF_ASM_CONDED(ror) + DEF_ASM_CONDED(rors) + DEF_ASM_CONDED(rrx) + DEF_ASM_CONDED(rrxs) _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
---
arm-asm.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++-------- arm-tok.h | 4 ++++ 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/arm-asm.c b/arm-asm.c index 6dc24c0..ef75091 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -413,18 +413,55 @@ static void asm_data_processing_opcode(TCCState *s1, int token) { Operand ops[3]; int nb_ops; + Operand shift = {}; + int nb_shift = 0; + uint32_t operands = 0; /* 16 entries per instruction for the different condition codes */ uint32_t opcode_idx = (ARM_INSTRUCTION_GROUP(token) - TOK_ASM_andeq) >> 4; - for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ++nb_ops) { + for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ) { + if (tok == TOK_ASM_asl || tok == TOK_ASM_lsl || tok == TOK_ASM_lsr || tok == TOK_ASM_asr || tok == TOK_ASM_ror || tok == TOK_ASM_rrx) + break; parse_operand(s1, &ops[nb_ops]); - if (tok != ',') { - ++nb_ops; + ++nb_ops; + if (tok != ',') break; - } next(); // skip ',' } + if (tok == ',') + next(); + switch (tok) { + case TOK_ASM_asl: + case TOK_ASM_lsl: + case TOK_ASM_asr: + case TOK_ASM_lsr: + case TOK_ASM_ror: + switch (tok) { + case TOK_ASM_asl: + /* fallthrough */ + case TOK_ASM_lsl: + operands |= ENCODE_BARREL_SHIFTER_MODE_LSL; + break; + case TOK_ASM_asr: + operands |= ENCODE_BARREL_SHIFTER_MODE_ASR; + break; + case TOK_ASM_lsr: + operands |= ENCODE_BARREL_SHIFTER_MODE_LSR; + break; + case TOK_ASM_ror: + operands |= ENCODE_BARREL_SHIFTER_MODE_ROR; + break; + } + next(); + parse_operand(s1, &shift); + nb_shift = 1; + break; + case TOK_ASM_rrx: + next(); + operands |= ENCODE_BARREL_SHIFTER_MODE_ROR; + break; + } if (nb_ops < 2) expect("at least two operands"); else if (nb_ops == 2) { @@ -437,7 +474,6 @@ static void asm_data_processing_opcode(TCCState *s1, int token) return; } else { uint32_t opcode = 0; - uint32_t operands = 0; // data processing (general case): // operands: @@ -461,16 +497,13 @@ static void asm_data_processing_opcode(TCCState *s1, int token) operands |= ENCODE_RN(ops[1].reg); switch (ops[2].type) { case OP_REG32: - // TODO: Parse and encode shift. operands |= ops[2].reg; break; case OP_IM8: - // TODO: Parse and encode rotation. operands |= ENCODE_IMMEDIATE_FLAG; operands |= ops[2].e.v; break; case OP_IM8N: // immediate negative value - // TODO: Parse and encode rotation. operands |= ENCODE_IMMEDIATE_FLAG; /* Instruction swapping: 0001 = EOR - Rd:= Op1 EOR Op2 -> difficult @@ -534,6 +567,13 @@ static void asm_data_processing_opcode(TCCState *s1, int token) expect("(second source operand) register or immediate value"); } + if (nb_shift) { + if (operands & ENCODE_IMMEDIATE_FLAG) + tcc_error("immediate rotation not implemented"); + else + operands |= asm_encode_shift(&shift); + } + /* S=0 and S=1 entries alternate one after another, in that order */ opcode |= (opcode_idx & 1) ? ENCODE_SET_CONDITION_CODES : 0; asm_emit_opcode(token, opcode | operands); diff --git a/arm-tok.h b/arm-tok.h index a1fb158..6d2483b 100644 --- a/arm-tok.h +++ b/arm-tok.h @@ -28,6 +28,10 @@ DEF_ASM(lr) /* alias for r14 */ DEF_ASM(pc) /* alias for r15 */ + /* data processing directives */ + + DEF_ASM(asl) + #define ARM_INSTRUCTION_GROUP(tok) ((((tok) - TOK_ASM_nopeq) & 0xFFFFFFF0) + TOK_ASM_nopeq) /* Note: condition code is 4 bits */ _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
---
arm-asm.c | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/arm-asm.c b/arm-asm.c index ef75091..f672301 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -201,6 +201,9 @@ static void asm_unary_opcode(TCCState *s1, int token) static void asm_binary_opcode(TCCState *s1, int token) { Operand ops[2]; + Operand rotation; + uint32_t encoded_rotation = 0; + uint64_t amount; parse_operand(s1, &ops[0]); if (tok == ',') next(); @@ -212,27 +215,55 @@ static void asm_binary_opcode(TCCState *s1, int token) return; } - if (ops[1].type != OP_REG32) + if (ops[1].type != OP_REG32) { expect("(source operand) register"); - else switch (ARM_INSTRUCTION_GROUP(token)) { + return; + } + + if (tok == ',') { + next(); // skip ',' + if (tok == TOK_ASM_ror) { + next(); // skip 'ror' + parse_operand(s1, &rotation); + if (rotation.type != OP_IM8) { + expect("immediate value for rotation"); + return; + } else { + amount = rotation.e.v; + switch (amount) { + case 8: + encoded_rotation = 1 << 10; + break; + case 16: + encoded_rotation = 2 << 10; + break; + case 24: + encoded_rotation = 3 << 10; + break; + default: + expect("'8' or '16' or '24'"); + return; + } + } + } + } + switch (ARM_INSTRUCTION_GROUP(token)) { case TOK_ASM_clzeq: + if (encoded_rotation) + tcc_error("clz does not support rotation"); asm_emit_opcode(token, 0x16f0f10 | (ops[0].reg << 12) | ops[1].reg); break; case TOK_ASM_sxtbeq: - /* TODO: optional ROR (8|16|24) */ - asm_emit_opcode(token, 0x6af0070 | (ops[0].reg << 12) | ops[1].reg); + asm_emit_opcode(token, 0x6af0070 | (ops[0].reg << 12) | ops[1].reg | encoded_rotation); break; case TOK_ASM_sxtheq: - /* TODO: optional ROR (8|16|24) */ - asm_emit_opcode(token, 0x6bf0070 | (ops[0].reg << 12) | ops[1].reg); + asm_emit_opcode(token, 0x6bf0070 | (ops[0].reg << 12) | ops[1].reg | encoded_rotation); break; case TOK_ASM_uxtbeq: - /* TODO: optional ROR (8|16|24) */ - asm_emit_opcode(token, 0x6ef0070 | (ops[0].reg << 12) | ops[1].reg); + asm_emit_opcode(token, 0x6ef0070 | (ops[0].reg << 12) | ops[1].reg | encoded_rotation); break; case TOK_ASM_uxtheq: - /* TODO: optional ROR (8|16|24) */ - asm_emit_opcode(token, 0x6ff0070 | (ops[0].reg << 12) | ops[1].reg); + asm_emit_opcode(token, 0x6ff0070 | (ops[0].reg << 12) | ops[1].reg | encoded_rotation); break; default: expect("binary instruction"); _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
---
arm-asm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arm-asm.c b/arm-asm.c index f672301..fd6275a 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -77,6 +77,8 @@ static void parse_operand(TCCState *s1, Operand *op) } else next(); // skip register name + if ((1 << reg) < regset) + tcc_warning("registers will be processed in ascending order by hardware--but are not specified in ascending order here"); regset |= 1 << reg; if (tok != ',') break; _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
---
arm-asm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arm-asm.c b/arm-asm.c index fd6275a..847a4f3 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -732,8 +732,8 @@ static void asm_multiplication_opcode(TCCState *s1, int token) memcpy(&ops[2], &ops[0], sizeof(ops[1])); // ARM is actually like this! break; default: - memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2] - memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit + expect("at least three operands"); + return; } nb_ops = 3; } _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
---
arm-asm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arm-asm.c b/arm-asm.c index 847a4f3..d6adc20 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -217,11 +217,21 @@ static void asm_binary_opcode(TCCState *s1, int token) return; } + if (ops[0].reg == 15) { + tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL)); + return; + } + if (ops[1].type != OP_REG32) { expect("(source operand) register"); return; } + if (ops[1].reg == 15) { + tcc_error("'%s' does not support 'pc' as operand", get_tok_str(token, NULL)); + return; + } + if (tok == ',') { next(); // skip ',' if (tok == TOK_ASM_ror) { _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
---
arm-asm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arm-asm.c b/arm-asm.c index d6adc20..028f30c 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -222,6 +222,9 @@ static void asm_binary_opcode(TCCState *s1, int token) return; } + if (ops[0].reg == 13) + tcc_warning("Using 'sp' as operand with '%s' is deprecated by ARM", get_tok_str(token, NULL)); + if (ops[1].type != OP_REG32) { expect("(source operand) register"); return; @@ -232,6 +235,9 @@ static void asm_binary_opcode(TCCState *s1, int token) return; } + if (ops[1].reg == 13) + tcc_warning("Using 'sp' as operand with '%s' is deprecated by ARM", get_tok_str(token, NULL)); + if (tok == ',') { next(); // skip ',' if (tok == TOK_ASM_ror) { _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
---
arm-asm.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arm-asm.c b/arm-asm.c index 028f30c..b565127 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -466,8 +466,9 @@ static void asm_data_processing_opcode(TCCState *s1, int token) int nb_shift = 0; uint32_t operands = 0; - /* 16 entries per instruction for the different condition codes */ + /* modulo 16 entries per instruction for the different condition codes */ uint32_t opcode_idx = (ARM_INSTRUCTION_GROUP(token) - TOK_ASM_andeq) >> 4; + uint32_t opcode_nos = opcode_idx >> 1; // without "s"; "OpCode" in ARM docs for (nb_ops = 0; nb_ops < sizeof(ops)/sizeof(ops[0]); ) { if (tok == TOK_ASM_asl || tok == TOK_ASM_lsl || tok == TOK_ASM_lsr || tok == TOK_ASM_asr || tok == TOK_ASM_ror || tok == TOK_ASM_rrx) @@ -517,6 +518,11 @@ static void asm_data_processing_opcode(TCCState *s1, int token) memcpy(&ops[2], &ops[1], sizeof(ops[1])); // move ops[2] memcpy(&ops[1], &ops[0], sizeof(ops[0])); // ops[1] was implicit nb_ops = 3; + } else if (nb_ops == 3) { + if (opcode_nos == 0xd || opcode_nos == 0xf || opcode_nos == 0xa || opcode_nos == 0xb || opcode_nos == 0x8 || opcode_nos == 0x9) { // mov, mvn, cmp, cmn, tst, teq + tcc_error("'%s' cannot be used with three operands", get_tok_str(token, NULL)); + return; + } } if (nb_ops != 3) { expect("two or three operands"); @@ -533,16 +539,16 @@ static void asm_data_processing_opcode(TCCState *s1, int token) // bits 24...21: "OpCode"--see below /* operations in the token list are ordered by opcode */ - opcode = (opcode_idx >> 1) << 21; // drop "s" + opcode = opcode_nos << 21; // drop "s" if (ops[0].type != OP_REG32) expect("(destination operand) register"); - else if (opcode == 0xa << 21 || opcode == 0xb << 21 || opcode == 0x8 << 21 || opcode == 0x9 << 21 ) // cmp, cmn, tst, teq + else if (opcode_nos == 0xa || opcode_nos == 0xb || opcode_nos == 0x8 || opcode_nos == 0x9) // cmp, cmn, tst, teq operands |= ENCODE_SET_CONDITION_CODES; // force S set, otherwise it's a completely different instruction. else operands |= ENCODE_RD(ops[0].reg); if (ops[1].type != OP_REG32) expect("(first source operand) register"); - else if (!(opcode == 0xd << 21 || opcode == 0xf << 21)) // not: mov, mvn (those have only one source operand) + else if (!(opcode_nos == 0xd || opcode_nos == 0xf)) // not: mov, mvn (those have only one source operand) operands |= ENCODE_RN(ops[1].reg); switch (ops[2].type) { case OP_REG32: @@ -562,7 +568,7 @@ static void asm_data_processing_opcode(TCCState *s1, int token) 1001 = TEQ - CC on: Op1 EOR Op2 -> difficult 1100 = ORR - Rd:= Op1 OR Op2 -> difficult */ - switch (opcode_idx >> 1) { // "OpCode" in ARM docs + switch (opcode_nos) { #if 0 case 0x0: // AND - Rd:= Op1 AND Op2 opcode = 0xe << 21; // BIC _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
---
arm-asm.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arm-asm.c b/arm-asm.c index b565127..6eb680a 100644 --- a/arm-asm.c +++ b/arm-asm.c @@ -529,6 +529,13 @@ static void asm_data_processing_opcode(TCCState *s1, int token) return; } else { uint32_t opcode = 0; + if (nb_shift && shift.type == OP_REG32) { + if ((ops[0].type == OP_REG32 && ops[0].reg == 15) || + (ops[1].type == OP_REG32 && ops[1].reg == 15)) { + tcc_error("Using the 'pc' register in data processing instructions that have a register-controlled shift is not implemented by ARM"); + return; + } + } // data processing (general case): // operands: @@ -655,9 +662,10 @@ static void asm_shift_opcode(TCCState *s1, int token) return; } - if (ops[0].type != OP_REG32) + if (ops[0].type != OP_REG32) { expect("(destination operand) register"); - else + return; + } else operands |= ENCODE_RD(ops[0].reg); if (nb_ops == 2) { @@ -694,6 +702,13 @@ static void asm_shift_opcode(TCCState *s1, int token) break; } + if (ops[2].type == OP_REG32) { + if ((ops[0].type == OP_REG32 && ops[0].reg == 15) || + (ops[1].type == OP_REG32 && ops[1].reg == 15)) { + tcc_error("Using the 'pc' register in data processing instructions that have a register-controlled shift is not implemented by ARM"); + } + } + if (operands & ENCODE_IMMEDIATE_FLAG) operands |= asm_encode_rotation(&ops[2]); else _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
In reply to this post by Danny Milosavljevic
Improved unit tester:
#!/bin/sh set -e cd ~/src/tinycc-upstream/tinycc cat arm-tok.h |grep DEF_ASM_CONDED |grep -v '#define' |grep -v '/[*]' |sed -e 's;DEF_ASM_CONDED.\(.*\).$;\1;'| grep -v 'not useful' >L total_count=0 # Note: "{r3}" is definitely done differently on tcc than on as--but would complicate the tcc assembler to do it the same way. for s in $(cat L) do ok=0 for args in "r3, r4, r5, r6" \ "r3, r4, r5" \ "r3, r4, r5, asl #7" \ "r3, r4, r5, lsl #7" \ "r3, r4, r5, asr #7" \ "r3, r4, r5, lsr #7" \ "r3, r4, r5, ror #7" \ "r3, r4, r5, rrx" \ "r3, r4, r5, asl r6" \ "r3, r4, r5, lsl r6" \ "r3, r4, r5, asr r6" \ "r3, r4, r5, lsr r6" \ "r3, r4, r5, ror r6" \ "r3, r4, #5, asl #7" \ "r3, r4, #5, lsl #7" \ "r3, r4, #5, asr #7" \ "r3, r4, #5, lsr #7" \ "r3, r4, #5, ror #7" \ "r3, r4, #5, rrx" \ "r3, #5, r4" \ "r3, #4, #8" \ "r3, r4, asl #5" \ "r3, r4, lsl #5" \ "r3, r4, asr #5" \ "r3, r4, lsr #5" \ "r3, r4, ror #5" \ "r3, r4, ror #8" \ "r3, r4, asl r5" \ "r3, r4, lsl r5" \ "r3, r4, asr r5" \ "r3, r4, lsr r5" \ "r3, r4, ror r5" \ "r3, r4, ror #8" \ "r3, r4, ror #16" \ "r3, r4, ror #24" \ "r3, r4, rrx" \ "r3, #4, asl #5" \ "r3, #4, lsl #5" \ "r3, #4, asr #5" \ "r3, #4, lsr #5" \ "r3, #4, ror #5" \ "r3, r4, rrx" \ "r3, r4" \ "r3" \ "{r3,r4,r5}" \ "{r3,r5,r4}" \ "r2!, {r3,r4,r5}" \ "r2!, {r3,r5,r4}" \ "r2, [r3, r4]" \ "r2, [r3, r4]!" \ "r2, [r3, -r4]" \ "r2, [r3, -r4]!" \ "r2, [r3], r4" \ "r2, [r3, #4]" \ "r2, [r3, #-4]" \ "r2, r3, #4" \ "r2, r3, #-4" \ "r2, #4" \ "r2, #-4" \ "#4" \ "#-4" \ "" do echo "$s $args" > a.s #cat a.s if as -o a.o a.s 2>err then cat err total_count=`expr $total_count + 1` objdump -S a.o |grep "^[ ]*0:" >a.expected echo '__asm__("'"$s ${args}"'");' > a.c if ./tcc -o a.o -c a.c then objdump -S a.o |grep "^[ ]*0:" >a.got diff -u a.got a.expected || { echo "warning: $s $args did not work in tcc (see above)">&2 } else echo "warning: $s $args did not work in tcc">&2 fi ok=1 fi done if [ "${ok}" -eq "0" ] then echo "warning: $s could not be used.">&2 continue fi done echo "total count: ${total_count}">&2 _______________________________________________ Tinycc-devel mailing list [hidden email] https://lists.nongnu.org/mailman/listinfo/tinycc-devel |
Free forum by Nabble | Edit this page |