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