* emit one of: * mov % , (% ) * mov , (% ) */
| 596 | * mov <imm>, <ofs>(%<dreg>) |
| 597 | */ |
| 598 | static void |
| 599 | emit_st_common(struct bpf_jit_state *st, uint32_t op, uint32_t sreg, |
| 600 | uint32_t dreg, uint32_t imm, int32_t ofs) |
| 601 | { |
| 602 | uint32_t mods, imsz, opsz, opx; |
| 603 | const uint8_t prfx16 = 0x66; |
| 604 | |
| 605 | /* 8 bit instruction opcodes */ |
| 606 | static const uint8_t op8[] = {0xC6, 0x88}; |
| 607 | |
| 608 | /* 16/32/64 bit instruction opcodes */ |
| 609 | static const uint8_t ops[] = {0xC7, 0x89}; |
| 610 | |
| 611 | /* is the instruction has immediate value or src reg? */ |
| 612 | opx = (BPF_CLASS(op) == BPF_STX); |
| 613 | |
| 614 | opsz = BPF_SIZE(op); |
| 615 | if (opsz == BPF_H) |
| 616 | emit_bytes(st, &prfx16, sizeof(prfx16)); |
| 617 | |
| 618 | emit_rex(st, op, sreg, dreg); |
| 619 | |
| 620 | if (opsz == BPF_B) |
| 621 | emit_bytes(st, &op8[opx], sizeof(op8[opx])); |
| 622 | else |
| 623 | emit_bytes(st, &ops[opx], sizeof(ops[opx])); |
| 624 | |
| 625 | imsz = imm_size(ofs); |
| 626 | mods = (imsz == 1) ? MOD_IDISP8 : MOD_IDISP32; |
| 627 | |
| 628 | emit_modregrm(st, mods, sreg, dreg); |
| 629 | |
| 630 | if (dreg == RSP || dreg == R12) |
| 631 | emit_sib(st, SIB_SCALE_1, dreg, dreg); |
| 632 | |
| 633 | emit_imm(st, ofs, imsz); |
| 634 | |
| 635 | if (opx == 0) { |
| 636 | imsz = RTE_MIN(bpf_size(opsz), sizeof(imm)); |
| 637 | emit_imm(st, imm, imsz); |
| 638 | } |
| 639 | } |
| 640 | |
| 641 | static void |
| 642 | emit_st_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg, uint32_t imm, |
no test coverage detected