Revision 8984bd2e target-arm/op_helper.c

b/target-arm/op_helper.c
304 304
    }
305 305
}
306 306

  
307
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
308
   The only way to do that in TCG is a conditional branch, which clobbers
309
   all our temporaries.  For now implement these as helper functions.  */
310

  
311
uint32_t HELPER (add_cc)(uint32_t a, uint32_t b)
312
{
313
    uint32_t result;
314
    result = T0 + T1;
315
    env->NZF = result;
316
    env->CF = result < a;
317
    env->VF = (a ^ b ^ -1) & (a ^ result);
318
    return result;
319
}
320

  
321
uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
322
{
323
    uint32_t result;
324
    if (!env->CF) {
325
        result = a + b;
326
        env->CF = result < a;
327
    } else {
328
        result = a + b + 1;
329
        env->CF = result <= a;
330
    }
331
    env->VF = (a ^ b ^ -1) & (a ^ result);
332
    env->NZF = result;
333
    return result;
334
}
335

  
336
uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
337
{
338
    uint32_t result;
339
    result = a - b;
340
    env->NZF = result;
341
    env->CF = a >= b;
342
    env->VF = (a ^ b) & (a ^ result);
343
    return result;
344
}
345

  
346
uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
347
{
348
    uint32_t result;
349
    if (!env->CF) {
350
        result = a - b - 1;
351
        env->CF = a > b;
352
    } else {
353
        result = a - b;
354
        env->CF = a >= b;
355
    }
356
    env->VF = (a ^ b) & (a ^ result);
357
    env->NZF = result;
358
    return result;
359
}
360

  
361
/* Similarly for variable shift instructions.  */
362

  
363
uint32_t HELPER(shl)(uint32_t x, uint32_t i)
364
{
365
    int shift = i & 0xff;
366
    if (shift >= 32)
367
        return 0;
368
    return x << shift;
369
}
370

  
371
uint32_t HELPER(shr)(uint32_t x, uint32_t i)
372
{
373
    int shift = i & 0xff;
374
    if (shift >= 32)
375
        return 0;
376
    return (uint32_t)x >> shift;
377
}
378

  
379
uint32_t HELPER(sar)(uint32_t x, uint32_t i)
380
{
381
    int shift = i & 0xff;
382
    if (shift >= 32)
383
        shift = 31;
384
    return (int32_t)x >> shift;
385
}
386

  
387
uint32_t HELPER(ror)(uint32_t x, uint32_t i)
388
{
389
    int shift = i & 0xff;
390
    if (shift == 0)
391
        return x;
392
    return (x >> shift) | (x << (32 - shift));
393
}
394

  
395
uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
396
{
397
    int shift = i & 0xff;
398
    if (shift >= 32) {
399
        if (shift == 32)
400
            env->CF = x & 1;
401
        else
402
            env->CF = 0;
403
        return 0;
404
    } else if (shift != 0) {
405
        env->CF = (x >> (32 - shift)) & 1;
406
        return x << shift;
407
    }
408
    return x;
409
}
410

  
411
uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
412
{
413
    int shift = i & 0xff;
414
    if (shift >= 32) {
415
        if (shift == 32)
416
            env->CF = (x >> 31) & 1;
417
        else
418
            env->CF = 0;
419
        return 0;
420
    } else if (shift != 0) {
421
        env->CF = (x >> (shift - 1)) & 1;
422
        return x >> shift;
423
    }
424
    return x;
425
}
426

  
427
uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
428
{
429
    int shift = i & 0xff;
430
    if (shift >= 32) {
431
        env->CF = (x >> 31) & 1;
432
        return (int32_t)x >> 31;
433
    } else if (shift != 0) {
434
        env->CF = (x >> (shift - 1)) & 1;
435
        return (int32_t)x >> shift;
436
    }
437
    return x;
438
}
439

  
440
uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
441
{
442
    int shift1, shift;
443
    shift1 = i & 0xff;
444
    shift = shift1 & 0x1f;
445
    if (shift == 0) {
446
        if (shift1 != 0)
447
            env->CF = (x >> 31) & 1;
448
        return x;
449
    } else {
450
        env->CF = (x >> (shift - 1)) & 1;
451
        return ((uint32_t)x >> shift) | (x << (32 - shift));
452
    }
453
}
454

  

Also available in: Unified diff