(ctx: *mut c_void, regid: c_int, value: *const c_void)
| 200 | } |
| 201 | |
| 202 | pub unsafe extern "C" fn reg_write(ctx: *mut c_void, regid: c_int, value: *const c_void) -> uc_err { |
| 203 | debug!("icicle_unicorn_api::reg_write({regid})"); |
| 204 | let ctx = &mut *ctx.cast::<Context>(); |
| 205 | let vm = unsafe { &mut *ctx.vm }; |
| 206 | |
| 207 | match regid as uc_arm_reg::Type { |
| 208 | uc_arm_reg::UC_ARM_REG_PC => { |
| 209 | let new_pc = (*value.cast::<u32>() & !0b1) as u64; |
| 210 | vm.cpu.set_isa_mode(1); |
| 211 | vm.cpu.exception.code = ExceptionCode::ExternalAddr as u32; |
| 212 | vm.cpu.exception.value = new_pc; |
| 213 | |
| 214 | // @fixme: this is part of the API for interrupt frames, so should be part of the code |
| 215 | // there instead changing things here. |
| 216 | vm.lifter.set_context(vm.cpu.arch.isa_mode_context[1]); |
| 217 | vm.cpu.write_pc(new_pc); |
| 218 | } |
| 219 | uc_arm_reg::UC_ARM_REG_XPSR => { |
| 220 | let xpsr_reg = ctx.uc_vars[regid as usize]; |
| 221 | let vm = unsafe { &mut *ctx.vm }; |
| 222 | vm.cpu.write_reg(xpsr_reg, *value.cast::<u32>() as u64); |
| 223 | } |
| 224 | _ => { |
| 225 | let data = ctx.get_reg_slice(regid).unwrap_or_else(|| invalid_reg(regid)); |
| 226 | if data.len() == 4 { |
| 227 | *data.as_mut_ptr().cast::<u32>() = *value.cast::<u32>(); |
| 228 | } |
| 229 | else { |
| 230 | copy_value_cold(value, data); |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | UC_ERR_OK |
| 236 | } |
| 237 | |
| 238 | #[cold] |
| 239 | unsafe fn copy_value_cold(value: *const std::ffi::c_void, data: &mut [u8]) { |
no test coverage detected