| 512 | } |
| 513 | |
| 514 | static const char * |
| 515 | eval_divmod(uint32_t op, struct bpf_reg_val *rd, struct bpf_reg_val *rs, |
| 516 | size_t opsz, uint64_t msk) |
| 517 | { |
| 518 | /* both operands are constants */ |
| 519 | if (rd->u.min == rd->u.max && rs->u.min == rs->u.max) { |
| 520 | if (rs->u.max == 0) |
| 521 | return "division by 0"; |
| 522 | if (op == BPF_DIV) { |
| 523 | rd->u.min /= rs->u.min; |
| 524 | rd->u.max /= rs->u.max; |
| 525 | } else { |
| 526 | rd->u.min %= rs->u.min; |
| 527 | rd->u.max %= rs->u.max; |
| 528 | } |
| 529 | } else { |
| 530 | if (op == BPF_MOD) |
| 531 | rd->u.max = RTE_MIN(rd->u.max, rs->u.max - 1); |
| 532 | else |
| 533 | rd->u.max = rd->u.max; |
| 534 | rd->u.min = 0; |
| 535 | } |
| 536 | |
| 537 | /* if we have 32-bit values - extend them to 64-bit */ |
| 538 | if (opsz == sizeof(uint32_t) * CHAR_BIT) { |
| 539 | rd->s.min = (int32_t)rd->s.min; |
| 540 | rd->s.max = (int32_t)rd->s.max; |
| 541 | rs->s.min = (int32_t)rs->s.min; |
| 542 | rs->s.max = (int32_t)rs->s.max; |
| 543 | } |
| 544 | |
| 545 | /* both operands are constants */ |
| 546 | if (rd->s.min == rd->s.max && rs->s.min == rs->s.max) { |
| 547 | if (rs->s.max == 0) |
| 548 | return "division by 0"; |
| 549 | if (op == BPF_DIV) { |
| 550 | rd->s.min /= rs->s.min; |
| 551 | rd->s.max /= rs->s.max; |
| 552 | } else { |
| 553 | rd->s.min %= rs->s.min; |
| 554 | rd->s.max %= rs->s.max; |
| 555 | } |
| 556 | } else if (op == BPF_MOD) { |
| 557 | rd->s.min = RTE_MAX(rd->s.max, 0); |
| 558 | rd->s.min = RTE_MIN(rd->s.min, 0); |
| 559 | } else |
| 560 | eval_smax_bound(rd, msk); |
| 561 | |
| 562 | rd->s.max &= msk; |
| 563 | rd->s.min &= msk; |
| 564 | |
| 565 | return NULL; |
| 566 | } |
| 567 | |
| 568 | static void |
| 569 | eval_neg(struct bpf_reg_val *rd, size_t opsz, uint64_t msk) |
no test coverage detected