// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include "decode-insn.h"
#include "simulate-insn.h"
static inline bool csky_insn_reg_get_val(struct pt_regs *regs,
unsigned long index,
unsigned long *ptr)
{
if (index < 14 )
*ptr = *(®s->a0 + index);
if (index > 15 && index < 31 )
*ptr = *(®s->exregs[0 ] + index - 16 );
switch (index) {
case 14 :
*ptr = regs->usp;
break ;
case 15 :
*ptr = regs->lr;
break ;
case 31 :
*ptr = regs->tls;
break ;
default :
goto fail;
}
return true ;
fail:
return false ;
}
static inline bool csky_insn_reg_set_val(struct pt_regs *regs,
unsigned long index,
unsigned long val)
{
if (index < 14 )
*(®s->a0 + index) = val;
if (index > 15 && index < 31 )
*(®s->exregs[0 ] + index - 16 ) = val;
switch (index) {
case 14 :
regs->usp = val;
break ;
case 15 :
regs->lr = val;
break ;
case 31 :
regs->tls = val;
break ;
default :
goto fail;
}
return true ;
fail:
return false ;
}
void __kprobes
simulate_br16(u32 opcode, long addr, struct pt_regs *regs)
{
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 x3ff) << 1 , 9 ));
}
void __kprobes
simulate_br32(u32 opcode, long addr, struct pt_regs *regs)
{
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
}
void __kprobes
simulate_bt16(u32 opcode, long addr, struct pt_regs *regs)
{
if (regs->sr & 1 )
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 x3ff) << 1 , 9 ));
else
instruction_pointer_set(regs, addr + 2 );
}
void __kprobes
simulate_bt32(u32 opcode, long addr, struct pt_regs *regs)
{
if (regs->sr & 1 )
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
else
instruction_pointer_set(regs, addr + 4 );
}
void __kprobes
simulate_bf16(u32 opcode, long addr, struct pt_regs *regs)
{
if (!(regs->sr & 1 ))
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 x3ff) << 1 , 9 ));
else
instruction_pointer_set(regs, addr + 2 );
}
void __kprobes
simulate_bf32(u32 opcode, long addr, struct pt_regs *regs)
{
if (!(regs->sr & 1 ))
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
else
instruction_pointer_set(regs, addr + 4 );
}
void __kprobes
simulate_jmp16(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = (opcode >> 2 ) & 0 xf;
csky_insn_reg_get_val(regs, tmp, &tmp);
instruction_pointer_set(regs, tmp & 0 xfffffffe);
}
void __kprobes
simulate_jmp32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
csky_insn_reg_get_val(regs, tmp, &tmp);
instruction_pointer_set(regs, tmp & 0 xfffffffe);
}
void __kprobes
simulate_jsr16(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = (opcode >> 2 ) & 0 xf;
csky_insn_reg_get_val(regs, tmp, &tmp);
regs->lr = addr + 2 ;
instruction_pointer_set(regs, tmp & 0 xfffffffe);
}
void __kprobes
simulate_jsr32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
csky_insn_reg_get_val(regs, tmp, &tmp);
regs->lr = addr + 4 ;
instruction_pointer_set(regs, tmp & 0 xfffffffe);
}
void __kprobes
simulate_lrw16(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long val;
unsigned long tmp = (opcode & 0 x300) >> 3 ;
unsigned long offset = ((opcode & 0 x1f) | tmp) << 2 ;
tmp = (opcode & 0 xe0) >> 5 ;
val = *(unsigned int *)(instruction_pointer(regs) + offset);
csky_insn_reg_set_val(regs, tmp, val);
}
void __kprobes
simulate_lrw32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long val;
unsigned long offset = (opcode & 0 xffff0000) >> 14 ;
unsigned long tmp = opcode & 0 x0000001f;
val = *(unsigned int *)
((instruction_pointer(regs) + offset) & 0 xfffffffc);
csky_insn_reg_set_val(regs, tmp, val);
}
void __kprobes
simulate_pop16(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long *tmp = (unsigned long *)regs->usp;
int i;
for (i = 0 ; i < (opcode & 0 xf); i++) {
csky_insn_reg_set_val(regs, i + 4 , *tmp);
tmp += 1 ;
}
if (opcode & 0 x10) {
csky_insn_reg_set_val(regs, 15 , *tmp);
tmp += 1 ;
}
regs->usp = (unsigned long )tmp;
instruction_pointer_set(regs, regs->lr);
}
void __kprobes
simulate_pop32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long *tmp = (unsigned long *)regs->usp;
int i;
for (i = 0 ; i < ((opcode & 0 xf0000) >> 16 ); i++) {
csky_insn_reg_set_val(regs, i + 4 , *tmp);
tmp += 1 ;
}
if (opcode & 0 x100000) {
csky_insn_reg_set_val(regs, 15 , *tmp);
tmp += 1 ;
}
for (i = 0 ; i < ((opcode & 0 xe00000) >> 21 ); i++) {
csky_insn_reg_set_val(regs, i + 16 , *tmp);
tmp += 1 ;
}
if (opcode & 0 x1000000) {
csky_insn_reg_set_val(regs, 29 , *tmp);
tmp += 1 ;
}
regs->usp = (unsigned long )tmp;
instruction_pointer_set(regs, regs->lr);
}
void __kprobes
simulate_bez32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
csky_insn_reg_get_val(regs, tmp, &tmp);
if (tmp == 0 ) {
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
} else
instruction_pointer_set(regs, addr + 4 );
}
void __kprobes
simulate_bnez32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
csky_insn_reg_get_val(regs, tmp, &tmp);
if (tmp != 0 ) {
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
} else
instruction_pointer_set(regs, addr + 4 );
}
void __kprobes
simulate_bnezad32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
long val;
csky_insn_reg_get_val(regs, tmp, (unsigned long *)&val);
val -= 1 ;
if (val > 0 ) {
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
} else
instruction_pointer_set(regs, addr + 4 );
csky_insn_reg_set_val(regs, tmp, (unsigned long )val);
}
void __kprobes
simulate_bhsz32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
unsigned long val;
csky_insn_reg_get_val(regs, tmp, &val);
if ((long ) val >= 0 ) {
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
} else
instruction_pointer_set(regs, addr + 4 );
}
void __kprobes
simulate_bhz32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
unsigned long val;
csky_insn_reg_get_val(regs, tmp, &val);
if ((long ) val > 0 ) {
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
} else
instruction_pointer_set(regs, addr + 4 );
}
void __kprobes
simulate_blsz32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
unsigned long val;
csky_insn_reg_get_val(regs, tmp, &val);
if ((long ) val <= 0 ) {
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
} else
instruction_pointer_set(regs, addr + 4 );
}
void __kprobes
simulate_blz32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp = opcode & 0 x1f;
unsigned long val;
csky_insn_reg_get_val(regs, tmp, &val);
if ((long ) val < 0 ) {
instruction_pointer_set(regs,
addr + sign_extend32((opcode & 0 xffff0000) >> 15 , 15 ));
} else
instruction_pointer_set(regs, addr + 4 );
}
void __kprobes
simulate_bsr32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long tmp;
tmp = (opcode & 0 xffff) << 16 ;
tmp |= (opcode & 0 xffff0000) >> 16 ;
instruction_pointer_set(regs,
addr + sign_extend32((tmp & 0 x3ffffff) << 1 , 15 ));
regs->lr = addr + 4 ;
}
void __kprobes
simulate_jmpi32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long val;
unsigned long offset = ((opcode & 0 xffff0000) >> 14 );
val = *(unsigned int *)
((instruction_pointer(regs) + offset) & 0 xfffffffc);
instruction_pointer_set(regs, val);
}
void __kprobes
simulate_jsri32(u32 opcode, long addr, struct pt_regs *regs)
{
unsigned long val;
unsigned long offset = ((opcode & 0 xffff0000) >> 14 );
val = *(unsigned int *)
((instruction_pointer(regs) + offset) & 0 xfffffffc);
regs->lr = addr + 4 ;
instruction_pointer_set(regs, val);
}
Messung V0.5 in Prozent C=91 H=88 G=89
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland