Branch data Line data Source code
1 : : #include "asar.h"
2 : : #include "assembleblock.h"
3 : : #include "asar_math.h"
4 : :
5 : : #define write1 write1_pick
6 : :
7 : 366 : static int64_t getnum_ck(const char* math)
8 : : {
9 [ + + ]: 366 : return pass == 2 ? getnum(math) : 0;
10 : : }
11 : :
12 : 0 : void asinit_superfx()
13 : : {
14 : 0 : }
15 : :
16 : 6 : void asend_superfx()
17 : : {
18 : 6 : }
19 : :
20 : 642 : static void range(int min, int mid, int max)
21 : : {
22 [ - + ]: 642 : if (mid<min || mid>max) asar_throw_error(0, error_type_block, error_id_superfx_invalid_register, min, max);
23 : 642 : }
24 : :
25 : : enum reg_t {
26 : : reg_parr,
27 : : reg_r,
28 : : reg_hash,
29 : : };
30 : 5166 : static bool getreg(const char * par, int * reg, reg_t type)
31 : : {
32 : : int ret;
33 : 5166 : *reg=-1;
34 [ + + + + ]: 5166 : if (type==reg_parr && *par++!='(') return false;
35 [ + + + + ]: 3798 : if (type==reg_parr && to_lower(*par++)!='r') return false;
36 [ + + + + ]: 3600 : if (type==reg_r && to_lower(*par++)!='r') return false;
37 [ + + + + ]: 2670 : if (type==reg_hash && *par++!='#') return false;
38 [ + - ]: 1698 : if (!is_digit(par[0])) return false;
39 [ + + ]: 1698 : if (is_digit(par[1]))
40 : : {
41 [ + - + - ]: 600 : if (par[0]!='1' || par[1]>'5') return false;
42 : 600 : ret=par[1]-'0'+10;
43 : 600 : par+=2;
44 : : }
45 : : else
46 : : {
47 : 1098 : ret=par[0]-'0';
48 : 1098 : par+=1;
49 : : }
50 [ + + + - ]: 1698 : if (type==reg_parr && *par++!=')') return false;
51 [ + - ]: 1698 : if (*par) return false;
52 : 1698 : *reg=ret;
53 : 1698 : return true;
54 : : }
55 : :
56 : : //for LMS and SMS short addressing forms, check range & evenness
57 : 96 : static bool check_short_addr(int num) {
58 [ + - - + ]: 96 : if (num % 2 > 0 || num < 0 || num > 0x1FE) {
59 : 0 : asar_throw_error(0, error_type_block, error_id_superfx_invalid_short_address, hex((unsigned int)num).data());
60 : 0 : return false;
61 : : }
62 : : return true;
63 : : }
64 : :
65 : 1827 : bool asblock_superfx(char** word, int numwords)
66 : : {
67 : : #define is(test) (!stricmp(word[0], test))
68 : : char * par= nullptr;
69 [ + + ]: 1827 : if (word[1]) par= duplicate_string(word[1]);
70 : : autoptr<char*> parptr=par;
71 : : if(0);
72 [ + - - + ]: 1827 : else if (assemblemapper(word, numwords)) return true;
73 [ + + ]: 1827 : else if (numwords==1)
74 : : {
75 : : #define op(from, to) if (is(from)) { write1(to); return true; }
76 : : #define op3d(from, to) if (is(from)) { write1(0x3D); write1(to); return true; }
77 : : #define op3e(from, to) if (is(from)) { write1(0x3E); write1(to); return true; }
78 : : #define op3f(from, to) if (is(from)) { write1(0x3F); write1(to); return true; }
79 : 105 : op("STOP", 0x00);
80 : 102 : op("NOP", 0x01);
81 : 90 : op("CACHE", 0x02);
82 : 87 : op("LSR", 0x03);
83 : 84 : op("ROL", 0x04);
84 : 81 : op("LOOP", 0x3C);
85 : 78 : op("ALT1", 0x3D);
86 : 75 : op("ALT2", 0x3E);
87 : 72 : op("ALT3", 0x3F);
88 : 69 : op("PLOT", 0x4C);
89 : 66 : op("SWAP", 0x4D);
90 : 63 : op("COLOR", 0x4E);
91 : 60 : op("NOT", 0x4F);
92 : 57 : op("MERGE", 0x70);
93 : 54 : op("SBK", 0x90);
94 : 51 : op("SEX", 0x95);
95 : 48 : op("ASR", 0x96);
96 : 45 : op("ROR", 0x97);
97 : 42 : op("LOB", 0x9E);
98 : 39 : op("FMULT", 0x9F);
99 : 36 : op("HIB", 0xC0);
100 : 33 : op("GETC", 0xDF);
101 : 30 : op("GETB", 0xEF);
102 : 27 : op3d("RPIX", 0x4C);
103 : 24 : op3d("CMODE", 0x4E);
104 : 21 : op3d("DIV2", 0x96);
105 : 18 : op3d("LMULT", 0x9F);
106 : 15 : op3d("GETBH", 0xEF);
107 : 12 : op3e("RAMB", 0xDF);
108 : 9 : op3e("GETBL", 0xEF);
109 : 6 : op3f("ROMB", 0xDF);
110 : 3 : op3f("GETBS", 0xEF);
111 : : #undef op
112 : : #undef op3d
113 : : #undef op3e
114 : : #undef op3f
115 : : return false;
116 : : }
117 [ + - ]: 1722 : else if (numwords==2)
118 : : {
119 : 1722 : string tmp=par;
120 : : int numwordsinner;
121 : 1722 : autoptr<char*> parcpy= duplicate_string(par);
122 [ + - ]: 1722 : autoptr<char**> arg=qpsplit(parcpy, ',', &numwordsinner);
123 : : bool ret=false;
124 : : #define ok() ret=true
125 : : #define op(op) if (is(op)) ok()
126 : : #define w3d(val) ,write1(0x3D) w(val)
127 : : #define w3e(val) ,write1(0x3E) w(val)
128 : : #define w3f(val) ,write1(0x3F) w(val)
129 [ + + ]: 1722 : if (numwordsinner ==1)
130 : : {
131 : : #define w(val) ,write1((unsigned int)(val+reg))
132 : : #define reg_range(min, max) ,range(min, reg, max)
133 : : int reg;
134 [ + + ]: 1404 : if (getreg(par, ®, reg_r))
135 : : {
136 : 786 : op("TO") w(0x10);
137 : 786 : op("WITH") w(0x20);
138 : 786 : op("ADD") w(0x50);
139 : 786 : op("SUB") w(0x60);
140 : 786 : op("AND") reg_range(1, 15) w(0x70);
141 : 786 : op("MULT") w(0x80);
142 : 786 : op("JMP") reg_range(8, 13) w(0x90);
143 : 786 : op("FROM") w(0xB0);
144 : 786 : op("OR") reg_range(1, 15) w(0xC0);
145 : 786 : op("INC") reg_range(0, 14) w(0xD0);
146 : 786 : op("DEC") reg_range(0, 14) w(0xE0);
147 : :
148 : 786 : op("ADC") w3d(0x50);
149 : 786 : op("SBC") w3d(0x60);
150 : 786 : op("BIC") reg_range(1, 15) w3d(0x70);
151 : 786 : op("UMULT") w3d(0x80);
152 : 786 : op("LJMP") reg_range(8, 13) w3d(0x90);
153 : 786 : op("XOR") reg_range(1, 15) w3d(0xC0);
154 : :
155 : 786 : op("CMP") w3f(0x60);
156 : : }
157 [ + + ]: 1404 : if (getreg(par, ®, reg_hash))
158 : : {
159 : 432 : op("LINK") reg_range(1, 4) w(0x90);
160 : :
161 : 432 : op("ADD") w3e(0x50);
162 : 432 : op("SUB") w3e(0x60);
163 : 432 : op("AND") reg_range(1, 15) w3e(0x70);
164 : 432 : op("MULT") w3e(0x80);
165 : 432 : op("OR") reg_range(1, 15) w3e(0xC0);
166 : :
167 : 432 : op("ADC") w3f(0x50);
168 : 432 : op("BIC") reg_range(1, 15) w3f(0x70);
169 : 432 : op("UMULT") w3f(0x80);
170 : 432 : op("XOR") reg_range(1, 15) w3f(0xC0);
171 : : }
172 [ + + ]: 1404 : if (getreg(par, ®, reg_parr))
173 : : {
174 : 144 : op("STW") reg_range(0, 11) w(0x30);
175 : 144 : op("LDW") reg_range(0, 11) w(0x40);
176 : 144 : op("STB") reg_range(0, 11) w3d(0x30);
177 : 144 : op("LDB") reg_range(0, 11) w3d(0x40);
178 : : }
179 : : #undef w
180 : : #undef reg_range
181 : : int byte=-1;
182 : : #define br(name, val) if (is(name)) byte=val;
183 : 1404 : br("BRA", 0x05);
184 : 1404 : br("BGE", 0x06);
185 : 1404 : br("BLT", 0x07);
186 : 1404 : br("BNE", 0x08);
187 : 1404 : br("BEQ", 0x09);
188 : 1404 : br("BPL", 0x0A);
189 : 1404 : br("BMI", 0x0B);
190 : 1404 : br("BCC", 0x0C);
191 : 1404 : br("BCS", 0x0D);
192 : 1404 : br("BVC", 0x0E);
193 : 1404 : br("BVS", 0x0F);
194 : : #undef br
195 [ + + ]: 1401 : if (byte!=-1)
196 : : {
197 : : ret=true;
198 : 33 : int len=getlen(par);
199 : 33 : unsigned int num=getnum_ck(par);
200 [ - + ]: 33 : if (len==1)
201 : : {
202 : 0 : write1((unsigned int)byte); write1(num);
203 : : }
204 : : else
205 : : {
206 : 33 : int pos=(int)getnum_ck(par)-((snespos&0xFFFFFF)+2);
207 : 33 : write1((unsigned int)byte); write1((unsigned int)pos);
208 [ + + + - ]: 33 : if (pass==2 && (pos<-128 || pos>127))
209 : : {
210 : 0 : asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(pos).data());
211 : : }
212 : : }
213 : : }
214 : : }
215 [ + + ]: 1722 : if (numwordsinner==2)
216 : : {
217 : : #define w(val) ,write1((unsigned int)(val))
218 : 318 : int reg1; bool isreg1=getreg(arg[0], ®1, reg_r);
219 : 318 : int reg2; bool isreg2=getreg(arg[1], ®2, reg_r);
220 [ + + ]: 318 : if (isreg1)
221 : : {
222 [ + + ]: 213 : if (isreg2)
223 : : {
224 : 6 : op("MOVE") w(0x20+reg2) w(0x10+reg1);
225 : 6 : op("MOVES") w(0x20+reg1) w(0xB0+reg2);
226 : : }
227 [ + + ]: 213 : if (arg[1][0]=='#')
228 : : {
229 : 99 : unsigned int num=getnum_ck(arg[1]+1);
230 : 99 : num&=0xFFFF;
231 : 99 : op("IBT") w(0xA0+reg1) w(num);
232 : 99 : op("IWT") w(0xF0+reg1) w(num) w(num>>8);
233 [ + - ]: 99 : if (num<0x80 || num>=0xFF80)
234 : : {
235 : 99 : op("MOVE") w(0xA0+reg1) w(num);
236 : : }
237 : : else
238 : : {
239 : 0 : op("MOVE") w(0xF0+reg1) w(num) w(num>>8);
240 : : }
241 : : }
242 [ + + ]: 213 : if (getreg(arg[1], ®2, reg_parr))
243 : : {
244 [ + - ]: 6 : if (reg1==0)
245 : : {
246 : 6 : op("MOVEB") w(0x3D) w(0x40+reg2);
247 : 6 : op("MOVEW") w(0x40+reg2);
248 : : }
249 : : else
250 : : {
251 : 0 : op("MOVEB") w(0x10+reg1) w(0x3D) w(0x40+reg2);
252 : 0 : op("MOVEW") w(0x10+reg1) w(0x40+reg2);
253 : : }
254 : : }
255 [ + + ]: 207 : else if (arg[1][0]=='(')
256 : : {
257 : : char * endpar=strchr(arg[1], ')');
258 [ + - + - ]: 99 : if (!endpar || endpar[1]) return false;
259 : 99 : unsigned int num=getnum_ck(arg[1]);
260 : 99 : op("LM") w(0x3D) w(0xF0+reg1) w(num) w(num>>8);
261 : :
262 [ + + ]: 99 : if (is("LMS")) {
263 : : ok();
264 [ + - + - ]: 48 : if (check_short_addr((int)num))
265 : : {
266 : 48 : ok() w(0x3D) w(0xA0+reg1) w(num>>1);
267 : : }
268 : : }
269 : :
270 [ + - - + ]: 99 : if (num&1 || num>=0x200)
271 : : {
272 : 0 : op("MOVE") w(0x3D) w(0xF0+reg1) w(num) w(num>>8);
273 : : }
274 : : else
275 : : {
276 : 99 : op("MOVE") w(0x3D) w(0xA0+reg1) w(num);
277 : : }
278 : : }
279 [ + + ]: 213 : if (is("LEA"))
280 : : {
281 : 3 : unsigned int num=getnum_ck(arg[1]);
282 : 3 : ok() w(0xF0+reg1) w(num) w(num>>8);
283 : : }
284 : : }
285 [ - + ]: 105 : else if (isreg2)
286 : : {
287 [ + + ]: 105 : if (getreg(arg[0], ®1, reg_parr))
288 : : {
289 [ + - ]: 6 : if (reg1==0)
290 : : {
291 : 6 : op("MOVEB") w(0x3D) w(0x30+reg2);
292 : 6 : op("MOVEW") w(0x30+reg2);
293 : : }
294 : : else
295 : : {
296 : 0 : op("MOVEB") w(0xB0+reg1) w(0x3D) w(0x30+reg2);
297 : 0 : op("MOVEW") w(0xB0+reg1) w(0x30+reg2);
298 : : }
299 : : }
300 [ - + ]: 99 : else if (arg[0][0]=='(')
301 : : {
302 : : char * endpar=strchr(arg[0], ')');
303 [ + - + - ]: 99 : if (!endpar || endpar[1]) return false;
304 : 99 : unsigned int num=getnum_ck(arg[0]);
305 : 99 : op("SM") w(0x3E) w(0xF0+reg2) w(num) w(num>>8);
306 : :
307 [ + + ]: 99 : if (is("SMS"))
308 : : {
309 : : ok();
310 [ + - + - ]: 48 : if (check_short_addr((int)num))
311 : : {
312 : 48 : ok() w(0x3E) w(0xA0+reg2) w(num>>1);
313 : : }
314 : : }
315 : :
316 [ + - - + ]: 99 : if (num&1 || num>=0x200)
317 : : {
318 : 0 : op("MOVE") w(0x3E) w(0xF0+reg2) w(num) w(num>>8);
319 : : }
320 : : else
321 : : {
322 : 99 : op("MOVE") w(0x3E) w(0xA0+reg2) w(num);
323 : : }
324 : : }
325 : : }
326 : : }
327 : : #undef ok
328 : : #undef op
329 : : #undef w3d
330 : : #undef w3e
331 : : #undef w3f
332 : 1722 : return ret;
333 : 1722 : }
334 : : return false;
335 : 1827 : }
|