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 : 335 : void asinit_65816()
8 : : {
9 : 335 : }
10 : :
11 : 309 : void asend_65816()
12 : : {
13 : 309 : }
14 : :
15 : : extern bool fastrom;
16 : : extern int recent_opcode_num;
17 : :
18 : 7588 : bool asblock_65816(char** word, int numwords)
19 : : {
20 : : #define is(test) (!stricmpwithupper(word[0], test))
21 : : //#define par word[1]
22 [ + + ]: 7588 : if(word[0][0] == '\'') return false;
23 : 7387 : string par;
24 [ + + ]: 13909 : for(int i = 1; i < numwords; i++){
25 [ + + ]: 6522 : if(i > 1) par += " ";
26 : 6522 : par += word[i];
27 : : }
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 matchr(right) (word[1] && striend(par, right))
36 : : #define matchl(left) (word[1] && stribegin(par, left))
37 : : #define init(left, right) par.strip_suffix(right); par.strip_prefix(left); getvars(false)
38 : : #define init_index(left, right) itrim(par, left, right); getvars(false)
39 : : #define bankoptinit(left) par.strip_prefix(left); getvars(true)
40 : : #define blankinit() len=1; explicitlen=false; num=0
41 : : #define end() return false
42 : : #define as0( op, byte) if (is(op) ) { write1((unsigned int)byte); return true; }
43 : : #define as1( op, byte) if (len==1 && is(op)) { write1((unsigned int)byte); write1(num); return true; }
44 : : #define as2( op, byte) if (len==2 && is(op)) { write1((unsigned int)byte); write2(num); return true; }
45 : : #define as3( op, byte) if (len==3 && is(op)) { write1((unsigned int)byte); write3(num); return true; }
46 : : //#define as23( op, byte) if (is(op) && (len==2 || len==3)) { write1(byte); write2(num); return true; }
47 : : #define as32( op, byte) if (is(op) && ((len==2 && !explicitlen) || len==3)) { write1((unsigned int)byte); write3(num); return true; }
48 : : #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); } \
49 : : else { write1((unsigned int)byte); write2(num); } return true; }
50 : : #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); } \
51 : : else { write1((unsigned int)byte); write2(num); } return true; }
52 : : #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; }
53 : : #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); \
54 : : 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()); \
55 : : return true; }
56 : : #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);\
57 : : 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()); \
58 : : return true; }
59 : : #define the8(offset, len) as##len("ORA", offset+0x00); as##len("AND", offset+0x20); as##len("EOR", offset+0x40); as##len("ADC", offset+0x60); \
60 : : as##len("STA", offset+0x80); as##len("LDA", offset+0xA0); as##len("CMP", offset+0xC0); as##len("SBC", offset+0xE0)
61 : : #define thenext8(offset, len) as##len("ASL", offset+0x00); as##len("BIT", offset+0x1E); as##len("ROL", offset+0x20); as##len("LSR", offset+0x40); \
62 : : as##len("ROR", offset+0x60); as##len("LDY", offset+0x9E); as##len("DEC", offset+0xC0); as##len("INC", offset+0xE0)
63 : : #define thefinal7(offset, len) as##len("TSB", offset+0x00); as##len("TRB", offset+0x10); as##len("STY", offset+0x80); as##len("STX", offset+0x82); \
64 : : as##len("LDX", offset+0xA2); as##len("CPY", offset+0xC0); as##len("CPX", offset+0xE0)
65 : : #define onlythe8(left, right, offset) else if (match(left, right)) do { init_index(left, right); the8(offset, 1); end(); } while(0)
66 [ + + + + : 7387 : else if ((strlen(word[0])!=3 && (strlen(word[0])!=5 || word[0][3]!='.'))) return false;
+ + ]
67 [ + + ]: 2262 : else if (numwords == 1)
68 : : {
69 : : blankinit();
70 : 606 : as0("PHP", 0x08); as0("ASL", 0x0A); as0("PHD", 0x0B); as0("CLC", 0x18);
71 : 597 : as0("INC", 0x1A); as0("TCS", 0x1B); as0("PLP", 0x28); as0("ROL", 0x2A);
72 : 591 : as0("PLD", 0x2B); as0("SEC", 0x38); as0("DEC", 0x3A); as0("TSC", 0x3B);
73 : 582 : as0("RTI", 0x40); as0("PHA", 0x48); as0("LSR", 0x4A); as0("PHK", 0x4B);
74 : 573 : as0("CLI", 0x58); as0("PHY", 0x5A); as0("TCD", 0x5B); as0("RTS", 0x60);
75 : 561 : as0("PLA", 0x68); as0("ROR", 0x6A); as0("RTL", 0x6B); as0("SEI", 0x78);
76 : 552 : as0("PLY", 0x7A); as0("TDC", 0x7B); as0("DEY", 0x88); as0("TXA", 0x8A);//these tables are blatantly stolen from xkas
77 : 540 : as0("PHB", 0x8B); as0("TYA", 0x98); as0("TXS", 0x9A); as0("TXY", 0x9B);
78 : 528 : as0("TAY", 0xA8); as0("TAX", 0xAA); as0("PLB", 0xAB); as0("CLV", 0xB8);
79 : 516 : as0("TSX", 0xBA); as0("TYX", 0xBB); as0("INY", 0xC8); as0("DEX", 0xCA);
80 : 504 : as0("WAI", 0xCB); as0("CLD", 0xD8); as0("PHX", 0xDA); as0("STP", 0xDB);
81 : 492 : as0("INX", 0xE8); as0("NOP", 0xEA); as0("XBA", 0xEB); as0("SED", 0xF8);
82 : 15 : as0("PLX", 0xFA); as0("XCE", 0xFB);
83 : 9 : as1("BRK", 0x00); as1("COP", 0x02); as1("WDM", 0x42);
84 : : //as0("DEA", 0x3A); as0("INA", 0x1A); as0("TAD", 0x5B); as0("TDA", 0x7B);//nobody cares about these, but keeping them does no harm
85 : : //as0("TAS", 0x1B); as0("TSA", 0x3B); as0("SWA", 0xEB); //actually, it does: it may make some users think it's correct.
86 : : end();
87 : : }
88 [ + + ]: 1656 : else if (!stricmp(word[1], "A"))
89 : : {
90 : : blankinit();
91 : 21 : as0("ASL", 0x0A); as0("LSR", 0x4A); as0("ROL", 0x2A); as0("ROR", 0x6A);
92 : 9 : as0("INC", 0x1A); as0("DEC", 0x3A);
93 : 3 : goto opAFallback;//yay goto
94 : : }
95 [ + + ]: 1635 : else if (matchl("#"))
96 : : {
97 : 231 : bankoptinit('#');
98 : 227 : as_a("ORA", 0x09); as_a("AND", 0x29); as_a("EOR", 0x49); as_a("ADC", 0x69);
99 : 174 : as_a("BIT", 0x89); as_a("LDA", 0xA9); as_a("CMP", 0xC9); as_a("SBC", 0xE9);
100 : 99 : as_xy("CPX", 0xE0); as_xy("CPY", 0xC0); as_xy("LDX", 0xA2); as_xy("LDY", 0xA0);
101 : 72 : as_rep("ASL", 0x0A); as_rep("LSR", 0x4A); as_rep("ROL", 0x2A); as_rep("ROR", 0x6A);
102 : 48 : as_rep("INC", 0x1A); as_rep("DEC", 0x3A); as_rep("INX", 0xE8); as_rep("DEX", 0xCA);
103 : 138 : as_rep("INY", 0xC8); as_rep("DEY", 0x88); as_rep("NOP", 0xEA);
104 : 15 : as1("REP", 0xC2); as1("SEP", 0xE2);
105 : 9 : as1("BRK", 0x00); as1("COP", 0x02); as1("WDM", 0x42);
106 : : end();
107 : : }
108 : 1404 : onlythe8("(", ",s),y", 0x13);
109 : 1380 : onlythe8("[", "],y", 0x17);
110 : 1356 : onlythe8("(", "),y", 0x11);
111 : 1332 : onlythe8("", ",s", 0x03);
112 [ + + - + ]: 1308 : else if (match("[", "]"))
113 : : {
114 : 33 : init('[', ']');
115 : 33 : the8(0x07, 1);
116 : 9 : as2("JMP", 0xDC); as2("JML", 0xDC);
117 : : end();
118 : : }
119 [ + + + + ]: 1275 : else if (match("(", ",x)"))
120 : : {
121 : 30 : init_index("(", ",x)");
122 : 30 : the8(0x01, 1);
123 : 6 : as2("JMP", 0x7C); as2("JSR", 0xFC);
124 : : end();
125 : : }
126 [ + + - + ]: 1245 : else if (match("(", ")"))
127 : : {
128 : 30 : init('(', ')');
129 : 30 : the8(0x12, 1);
130 : 6 : as1("PEI", 0xD4);
131 : 3 : as2("JMP", 0x6C);
132 : : end();
133 : : }
134 [ + + ]: 1215 : else if (matchr(",x"))
135 : : {
136 : 255 : init_index("", ",x");
137 [ + - - + : 255 : if (match("(", ")")) asar_throw_warning(0, warning_id_65816_yy_x_does_not_exist);
- - - - ]
138 : 255 : the8(0x1F, 3);
139 : 207 : the8(0x1D, 2);
140 : 159 : the8(0x15, 1);
141 : 111 : thenext8(0x16, 1);
142 : 63 : thenext8(0x1E, 2);
143 : 15 : as1("STZ", 0x74);
144 : 9 : as1("STY", 0x94);
145 : 6 : as2("STZ", 0x9E);
146 : : end();
147 : : }
148 [ + + ]: 960 : else if (matchr(",y"))
149 : : {
150 : 39 : init_index("", ",y");
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 [ + + + + ]: 921 : if ((is("MVN") || is("MVP")))
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 : 3 : snes_label tmp;
180 [ + + + - : 3 : if (pass && !labelval(par, &tmp)) return false;
- + - + ]
181 : 3 : len=getlen(par);
182 : : num=tmp.pos;
183 : : }
184 [ + + + + ]: 918 : if (is("JSR") || is("JMP"))
185 : : {
186 : 24 : int tmp=optimizeforbank;
187 : 24 : optimizeforbank=-1;
188 : 24 : getvars(false)
189 : 24 : optimizeforbank=tmp;
190 : : }
191 : : else
192 : : {
193 : 894 : getvars(false)
194 : : }
195 : 917 : the8(0x0F, 3);
196 : 846 : the8(0x0D, 2);
197 : 744 : the8(0x05, 1);
198 : 684 : thenext8(0x06, 1);
199 : 636 : thenext8(0x0E, 2);
200 : 588 : thefinal7(0x04, 1);
201 : 546 : thefinal7(0x0C, 2);
202 : 504 : as1("STZ", 0x64);
203 : 498 : as2("STZ", 0x9C);
204 : 492 : as2("JMP", 0x4C);
205 : 489 : as2("JSR", 0x20);
206 : 468 : as32("JML", 0x5C);
207 : 462 : as32("JSL", 0x22);
208 : 432 : as2("MVN", 0x54);
209 : 432 : as2("MVP", 0x44);
210 : 432 : as2("PEA", 0xF4);
211 : 429 : as_rel1("BRA", 0x80);
212 : 426 : as_rel1("BCC", 0x90);
213 : 423 : as_rel1("BCS", 0xB0);
214 : 420 : as_rel1("BEQ", 0xF0);
215 : 414 : as_rel1("BNE", 0xD0);
216 : 411 : as_rel1("BMI", 0x30);
217 : 408 : as_rel1("BPL", 0x10);
218 : 405 : as_rel1("BVC", 0x50);
219 : 402 : as_rel1("BVS", 0x70);
220 : 399 : as_rel2("BRL", 0x82);
221 : 396 : as_rel2("PER", 0x62);
222 : : end();
223 : : }
224 : : return false;
225 : 7387 : }
|