[PATCH] arm-asm: Support shift of 0 in asm_shift_opcode

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] arm-asm: Support shift of 0 in asm_shift_opcode

Danny Milosavljevic
---
 arm-asm.c | 56 +++++++++++++++++++++----------------------------------
 1 file changed, 21 insertions(+), 35 deletions(-)

diff --git a/arm-asm.c b/arm-asm.c
index 64588ea..f392f4f 100644
--- a/arm-asm.c
+++ b/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)
 {
     uint64_t amount;
@@ -690,6 +670,7 @@ static void asm_shift_opcode(TCCState *s1, int token)
 {
     Operand ops[3];
     int nb_ops;
+    int definitely_neutral = 0;
     uint32_t opcode = 0xd << 21; // MOV
     uint32_t operands = 0;
 
@@ -736,6 +717,15 @@ static void asm_shift_opcode(TCCState *s1, int token)
         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) {
     case OP_REG32:
         operands |= ops[1].reg;
@@ -746,40 +736,36 @@ static void asm_shift_opcode(TCCState *s1, int token)
         break;
     }
 
-    if (ops[2].type == OP_REG32) {
+    switch (ops[2].type) {
+    case 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
         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;
+    }
 
-    switch (ARM_INSTRUCTION_GROUP(token)) {
+    if (!definitely_neutral) 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;

_______________________________________________
Tinycc-devel mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel