arm-asm: For data processing instructions, support shifts and rotations.

This commit is contained in:
Danny Milosavljevic 2020-12-27 14:50:45 +01:00
parent abef8f6ca7
commit daaa88ce68
No known key found for this signature in database
GPG Key ID: E71A35542C30BAA5
2 changed files with 52 additions and 8 deletions

View File

@ -413,17 +413,54 @@ static void asm_data_processing_opcode(TCCState *s1, int token)
{ {
Operand ops[3]; Operand ops[3];
int nb_ops; int nb_ops;
Operand shift = {};
int nb_shift = 0;
uint32_t operands = 0;
/* 16 entries per instruction for the different condition codes */ /* 16 entries per instruction for the different condition codes */
uint32_t opcode_idx = (ARM_INSTRUCTION_GROUP(token) - TOK_ASM_andeq) >> 4; 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]); 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; break;
} }
next(); // skip ',' 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) if (nb_ops < 2)
expect("at least two operands"); expect("at least two operands");
@ -437,7 +474,6 @@ static void asm_data_processing_opcode(TCCState *s1, int token)
return; return;
} else { } else {
uint32_t opcode = 0; uint32_t opcode = 0;
uint32_t operands = 0;
// data processing (general case): // data processing (general case):
// operands: // operands:
@ -461,16 +497,13 @@ static void asm_data_processing_opcode(TCCState *s1, int token)
operands |= ENCODE_RN(ops[1].reg); operands |= ENCODE_RN(ops[1].reg);
switch (ops[2].type) { switch (ops[2].type) {
case OP_REG32: case OP_REG32:
// TODO: Parse and encode shift.
operands |= ops[2].reg; operands |= ops[2].reg;
break; break;
case OP_IM8: case OP_IM8:
// TODO: Parse and encode rotation.
operands |= ENCODE_IMMEDIATE_FLAG; operands |= ENCODE_IMMEDIATE_FLAG;
operands |= ops[2].e.v; operands |= ops[2].e.v;
break; break;
case OP_IM8N: // immediate negative value case OP_IM8N: // immediate negative value
// TODO: Parse and encode rotation.
operands |= ENCODE_IMMEDIATE_FLAG; operands |= ENCODE_IMMEDIATE_FLAG;
/* Instruction swapping: /* Instruction swapping:
0001 = EOR - Rd:= Op1 EOR Op2 -> difficult 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"); 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 */ /* S=0 and S=1 entries alternate one after another, in that order */
opcode |= (opcode_idx & 1) ? ENCODE_SET_CONDITION_CODES : 0; opcode |= (opcode_idx & 1) ? ENCODE_SET_CONDITION_CODES : 0;
asm_emit_opcode(token, opcode | operands); asm_emit_opcode(token, opcode | operands);

View File

@ -28,6 +28,10 @@
DEF_ASM(lr) /* alias for r14 */ DEF_ASM(lr) /* alias for r14 */
DEF_ASM(pc) /* alias for r15 */ 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) #define ARM_INSTRUCTION_GROUP(tok) ((((tok) - TOK_ASM_nopeq) & 0xFFFFFFF0) + TOK_ASM_nopeq)
/* Note: condition code is 4 bits */ /* Note: condition code is 4 bits */