fetch one byte from [ip], decrypt with current cipher state, update state, advance ip, leave result in low 8 of dst
| 109 | // fetch one byte from [ip], decrypt with current cipher state, update state, |
| 110 | // advance ip, leave result in low 8 of dst |
| 111 | void emit_fetch_byte_dec(X64Emitter& e, const VMConfig& vm, std::uint8_t dst) { |
| 112 | const auto& r = vm.dispatcher_regs(); |
| 113 | const std::int32_t add_off = static_cast<std::int32_t>(vm.state_layout().cipher_extra) + kCipherAddOff; |
| 114 | const std::int32_t mult_off = static_cast<std::int32_t>(vm.state_layout().cipher_extra) + kCipherMultOff; |
| 115 | const std::int32_t sbox_off = static_cast<std::int32_t>(vm.state_layout().cipher_extra) + kSboxInvOff; |
| 116 | |
| 117 | // movzx dst, byte [ip] |
| 118 | e.emit_rex( |
| 119 | false, |
| 120 | dst >= 8, |
| 121 | false, |
| 122 | r.ip >= 8 |
| 123 | ); |
| 124 | e.u8(0x0F); e.u8(0xB6); |
| 125 | e.emit_modrm_mem( |
| 126 | dst & 7, |
| 127 | r.ip, |
| 128 | rx::none, |
| 129 | 0, |
| 130 | 0 |
| 131 | ); |
| 132 | |
| 133 | // inc ip |
| 134 | e.inc_reg(r.ip, true); |
| 135 | |
| 136 | // mix byte with cipher_state low, then advance state |
| 137 | auto add_cs_mem = [&](std::int32_t disp) { |
| 138 | e.emit_rex( |
| 139 | true, |
| 140 | r.cipher_state >= 8, |
| 141 | false, |
| 142 | r.state_ptr >= 8 |
| 143 | ); |
| 144 | e.u8(0x03); // ADD r64, r/m64 |
| 145 | |
| 146 | e.emit_modrm_mem( |
| 147 | r.cipher_state & 7, |
| 148 | r.state_ptr, |
| 149 | rx::none, |
| 150 | 0, |
| 151 | disp |
| 152 | ); |
| 153 | }; |
| 154 | |
| 155 | auto imul_cs_mem = [&](std::int32_t disp) { |
| 156 | e.emit_rex( |
| 157 | true, |
| 158 | r.cipher_state >= 8, |
| 159 | false, |
| 160 | r.state_ptr >= 8 |
| 161 | ); |
| 162 | e.u8(0x0F); e.u8(0xAF); // IMUL r64, r/m64 |
| 163 | |
| 164 | e.emit_modrm_mem( |
| 165 | r.cipher_state & 7, |
| 166 | r.state_ptr, |
| 167 | rx::none, |
| 168 | 0, |
no test coverage detected