mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-24 07:50:12 +08:00
arm-asm: For data processing instructions, support shifts and rotations.
This commit is contained in:
parent
abef8f6ca7
commit
daaa88ce68
54
arm-asm.c
54
arm-asm.c
@ -413,17 +413,54 @@ 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;
|
||||
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(); // 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)
|
||||
expect("at least two operands");
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user