arm-asm: Support shift of 0 in asm_shift_opcode
This commit is contained in:
parent
9539f51369
commit
a7205f738b
1 changed files with 21 additions and 35 deletions
56
arm-asm.c
56
arm-asm.c
|
@ -433,26 +433,6 @@ 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)
|
static uint32_t asm_encode_shift(Operand* shift)
|
||||||
{
|
{
|
||||||
uint64_t amount;
|
uint64_t amount;
|
||||||
|
@ -690,6 +670,7 @@ static void asm_shift_opcode(TCCState *s1, int token)
|
||||||
{
|
{
|
||||||
Operand ops[3];
|
Operand ops[3];
|
||||||
int nb_ops;
|
int nb_ops;
|
||||||
|
int definitely_neutral = 0;
|
||||||
uint32_t opcode = 0xd << 21; // MOV
|
uint32_t opcode = 0xd << 21; // MOV
|
||||||
uint32_t operands = 0;
|
uint32_t operands = 0;
|
||||||
|
|
||||||
|
@ -736,6 +717,15 @@ static void asm_shift_opcode(TCCState *s1, int token)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (ARM_INSTRUCTION_GROUP(token)) {
|
||||||
|
case TOK_ASM_lslseq:
|
||||||
|
case TOK_ASM_lsrseq:
|
||||||
|
case TOK_ASM_asrseq:
|
||||||
|
case TOK_ASM_rorseq:
|
||||||
|
opcode |= ENCODE_SET_CONDITION_CODES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (ops[1].type) {
|
switch (ops[1].type) {
|
||||||
case OP_REG32:
|
case OP_REG32:
|
||||||
operands |= ops[1].reg;
|
operands |= ops[1].reg;
|
||||||
|
@ -746,40 +736,36 @@ static void asm_shift_opcode(TCCState *s1, int token)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ops[2].type == OP_REG32) {
|
switch (ops[2].type) {
|
||||||
|
case OP_REG32:
|
||||||
if ((ops[0].type == OP_REG32 && ops[0].reg == 15) ||
|
if ((ops[0].type == OP_REG32 && ops[0].reg == 15) ||
|
||||||
(ops[1].type == OP_REG32 && ops[1].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");
|
tcc_error("Using the 'pc' register in data processing instructions that have a register-controlled shift is not implemented by ARM");
|
||||||
}
|
}
|
||||||
|
operands |= asm_encode_shift(&ops[2]);
|
||||||
|
break;
|
||||||
|
case OP_IM8:
|
||||||
|
if (ops[2].e.v)
|
||||||
|
operands |= asm_encode_shift(&ops[2]);
|
||||||
|
else
|
||||||
|
definitely_neutral = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operands & ENCODE_IMMEDIATE_FLAG)
|
if (!definitely_neutral) switch (ARM_INSTRUCTION_GROUP(token)) {
|
||||||
operands |= asm_encode_rotation(&ops[2]);
|
|
||||||
else
|
|
||||||
operands |= asm_encode_shift(&ops[2]);
|
|
||||||
|
|
||||||
switch (ARM_INSTRUCTION_GROUP(token)) {
|
|
||||||
case TOK_ASM_lslseq:
|
case TOK_ASM_lslseq:
|
||||||
opcode |= ENCODE_SET_CONDITION_CODES;
|
|
||||||
/* fallthrough */
|
|
||||||
case TOK_ASM_lsleq:
|
case TOK_ASM_lsleq:
|
||||||
operands |= ENCODE_BARREL_SHIFTER_MODE_LSL;
|
operands |= ENCODE_BARREL_SHIFTER_MODE_LSL;
|
||||||
break;
|
break;
|
||||||
case TOK_ASM_lsrseq:
|
case TOK_ASM_lsrseq:
|
||||||
opcode |= ENCODE_SET_CONDITION_CODES;
|
|
||||||
/* fallthrough */
|
|
||||||
case TOK_ASM_lsreq:
|
case TOK_ASM_lsreq:
|
||||||
operands |= ENCODE_BARREL_SHIFTER_MODE_LSR;
|
operands |= ENCODE_BARREL_SHIFTER_MODE_LSR;
|
||||||
break;
|
break;
|
||||||
case TOK_ASM_asrseq:
|
case TOK_ASM_asrseq:
|
||||||
opcode |= ENCODE_SET_CONDITION_CODES;
|
|
||||||
/* fallthrough */
|
|
||||||
case TOK_ASM_asreq:
|
case TOK_ASM_asreq:
|
||||||
operands |= ENCODE_BARREL_SHIFTER_MODE_ASR;
|
operands |= ENCODE_BARREL_SHIFTER_MODE_ASR;
|
||||||
break;
|
break;
|
||||||
case TOK_ASM_rorseq:
|
case TOK_ASM_rorseq:
|
||||||
opcode |= ENCODE_SET_CONDITION_CODES;
|
|
||||||
/* fallthrough */
|
|
||||||
case TOK_ASM_roreq:
|
case TOK_ASM_roreq:
|
||||||
operands |= ENCODE_BARREL_SHIFTER_MODE_ROR;
|
operands |= ENCODE_BARREL_SHIFTER_MODE_ROR;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue