Branch data Line data Source code
1 : : #include "asar.h"
2 : : #include "warnings.h"
3 : : #include "errors.h"
4 : : #include "assembleblock.h"
5 : : #include "asar_math.h"
6 : :
7 : : #include "arch-shared.h"
8 : :
9 : : #define write1 write1_pick
10 : :
11 : 281 : void asinit_65816()
12 : : {
13 : 281 : }
14 : :
15 : 255 : void asend_65816()
16 : : {
17 : 255 : }
18 : :
19 : : extern bool fastrom;
20 : : extern int recent_opcode_num;
21 : :
22 : 110776 : bool asblock_65816(char** word, int numwords)
23 : : {
24 : : #define is(test) (!stricmpwithupper(word[0], test))
25 : : //#define par word[1]
26 : 110776 : string par;
27 [ + + ]: 110776 : if (word[1]) par = word[1];
28 : : unsigned int num;
29 : : int len=0;//declared here for A->generic fallback
30 : : bool explicitlen = false;
31 : : bool hexconstant = false;
32 : : if(0);
33 : : #define getvars(optbank) num=(pass==2)?getnum(par):0; hexconstant=is_hex_constant(par); if (word[0][3]=='.') { len=getlenfromchar(word[0][4]); explicitlen=true; word[0][3]='\0'; } else {len=getlen(par, optbank); explicitlen=false;}
34 : : #define match(left, right) (word[1] && stribegin(par, left) && striend(par, right))
35 : : #define init(left, right) strip_suffix(par, right); strip_prefix(par, left); getvars(false)
36 : : #define init_index(left, right) itrim(par, left, right); getvars(false)
37 : : #define bankoptinit(left) strip_prefix(par, left); getvars(true)
38 : : #define blankinit() len=1; explicitlen=false; num=0
39 : : #define end() return false
40 : : #define as0( op, byte) if (is(op) ) { write1((unsigned int)byte); return true; }
41 : : #define as1( op, byte) if (is(op) && len==1) { write1((unsigned int)byte); write1(num); return true; }
42 : : #define as2( op, byte) if (is(op) && len==2) { write1((unsigned int)byte); write2(num); return true; } \
43 : : /*if (is(op) && len==3 && emulate) { write1(byte); write2(num); return true; }*/
44 : : #define as3( op, byte) if (is(op) && len==3) { write1((unsigned int)byte); write3(num); return true; }
45 : : //#define as23( op, byte) if (is(op) && (len==2 || len==3)) { write1(byte); write2(num); return true; }
46 : : #define as32( op, byte) if (is(op) && ((len==2 && !explicitlen) || len==3)) { write1((unsigned int)byte); write3(num); return true; }
47 : : #define as_a( op, byte) if (is(op)) { if(!explicitlen && !hexconstant) asar_throw_warning(0, warning_id_implicitly_sized_immediate); if (len==1) { write1(byte); write1(num); } \
48 : : else { write1((unsigned int)byte); write2(num); } return true; }
49 : : #define as_xy( op, byte) if (is(op)) { if(!explicitlen && !hexconstant) asar_throw_warning(0, warning_id_implicitly_sized_immediate); if (len==1) { write1(byte); write1(num); } \
50 : : else { write1((unsigned int)byte); write2(num); } return true; }
51 : : #define as_rep( op, byte) if (is(op)) { if (pass<2) { num=getnum(par); } if(foundlabel) asar_throw_error(0, error_type_block, error_id_no_labels_here); for (unsigned int i=0;i<num;i++) { write1((unsigned int)byte); } recent_opcode_num = num; return true; }
52 : : #define as_rel1(op, byte) if (is(op)) { int pos=(!foundlabel)?(int)num:(int)num-((snespos&0xFFFFFF)+2); write1((unsigned int)byte); write1((unsigned int)pos); \
53 : : 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()); \
54 : : return true; }
55 : : #define as_rel2(op, byte) if (is(op)) { int pos=(!foundlabel)?(int)num:(int)num-((snespos&0xFFFFFF)+3); write1((unsigned int)byte); write2((unsigned int)pos);\
56 : : if (pass==2 && foundlabel && (pos<-32768 || pos>32767)) asar_throw_error(2, error_type_block, error_id_relative_branch_out_of_bounds, dec(pos).data()); \
57 : : return true; }
58 : : #define the8(offset, len) as##len("ORA", offset+0x00); as##len("AND", offset+0x20); as##len("EOR", offset+0x40); as##len("ADC", offset+0x60); \
59 : : as##len("STA", offset+0x80); as##len("LDA", offset+0xA0); as##len("CMP", offset+0xC0); as##len("SBC", offset+0xE0)
60 : : #define thenext8(offset, len) as##len("ASL", offset+0x00); as##len("BIT", offset+0x1E); as##len("ROL", offset+0x20); as##len("LSR", offset+0x40); \
61 : : as##len("ROR", offset+0x60); as##len("LDY", offset+0x9E); as##len("DEC", offset+0xC0); as##len("INC", offset+0xE0)
62 : : #define thefinal7(offset, len) as##len("TSB", offset+0x00); as##len("TRB", offset+0x10); as##len("STY", offset+0x80); as##len("STX", offset+0x82); \
63 : : as##len("LDX", offset+0xA2); as##len("CPY", offset+0xC0); as##len("CPX", offset+0xE0)
64 : : #define onlythe8(left, right, offset) else if (match(left, right)) do { init_index(left, right); the8(offset, 1); end(); } while(0)
65 [ + + + + : 110776 : else if ((strlen(word[0])!=3 && (strlen(word[0])!=5 || word[0][3]!='.')) || (word[1] && word[2])) return false;
+ + + + +
+ ]
66 [ + + ]: 2167 : else if (!word[1])
67 : : {
68 : : blankinit();
69 : 570 : as0("PHP", 0x08); as0("ASL", 0x0A); as0("PHD", 0x0B); as0("CLC", 0x18);
70 : 561 : as0("INC", 0x1A); as0("TCS", 0x1B); as0("PLP", 0x28); as0("ROL", 0x2A);
71 : 555 : as0("PLD", 0x2B); as0("SEC", 0x38); as0("DEC", 0x3A); as0("TSC", 0x3B);
72 : 546 : as0("RTI", 0x40); as0("PHA", 0x48); as0("LSR", 0x4A); as0("PHK", 0x4B);
73 : 537 : as0("CLI", 0x58); as0("PHY", 0x5A); as0("TCD", 0x5B); as0("RTS", 0x60);
74 : 525 : as0("PLA", 0x68); as0("ROR", 0x6A); as0("RTL", 0x6B); as0("SEI", 0x78);
75 : 516 : as0("PLY", 0x7A); as0("TDC", 0x7B); as0("DEY", 0x88); as0("TXA", 0x8A);//these tables are blatantly stolen from xkas
76 : 504 : as0("PHB", 0x8B); as0("TYA", 0x98); as0("TXS", 0x9A); as0("TXY", 0x9B);
77 : 492 : as0("TAY", 0xA8); as0("TAX", 0xAA); as0("PLB", 0xAB); as0("CLV", 0xB8);
78 : 480 : as0("TSX", 0xBA); as0("TYX", 0xBB); as0("INY", 0xC8); as0("DEX", 0xCA);
79 : 468 : as0("WAI", 0xCB); as0("CLD", 0xD8); as0("PHX", 0xDA); as0("STP", 0xDB);
80 : 456 : as0("INX", 0xE8); as0("NOP", 0xEA); as0("XBA", 0xEB); as0("SED", 0xF8);
81 : 15 : as0("PLX", 0xFA); as0("XCE", 0xFB);
82 : 9 : as1("BRK", 0x00); as1("COP", 0x02); as1("WDM", 0x42);
83 : : //as0("DEA", 0x3A); as0("INA", 0x1A); as0("TAD", 0x5B); as0("TDA", 0x7B);//nobody cares about these, but keeping them does no harm
84 : : //as0("TAS", 0x1B); as0("TSA", 0x3B); as0("SWA", 0xEB); //actually, it does: it may make some users think it's correct.
85 : : end();
86 : : }
87 [ + + ]: 1597 : else if (!stricmp(word[1], "A"))
88 : : {
89 : : blankinit();
90 : 21 : as0("ASL", 0x0A); as0("LSR", 0x4A); as0("ROL", 0x2A); as0("ROR", 0x6A);
91 : 9 : as0("INC", 0x1A); as0("DEC", 0x3A);
92 : 3 : goto opAFallback;//yay goto
93 : : }
94 [ + + - + ]: 1576 : else if (match("#", ""))
95 : : {
96 : 231 : bankoptinit('#');
97 : 230 : as_a("ORA", 0x09); as_a("AND", 0x29); as_a("EOR", 0x49); as_a("ADC", 0x69);
98 : 177 : as_a("BIT", 0x89); as_a("LDA", 0xA9); as_a("CMP", 0xC9); as_a("SBC", 0xE9);
99 : 102 : as_xy("CPX", 0xE0); as_xy("CPY", 0xC0); as_xy("LDX", 0xA2); as_xy("LDY", 0xA0);
100 : 75 : as_rep("ASL", 0x0A); as_rep("LSR", 0x4A); as_rep("ROL", 0x2A); as_rep("ROR", 0x6A);
101 : 51 : as_rep("INC", 0x1A); as_rep("DEC", 0x3A); as_rep("INX", 0xE8); as_rep("DEX", 0xCA);
102 : 141 : as_rep("INY", 0xC8); as_rep("DEY", 0x88); as_rep("NOP", 0xEA);
103 : 18 : as1("REP", 0xC2); as1("SEP", 0xE2);
104 : 12 : as1("BRK", 0x00); as1("COP", 0x02); as1("WDM", 0x42);
105 : : end();
106 : : }
107 : 1345 : onlythe8("(", ",s),y", 0x13);
108 : 1321 : onlythe8("[", "],y", 0x17);
109 : 1297 : onlythe8("(", "),y", 0x11);
110 : 1273 : onlythe8("", ",s", 0x03);
111 [ + + - + ]: 1249 : else if (match("[", "]"))
112 : : {
113 : 33 : init('[', ']');
114 : 33 : the8(0x07, 1);
115 : 9 : as2("JMP", 0xDC); as2("JML", 0xDC);
116 : : end();
117 : : }
118 [ + + + + ]: 1216 : else if (match("(", ",x)"))
119 : : {
120 : 30 : init_index("(", ",x)");
121 : 30 : the8(0x01, 1);
122 : 6 : as2("JMP", 0x7C); as2("JSR", 0xFC);
123 : : end();
124 : : }
125 [ + + + - : 1186 : else if (match("(", ")") && confirmqpar(substr(word[1]+1, (int)(strlen(word[1]+1)-1))))
+ - + + ]
126 : : {
127 : 30 : init('(', ')');
128 : 30 : the8(0x12, 1);
129 : 6 : as1("PEI", 0xD4);
130 : 3 : as2("JMP", 0x6C);
131 : : end();
132 : : }
133 [ + - + - : 1156 : else if (match("", ",x"))
+ + ]
134 : : {
135 : 258 : init_index("", ",x");
136 [ + - - + : 258 : if (match("(", ")") && confirmqpar(substr(word[1] + 1, (int)(strlen(word[1] + 1) - 2 - 1)))) asar_throw_warning(0, warning_id_65816_yy_x_does_not_exist);
- - - - -
+ - - ]
137 : 258 : the8(0x1F, 3);
138 : 208 : the8(0x1D, 2);
139 : 159 : the8(0x15, 1);
140 : 111 : thenext8(0x16, 1);
141 : 63 : thenext8(0x1E, 2);
142 : 15 : as1("STZ", 0x74);
143 : 9 : as1("STY", 0x94);
144 : 6 : as2("STZ", 0x9E);
145 : : end();
146 : : }
147 [ + - + - : 898 : else if (match("", ",y"))
+ + ]
148 : : {
149 : 39 : init_index("", ",y");
150 [ - + - - ]: 39 : if (len==3 && emulatexkas) len=2;
151 : 39 : as1("LDX", 0xB6);
152 : 33 : as1("STX", 0x96);
153 : 30 : as2("LDX", 0xBE);
154 [ - + - - : 24 : if (len==1 && (is("ORA") || is("AND") || is("EOR") || is("ADC") || is("STA") || is("LDA") || is("CMP") || is("SBC")))
- - - - -
- - - - -
- - - - ]
155 : : {
156 : 0 : asar_throw_warning(0, warning_id_65816_xx_y_assume_16_bit, word[0]);
157 : : len=2;
158 : : }
159 : 24 : the8(0x19, 2);
160 : : end();
161 : : }
162 : : else
163 : : {
164 [ + + + + : 859 : if ((is("MVN") || is("MVP")) && confirmqpar(par))
+ - + - ]
165 : : {
166 : : int numargs;
167 [ + - ]: 6 : autoptr<char**>param=qpsplit(par.temp_raw(), ",", &numargs);
168 [ + - ]: 6 : if (numargs ==2)
169 : : {
170 [ + + + - ]: 9 : write1(is("MVN")?(unsigned int)0x54:(unsigned int)0x44);
171 [ + + + - : 6 : write1(pass==2?getnum(param[0]):0);
+ - ]
172 [ + + + - : 6 : write1(pass==2?getnum(param[1]):0);
+ - ]
173 : : return true;
174 : : }
175 : 6 : }
176 : : if (false)
177 : : {
178 : : opAFallback:
179 : : snes_label tmp;
180 [ + + + - : 3 : if (pass && !labelval(par, &tmp)) return false;
- + - + ]
181 : 3 : len=getlen(par);
182 : : num=tmp.pos;
183 : : }
184 [ + + + + ]: 856 : if (is("JSR") || is("JMP"))
185 : : {
186 : 27 : int tmp=optimizeforbank;
187 : 27 : optimizeforbank=-1;
188 : 27 : getvars(false)
189 : 27 : optimizeforbank=tmp;
190 : : }
191 : : else
192 : : {
193 : 829 : getvars(false)
194 : : }
195 : 856 : the8(0x0F, 3);
196 : 796 : the8(0x0D, 2);
197 : 715 : the8(0x05, 1);
198 : 658 : thenext8(0x06, 1);
199 : 610 : thenext8(0x0E, 2);
200 : 562 : thefinal7(0x04, 1);
201 : 520 : thefinal7(0x0C, 2);
202 : 478 : as1("STZ", 0x64);
203 : 472 : as2("STZ", 0x9C);
204 : 466 : as2("JMP", 0x4C);
205 : 460 : as2("JSR", 0x20);
206 : 439 : as32("JML", 0x5C);
207 : 430 : as32("JSL", 0x22);
208 : 400 : as2("MVN", 0x54);
209 : 400 : as2("MVP", 0x44);
210 : 400 : as2("PEA", 0xF4);
211 [ + + ]: 397 : if (emulatexkas)
212 : : {
213 : 15 : asar_throw_warning(0, warning_id_feature_deprecated, "usage of jmp instead of jml ", "use jml instead");
214 : 15 : as3("JMP", 0x5C);//all my hate
215 : : //as3("JSR", 0x22);
216 : : }
217 : 397 : as_rel1("BRA", 0x80);
218 : 391 : as_rel1("BCC", 0x90);
219 : 388 : as_rel1("BCS", 0xB0);
220 : 385 : as_rel1("BEQ", 0xF0);
221 : 379 : as_rel1("BNE", 0xD0);
222 : 376 : as_rel1("BMI", 0x30);
223 : 373 : as_rel1("BPL", 0x10);
224 : 370 : as_rel1("BVC", 0x50);
225 : 367 : as_rel1("BVS", 0x70);
226 : 364 : as_rel2("BRL", 0x82);
227 : 361 : as_rel2("PER", 0x62);
228 : : end();
229 : : }
230 : : return true;
231 : 110776 : }
|