{"record":{"id":"746db49f15f41c31","repo":"ruby/ruby","slug":"invalid-operand-combination-to-msr-instruction","errorCode":null,"errorMessage":"Invalid operand combination to msr instruction","messagePattern":"Invalid operand combination to msr instruction","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"zjit/src/asm/arm64/mod.rs","lineNumber":776,"sourceCode":"/// MRS - move a system register into a general-purpose register\npub fn mrs(cb: &mut CodeBlock, rt: A64Opnd, systemregister: SystemRegister) {\n    let bytes: [u8; 4] = match rt {\n        A64Opnd::Reg(rt) => {\n            SysReg::mrs(rt.reg_no, systemregister).into()\n        },\n        _ => panic!(\"Invalid operand combination to mrs instruction\")\n    };\n\n    cb.write_bytes(&bytes);\n}\n\n/// MSR - move a general-purpose register into a system register\npub fn msr(cb: &mut CodeBlock, systemregister: SystemRegister, rt: A64Opnd) {\n    let bytes: [u8; 4] = match rt {\n        A64Opnd::Reg(rt) => {\n            SysReg::msr(systemregister, rt.reg_no).into()\n        },\n        _ => panic!(\"Invalid operand combination to msr instruction\")\n    };\n\n    cb.write_bytes(&bytes);\n}\n\n/// MUL - multiply two registers, put the result in a third register\npub fn mul(cb: &mut CodeBlock, rd: A64Opnd, rn: A64Opnd, rm: A64Opnd) {\n    let bytes: [u8; 4] = match (rd, rn, rm) {\n        (A64Opnd::Reg(rd), A64Opnd::Reg(rn), A64Opnd::Reg(rm)) => {\n            assert!(rd.num_bits == rn.num_bits && rn.num_bits == rm.num_bits, \"Expected registers to be the same size\");\n\n            MAdd::mul(rd.reg_no, rn.reg_no, rm.reg_no, rd.num_bits).into()\n        },\n        _ => panic!(\"Invalid operand combination to mul instruction\")\n    };\n\n    cb.write_bytes(&bytes);\n}","sourceCodeStart":758,"sourceCodeEnd":794,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/zjit/src/asm/arm64/mod.rs#L758-L794","documentation":"Panic from the msr helper in zjit's ARM64 assembler (zjit/src/asm/arm64/mod.rs:776). msr (write general-purpose register to a system register) matches only A64Opnd::Reg(rt); any other rt variant hits the wildcard arm and panics 'Invalid operand combination to msr instruction'. The first parameter is the SystemRegister enum itself, so the failure is always the register-side operand: it must be Reg, not Imm/UImm/Mem/None.","triggerScenarios":"Calling msr(cb, SystemRegister::FPCR, A64Opnd::UImm(0)) hoping to write a constant directly; passing a Mem operand as the value; passing None.","commonSituations":"Setting floating-point or debug flags (FPCR, DACR) from a JIT; assuming an immediate-to-system-register form exists like some macro-assembler shorthands; swapping mrs/msr argument orders during refactors.","solutions":["Load the constant into a register first, then msr with a Reg operand: movz(cb, x0, A64Opnd::new_uimm(0), 0); msr(cb, SystemRegister::FPCR, x0).","Ensure rt is A64Opnd::Reg — check with is_reg() when the operand is computed.","Verify argument order: msr(cb, SystemRegister, rt), the reverse of mrs(cb, rt, SystemRegister)."],"exampleFix":"// before\nmsr(cb, SystemRegister::FPCR, A64Opnd::new_uimm(0)); // panics: UImm rt\n\n// after\nmovz(cb, x0, A64Opnd::new_uimm(0), 0);\nmsr(cb, SystemRegister::FPCR, x0);","handlingStrategy":"type-guard","validationCode":"assert!(rt.is_reg(), \"msr value must be a register operand\");\nmsr(cb, SystemRegister::FPCR, rt);","typeGuard":"fn msr_operand_ok(rt: A64Opnd) -> bool { rt.is_reg() }","tryCatchPattern":null,"preventionTips":["No immediate-to-system-register form exists — always materialize constants into a register first.","Guard with is_reg() when the value operand comes from a generic lowering path.","Keep mrs/msr call sites adjacent and cross-check their mirrored argument order."],"tags":["rust","arm64","aarch64","assembler","zjit","jit","msr","system-register","operand-mismatch"],"backgroundTag":"assembler-invalid-operand","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}