LCOV - code coverage report
Current view: top level - asar - arch-65816.cpp (source / functions) Coverage Total Hit
Test: asar build #66 Lines: 93.4 % 137 128
Test Date: 2024-01-16 02:45:19 Functions: 100.0 % 3 3
Branches: 71.0 % 138 98

             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                 :         670 : void asinit_65816()
       8                 :             : {
       9                 :         670 : }
      10                 :             : 
      11                 :         618 : void asend_65816()
      12                 :             : {
      13                 :         618 : }
      14                 :             : 
      15                 :             : extern bool fastrom;
      16                 :             : extern int recent_opcode_num;
      17                 :             : 
      18                 :       17387 : bool asblock_65816(char** word, int numwords)
      19                 :             : {
      20                 :             : #define is(test) (!stricmpwithupper(word[0], test))
      21                 :             : //#define par word[1]
      22         [ +  + ]:       17387 :         if(word[0][0] == '\'') return false;
      23                 :       16985 :         string par;
      24         [ +  + ]:       32240 :         for(int i = 1; i < numwords; i++){
      25   [ +  +  +  - ]:       15255 :                 if(i > 1) par += " ";
      26                 :       15255 :                 par += word[i];
      27                 :             :         }
      28                 :             :         unsigned int num;
      29                 :        9598 :         int len=0;//declared here for A->generic fallback
      30                 :        9598 :         bool explicitlen = false;
      31                 :        9598 :         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   [ +  +  +  +  :       16985 :         else if ((strlen(word[0])!=3 && (strlen(word[0])!=5 || word[0][3]!='.'))) return false;
                   +  + ]
      67         [ +  + ]:        4524 :         else if (numwords == 1)
      68                 :             :         {
      69                 :         606 :                 blankinit();
      70                 :        1212 :                 as0("PHP", 0x08); as0("ASL", 0x0A); as0("PHD", 0x0B); as0("CLC", 0x18);
      71                 :        1194 :                 as0("INC", 0x1A); as0("TCS", 0x1B); as0("PLP", 0x28); as0("ROL", 0x2A);
      72                 :        1182 :                 as0("PLD", 0x2B); as0("SEC", 0x38); as0("DEC", 0x3A); as0("TSC", 0x3B);
      73                 :        1164 :                 as0("RTI", 0x40); as0("PHA", 0x48); as0("LSR", 0x4A); as0("PHK", 0x4B);
      74                 :        1146 :                 as0("CLI", 0x58); as0("PHY", 0x5A); as0("TCD", 0x5B); as0("RTS", 0x60);
      75                 :        1122 :                 as0("PLA", 0x68); as0("ROR", 0x6A); as0("RTL", 0x6B); as0("SEI", 0x78);
      76                 :        1104 :                 as0("PLY", 0x7A); as0("TDC", 0x7B); as0("DEY", 0x88); as0("TXA", 0x8A);//these tables are blatantly stolen from xkas
      77                 :        1080 :                 as0("PHB", 0x8B); as0("TYA", 0x98); as0("TXS", 0x9A); as0("TXY", 0x9B);
      78                 :        1056 :                 as0("TAY", 0xA8); as0("TAX", 0xAA); as0("PLB", 0xAB); as0("CLV", 0xB8);
      79                 :        1032 :                 as0("TSX", 0xBA); as0("TYX", 0xBB); as0("INY", 0xC8); as0("DEX", 0xCA);
      80                 :        1008 :                 as0("WAI", 0xCB); as0("CLD", 0xD8); as0("PHX", 0xDA); as0("STP", 0xDB);
      81                 :         984 :                 as0("INX", 0xE8); as0("NOP", 0xEA); as0("XBA", 0xEB); as0("SED", 0xF8);
      82                 :          30 :                 as0("PLX", 0xFA); as0("XCE", 0xFB);
      83                 :          18 :                 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                 :           0 :                 end();
      87                 :             :         }
      88   [ +  +  +  + ]:        3312 :         else if (!stricmp(word[1], "A"))
      89                 :             :         {
      90                 :          21 :                 blankinit();
      91                 :          42 :                 as0("ASL", 0x0A); as0("LSR", 0x4A); as0("ROL", 0x2A); as0("ROR", 0x6A);
      92                 :          18 :                 as0("INC", 0x1A); as0("DEC", 0x3A);
      93                 :           6 :                 goto opAFallback;//yay goto
      94                 :             :         }
      95   [ +  +  +  +  :        3270 :         else if (matchl("#"))
                   +  + ]
      96                 :             :         {
      97                 :         462 :                 bankoptinit('#');
      98                 :         454 :                 as_a("ORA", 0x09); as_a("AND", 0x29); as_a("EOR", 0x49); as_a("ADC", 0x69);
      99                 :         348 :                 as_a("BIT", 0x89); as_a("LDA", 0xA9); as_a("CMP", 0xC9); as_a("SBC", 0xE9);
     100                 :         198 :                 as_xy("CPX", 0xE0); as_xy("CPY", 0xC0); as_xy("LDX", 0xA2); as_xy("LDY", 0xA0);
     101                 :         138 :                 as_rep("ASL", 0x0A); as_rep("LSR", 0x4A); as_rep("ROL", 0x2A); as_rep("ROR", 0x6A);
     102                 :          93 :                 as_rep("INC", 0x1A); as_rep("DEC", 0x3A); as_rep("INX", 0xE8); as_rep("DEX", 0xCA);
     103                 :         249 :                 as_rep("INY", 0xC8); as_rep("DEY", 0x88); as_rep("NOP", 0xEA);
     104                 :          30 :                 as1("REP", 0xC2); as1("SEP", 0xE2);
     105                 :          18 :                 as1("BRK", 0x00); as1("COP", 0x02); as1("WDM", 0x42);
     106                 :           0 :                 end();
     107                 :             :         }
     108                 :        2808 :         onlythe8("(", ",s),y", 0x13);
     109                 :        2760 :         onlythe8("[", "],y", 0x17);
     110                 :        2712 :         onlythe8("(", "),y", 0x11);
     111                 :        2664 :         onlythe8("", ",s", 0x03);
     112   [ +  +  +  +  :        2616 :         else if (match("[", "]"))
             +  -  +  + ]
     113                 :             :         {
     114                 :          66 :                 init('[', ']');
     115                 :          66 :                 the8(0x07, 1);
     116                 :          18 :                 as2("JMP", 0xDC); as2("JML", 0xDC);
     117                 :           0 :                 end();
     118                 :             :         }
     119   [ +  +  +  +  :        2550 :         else if (match("(", ",x)"))
             +  +  +  + ]
     120                 :             :         {
     121                 :          60 :                 init_index("(", ",x)");
     122                 :          60 :                 the8(0x01, 1);
     123                 :          12 :                 as2("JMP", 0x7C); as2("JSR", 0xFC);
     124                 :           0 :                 end();
     125                 :             :         }
     126   [ +  +  +  +  :        2490 :         else if (match("(", ")"))
             +  -  +  + ]
     127                 :             :         {
     128                 :          60 :                 init('(', ')');
     129                 :          60 :                 the8(0x12, 1);
     130                 :          12 :                 as1("PEI", 0xD4);
     131                 :           6 :                 as2("JMP", 0x6C);
     132                 :           0 :                 end();
     133                 :             :         }
     134   [ +  +  +  +  :        2430 :         else if (matchr(",x"))
                   +  + ]
     135                 :             :         {
     136                 :         510 :                 init_index("", ",x");
     137   [ +  -  -  +  :         510 :                 if (match("(", ")")) asar_throw_warning(0, warning_id_65816_yy_x_does_not_exist);
          -  -  -  +  -  
                      - ]
     138                 :         510 :                 the8(0x1F, 3);
     139                 :         414 :                 the8(0x1D, 2);
     140                 :         318 :                 the8(0x15, 1);
     141                 :         222 :                 thenext8(0x16, 1);
     142                 :         126 :                 thenext8(0x1E, 2);
     143                 :          30 :                 as1("STZ", 0x74);
     144                 :          18 :                 as1("STY", 0x94);
     145                 :          12 :                 as2("STZ", 0x9E);
     146                 :           0 :                 end();
     147                 :             :         }
     148   [ +  +  +  +  :        1920 :         else if (matchr(",y"))
                   +  + ]
     149                 :             :         {
     150                 :          78 :                 init_index("", ",y");
     151                 :          78 :                 as1("LDX", 0xB6);
     152                 :          66 :                 as1("STX", 0x96);
     153                 :          60 :                 as2("LDX", 0xBE);
     154   [ -  +  -  -  :          48 :                 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                 :           0 :                         len=2;
     158                 :             :                 }
     159                 :          48 :                 the8(0x19, 2);
     160                 :           0 :                 end();
     161                 :             :         }
     162                 :             :         else
     163                 :             :         {
     164   [ +  +  +  +  :        1842 :                 if ((is("MVN") || is("MVP")))
                   +  + ]
     165                 :             :                 {
     166                 :             :                         int numargs;
     167         [ +  - ]:          12 :                         autoptr<char**>param=qpsplit(par.temp_raw(), ',', &numargs);
     168         [ +  - ]:          12 :                         if (numargs ==2)
     169                 :             :                         {
     170   [ +  +  +  - ]:          15 :                                 write1(is("MVN")?(unsigned int)0x54:(unsigned int)0x44);
     171   [ +  +  +  -  :          12 :                                 write1(pass==2?getnum(param[0]):0);
                   +  - ]
     172   [ +  +  +  -  :          12 :                                 write1(pass==2?getnum(param[1]):0);
                   +  - ]
     173                 :           6 :                                 return true;
     174                 :             :                         }
     175                 :          12 :                 }
     176                 :             :                 if (false)
     177                 :             :                 {
     178                 :           3 : opAFallback:
     179                 :           6 :                         snes_label tmp;
     180   [ +  +  +  -  :           6 :                         if (pass && !labelval(par, &tmp)) return false;
          +  +  -  +  +  
             +  -  +  -  
                      - ]
     181                 :           6 :                         len=getlen(par);
     182                 :           3 :                         num=tmp.pos;
     183                 :             :                 }
     184   [ +  +  +  +  :        1836 :                 if (is("JSR") || is("JMP"))
                   +  + ]
     185                 :             :                 {
     186                 :          48 :                         int tmp=optimizeforbank;
     187                 :          48 :                         optimizeforbank=-1;
     188                 :          48 :                         getvars(false)
     189                 :          48 :                         optimizeforbank=tmp;
     190                 :             :                 }
     191                 :             :                 else
     192                 :             :                 {
     193                 :        1788 :                         getvars(false)
     194                 :             :                 }
     195                 :        1834 :                 the8(0x0F, 3);
     196                 :        1692 :                 the8(0x0D, 2);
     197                 :        1488 :                 the8(0x05, 1);
     198                 :        1368 :                 thenext8(0x06, 1);
     199                 :        1272 :                 thenext8(0x0E, 2);
     200                 :        1176 :                 thefinal7(0x04, 1);
     201                 :        1092 :                 thefinal7(0x0C, 2);
     202                 :        1008 :                 as1("STZ", 0x64);
     203                 :         996 :                 as2("STZ", 0x9C);
     204                 :         984 :                 as2("JMP", 0x4C);
     205                 :         978 :                 as2("JSR", 0x20);
     206                 :         936 :                 as32("JML", 0x5C);
     207                 :         924 :                 as32("JSL", 0x22);
     208                 :         864 :                 as2("MVN", 0x54);
     209                 :         864 :                 as2("MVP", 0x44);
     210                 :         864 :                 as2("PEA", 0xF4);
     211                 :         858 :                 as_rel1("BRA", 0x80);
     212                 :         852 :                 as_rel1("BCC", 0x90);
     213                 :         846 :                 as_rel1("BCS", 0xB0);
     214                 :         840 :                 as_rel1("BEQ", 0xF0);
     215                 :         828 :                 as_rel1("BNE", 0xD0);
     216                 :         822 :                 as_rel1("BMI", 0x30);
     217                 :         816 :                 as_rel1("BPL", 0x10);
     218                 :         810 :                 as_rel1("BVC", 0x50);
     219                 :         804 :                 as_rel1("BVS", 0x70);
     220                 :         798 :                 as_rel2("BRL", 0x82);
     221                 :         792 :                 as_rel2("PER", 0x62);
     222                 :         393 :                 end();
     223                 :             :         }
     224                 :             :         return false;
     225                 :       16985 : }
        

Generated by: LCOV version 2.0-1