tools/objtool/arch/loongarch/decode.c

Source file repositories/reference/linux-study-clean/tools/objtool/arch/loongarch/decode.c

File Facts

System
Linux kernel
Corpus path
tools/objtool/arch/loongarch/decode.c
Extension
.c
Size
10404 bytes
Lines
440
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if ((inst.reg2i12_format.rd == CFI_SP) || (inst.reg2i12_format.rj == CFI_SP)) {
			/* addi.d sp,sp,si12 or addi.d fp,sp,si12 or addi.d sp,fp,si12 */
			insn->immediate = sign_extend64(inst.reg2i12_format.immediate, 11);
			ADD_OP(op) {
				op->src.type = OP_SRC_ADD;
				op->src.reg = inst.reg2i12_format.rj;
				op->src.offset = insn->immediate;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = inst.reg2i12_format.rd;
			}
		}
		if ((inst.reg2i12_format.rd == CFI_SP) && (inst.reg2i12_format.rj == CFI_FP)) {
			/* addi.d sp,fp,si12 */
			struct symbol *func = find_func_containing(insn->sec, insn->offset);

			if (!func)
				return false;

			func->frame_pointer = true;
		}
		break;
	case ldd_op:
		if (inst.reg2i12_format.rj == CFI_SP) {
			/* ld.d rd,sp,si12 */
			insn->immediate = sign_extend64(inst.reg2i12_format.immediate, 11);
			ADD_OP(op) {
				op->src.type = OP_SRC_REG_INDIRECT;
				op->src.reg = CFI_SP;
				op->src.offset = insn->immediate;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = inst.reg2i12_format.rd;
			}
		}
		break;
	case std_op:
		if (inst.reg2i12_format.rj == CFI_SP) {
			/* st.d rd,sp,si12 */
			insn->immediate = sign_extend64(inst.reg2i12_format.immediate, 11);
			ADD_OP(op) {
				op->src.type = OP_SRC_REG;
				op->src.reg = inst.reg2i12_format.rd;
				op->dest.type = OP_DEST_REG_INDIRECT;
				op->dest.reg = CFI_SP;
				op->dest.offset = insn->immediate;
			}
		}
		break;
	case andi_op:
		if (inst.reg2i12_format.rd == 0 &&
		    inst.reg2i12_format.rj == 0 &&
		    inst.reg2i12_format.immediate == 0)
			/* andi r0,r0,0 */
			insn->type = INSN_NOP;
		break;
	default:
		return false;
	}

	return true;
}

static bool decode_insn_reg2i14_fomat(union loongarch_instruction inst,
				      struct instruction *insn,
				      struct stack_op **ops_list,
				      struct stack_op *op)
{
	switch (inst.reg2i14_format.opcode) {
	case ldptrd_op:
		if (inst.reg2i14_format.rj == CFI_SP) {
			/* ldptr.d rd,sp,si14 */
			insn->immediate = sign_extend64(inst.reg2i14_format.immediate, 13);
			ADD_OP(op) {
				op->src.type = OP_SRC_REG_INDIRECT;
				op->src.reg = CFI_SP;
				op->src.offset = insn->immediate;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = inst.reg2i14_format.rd;
			}
		}
		break;
	case stptrd_op:
		if (inst.reg2i14_format.rj == CFI_SP) {
			/* stptr.d ra,sp,0 */
			if (inst.reg2i14_format.rd == LOONGARCH_GPR_RA &&
			    inst.reg2i14_format.immediate == 0)
				break;

			/* stptr.d rd,sp,si14 */
			insn->immediate = sign_extend64(inst.reg2i14_format.immediate, 13);
			ADD_OP(op) {

Annotation

Implementation Notes