-
Notifications
You must be signed in to change notification settings - Fork 5
/
nanac_builtins.c
145 lines (107 loc) · 3.24 KB
/
nanac_builtins.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "nanac.h"
int reg_swp( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
struct nanac_reg_s tmp = nanac_reg_get(cpu, arga);
nanac_reg_set(cpu, arga, nanac_reg_get(cpu, argb));
nanac_reg_set(cpu, argb, tmp);
return NANAC_OK;
}
int reg_mov( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
nanac_reg_set(cpu, arga, nanac_reg_get(cpu, argb));
return NANAC_OK;
}
int reg_clr( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
static const struct nanac_reg_s zero = {0};
nanac_reg_set(cpu, arga, zero);
nanac_reg_set(cpu, argb, zero);
return NANAC_OK;
}
int reg_win( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
if( (cpu->regs_win + arga) > NANAC_SETTING_MAXREGS )
return NANAC_ERROR_REGWIN_OVERFLOW;
if( (cpu->regs_win - argb) < 0 )
return NANAC_ERROR_REGWIN_UNDERFLOW;
cpu->regs_win += arga;
cpu->regs_win -= argb;
return NANAC_OK;
}
int jmp_to( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
cpu->eip = nanac_uint16(arga, argb);
return NANAC_NO_EPILOGUE;
}
int jmp_sub( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
if( cpu->call_depth >= NANAC_SETTING_MAXCALLS )
return NANAC_ERROR_SUBRET_OVERFLOW;
/* Save EIP in call stack */
cpu->call_stack[cpu->call_depth] = (cpu->eip + 1);
cpu->call_depth += 1;
return jmp_to(cpu, arga, argb);
}
int jmp_ret( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
if( cpu->call_depth <= 0 )
return NANAC_ERROR_SUBRET_UNDERFLOW;
/* Restore EIP from call stack */
cpu->call_depth -= 1;
cpu->eip = cpu->call_stack[cpu->call_depth];
return reg_win(cpu, arga, argb);
}
int jmp_die( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
(void)cpu; /* unused */
(void)arga; /* unused */
(void)argb; /* unused */
return NANAC_ERROR_DIE;
}
int cnd_common( struct nanac_s *cpu, int success )
{
/* Skip next opcode if conditional not successful */
if( ! success )
cpu->eip += 1;
return NANAC_OK;
}
int cnd_eq( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
return cnd_common( cpu, nanac_reg_get(cpu, arga).ptr == nanac_reg_get(cpu, argb).ptr );
}
int cnd_neq( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
return cnd_common( cpu, nanac_reg_get(cpu, arga).ptr != nanac_reg_get(cpu, argb).ptr );
}
int cnd_nil( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
return cnd_common( cpu, 0 == nanac_reg_get(cpu, arga).ptr || 0 == nanac_reg_get(cpu, argb).ptr );
}
int cnd_nz( struct nanac_s *cpu, unsigned char arga, unsigned char argb )
{
return cnd_common( cpu, 0 != nanac_reg_get(cpu, arga).ptr || 0 != nanac_reg_get(cpu, argb).ptr );
}
void nanac_mods_builtins ( struct nanac_mods_s *mods )
{
static const struct nanac_cmd_s _cmds_jmp[4] = {
{"to", &jmp_to},
{"die", &jmp_die},
{"sub", &jmp_sub},
{"ret", &jmp_ret}
};
static const struct nanac_cmd_s _cmds_cnd[4] = {
{"eq", &cnd_eq},
{"neq", &cnd_neq},
{"nil", &cnd_nil},
{"nz", &cnd_nz}
};
static const struct nanac_cmd_s _cmds_reg[4] = {
{"mov", ®_mov},
{"clr", ®_clr},
{"swp", ®_swp},
{"win", ®_win}
};
nanac_mods_add(mods, "jmp", 4, _cmds_jmp);
nanac_mods_add(mods, "cnd", 4, _cmds_cnd);
nanac_mods_add(mods, "reg", 4, _cmds_reg);
}