Subversion Repositories pentevo

Rev

Rev 796 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "memory.h"
  6. #include "dbglabls.h"
  7. #include "z80asm.h"
  8.  
  9. #include "util.h"
  10.  
  11. char asmbuf[0x40];
  12.  
  13. #define _iw  9
  14. #define _ib  10
  15. #define _shrt 27
  16. #define _ld 0x89
  17. #define _zr16 0x8A
  18. #define _zr8 0x8B
  19. #define _cb 0x8C
  20. #define _zjr 0x8D
  21. #define _hl 0x8E
  22. #define _zr81 0x8F
  23. #define _zop 0x90
  24. #define _zf 0x91
  25. #define _zr16a 0x92
  26. #define _zr8_ 0x9D
  27. #define _zr81_ 0x9E
  28.  
  29. static unsigned char asm_tab_z80[] =
  30. {
  31. #if 0
  32.    2,0xED,0xFF,0xFF,0xFF, // call unreal api
  33.    'u','a','p','i',0,
  34. #endif
  35.  
  36.    // fix bug out (c),a => out (0C),a
  37.    2, 0xED, 0x70, 0xFF, 0xFF, // in (c)
  38.    'i','n',' ','(','c',')',0,
  39.    2, 0xED, 0x71, 0xFF, 0xFF, // out (c),0
  40.    'o','u','t',' ','(','c',')',',','0',0,
  41.    2, 0xED, 0x40, 0xFF, 0xC7, // in r8,(c)
  42.    'i','n',' ',_zr8,',','(','c',')',0,
  43.    2, 0xED, 0x41, 0xFF, 0xC7, // out (c),r8
  44.    'o','u','t',' ','(','c',')',',',_zr8,0,
  45.  
  46.  
  47.    1,0xCB,0xFF, // all cb-opcodes
  48.    _cb,0,
  49.    1, 0x00, 0xFF, // nop
  50.    'n','o','p',0,
  51.    1, 0x08, 0xFF, // ex af,af'
  52.    'e','x',' ','a','f',',','a','f','\'',0,
  53.    1,0x02, 0xFF, // ld (bc),a
  54.    _ld, '(','b','c',')',',','a',0,
  55.    1,0x12, 0xFF, // ld (de),a
  56.    _ld, '(','d','e',')',',','a',0,
  57.    1,0x0A, 0xFF, // ld a,(bc)
  58.    _ld, 'a',',','(','b','c',')',0,
  59.    1,0x1A, 0xFF, // ld a,(de)
  60.    _ld, 'a',',','(','d','e',')',0,
  61.    1,0x03,0xCF, // inc r16
  62.    'i','n','c',' ',_zr16,0,
  63.    1,0x0B,0xCF, // dec r16
  64.    'd','e','c',' ',_zr16,0,
  65.    1,0x04,0xC7, // inc r8
  66.    'i','n','c',' ', _zr8,0,
  67.    1, 0x05, 0xC7, // dec r8
  68.    'd','e','c',' ', _zr8,0,
  69.    1, 0x07, 0xFF, // rlca
  70.    'r','l','c','a',0,
  71.    1, 0x17, 0xFF, // rla
  72.    'r','l','a',0,
  73.    1, 0x27, 0xFF, // daa
  74.    'd','a','a',0,
  75.    1, 0x37, 0xFF, // scf
  76.    's','c','f',0,
  77.    1, 0x0F, 0xFF, // rrca
  78.    'r','r','c','a',0,
  79.    1, 0x1F, 0xFF, // rra
  80.    'r','r','a',0,
  81.    1, 0x2F, 0xFF, // cpl
  82.    'c','p','l',0,
  83.    1, 0x3F, 0xFF, // ccf
  84.    'c','c','f',0,
  85.    1, 0x00, 0xC7, // relative jumps
  86.    _zjr, _shrt, 0,
  87.    1, 0x09, 0xCF, // add hl, r16
  88.    'a','d','d',' ',_hl,',',_zr16,0,
  89.    1, 0x32, 0xFF, // ld (nnnn),a
  90.    _ld,'(',_iw,')',',','a',0,
  91.    1, 0x3A, 0xFF, // ld a,(nnnn)
  92.    _ld,'a',',','(',_iw,')',0,
  93.    1, 0x22, 0xFF, // ld (nnnn),hl
  94.    _ld,'(',_iw,')',',',_hl,0,
  95.    1, 0x2A, 0xFF, // ld hl,(nnnn)
  96.    _ld,_hl,',','(',_iw,')',0,
  97.    1, 0x76, 0xFF, // halt
  98.    'h','a','l','t',0,
  99.    1, 0x40, 0xC0, // ld r8,r8
  100.    _ld, _zr8_, ',', _zr81_, 0,
  101.    1, 0x80, 0xC0, // op r8
  102.    _zop/*, ' '*/, _zr81, 0,
  103.    1, 0xC0, 0xC7, // ret cc
  104.    'r','e','t',' ',_zf,0,
  105.    1, 0xC2, 0xC7, // jp cc, nnnn
  106.    'j','p',' ',_zf,',',_iw,0,
  107.    1, 0xC4, 0xC7, // call cc, nnnn
  108.    'c','a','l','l',' ',_zf,',',_iw,0,
  109.    1, 0xC6, 0xC7, // op immb
  110.    _zop/*, ' '*/, _ib, 0,
  111.    1, 0xC1, 0xCF, // pop r16a
  112.    'p','o','p',' ',_zr16a,0,
  113.    1, 0xC5, 0xCF, // push r16a
  114.    'p','u','s','h',' ',_zr16a,0,
  115.    1, 0xC3, 0xFF, // jp nnnn
  116.    'j','p', ' ', _iw,0,
  117.    1, 0xD3, 0xFF, // out (nn),a
  118.    'o','u','t',' ','(',_ib,')',',','a',0,
  119.    1, 0xE3, 0xFF, // ex (sp),hl
  120.    'e','x',' ','(','s','p',')',',',_hl,0,
  121.    1, 0xF3, 0xFF, // di
  122.    'd','i',0,
  123.    1, 0xC9, 0xFF, // ret
  124.    'r','e','t',0,
  125.    1, 0xD9, 0xFF, // exx
  126.    'e','x','x',0,
  127.    1, 0xE9, 0xFF, // jp (hl)
  128.    'j','p',' ','(',_hl,')',0,
  129.    1, 0xF9, 0xFF, // ld sp, hl
  130.    _ld, 's','p',',',_hl,0,
  131.    1, 0xDB, 0xFF, // in a,(nn)
  132.    'i','n',' ','a',',','(',_ib,')',0,
  133.    1, 0xEB, 0xFF,  // ex de,hl  - no 'ex de,ix' !
  134.    'e','x',' ','d','e',',','h','l',0,
  135.    1, 0xFB, 0xFF, // ei
  136.    'e','i',0,
  137.    1, 0xCD, 0xFF, // call nnnn
  138.    'c','a','l','l',' ',_iw,0,
  139.    1, 0xC7, 0xFF, // rst 0
  140.    'r','s','t',' ','0',0,
  141.    1, 0xCF, 0xFF, // rst 8
  142.    'r','s','t',' ','8',0,
  143.    1, 0xD7, 0xFF, // rst 10
  144.    'r','s','t',' ','1','0',0,
  145.    1, 0xDF, 0xFF, // rst 18
  146.    'r','s','t',' ','1','8',0,
  147.    1, 0xE7, 0xFF, // rst 20
  148.    'r','s','t',' ','2','0',0,
  149.    1, 0xEF, 0xFF, // rst 28
  150.    'r','s','t',' ','2','8',0,
  151.    1, 0xF7, 0xFF, // rst 30
  152.    'r','s','t',' ','3','0',0,
  153.    1, 0xFF, 0xFF, // rst 38
  154.    'r','s','t',' ','3','8',0,
  155.  
  156.  
  157.    // ED opcodes
  158. #if 0 // moved above
  159.    2, 0xED, 0x70, 0xFF, 0xFF, // in (c)
  160.    'i','n',' ','(','c',')',0,
  161.    2, 0xED, 0x71, 0xFF, 0xFF, // out (c),0
  162.    'o','u','t',' ','(','c',')',',','0',0,
  163.    2, 0xED, 0x40, 0xFF, 0xC7, // in r8,(c)
  164.    'i','n',' ',_zr8,',','(','c',')',0,
  165.    2, 0xED, 0x41, 0xFF, 0xC7, // out (c),r8
  166.    'o','u','t',' ','(','c',')',',',_zr8,0,
  167. #endif
  168.    2, 0xED, 0x42, 0xFF, 0xCF, // sbc hl,r16
  169.    's','b','c',' ','h','l',',',_zr16,0,
  170.    2, 0xED, 0x4A, 0xFF, 0xCF, // adc hl,r16
  171.    'a','d','c',' ','h','l',',',_zr16,0,
  172.    2, 0xED, 0x43, 0xFF, 0xCF, // ld (nnnn), r16
  173.    _ld, '(',_iw,')',',',_zr16, 0,
  174.    2, 0xED, 0x4B, 0xFF, 0xCF, // ld r16, (nnnn)
  175.    _ld, _zr16, ',', '(',_iw,')', 0,
  176.    2, 0xED, 0x44, 0xFF, 0xC7, // neg
  177.    'n','e','g',0,
  178.    2, 0xED, 0x45, 0xFF, 0xCF, // retn
  179.    'r','e','t','n',0,
  180.    2, 0xED, 0x4D, 0xFF, 0xCF, // reti
  181.    'r','e','t','i',0,
  182.    2, 0xED, 0x46, 0xFF, 0xDF, // im 0
  183.    'i','m',' ','0',0,
  184.    2, 0xED, 0x56, 0xFF, 0xDF, // im 1
  185.    'i','m',' ','1',0,
  186.    2, 0xED, 0x5E, 0xFF, 0xDF, // im 2
  187.    'i','m',' ','2',0,
  188.    2, 0xED, 0x4E, 0xFF, 0xDF, // im 0/1
  189.    'i','m',' ','0','/','1',0,
  190.    2, 0xED, 0x47, 0xFF, 0xFF, // ld i,a
  191.    _ld, 'i',',','a',0,
  192.    2, 0xED, 0x57, 0xFF, 0xFF, // ld a,i
  193.    _ld, 'a',',','i',0,
  194.    2, 0xED, 0x67, 0xFF, 0xFF, // rrd
  195.    'r','r','d',0,
  196.    2, 0xED, 0x4F, 0xFF, 0xFF, // ld r,a
  197.    _ld, 'r',',','a',0,
  198.    2, 0xED, 0x5F, 0xFF, 0xFF, // ld a,r
  199.    _ld, 'a',',','r',0,
  200.    2, 0xED, 0x6F, 0xFF, 0xFF, // rld
  201.    'r','l','d',0,
  202.  
  203.    2, 0xED, 0xA0, 0xFF, 0xFF, // ldi
  204.    'l','d','i',0,
  205.    2, 0xED, 0xA1, 0xFF, 0xFF, // cpi
  206.    'c','p','i',0,
  207.    2, 0xED, 0xA2, 0xFF, 0xFF, // ini
  208.    'i','n','i',0,
  209.    2, 0xED, 0xA3, 0xFF, 0xFF, // outi
  210.    'o','u','t','i',0,
  211.    2, 0xED, 0xA8, 0xFF, 0xFF, // ldd
  212.    'l','d','d',0,
  213.    2, 0xED, 0xA9, 0xFF, 0xFF, // cpd
  214.    'c','p','d',0,
  215.    2, 0xED, 0xAA, 0xFF, 0xFF, // ind
  216.    'i','n','d',0,
  217.    2, 0xED, 0xAB, 0xFF, 0xFF, // outd
  218.    'o','u','t','d',0,
  219.  
  220.    2, 0xED, 0xB0, 0xFF, 0xFF, // ldir
  221.    'l','d','i','r',0,
  222.    2, 0xED, 0xB1, 0xFF, 0xFF, // cpir
  223.    'c','p','i','r',0,
  224.    2, 0xED, 0xB2, 0xFF, 0xFF, // inir
  225.    'i','n','i','r',0,
  226.    2, 0xED, 0xB3, 0xFF, 0xFF, // otir
  227.    'o','t','i','r',0,
  228.    2, 0xED, 0xB8, 0xFF, 0xFF, // lddr
  229.    'l','d','d','r',0,
  230.    2, 0xED, 0xB9, 0xFF, 0xFF, // cpdr
  231.    'c','p','d','r',0,
  232.    2, 0xED, 0xBA, 0xFF, 0xFF, // indr
  233.    'i','n','d','r',0,
  234.    2, 0xED, 0xBB, 0xFF, 0xFF, // otdr
  235.    'o','t','d','r',0,
  236.  
  237.    2, 0xED, 0x00, 0xFF, 0x00, // all others 'ED'
  238.    'n','o','p','*',0,
  239.  
  240.    // place immediates after all - 'ld a,b' is not 'ld a,0B'
  241.    1, 0x01, 0xCF, // ld r16,imm16
  242.    _ld, _zr16, ',', _iw, 0,
  243.    1, 0x06, 0xC7, // ld r8, imm8
  244.    _ld, _zr8, ',', _ib, 0,
  245.  
  246.    0 // end
  247. };
  248.  
  249.  
  250. #define abs(x) ((x)>0? (x):(-(x)))
  251.  
  252. // =======================================================================
  253. static char z80r16_1[] = "bc\0de\0hl\0sp";
  254. static char z80r16_2[] = "bc\0de\0ix\0sp";
  255. static char z80r16_3[] = "bc\0de\0iy\0sp";
  256. static char z80r8_1[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0h\0\0\0\0l\0\0\0\0(hl)\0a";
  257. static char z80r8_2[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0xh\0\0\0xl\0\0\0(1x)\0a";
  258. static char z80r8_3[] = "b\0\0\0\0c\0\0\0\0d\0\0\0\0e\0\0\0\0yh\0\0\0yl\0\0\0(1y)\0a";
  259. static char cbtab[] = "rlc \0\0\0rrc \0\0\0rl \0\0\0\0rr \0\0\0\0sla \0\0\0sra \0\0\0sli \0\0\0srl \0\0\0"
  260.                "bit 0,\0bit 1,\0bit 2,\0bit 3,\0bit 4,\0bit 5,\0bit 6,\0bit 7,\0"
  261.                "res 0,\0res 1,\0res 2,\0res 3,\0res 4,\0res 5,\0res 6,\0res 7,\0"
  262.                "set 0,\0set 1,\0set 2,\0set 3,\0set 4,\0set 5,\0set 6,\0set 7,\0";
  263. static char zjr[] = "xxxxxx\0xxxxxx\0djnz \0\0jr \0\0\0\0jr nz,\0jr z,\0\0jr nc,\0jr c,\0";
  264. //char zop[] = "add\0adc\0sub\0sbc\0and\0xor\0or\0\0cp"; lvd
  265. static char zop[] = "add a,\0\0adc a,\0\0sub \0\0\0\0sbc a,\0\0and \0\0\0\0xor \0\0\0\0or \0\0\0\0\0cp \0\0\0\0\0";
  266. static char zf[] = "nz\0z\0\0nc\0c\0\0po\0pe\0p\0\0m";
  267. // =======================================================================
  268.  
  269. static void disasm_address(char *line, unsigned addr, char labels)
  270. {
  271.    char *label = nullptr;
  272.    if (labels&&addr) label = mon_labels.find(am_r(addr));
  273.    if (label) {
  274.            //strcpy(line, label);
  275.                 int i;
  276.                 for (i=0;(i<20)&&label[i];i++)line[i]=label[i];
  277.                 line[i]=label[i];
  278.    } //Alone Coder 0.36.6
  279.    else sprintf(line, "%04X", addr & 0xFFFF);
  280. }
  281.  
  282. const unsigned char *disasm(const unsigned char *cmd, unsigned current, char labels)
  283. {
  284.     const unsigned char *st = cmd;
  285.     unsigned char z80p;
  286.     char *z80r16, *z80r8;
  287.  
  288.     z80r16 = z80r16_1;
  289.     z80r8 = z80r8_1;
  290.     z80p = 0;
  291.     for(;;)
  292.     { // z80 prefixes
  293.         if(*cmd == 0xDD)
  294.         {
  295.             z80r16 = z80r16_2;
  296.             z80r8 = z80r8_2;
  297.             z80p = 0xDD;
  298.         }
  299.         else if(*cmd == 0xFD)
  300.         {
  301.             z80r16 = z80r16_3;
  302.             z80r8 = z80r8_3; z80p = 0xFD;
  303.         }
  304.         else break;
  305.         cmd++;
  306.     }
  307.  
  308.     for(unsigned char *ptr = asm_tab_z80; *ptr; )
  309.     {
  310.         // cmd - start of command, c1 - mod/rm, cm - current pointer
  311.         const unsigned char *rcmd = cmd;
  312.         if(*cmd == 0xED)
  313.         {
  314.             rcmd++;
  315.             z80r16 = z80r16_1;
  316.             z80r8 = z80r8_1;
  317.             z80p = 0;
  318.         }
  319.         const unsigned char *cm = rcmd + 1;
  320.  
  321.         for(int j = 0; j < *ptr; j++) // match mask
  322.             if((cmd[j] & ptr[j + *ptr + 1]) != ptr[j + 1]) goto nextcmd;
  323.         *asmbuf = 0;
  324.         unsigned char *pt;
  325.         for(pt = ptr + (2 * *ptr) + 1; *pt; pt++)
  326.         { // scan all commands
  327.             char ln[/*32*/64];
  328.             const char *l1 = ln;
  329.             ln[0] = 0; //Alone Coder 0.36.6
  330.             switch(*pt)
  331.             {
  332.             case _zr16: // in rcmd & 0x30
  333.             l1 = z80r16 + 3 * ((*rcmd >> 4) & 3);
  334.             break;
  335.             case _zr16a: // in rcmd & 0x30
  336.             if(((*rcmd >> 4) & 3) == 3) l1 = "af";
  337.             else l1 = z80r16 + 3 * ((*rcmd >> 4) & 3);
  338.             break;
  339.             case _hl: // hl/ix/iy
  340.             l1 = z80r16 + 3 * 2;
  341.             break;
  342.             case _zjr: // relative jumps
  343.             l1 = zjr + 7 * ((*rcmd >> 3) & 7);
  344.             break;
  345.             case _zop: // z80 operations at rcmd & 0x38
  346.                //l1 = zop+4*((*rcmd>>3)&7); lvd
  347.             l1 = zop + 8 * ((*rcmd >> 3) & 7);
  348.             break;
  349.             case _zf: // z80 flags at rcmd & 0x38
  350.             l1 = zf + 3 * ((*rcmd >> 3) & 7);
  351.             break;
  352.             case _cb: // all CB-opcodes
  353.             {
  354.                 if(!z80p)
  355.                 {
  356.                     sprintf(ln, "%s%s", cbtab + (*cm >> 3) * 7, z80r8_1 + (*cm & 7) * 5);
  357.                     cm++;
  358.                 }
  359.                 else
  360.                 {
  361.                     if((cm[1] & 7) != 6 && ((cm[1] & 0xC0) != 0x40)) // operand is reg,(ix+nn)
  362.                         sprintf(ln, "%s%s,(i%c%c%02X)", cbtab + (cm[1] >> 3) * 7, z80r8_1 + (cm[1] & 7) * 5, z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
  363.                     else // only (ix+nn)
  364.                         sprintf(ln, "%s(i%c%c%02X)", cbtab + (cm[1] >> 3) * 7, z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
  365.                     cm += 2;
  366.                 }
  367.                 break;
  368.             }
  369.             case _zr8: // in rcmd & 0x38
  370.             if(z80p && ((*rcmd & 0x38) == 0x30))
  371.             {
  372.                 sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
  373.                 cm++;
  374.             }
  375.             else l1 = z80r8 + 5 * ((*rcmd >> 3) & 7);
  376.             break;
  377.             case _zr8_: // in rcmd & 0x38, in ld r8,r8
  378.             if(!z80p || (*rcmd & 7) == 6) { l1 = z80r8_1 + 5 * ((*rcmd >> 3) & 7); break; }
  379.             if((*rcmd & 0x38) == 0x30)
  380.             {
  381.                 sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
  382.                 cm++;
  383.             }
  384.             else l1 = z80r8 + 5 * ((*rcmd >> 3) & 7);
  385.             break;
  386.             case _zr81: // in rcmd & 7
  387.             if(z80p && (*rcmd & 7) == 6)
  388.             {
  389.                 sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
  390.                 cm++;
  391.             }
  392.             else l1 = z80r8 + 5 * (*rcmd & 7);
  393.             break;
  394.             case _zr81_: // in rcmd & 7, in ld r8,r8
  395.             if(!z80p || ((*rcmd & 0x38) == 0x30)) { l1 = z80r8_1 + 5 * (*rcmd & 7); break; }
  396.             if((*rcmd & 7) == 6)
  397.             {
  398.                 sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
  399.                 cm++;
  400.             }
  401.             else l1 = z80r8 + 5 * (*rcmd & 7);
  402.             break;
  403.             case _ld:
  404.             l1 = "ld "; break;
  405.             case _shrt: // short jump
  406.             disasm_address(ln, unsigned(current + cm - st + *(signed char*)cm + 1), labels);
  407.             cm++;
  408.             break;
  409.             case _ib: // immediate byte at cm
  410.             sprintf(ln, "%02X", *cm++);
  411.             break;
  412.             case _iw: // immediate word at cm
  413.             disasm_address(ln, *(unsigned short*)cm, labels); cm += 2;
  414.             break;
  415.             default:
  416.             *(short*)ln = *pt;
  417.             }
  418.             strcat(asmbuf, l1);
  419.         }
  420.         // make tabulation between instruction and operands
  421.         {
  422.             //                        if( !cpu.logena ) //LVD
  423.             {
  424.                 char b1[0x40], *p = asmbuf, *q = b1;
  425.                 while(*p != ' ' && *p) *q++ = *p++;
  426.                 *q++ = *p;
  427.                 if(*p)
  428.                 {
  429.                     while(q < b1 + 5) *q++ = ' '; // +5 - tab size=5, was 4
  430.                     while(*++p) *q++ = *p;
  431.                 }
  432.                 *q = 0;
  433.                 strcpy(asmbuf, b1);
  434.             }
  435.             return max(cm, cmd + *ptr);
  436.         }
  437.     nextcmd:
  438.         ptr += (2 * *ptr) + 1; while(*ptr++); // skip mask,code and instruction
  439.     }
  440.     strcpy(asmbuf, "???"); return cmd + 1;
  441. }
  442.  
  443. static int getindex(unsigned char **ptr, char *table, unsigned width, int size) {
  444.    unsigned max = 0, imax; // find max match - fdiv and fdivr must be found as fdivr
  445.    for (unsigned i = 0; i < unsigned(size); i++)
  446.    {
  447.        size_t ln = strlen(table + i * width);
  448.        if(!strncmp((char*)*ptr, table + i * width, ln))
  449.        {
  450.            if(ln > max)
  451.            {
  452.                max = unsigned(ln);
  453.                imax = i;
  454.            }
  455.        }
  456.    }
  457.    if (max) {
  458.       (*ptr) += strlen(table + imax*width);
  459.       return int(imax);
  460.    }
  461.    return -1;
  462. }
  463. static int scanhex(unsigned char **ptr) {
  464.    int r = 0, s = 1;
  465.    if(**ptr == '-')
  466.    {
  467.        (*ptr)++;
  468.        s = -1;
  469.    }
  470.    if (**ptr == '+') (*ptr)++;
  471.    while(isdigit(**ptr) || (**ptr >= 'a' && **ptr <= 'f'))
  472.    {
  473.        r = 16 * r + hexdigit(**ptr);
  474.        (*ptr)++;
  475.    }
  476.    return r*s;
  477. }
  478. static unsigned char cmdb[16];
  479. unsigned char asmresult[24];
  480. static unsigned char z80p;
  481. static unsigned char a_command[0x40];
  482.  
  483. static int z80scanr8(unsigned char **ptr, unsigned char **cm) {
  484.    int in = getindex(ptr, z80r8_1, 5, 8);
  485.    if (in >= 0) return in;
  486.    char *r8 = z80r8_1;
  487.    if (z80p == 0xDD) r8 = z80r8_2;
  488.    if (z80p == 0xFD) r8 = z80r8_3;
  489.    in = getindex(ptr, r8, 5, 8);
  490.    if (!z80p) return in;
  491.    if (*(unsigned short*)(*ptr) != WORD2('(','i')) return in;
  492.    (*ptr) += 3;
  493.    char c = char(*(*ptr - 1));
  494.    if ((z80p == 0xDD && c != 'x') || (z80p == 0xFD && c != 'y')) return -1;
  495.    int ofs = (**ptr == ')') ? 0 : scanhex(ptr);
  496.    if (ofs > 127 || ofs < -128) return -1;
  497.    if (*((*ptr)++) != ')') return -1;
  498.    *(signed char*)(*cm)++ = (signed char)ofs;
  499.    return 6;
  500. }
  501.  
  502. static unsigned assemble(unsigned addr)
  503. {
  504.    char *z80r16 = z80r16_1;
  505.    if (z80p == 0xDD) z80r16 = z80r16_2;
  506.    if (z80p == 0xFD) z80r16 = z80r16_3;
  507.  
  508.    for (unsigned char *p1 = asm_tab_z80; *p1; ) {
  509.       memset(cmdb, 0, sizeof(cmdb));
  510.       unsigned char *cc = a_command; memcpy(cmdb, p1+1, *p1);
  511.       unsigned char *cmd = cmdb;
  512.       unsigned char *rcmd = cmd;
  513.       unsigned char *cm;
  514.       if (*cmd == 0xED) { rcmd++; if (z80p) goto nextcmd; }
  515.       cm = rcmd+1;
  516.  
  517.       int in;
  518.           unsigned char *ptr; //Alone Coder
  519.       for (/*unsigned char * */ptr = p1+2 * *p1+1; *ptr; ptr++) {
  520.          switch (*ptr) {
  521.             case _zr16: // in rcmd & 0x30
  522.                if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd;
  523.                *rcmd |= (in << 4);
  524.                break;
  525.             case _zr16a: // in rcmd & 0x30
  526.                if (*(unsigned short*)cc == WORD2('a','f')) {
  527.                   cc += 2;
  528.                   in = 3;
  529.                } else {
  530.                   if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd;
  531.                }
  532.                *rcmd |= (in << 4);
  533.                break;
  534.             case _zjr: // relative jumps
  535.                if ((in = getindex(&cc, zjr, 7, 8)) < 0) goto nextcmd;
  536.                *rcmd |= (in << 3);
  537.                break;
  538.             case _zop: // z80 ops
  539.                if ((in = getindex(&cc, zop, 8, 8)) < 0) goto nextcmd;
  540.                *rcmd |= (in << 3);
  541.                break;
  542.             case _zf: // z80 flags
  543.                if ((in = getindex(&cc, zf, 3, 8)) < 0) goto nextcmd;
  544.                *rcmd |= (in << 3);
  545.                break;
  546.             case _hl: // hl/ix/iy
  547.                if ((in = getindex(&cc, z80r16, 3, 4)) != 2) goto nextcmd;
  548.                break;
  549.             case _cb: // all CB-opcodes
  550.             {
  551.                if ((in = getindex(&cc, cbtab, 7, 32)) < 0) goto nextcmd;
  552.                int in1 = getindex(&cc, z80r8_1, 5, 8);
  553.                if (!z80p) {
  554.                   if (in1 < 0) goto nextcmd;
  555.                } else {
  556.                   if (in1 < 0) {
  557.                      in1 = z80scanr8(&cc, &cm);
  558.                      if (in1 < 0) goto nextcmd;
  559.                   } else {
  560.                      if (*cc++ != ',' || z80scanr8(&cc, &cm) != 6) goto nextcmd;
  561.                   }
  562.                }
  563.                *cm++ = u8(in*8+in1);
  564.                break;
  565.             }
  566.             case _zr8: // r8 in *rcmd & 0x38
  567.             case _zr8_: // r8 in *rcmd & 0x38, in ld r8,r8
  568.                if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd;
  569.                *rcmd |= in<<3;
  570.                break;
  571.             case _zr81: // r8 in *rcmd & 7
  572.             case _zr81_: // r8 in *rcmd & 7, in ld r8,r8
  573.                if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd;
  574.                *rcmd |= in;
  575.                break;
  576.             case _ld:
  577.                if ((*(unsigned*)cc & 0xFFFFFF) != WORD4('l','d',' ',0)) goto nextcmd;
  578.                cc += 3; break;
  579.             case _shrt: // short jump
  580.             {
  581.                if (!ishex(char(*cc))) goto nextcmd;
  582.                in = scanhex(&cc);
  583.                int x = i16(in-(int)addr+cmdb-cm-1);
  584.                if (x > 0x7F || x < -0x80) goto nextcmd;
  585.                *(char*)cm = char(x); cm++;
  586.                break;
  587.             }
  588.             case _ib: // immediate byte at cm
  589.                if (*cc == '\'' && cc[2] == '\'') { in = cc[1]; cc+=3; goto imm; }
  590.                if (!ishex(char(*cc))) goto nextcmd;
  591.                in = scanhex(&cc);
  592.                if ((unsigned)in > 0xFF) goto nextcmd;
  593. imm:
  594.                *(char*)cm++ = (char)in;
  595.                break;
  596.             case _iw: // immediate word at cm
  597.                if (!ishex(char(*cc))) goto nextcmd;
  598.                in = scanhex(&cc);
  599.                if ((unsigned)in > 0xFFFF) goto nextcmd;
  600.                *(unsigned short*)cm = (unsigned short)in; cm += 2;
  601.                break;
  602.             default:
  603.                if (*ptr != *cc++) goto nextcmd;
  604.          }
  605.       }
  606.       if (!*cc) return max(unsigned(cm-cmdb), unsigned(*p1));
  607. nextcmd:
  608.       p1 += (2 * *p1) + 1; while (*p1++);
  609.    }
  610.    return 0;
  611. }
  612.  
  613. unsigned assemble_cmd(unsigned char *cmd, unsigned addr)
  614. {
  615.    unsigned char *res = a_command;
  616.    unsigned char bf[0x40]; strcpy((char*)bf, (char*)cmd);
  617.    for (res = bf; *res; res++) { // don't allow to kill space befor (# - place 0x01
  618.       if (*(short*)res == WORD2(' ','(')) *(short*)res = WORD2(1,'(');
  619.       if (*(short*)res == WORD2(' ','#')) *(short*)res = WORD2(1,'#');
  620.    }
  621.    res = a_command; cmd = bf;
  622.    while (*cmd == ' ') cmd++;
  623.    while (*cmd && *cmd != ' ') *res++ = u8(tolower(*cmd++));
  624.    while (*cmd) {
  625.       while (*cmd == ' ' && (!isalnum(cmd[1]) || !isalnum(res[-1]))) cmd++;
  626.       *res++ = (cmd[-1] == '\'') ? *cmd : u8(tolower(*cmd));
  627.       cmd++;
  628.    }
  629.    if (res[-1] == ' ') res[-1] = 0;
  630.    *res = 0;
  631.    // replace 0x01 to space again
  632.    for (res = a_command; *res; res++) if (!(*res-1)) *res = ' ';
  633.  
  634.    unsigned r;
  635.    z80p = 0;    if ((r = assemble(addr))) goto inspref1;
  636.    z80p = 0xDD; if ((r = assemble(addr))) goto inspref1;
  637.    z80p = 0xFD; if ((r = assemble(addr))) goto inspref1;
  638.    return 0;
  639. inspref1:
  640.    unsigned char *p = asmresult;
  641.    if (z80p) *p++ = z80p;
  642.    for (unsigned i=0; i < r; i++) *p++ = cmdb[i];
  643.    return r + (z80p ? 1 : 0);
  644. }
  645.