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 : : static int writesizeto=-1;
8 : : static int inlinestartpos=0;
9 : :
10 : 1071 : static int64_t getnum_ck(const char* math)
11 : : {
12 [ + + ]: 1071 : return pass == 2 ? getnum(math) : 0;
13 : : }
14 : :
15 : 0 : void asinit_spc700()
16 : : {
17 : 0 : }
18 : :
19 : 15 : void asend_spc700()
20 : : {
21 : 15 : }
22 : :
23 : 3645 : static bool matchandwrite(const char * str, const char * left, const char * right, string& remainder)
24 : : {
25 [ + + ]: 3774 : for (int i=0;left[i];i++)
26 : : {
27 [ + + ]: 1461 : if (to_lower(*str)!=left[i]) return false;
28 : 129 : str++;
29 : : }
30 : 2313 : int mainlen=(int)(strlen(str)-strlen(right));
31 [ + + ]: 2313 : if(mainlen < 0) return false;
32 [ + + ]: 2496 : for (int i=0;right[i];i++)
33 : : {
34 [ + + ]: 1404 : if (to_lower(str[mainlen+i])!=right[i]) return false;
35 : : }
36 : 1092 : remainder=substr(str, mainlen);
37 : 1092 : return true;
38 : : }
39 : :
40 : 1038 : static bool bitmatch(const char * opnamein, string& opnameout, const char * str, string& math, int& bit)
41 : : {
42 : : const char * opnameend=strchr(opnamein, '\0');
43 : : const char * dot=strrchr(str, '.');
44 [ + + + - : 1038 : if (dot && is_digit(dot[1]) && !dot[2])
+ - ]
45 : : {
46 : 21 : bit = dot[1]-'0';
47 [ - + ]: 21 : if (bit>=8) return false;
48 : 21 : math=substr(str, (int)(dot-str));
49 [ + + ]: 21 : if (opnameend[-1]=='1') opnameout=substr(opnamein, (int)(opnameend-opnamein-1));
50 : : else opnameout=opnamein;
51 : 21 : return true;
52 : : }
53 [ + + ]: 1017 : if (opnameend[-1]>='0' && opnameend[-1]<='7')
54 : : {
55 : : math=str;
56 : 129 : bit=opnameend[-1]-'0';
57 : 129 : opnameout=substr(opnamein, (int)(opnameend-opnamein-1));
58 : 129 : return true;
59 : : }
60 : : return false;
61 : : }
62 : :
63 : : #define isop(test) (!stricmp(op, test))
64 : 87 : static bool assinglebitwithc(const char * op, const char * math, int bits)
65 : : {
66 : : unsigned int num;
67 [ + + ]: 87 : if (math[0]=='!')
68 : : {
69 : : if(0);
70 [ + + ]: 6 : else if (isop("or")) write1(0x2A);
71 [ + - ]: 3 : else if (isop("and")) write1(0x6A);
72 : : else return false;
73 : 6 : num=getnum_ck(math+1);
74 : : }
75 : : else
76 : : {
77 : : if(0);
78 [ + + ]: 81 : else if (isop("or")) write1(0x0A);
79 [ + + ]: 78 : else if (isop("and")) write1(0x4A);
80 [ + + ]: 75 : else if (isop("eor")) write1(0x8A);
81 [ + + ]: 72 : else if (isop("mov")) write1(0xAA);
82 [ + + ]: 69 : else if (isop("not")) write1(0xEA);
83 : : else return false;
84 : 33 : num=getnum_ck(math);
85 : : }
86 [ - + - - ]: 39 : if (num>=0x2000) asar_throw_error(2, error_type_block, error_id_spc700_addr_out_of_range, hex(num, 4).data());
87 : 39 : write2(((unsigned int)bits<<13)|num);
88 : 39 : return true;
89 : : }
90 : : #undef isop
91 : :
92 : 1185 : bool asblock_spc700(char** word, int numwords)
93 : : {
94 : : #define is(test) (!stricmp(word[0], test))
95 : : #define is1(test) (!stricmp(word[0], test) && numwords==2)
96 : : #define par word[1]
97 [ + + ]: 1185 : if (numwords==1)
98 : : {
99 : : #define op(name, val) else if (is(name)) do { write1(val); } while(0)
100 : : if(0);
101 : 60 : op("nop", 0x00);
102 : 48 : op("brk", 0x0F);
103 : 45 : op("clrp", 0x20);
104 : 42 : op("setp", 0x40);
105 : 39 : op("clrc", 0x60);
106 : 36 : op("ret", 0x6F);
107 : 33 : op("reti", 0x7F);
108 : 30 : op("setc", 0x80);
109 : 27 : op("ei", 0xA0);
110 : 24 : op("di", 0xC0);
111 : 21 : op("clrv", 0xE0);
112 : 18 : op("notc", 0xED);
113 : 15 : op("sleep", 0xEF);
114 : 12 : op("stop", 0xFF);
115 : 9 : op("xcn", 0x9F);
116 : : else return false;
117 : : #undef op
118 : : }
119 [ + - ]: 1125 : else if (numwords==2)
120 : : {
121 : : int numwordsinner;
122 : : //Detect opcode length before continuing
123 : : int opLen=0; //In case of .b or .w, this overwrites auto-detection of opcode length
124 : : unsigned int periodLocCount=0;
125 : : do {
126 [ + + ]: 3978 : if (word[0][periodLocCount] == '.') {
127 : 336 : opLen=getlenfromchar(word[0][periodLocCount+1]);
128 : 336 : word[0][periodLocCount]='\0';
129 : : }
130 : 3978 : periodLocCount++;
131 [ + + + + ]: 3978 : } while ((opLen == 0) && (periodLocCount < strlen(word[0])));
132 [ - + ]: 1125 : if (opLen > 2) { asar_throw_error(0, error_type_block, error_id_opcode_length_too_long); }
133 : 1125 : autoptr<char*> parcpy= duplicate_string(par);
134 [ + - ]: 1125 : autoptr<char**> arg=qpsplit(parcpy, ',', &numwordsinner);
135 [ + + ]: 1125 : if (numwordsinner ==1)
136 : : {
137 : 372 : string op;
138 : 372 : string math;
139 : : int bits;
140 : : #define isop(str) (!stricmp(word[0], str))
141 : : #define isam(str) (!stricmp(arg[0], str))
142 : : #define ismatch(left, right) (matchandwrite(arg[0], left, right, math))
143 : : #define eq(str) if (isam(str))
144 : : #define w0(hex) do { write1((unsigned int)hex); return true; } while(0)
145 : : #define w1(hex) do { write1((unsigned int)hex); write1(getnum_ck(math)); return true; } while(0)
146 : : #define w2(hex) do { write1((unsigned int)hex); write2(getnum_ck(math)); return true; } while(0)
147 : : #define wv(hex1, hex2) do { if ((opLen == 1) || (opLen == 0 && getlen(math) == 1)) { write1((unsigned int)hex1); write1(getnum_ck(math)); } else { write1((unsigned int)hex2); write2(getnum_ck(math)); } return true; } while(0)
148 : : #define wr(hex) do { int len=getlen(math); int num=(int)getnum_ck(math); int pos=(len==1)?num:num-((snespos&0xFFFFFF)+2); write1((unsigned int)hex); write1((unsigned int)pos); \
149 : : if (pass==2 && foundlabel && (pos<-128 || pos>127)) asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(pos).data()); \
150 : : return true; } while(0)
151 : : #define op0(str, hex) if (isop(str)) w0(hex)
152 : : #define op1(str, hex) if (isop(str)) w1(hex)
153 : : #define op2(str, hex) if (isop(str)) w2(hex)
154 : : #define opv(str, hex1, hex2) if (isop(str)) wv(hex1, hex2)
155 : : #define opr(str, hex) if (isop(str)) wr(hex)
156 : : #define match(left, right) if (ismatch(left, right))
157 : 372 : eq("a")
158 : : {
159 : 33 : op0("asl", 0x1C);
160 : 30 : op0("das", 0xBE);
161 : 27 : op0("daa", 0xDF);
162 : 24 : op0("dec", 0x9C);
163 : 21 : op0("inc", 0xBC);
164 : 18 : op0("lsr", 0x5C);
165 : 15 : op0("pop", 0xAE);
166 : 12 : op0("push", 0x2D);
167 : 9 : op0("rol", 0x3C);
168 : 6 : op0("ror", 0x7C);
169 : 3 : op0("xcn", 0x9F);
170 : : }
171 : 339 : eq("x")
172 : : {
173 : 12 : op0("dec", 0x1D);
174 : 9 : op0("inc", 0x3D);
175 : 6 : op0("pop", 0xCE);
176 : 3 : op0("push", 0x4D);
177 : : }
178 : 327 : eq("y")
179 : : {
180 : 12 : op0("dec", 0xDC);
181 : 9 : op0("inc", 0xFC);
182 : 6 : op0("pop", 0xEE);
183 : 3 : op0("push", 0x6D);
184 : : }
185 : 315 : eq("p")
186 : : {
187 : 6 : op0("pop", 0x8E);
188 : 3 : op0("push", 0x0D);
189 : : }
190 [ + + + - : 309 : if (isop("mul") && isam("ya")) w0(0xCF);
+ - ]
191 [ + + + + : 306 : if (isop("jmp") && ismatch("(", "+x)")) w2(0x1F);
+ - + - +
- ]
192 : 303 : match("", "+x")
193 : : {
194 : 18 : op1("asl", 0x1B);
195 : 15 : op1("dec", 0x9B);
196 : 12 : op1("inc", 0xBB);
197 : 9 : op1("lsr", 0x5B);
198 : 6 : op1("rol", 0x3B);
199 : 3 : op1("ror", 0x7B);
200 : : }
201 [ + + ]: 285 : if (bitmatch(word[0], op, arg[0], math, bits))
202 : : {
203 [ + - + + ]: 57 : if (assinglebitwithc(op, math, bits)) return true;
204 [ + + + - ]: 48 : else if (!stricmp(op, "set")) write1((unsigned int)(0x02|(bits<<5)));
205 [ + - + - ]: 24 : else if (!stricmp(op, "clr")) write1((unsigned int)(0x12|(bits<<5)));
206 : : else return false;
207 : 48 : unsigned int num=getnum_ck(math);
208 [ - + - - ]: 48 : if (num>=0x100) asar_throw_error(2, error_type_block, error_id_snes_address_out_of_bounds, hex(num, 6).data());
209 : 48 : write1(num);
210 : : return true;
211 : : }
212 : : if (true)
213 : : {
214 : 228 : math=arg[0];
215 [ + + ]: 228 : if (isop("tcall"))
216 : : {
217 : 48 : unsigned int num = getnum_ck(math);
218 [ - + - - ]: 48 : if (num >= 16) asar_throw_error(2, error_type_block, error_id_invalid_tcall);
219 : 48 : write1(((num<<4)|1));
220 : : return true;
221 : : }
222 : 180 : opv("asl", 0x0B, 0x0C);
223 : 162 : opv("dec", 0x8B, 0x8C);
224 : 144 : opv("inc", 0xAB, 0xAC);
225 : 126 : opv("lsr", 0x4B, 0x4C);
226 : 108 : opv("rol", 0x2B, 0x2C);
227 : 90 : opv("ror", 0x6B, 0x6C);
228 : 72 : op2("jmp", 0x5F);
229 : 66 : op2("call", 0x3F);
230 : 63 : op1("decw", 0x1A);
231 : 60 : op1("incw", 0x3A);
232 : 57 : op1("pcall", 0x4F);
233 : 54 : opr("bpl", 0x10);
234 : 51 : opr("bra", 0x2F);
235 : 48 : opr("bmi", 0x30);
236 : 45 : opr("bvc", 0x50);
237 : 42 : opr("bvs", 0x70);
238 : 39 : opr("bcc", 0x90);
239 : 36 : opr("bcs", 0xB0);
240 : 33 : opr("bne", 0xD0);
241 : 30 : opr("beq", 0xF0);
242 : : }
243 : : #undef isop
244 : : #undef isam
245 : : #undef eq
246 : : #undef w0
247 : : #undef w1
248 : : #undef w2
249 : : #undef wv
250 : : #undef wr
251 : : #undef op0
252 : : #undef op1
253 : : #undef op2
254 : : #undef opv
255 : : #undef opr
256 : : #undef match
257 : : return false;
258 : 372 : }
259 [ + - ]: 753 : if (numwordsinner==2)
260 : : {
261 : : #define iscc(str1, str2) (!stricmp(arg[0], str1) && !stricmp(arg[1], str2))
262 : : #define iscv(str1, left2, right2) (!stricmp(arg[0], str1) && matchandwrite(arg[1], left2, right2, s2))
263 : : #define isvc(left1, right1, str2) (matchandwrite(arg[0], left1, right1, s1) && !stricmp(arg[1], str2))
264 : : #define isvv(left1, right1, left2, right2) (matchandwrite(arg[0], left1, right1, s1) && matchandwrite(arg[1], left2, right2, s2))
265 : : #define cc(str1, str2) if (iscc(str1, str2))
266 : : #define cv(str1, left2, right2) if (iscv(str1, left2, right2))
267 : : #define vc(left1, right1, str2) if (isvc(left1, right1, str2))
268 : : #define vv(left1, right1, left2, right2) if (isvv(left1, right1, left2, right2))
269 : : #define w0(opcode) do { write1((unsigned int)opcode); return true; } while(0)
270 : : #define w1(opcode, math) do { write1((unsigned int)opcode); unsigned int val=getnum_ck(math); \
271 : : if ((((val&0xFF00)&&(val&0x80000000)==0)||(((val&0xFF00)!=0xFF00)&&(val&0x80000000)))&&opLen!=1) asar_throw_warning(0, warning_id_spc700_assuming_8_bit); write1(val);return true; } while(0)
272 : : #define w2(opcode, math) do { write1((unsigned int)opcode); write2(getnum_ck(math)); return true; } while(0)
273 : : #define wv(opcode1, opcode2, math) do { if ((opLen == 1) || (opLen == 0 && getlen(math)==1)) { write1((unsigned int)opcode1); write1(getnum_ck(math)); } \
274 : : else { write1((unsigned int)opcode2); write2(getnum_ck(math)); } return true; } while(0)
275 : : #define w11(opcode, math1, math2) do { write1((unsigned int)opcode); write1(getnum_ck(math1)); write1(getnum_ck(math2)); return true; } while(0)
276 : : #define wr(opcode, math) do { int len=getlen(math); int num=(int)getnum_ck(math); int pos=(len==1)?num:num-(snespos+2); \
277 : : if (pass && foundlabel && (pos<-128 || pos>127)) asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(pos).data()); \
278 : : write1((unsigned int)opcode); write1((unsigned int)pos); return true; } while(0)
279 : : #define w1r(opcode, math1, math2) do { int len=getlen(math2); int num=(int)getnum_ck(math2); int pos=(len==1)?num:num-(snespos+3); \
280 : : if (pass && foundlabel && (pos<-128 || pos>127)) asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(pos).data()); \
281 : : write1((unsigned int)opcode); write1(getnum_ck(math1)); write1((unsigned int)pos); return true; } while(0)
282 : 753 : string s1;
283 : 753 : string s2;
284 : 753 : string op;
285 : 753 : string math;
286 : : int bits;
287 : : #define isop(test) (!stricmp(op, test))
288 [ + + + - ]: 753 : if (!stricmp(arg[0], "c") && bitmatch(word[0], op, arg[1], math, bits))
289 : : {
290 [ + - - + ]: 30 : if (assinglebitwithc(op, math, bits)) return true;
291 : : }
292 [ + + ]: 723 : if (bitmatch(word[0], op, arg[0], s1, bits))
293 : : {
294 [ + + - + ]: 63 : if (isop("mov") && !stricmp(arg[1], "c"))
295 : : {
296 : 3 : unsigned int num=getnum_ck(s1);
297 [ - + - - ]: 3 : if (num>=0x2000) asar_throw_error(2, error_type_block, error_id_snes_address_out_of_bounds, hex((unsigned int)num, 6).data());
298 : 3 : write1(0xCA);
299 : 3 : write2(((unsigned int)bits<<13)|num);
300 : : return true;
301 : : }
302 : : if(0);
303 [ + + + - ]: 60 : else if (isop("bbs")) write1((unsigned int)(0x03|(bits<<5)));
304 [ + - + - ]: 24 : else if (isop("bbc")) write1((unsigned int)(0x13|(bits<<5)));
305 : : else return false;
306 : 60 : unsigned int num=getnum_ck(s1);
307 [ - + - - ]: 60 : if (num>=0x100) asar_throw_error(2, error_type_block, error_id_snes_address_out_of_bounds, hex(num, 6).data());
308 : 60 : write1(num);
309 : 60 : write1((getnum_ck(arg[1])- (unsigned int)(snespos+1)));
310 : : return true;
311 : : }
312 : : #undef isop
313 [ + + ]: 660 : if (is("mov"))
314 : : {
315 [ - + - - : 219 : if (iscc("(x)+", "a")) asar_throw_error(0, error_type_block, error_id_use_xplus);
- - ]
316 : 219 : cc("(x+)" , "a" ) w0(0xAF);
317 : 216 : cc("(x)" , "a" ) w0(0xC6);
318 [ + + - + : 213 : if (iscc("a", "(x)+")) asar_throw_error(0, error_type_block, error_id_use_xplus);
- - ]
319 : 213 : cc("a" , "(x+)" ) w0(0xBF);
320 : 210 : cc("a" , "(x)" ) w0(0xE6);
321 : 207 : cc("a" , "x" ) w0(0x7D);
322 : 204 : cc("a" , "y" ) w0(0xDD);
323 : 201 : cc("x" , "a" ) w0(0x5D);
324 : 198 : cc("x" , "sp" ) w0(0x9D);
325 : 195 : cc("y" , "a" ) w0(0xFD);
326 : 192 : cc("sp" , "x" ) w0(0xBD);
327 : :
328 : 189 : vc("(","+x)", "a" ) w1(0xC7, s1);
329 : 186 : vc("(",")+y", "a" ) w1(0xD7, s1);
330 : 183 : vc("","+x" , "a" ) wv(0xD4, 0xD5, s1);
331 : 165 : vc("","+y" , "a" ) w2(0xD6, s1);
332 : 162 : vc("","" , "a" ) wv(0xC4, 0xC5, s1);
333 : 144 : vc("","+x" , "y" ) w1(0xDB, s1);
334 : 141 : vc("","+y" , "x" ) w1(0xD9, s1);
335 : 138 : vc("","" , "x" ) wv(0xD8, 0xC9, s1);
336 : 120 : vc("","" , "y" ) wv(0xCB, 0xCC, s1);
337 : :
338 : 102 : cv("a" , "#","" ) w1(0xE8, s2);
339 : 99 : cv("a" , "(","+x)") w1(0xE7, s2);
340 : 96 : cv("a" , "(",")+y") w1(0xF7, s2);
341 : 93 : cv("a" , "","+x" ) wv(0xF4, 0xF5, s2);
342 : 75 : cv("a" , "","+y" ) w2(0xF6, s2);
343 : 72 : cv("a" , "","" ) wv(0xE4, 0xE5, s2);
344 : 54 : cv("x" , "#","" ) w1(0xCD, s2);
345 : 51 : cv("x" , "","+y" ) w1(0xF9, s2);
346 : 48 : cv("x" , "","" ) wv(0xF8, 0xE9, s2);
347 : 30 : cv("y" , "#","" ) w1(0x8D, s2);
348 : 27 : cv("y" , "","+x" ) w1(0xFB, s2);
349 : 24 : cv("y" , "","" ) wv(0xEB, 0xEC, s2);
350 : :
351 : 6 : vv("","" , "#","" ) w11(0x8F, s2, s1);
352 : 3 : vv("","" , "","" ) w11(0xFA, s2, s1);
353 : : }
354 [ + + ]: 441 : if (is("cmp"))
355 : : {
356 : 102 : cv("x", "#","") w1(0xC8, s2);
357 : 99 : cv("x", "","" ) wv(0x3E, 0x1E, s2);
358 : 81 : cv("y", "#","") w1(0xAD, s2);
359 : 78 : cv("y", "","" ) wv(0x7E, 0x5E, s2);
360 : : }
361 [ + + + + : 399 : if (is("or") || is("and") || is("eor") || is("cmp") || is("adc") || is("sbc"))
+ + + + +
+ + + ]
362 : : {
363 : : int offset = 0;
364 : : if (is("or" )) offset=0x00;
365 [ + + ]: 360 : if (is("and")) offset=0x20;
366 [ + + ]: 360 : if (is("eor")) offset=0x40;
367 [ + + ]: 360 : if (is("cmp")) offset=0x60;
368 [ + + ]: 360 : if (is("adc")) offset=0x80;
369 [ + + ]: 360 : if (is("sbc")) offset=0xA0;
370 : :
371 : 360 : cc("a" , "(x)" ) w0(offset+0x06);
372 : 342 : cc("(x)", "(y)" ) w0(offset+0x19);
373 : :
374 : 324 : cv("a" , "#","" ) w1(offset+0x08, s2);
375 : 306 : cv("a" , "(","+x)") w1(offset+0x07, s2);
376 : 288 : cv("a" , "(",")+y") w1(offset+0x17, s2);
377 : 270 : cv("a" , "","+x" ) wv(offset+0x14, offset+0x15, s2);
378 : 162 : cv("a" , "","+y" ) w2(offset+0x16, s2);
379 : 144 : cv("a" , "","" ) wv(offset+0x04, offset+0x05, s2);
380 : :
381 : 36 : vv("","", "#","" ) w11(offset+0x18, s2, s1);
382 : 18 : vv("","", "","" ) w11(offset+0x09, s2, s1);
383 : : }
384 : 39 : vc("","", "a")
385 : : {
386 [ + + + - : 6 : if (is("tset")) w2(0x0E, s1);
+ - + - ]
387 [ + - + - : 3 : if (is("tclr")) w2(0x4E, s1);
+ - + - ]
388 : : }
389 [ + + + - : 33 : if (is("div") && iscc("ya", "x")) w0(0x9E);
- + + - ]
390 : 30 : cv("ya", "","")
391 : : {
392 [ + + + - : 12 : if (is("cmpw")) w1(0x5A, s2);
+ - - + -
- + - - +
- - - - +
- ]
393 [ + + + - : 9 : if (is("addw")) w1(0x7A, s2);
+ - - + -
- + - - +
- - - - +
- ]
394 [ + + + - : 6 : if (is("subw")) w1(0x9A, s2);
+ - - + -
- + - - +
- - - - +
- ]
395 [ + - + - : 3 : if (is("movw")) w1(0xBA, s2);
+ - - + -
- + - - +
- - - - +
- ]
396 : : }
397 [ + + + - : 18 : if (is("movw") && isvc("","", "ya")) w1(0xDA, s1);
- + + - +
- - + - -
+ - - + -
- - - +
- ]
398 [ + + + + : 15 : if (is("cbne") && isvv("","+x", "","")) w1r(0xDE, s1, s2);
- + + - +
- + - + +
+ + - + -
- + - + -
+ - + - ]
399 [ + + + + : 12 : if (is("dbnz") && iscv("y", "","")) wr(0xFE, s2);
- + + - +
- + - + +
+ + - + -
- + - +
- ]
400 : 9 : vv("","", "","")
401 : : {
402 [ + + + - : 9 : if (is("dbnz")) w1r(0x6E, s1, s2);
+ - + - +
+ + + - +
- - + - +
- + - +
- ]
403 [ + + + - : 6 : if (is("cbne")) w1r(0x2E, s1, s2);
+ - + - +
+ + + - +
- - + - +
- + - +
- ]
404 : : }
405 : : #undef iscc
406 : : #undef iscv
407 : : #undef isvc
408 : : #undef isvv
409 : : #undef cc
410 : : #undef cv
411 : : #undef vc
412 : : #undef vv
413 : : #undef w0
414 : : #undef w1
415 : : #undef w2
416 : : #undef wv
417 : : #undef w11
418 : 3 : return false;
419 : 753 : }
420 : : return false;
421 : 1125 : }
422 : : else return false;
423 : : return true;
424 : : }
|