> compile NEMU
221220000 张三 Linux zzy 5.15.146.1-microsoft-standard-WSL2 #1 SMP Thu Jan 11 04:09:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux 13:13:10 up 1 day, 12:03, 1 user, load average: 0.41, 0.23, 0.13
This commit is contained in:
@ -1,5 +1,14 @@
|
||||
mainmenu "NEMU Configuration Menu"
|
||||
|
||||
menu "NEMU Configuration Options"
|
||||
config CONFIG_WATCHPOINT
|
||||
bool "Enable Watchpoint"
|
||||
default n
|
||||
help
|
||||
Say Y here if you want to enable watchpoint functionality.
|
||||
This will add performance overhead but is useful for debugging.
|
||||
endmenu
|
||||
|
||||
choice
|
||||
prompt "Base ISA"
|
||||
default ISA_riscv
|
||||
|
@ -38,6 +38,15 @@ static void trace_and_difftest(Decode *_this, vaddr_t dnpc) {
|
||||
#endif
|
||||
if (g_print_step) { IFDEF(CONFIG_ITRACE, puts(_this->logbuf)); }
|
||||
IFDEF(CONFIG_DIFFTEST, difftest_step(_this->pc, dnpc));
|
||||
|
||||
#ifdef CONFIG_WATCHPOINT
|
||||
bool wp_check_hit(void);
|
||||
if (wp_check_hit()) {
|
||||
printf("watchpoint hit\n");
|
||||
isa_reg_display();
|
||||
nemu_state.state = NEMU_STOP;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void exec_once(Decode *s, vaddr_t pc) {
|
||||
|
@ -42,21 +42,21 @@ static struct rule {
|
||||
int token_type;
|
||||
} rules[] = {
|
||||
|
||||
{" +", TK_NOTYPE}, // spaces
|
||||
{"\\+", '+'}, // plus
|
||||
{"==", TK_EQ}, // equal
|
||||
{"\\!=", TK_NEQ}, // not equal
|
||||
{"\\&\\&", TK_AND}, // and
|
||||
{" +", TK_NOTYPE}, // spaces
|
||||
{"\\+", '+'}, // plus
|
||||
{"==", TK_EQ}, // equal
|
||||
{"\\!=", TK_NEQ}, // not equal
|
||||
{"\\&\\&", TK_AND}, // and
|
||||
|
||||
{"-", '-'}, // sub
|
||||
{"\\*", '*'}, // mul
|
||||
{"/", '/'}, // div
|
||||
{"\\(", '('}, // (
|
||||
{"\\)", ')'}, // )
|
||||
{"-", '-'}, // sub
|
||||
{"\\*", '*'}, // mul
|
||||
{"/", '/'}, // div
|
||||
{"\\(", '('}, // (
|
||||
{"\\)", ')'}, // )
|
||||
|
||||
{"0[xX][0-9a-fA-F]+", TK_HEX}, // hex number
|
||||
{"[0-9]+", TK_DEC}, // dec number
|
||||
{"\\$[0-9a-z]+", TK_REG}, // register
|
||||
{"0[xX][0-9a-fA-F]+", TK_HEX}, // hex number
|
||||
{"[0-9]+", TK_DEC}, // dec number
|
||||
{"\\$[0-9a-z]+", TK_REG}, // register
|
||||
};
|
||||
|
||||
#define NR_REGEX ARRLEN(rules)
|
||||
@ -266,8 +266,8 @@ uint32_t eval(const Token* arr, int p, int q, bool* success) {
|
||||
case TK_EQ: return val_l == val_r;
|
||||
case TK_NEQ: return val_l != val_r;
|
||||
case TK_AND: return val_l && val_r;
|
||||
case '+': return val_l + val_r;
|
||||
case '-': return val_l - val_r;
|
||||
case '+': return (uint32_t)val_l + (uint32_t)val_r;
|
||||
case '-': return (uint32_t)val_l - (uint32_t)val_r;
|
||||
case '*': return val_l * val_r;
|
||||
case '/': return val_l / val_r;
|
||||
default: *success &= false; return 0;
|
||||
|
@ -90,12 +90,14 @@ static int cmd_x(char *args) {
|
||||
char *arg0 = strtok(NULL, " ");
|
||||
char *arg1 = strtok(NULL, " ");
|
||||
if (arg0 == NULL || arg1 == NULL) {
|
||||
goto END;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
vaddr_t addr = 0;
|
||||
if (!sscanf(arg1, FMT_PADDR, &addr)) {
|
||||
goto END;
|
||||
bool success = true;
|
||||
expr(arg1, &success);
|
||||
if (!success) {
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
size_t N = atoi(arg0);
|
||||
@ -106,7 +108,7 @@ static int cmd_x(char *args) {
|
||||
addr += 4;
|
||||
}
|
||||
return 0;
|
||||
END:
|
||||
ERROR:
|
||||
p_help("x");
|
||||
return 0;
|
||||
}
|
||||
@ -119,12 +121,50 @@ static int cmd_p(char *args) {
|
||||
} else {
|
||||
printf("Invalid expression\n");
|
||||
}
|
||||
return success;
|
||||
return !success;
|
||||
}
|
||||
|
||||
static int cmd_w(char *args) { return 0; }
|
||||
|
||||
static int cmd_d(char *args) { return 0; }
|
||||
typedef void WP;
|
||||
WP* new_wp(char* expr, int len);
|
||||
WP* get_wp(int NO);
|
||||
void free_wp(WP* wp);
|
||||
static int cmd_w(char *args) {
|
||||
char*arg = strtok(NULL, " ");
|
||||
if (arg == NULL) {
|
||||
goto ERROR;
|
||||
}
|
||||
if (new_wp(arg, strlen(arg)) != NULL) {
|
||||
printf("Watchpoint Set Failure\n");
|
||||
goto ERROR;
|
||||
}
|
||||
return 0;
|
||||
ERROR:
|
||||
p_help("w");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmd_d(char *args) {
|
||||
char* arg = strtok(NULL, " ");
|
||||
if (arg == NULL) {
|
||||
goto ERROR;
|
||||
}
|
||||
int number = atoi(arg);
|
||||
if (number == 0 && arg[0] != '0') {
|
||||
printf("Invalid watchpoint number\n");
|
||||
goto ERROR;
|
||||
}
|
||||
WP* wp = get_wp(number);
|
||||
if (wp == NULL) {
|
||||
printf("No such watchpoint\n");
|
||||
goto ERROR;
|
||||
}
|
||||
free_wp(wp);
|
||||
return 0;
|
||||
ERROR:
|
||||
p_help("d");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
|
@ -18,11 +18,13 @@
|
||||
#define NR_WP 32
|
||||
|
||||
typedef struct watchpoint {
|
||||
struct watchpoint *next; // can use WP** to access the next element
|
||||
int NO;
|
||||
struct watchpoint *next;
|
||||
|
||||
/* TODO: Add more members if necessary */
|
||||
|
||||
word_t val;
|
||||
bool hit;
|
||||
char expr[65532];
|
||||
} WP;
|
||||
|
||||
static WP wp_pool[NR_WP] = {};
|
||||
@ -33,6 +35,9 @@ void init_wp_pool() {
|
||||
for (i = 0; i < NR_WP; i ++) {
|
||||
wp_pool[i].NO = i;
|
||||
wp_pool[i].next = (i == NR_WP - 1 ? NULL : &wp_pool[i + 1]);
|
||||
|
||||
wp_pool[i].hit = false;
|
||||
wp_pool[i].expr[0] = '\0';
|
||||
}
|
||||
|
||||
head = NULL;
|
||||
@ -41,3 +46,65 @@ void init_wp_pool() {
|
||||
|
||||
/* TODO: Implement the functionality of watchpoint */
|
||||
|
||||
bool wp_check_hit(void) {
|
||||
bool res = false;
|
||||
for (WP* tmp = head; tmp != NULL; tmp = tmp->next) {
|
||||
bool success = true;
|
||||
word_t val = expr(tmp->expr, &success);
|
||||
assert(success);
|
||||
if (val != tmp->val) {
|
||||
tmp->hit = true;
|
||||
tmp->val = val;
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static WP* del_wp(WP* head, WP* pos) {
|
||||
for (WP** i = &head; (*i) != NULL && (*i)->next != NULL; i = (WP**)*i) {
|
||||
if ((**i).NO == pos->NO) {
|
||||
WP* res = *i;
|
||||
*i = (**i).next;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
WP* new_wp(char* _expr, int len) {
|
||||
bool success = true;
|
||||
word_t val = expr(_expr, &success);
|
||||
if (!success) {
|
||||
return NULL;
|
||||
}
|
||||
WP* wp = del_wp(free_, free_);
|
||||
if (wp == NULL) {
|
||||
assert(0);
|
||||
}
|
||||
wp->next = head;
|
||||
head = wp;
|
||||
strncpy(wp->expr, _expr, MIN(sizeof(wp->expr), len));
|
||||
wp->val = val;
|
||||
return head;
|
||||
}
|
||||
|
||||
WP* get_wp(int NO) {
|
||||
for (WP* tmp = head; tmp != NULL; tmp = tmp->next) {
|
||||
if (tmp->NO == NO) {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_wp(WP *_wp) {
|
||||
WP* wp = del_wp(head, _wp);
|
||||
wp->next = free_;
|
||||
free_ = wp;
|
||||
wp->expr[0] = '\0';
|
||||
wp->hit = false;
|
||||
wp->val = 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user