-
Notifications
You must be signed in to change notification settings - Fork 5
/
nanac_vm.c
107 lines (73 loc) · 1.96 KB
/
nanac_vm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include "nanac.h"
#include <string.h>
#include <stdio.h>
void nanac_init( struct nanac_s *cpu, struct nanac_mods_s *mods )
{
memset(cpu, 0, sizeof(*cpu));
cpu->mods = mods;
}
void nanac_mods_init( struct nanac_mods_s *mods )
{
memset(mods, 0, sizeof(*mods));
}
int nanac_mods_add( struct nanac_mods_s *mods, const char *name, const unsigned char cmds_len, const struct nanac_cmd_s *cmds )
{
struct nanac_mod_s *mod;
/* Constrained by uint8 */
if( mods->cnt >= 0xFF )
return 0;
mod = &mods->idx[mods->cnt++];
mod->name = name;
mod->cmds_len = cmds_len;
mod->cmds = cmds;
return 1;
}
#define FLAG_VALID(cpu, offset) (offset < (8*sizeof(cpu->flags)))
const struct nanac_op_s *nanac_op( const struct nanac_s *cpu, const unsigned short eip )
{
if( eip < cpu->ops_sz )
return &cpu->ops[eip];
return NULL;
}
struct nanac_reg_s nanac_reg_get(const struct nanac_s *cpu, const unsigned char reg)
{
return cpu->regs[(unsigned char)(cpu->regs_win + reg)];
}
void nanac_reg_set(struct nanac_s *cpu, const unsigned char reg, const struct nanac_reg_s val)
{
cpu->regs[(unsigned char)(cpu->regs_win + reg)] = val;
}
int nanac_step_epilogue( struct nanac_s *cpu, int ret )
{
if( ret == NANAC_OK )
cpu->eip += 1;
return ret;
}
int nanac_step( struct nanac_s *cpu, const struct nanac_op_s *op )
{
const struct nanac_mod_s *mod = &cpu->mods->idx[op->mod];
const struct nanac_cmd_s *cmd;
if( ! mod )
return NANAC_ERROR_STEP_NOMOD;
if( op->cmd >= mod->cmds_len )
return NANAC_ERROR_STEP_NOCMD;
cmd = &mod->cmds[op->cmd];
#ifdef NANAC_TRACE
printf("@%-4X %s %s %d %d\n", cpu->eip, mod->name, cmd->name, op->arga, op->argb);
#endif
return nanac_step_epilogue(cpu, cmd->run(cpu, op->arga, op->argb));
}
int nanac_run( struct nanac_s *cpu )
{
int escape = 0;
while( escape >= 0 )
{
const struct nanac_op_s *op = nanac_op( cpu, cpu->eip );
if( ! op ) {
escape = NANAC_ERROR_STEP_BADOP;
break;
}
escape = nanac_step( cpu, op );
}
return escape;
}