Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 
0003 #include <linux/bitops.h>
0004 #include <linux/kernel.h>
0005 #include <linux/kprobes.h>
0006 
0007 #include "decode-insn.h"
0008 #include "simulate-insn.h"
0009 
0010 static inline bool csky_insn_reg_get_val(struct pt_regs *regs,
0011                      unsigned long index,
0012                      unsigned long *ptr)
0013 {
0014     if (index < 14)
0015         *ptr = *(&regs->a0 + index);
0016 
0017     if (index > 15 && index < 31)
0018         *ptr = *(&regs->exregs[0] + index - 16);
0019 
0020     switch (index) {
0021     case 14:
0022         *ptr = regs->usp;
0023         break;
0024     case 15:
0025         *ptr = regs->lr;
0026         break;
0027     case 31:
0028         *ptr = regs->tls;
0029         break;
0030     default:
0031         goto fail;
0032     }
0033 
0034     return true;
0035 fail:
0036     return false;
0037 }
0038 
0039 static inline bool csky_insn_reg_set_val(struct pt_regs *regs,
0040                      unsigned long index,
0041                      unsigned long val)
0042 {
0043     if (index < 14)
0044         *(&regs->a0 + index) = val;
0045 
0046     if (index > 15 && index < 31)
0047         *(&regs->exregs[0] + index - 16) = val;
0048 
0049     switch (index) {
0050     case 14:
0051         regs->usp = val;
0052         break;
0053     case 15:
0054         regs->lr = val;
0055         break;
0056     case 31:
0057         regs->tls = val;
0058         break;
0059     default:
0060         goto fail;
0061     }
0062 
0063     return true;
0064 fail:
0065     return false;
0066 }
0067 
0068 void __kprobes
0069 simulate_br16(u32 opcode, long addr, struct pt_regs *regs)
0070 {
0071     instruction_pointer_set(regs,
0072         addr + sign_extend32((opcode & 0x3ff) << 1, 9));
0073 }
0074 
0075 void __kprobes
0076 simulate_br32(u32 opcode, long addr, struct pt_regs *regs)
0077 {
0078     instruction_pointer_set(regs,
0079         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0080 }
0081 
0082 void __kprobes
0083 simulate_bt16(u32 opcode, long addr, struct pt_regs *regs)
0084 {
0085     if (regs->sr & 1)
0086         instruction_pointer_set(regs,
0087             addr + sign_extend32((opcode & 0x3ff) << 1, 9));
0088     else
0089         instruction_pointer_set(regs, addr + 2);
0090 }
0091 
0092 void __kprobes
0093 simulate_bt32(u32 opcode, long addr, struct pt_regs *regs)
0094 {
0095     if (regs->sr & 1)
0096         instruction_pointer_set(regs,
0097             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0098     else
0099         instruction_pointer_set(regs, addr + 4);
0100 }
0101 
0102 void __kprobes
0103 simulate_bf16(u32 opcode, long addr, struct pt_regs *regs)
0104 {
0105     if (!(regs->sr & 1))
0106         instruction_pointer_set(regs,
0107             addr + sign_extend32((opcode & 0x3ff) << 1, 9));
0108     else
0109         instruction_pointer_set(regs, addr + 2);
0110 }
0111 
0112 void __kprobes
0113 simulate_bf32(u32 opcode, long addr, struct pt_regs *regs)
0114 {
0115     if (!(regs->sr & 1))
0116         instruction_pointer_set(regs,
0117             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0118     else
0119         instruction_pointer_set(regs, addr + 4);
0120 }
0121 
0122 void __kprobes
0123 simulate_jmp16(u32 opcode, long addr, struct pt_regs *regs)
0124 {
0125     unsigned long tmp = (opcode >> 2) & 0xf;
0126 
0127     csky_insn_reg_get_val(regs, tmp, &tmp);
0128 
0129     instruction_pointer_set(regs, tmp & 0xfffffffe);
0130 }
0131 
0132 void __kprobes
0133 simulate_jmp32(u32 opcode, long addr, struct pt_regs *regs)
0134 {
0135     unsigned long tmp = opcode & 0x1f;
0136 
0137     csky_insn_reg_get_val(regs, tmp, &tmp);
0138 
0139     instruction_pointer_set(regs, tmp & 0xfffffffe);
0140 }
0141 
0142 void __kprobes
0143 simulate_jsr16(u32 opcode, long addr, struct pt_regs *regs)
0144 {
0145     unsigned long tmp = (opcode >> 2) & 0xf;
0146 
0147     csky_insn_reg_get_val(regs, tmp, &tmp);
0148 
0149     regs->lr = addr + 2;
0150 
0151     instruction_pointer_set(regs, tmp & 0xfffffffe);
0152 }
0153 
0154 void __kprobes
0155 simulate_jsr32(u32 opcode, long addr, struct pt_regs *regs)
0156 {
0157     unsigned long tmp = opcode & 0x1f;
0158 
0159     csky_insn_reg_get_val(regs, tmp, &tmp);
0160 
0161     regs->lr = addr + 4;
0162 
0163     instruction_pointer_set(regs, tmp & 0xfffffffe);
0164 }
0165 
0166 void __kprobes
0167 simulate_lrw16(u32 opcode, long addr, struct pt_regs *regs)
0168 {
0169     unsigned long val;
0170     unsigned long tmp = (opcode & 0x300) >> 3;
0171     unsigned long offset = ((opcode & 0x1f) | tmp) << 2;
0172 
0173     tmp = (opcode & 0xe0) >> 5;
0174 
0175     val = *(unsigned int *)(instruction_pointer(regs) + offset);
0176 
0177     csky_insn_reg_set_val(regs, tmp, val);
0178 }
0179 
0180 void __kprobes
0181 simulate_lrw32(u32 opcode, long addr, struct pt_regs *regs)
0182 {
0183     unsigned long val;
0184     unsigned long offset = (opcode & 0xffff0000) >> 14;
0185     unsigned long tmp = opcode & 0x0000001f;
0186 
0187     val = *(unsigned int *)
0188         ((instruction_pointer(regs) + offset) & 0xfffffffc);
0189 
0190     csky_insn_reg_set_val(regs, tmp, val);
0191 }
0192 
0193 void __kprobes
0194 simulate_pop16(u32 opcode, long addr, struct pt_regs *regs)
0195 {
0196     unsigned long *tmp = (unsigned long *)regs->usp;
0197     int i;
0198 
0199     for (i = 0; i < (opcode & 0xf); i++) {
0200         csky_insn_reg_set_val(regs, i + 4, *tmp);
0201         tmp += 1;
0202     }
0203 
0204     if (opcode & 0x10) {
0205         csky_insn_reg_set_val(regs, 15, *tmp);
0206         tmp += 1;
0207     }
0208 
0209     regs->usp = (unsigned long)tmp;
0210 
0211     instruction_pointer_set(regs, regs->lr);
0212 }
0213 
0214 void __kprobes
0215 simulate_pop32(u32 opcode, long addr, struct pt_regs *regs)
0216 {
0217     unsigned long *tmp = (unsigned long *)regs->usp;
0218     int i;
0219 
0220     for (i = 0; i < ((opcode & 0xf0000) >> 16); i++) {
0221         csky_insn_reg_set_val(regs, i + 4, *tmp);
0222         tmp += 1;
0223     }
0224 
0225     if (opcode & 0x100000) {
0226         csky_insn_reg_set_val(regs, 15, *tmp);
0227         tmp += 1;
0228     }
0229 
0230     for (i = 0; i < ((opcode & 0xe00000) >> 21); i++) {
0231         csky_insn_reg_set_val(regs, i + 16, *tmp);
0232         tmp += 1;
0233     }
0234 
0235     if (opcode & 0x1000000) {
0236         csky_insn_reg_set_val(regs, 29, *tmp);
0237         tmp += 1;
0238     }
0239 
0240     regs->usp = (unsigned long)tmp;
0241 
0242     instruction_pointer_set(regs, regs->lr);
0243 }
0244 
0245 void __kprobes
0246 simulate_bez32(u32 opcode, long addr, struct pt_regs *regs)
0247 {
0248     unsigned long tmp = opcode & 0x1f;
0249 
0250     csky_insn_reg_get_val(regs, tmp, &tmp);
0251 
0252     if (tmp == 0) {
0253         instruction_pointer_set(regs,
0254             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0255     } else
0256         instruction_pointer_set(regs, addr + 4);
0257 }
0258 
0259 void __kprobes
0260 simulate_bnez32(u32 opcode, long addr, struct pt_regs *regs)
0261 {
0262     unsigned long tmp = opcode & 0x1f;
0263 
0264     csky_insn_reg_get_val(regs, tmp, &tmp);
0265 
0266     if (tmp != 0) {
0267         instruction_pointer_set(regs,
0268             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0269     } else
0270         instruction_pointer_set(regs, addr + 4);
0271 }
0272 
0273 void __kprobes
0274 simulate_bnezad32(u32 opcode, long addr, struct pt_regs *regs)
0275 {
0276     unsigned long tmp = opcode & 0x1f;
0277     long val;
0278 
0279     csky_insn_reg_get_val(regs, tmp, (unsigned long *)&val);
0280 
0281     val -= 1;
0282 
0283     if (val > 0) {
0284         instruction_pointer_set(regs,
0285             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0286     } else
0287         instruction_pointer_set(regs, addr + 4);
0288 
0289     csky_insn_reg_set_val(regs, tmp, (unsigned long)val);
0290 }
0291 
0292 void __kprobes
0293 simulate_bhsz32(u32 opcode, long addr, struct pt_regs *regs)
0294 {
0295     unsigned long tmp = opcode & 0x1f;
0296     unsigned long val;
0297 
0298     csky_insn_reg_get_val(regs, tmp, &val);
0299 
0300     if ((long) val >= 0) {
0301         instruction_pointer_set(regs,
0302             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0303     } else
0304         instruction_pointer_set(regs, addr + 4);
0305 }
0306 
0307 void __kprobes
0308 simulate_bhz32(u32 opcode, long addr, struct pt_regs *regs)
0309 {
0310     unsigned long tmp = opcode & 0x1f;
0311     unsigned long val;
0312 
0313     csky_insn_reg_get_val(regs, tmp, &val);
0314 
0315     if ((long) val > 0) {
0316         instruction_pointer_set(regs,
0317             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0318     } else
0319         instruction_pointer_set(regs, addr + 4);
0320 }
0321 
0322 void __kprobes
0323 simulate_blsz32(u32 opcode, long addr, struct pt_regs *regs)
0324 {
0325     unsigned long tmp = opcode & 0x1f;
0326     unsigned long val;
0327 
0328     csky_insn_reg_get_val(regs, tmp, &val);
0329 
0330     if ((long) val <= 0) {
0331         instruction_pointer_set(regs,
0332             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0333     } else
0334         instruction_pointer_set(regs, addr + 4);
0335 }
0336 
0337 void __kprobes
0338 simulate_blz32(u32 opcode, long addr, struct pt_regs *regs)
0339 {
0340     unsigned long tmp = opcode & 0x1f;
0341     unsigned long val;
0342 
0343     csky_insn_reg_get_val(regs, tmp, &val);
0344 
0345     if ((long) val < 0) {
0346         instruction_pointer_set(regs,
0347             addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
0348     } else
0349         instruction_pointer_set(regs, addr + 4);
0350 }
0351 
0352 void __kprobes
0353 simulate_bsr32(u32 opcode, long addr, struct pt_regs *regs)
0354 {
0355     unsigned long tmp;
0356 
0357     tmp = (opcode & 0xffff) << 16;
0358     tmp |= (opcode & 0xffff0000) >> 16;
0359 
0360     instruction_pointer_set(regs,
0361         addr + sign_extend32((tmp & 0x3ffffff) << 1, 15));
0362 
0363     regs->lr = addr + 4;
0364 }
0365 
0366 void __kprobes
0367 simulate_jmpi32(u32 opcode, long addr, struct pt_regs *regs)
0368 {
0369     unsigned long val;
0370     unsigned long offset = ((opcode & 0xffff0000) >> 14);
0371 
0372     val = *(unsigned int *)
0373         ((instruction_pointer(regs) + offset) & 0xfffffffc);
0374 
0375     instruction_pointer_set(regs, val);
0376 }
0377 
0378 void __kprobes
0379 simulate_jsri32(u32 opcode, long addr, struct pt_regs *regs)
0380 {
0381     unsigned long val;
0382     unsigned long offset = ((opcode & 0xffff0000) >> 14);
0383 
0384     val = *(unsigned int *)
0385         ((instruction_pointer(regs) + offset) & 0xfffffffc);
0386 
0387     regs->lr = addr + 4;
0388 
0389     instruction_pointer_set(regs, val);
0390 }