Revision 94953e6d

b/tcg/arm/tcg-target.c
179 179
    return 0;
180 180
}
181 181

  
182
static inline uint32_t rotl(uint32_t val, int n)
183
{
184
  return (val << n) | (val >> (32 - n));
185
}
186

  
187
/* ARM immediates for ALU instructions are made of an unsigned 8-bit
188
   right-rotated by an even amount between 0 and 30. */
189
static inline int encode_imm(uint32_t imm)
190
{
191
    /* simple case, only lower bits */
192
    if ((imm & ~0xff) == 0)
193
        return 0;
194
    /* then try a simple even shift */
195
    shift = ctz32(imm) & ~1;
196
    if (((imm >> shift) & ~0xff) == 0)
197
        return 32 - shift;
198
    /* now try harder with rotations */
199
    if ((rotl(imm, 2) & ~0xff) == 0)
200
        return 2;
201
    if ((rotl(imm, 4) & ~0xff) == 0)
202
        return 4;
203
    if ((rotl(imm, 6) & ~0xff) == 0)
204
        return 6;
205
    /* imm can't be encoded */
206
    return -1;
207
}
182 208

  
183 209
static inline int check_fit_imm(uint32_t imm)
184 210
{
185
    /* XXX: use rotation */
186
    return (imm & ~0xff) == 0;
211
    return encode_imm(imm) >= 0;
187 212
}
188 213

  
189 214
/* Test if a constant matches the constraint.
......
1407 1432
        c = ARITH_EOR;
1408 1433
        /* Fall through.  */
1409 1434
    gen_arith:
1410
        if (const_args[2])
1435
        if (const_args[2]) {
1436
            int rot;
1437
            rot = encode_imm(args[2]);
1411 1438
            tcg_out_dat_imm(s, COND_AL, c,
1412
                            args[0], args[1], args[2]);
1413
        else
1439
                            args[0], args[1], rotl(args[2], rot) | (rot << 7));
1440
        } else
1414 1441
            tcg_out_dat_reg(s, COND_AL, c,
1415 1442
                            args[0], args[1], args[2], SHIFT_IMM_LSL(0));
1416 1443
        break;

Also available in: Unified diff