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