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
56
arm-asm.c
56
arm-asm.c
@ -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);
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user