0001
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 = *(®s->a0 + index);
0016
0017 if (index > 15 && index < 31)
0018 *ptr = *(®s->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 *(®s->a0 + index) = val;
0045
0046 if (index > 15 && index < 31)
0047 *(®s->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 }