Subversion Repositories pentevo

Rev

Rev 887 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 1
#include "std.h"
2
 
3
#include "emul.h"
4
#include "vars.h"
5
#include "memory.h"
6
#include "dbglabls.h"
784 DimkaM 7
#include "z80asm.h"
716 lvd 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
 
784 DimkaM 29
static unsigned char asm_tab_z80[] =
716 lvd 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
 
247
};
248
 
249
 
250
#define abs(x) ((x)>0? (x):(-(x)))
251
 
252
// =======================================================================
784 DimkaM 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"
716 lvd 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";
784 DimkaM 263
static char zjr[] = "xxxxxx\0xxxxxx\0djnz \0\0jr \0\0\0\0jr nz,\0jr z,\0\0jr nc,\0jr c,\0";
716 lvd 264
//char zop[] = "add\0adc\0sub\0sbc\0and\0xor\0or\0\0cp"; lvd
784 DimkaM 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";
716 lvd 267
// =======================================================================
268
 
784 DimkaM 269
static void disasm_address(char *line, unsigned addr, char labels)
716 lvd 270
{
784 DimkaM 271
   char *label = nullptr;
887 lvd 272
   char *virtlabel = nullptr;
273
   if (labels&&addr)
274
   {
275
       label = mon_labels.find(am_r(addr));
276
       virtlabel = mon_labels.find(((unsigned char *)NULL)+addr);
277
   }
278
   if (virtlabel) label=virtlabel;
716 lvd 279
   if (label) {
280
           //strcpy(line, label);
281
                int i;
282
                for (i=0;(i<20)&&label[i];i++)line[i]=label[i];
283
                line[i]=label[i];
284
   } //Alone Coder 0.36.6
285
   else sprintf(line, "%04X", addr & 0xFFFF);
286
}
287
 
784 DimkaM 288
const unsigned char *disasm(const unsigned char *cmd, unsigned current, char labels)
716 lvd 289
{
784 DimkaM 290
    const unsigned char *st = cmd;
291
    unsigned char z80p;
292
    char *z80r16, *z80r8;
716 lvd 293
 
784 DimkaM 294
    z80r16 = z80r16_1;
295
    z80r8 = z80r8_1;
296
    z80p = 0;
297
    for(;;)
298
    { // z80 prefixes
299
        if(*cmd == 0xDD)
300
        {
301
            z80r16 = z80r16_2;
302
            z80r8 = z80r8_2;
303
            z80p = 0xDD;
304
        }
305
        else if(*cmd == 0xFD)
306
        {
307
            z80r16 = z80r16_3;
308
            z80r8 = z80r8_3; z80p = 0xFD;
309
        }
310
        else break;
311
        cmd++;
312
    }
716 lvd 313
 
784 DimkaM 314
    for(unsigned char *ptr = asm_tab_z80; *ptr; )
315
    {
316
        // cmd - start of command, c1 - mod/rm, cm - current pointer
317
        const unsigned char *rcmd = cmd;
318
        if(*cmd == 0xED)
319
        {
320
            rcmd++;
321
            z80r16 = z80r16_1;
322
            z80r8 = z80r8_1;
323
            z80p = 0;
324
        }
325
        const unsigned char *cm = rcmd + 1;
716 lvd 326
 
784 DimkaM 327
        for(int j = 0; j < *ptr; j++) // match mask
328
            if((cmd[j] & ptr[j + *ptr + 1]) != ptr[j + 1]) goto nextcmd;
329
        *asmbuf = 0;
330
        unsigned char *pt;
331
        for(pt = ptr + (2 * *ptr) + 1; *pt; pt++)
332
        { // scan all commands
333
            char ln[/*32*/64];
334
            const char *l1 = ln;
335
            ln[0] = 0; //Alone Coder 0.36.6
336
            switch(*pt)
337
            {
716 lvd 338
            case _zr16: // in rcmd & 0x30
784 DimkaM 339
            l1 = z80r16 + 3 * ((*rcmd >> 4) & 3);
340
            break;
716 lvd 341
            case _zr16a: // in rcmd & 0x30
784 DimkaM 342
            if(((*rcmd >> 4) & 3) == 3) l1 = "af";
343
            else l1 = z80r16 + 3 * ((*rcmd >> 4) & 3);
344
            break;
716 lvd 345
            case _hl: // hl/ix/iy
784 DimkaM 346
            l1 = z80r16 + 3 * 2;
347
            break;
716 lvd 348
            case _zjr: // relative jumps
784 DimkaM 349
            l1 = zjr + 7 * ((*rcmd >> 3) & 7);
350
            break;
716 lvd 351
            case _zop: // z80 operations at rcmd & 0x38
352
               //l1 = zop+4*((*rcmd>>3)&7); lvd
784 DimkaM 353
            l1 = zop + 8 * ((*rcmd >> 3) & 7);
354
            break;
716 lvd 355
            case _zf: // z80 flags at rcmd & 0x38
784 DimkaM 356
            l1 = zf + 3 * ((*rcmd >> 3) & 7);
357
            break;
716 lvd 358
            case _cb: // all CB-opcodes
359
            {
784 DimkaM 360
                if(!z80p)
361
                {
362
                    sprintf(ln, "%s%s", cbtab + (*cm >> 3) * 7, z80r8_1 + (*cm & 7) * 5);
363
                    cm++;
364
                }
365
                else
366
                {
367
                    if((cm[1] & 7) != 6 && ((cm[1] & 0xC0) != 0x40)) // operand is reg,(ix+nn)
368
                        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));
369
                    else // only (ix+nn)
370
                        sprintf(ln, "%s(i%c%c%02X)", cbtab + (cm[1] >> 3) * 7, z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
371
                    cm += 2;
372
                }
373
                break;
716 lvd 374
            }
375
            case _zr8: // in rcmd & 0x38
784 DimkaM 376
            if(z80p && ((*rcmd & 0x38) == 0x30))
377
            {
378
                sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
379
                cm++;
380
            }
381
            else l1 = z80r8 + 5 * ((*rcmd >> 3) & 7);
382
            break;
716 lvd 383
            case _zr8_: // in rcmd & 0x38, in ld r8,r8
784 DimkaM 384
            if(!z80p || (*rcmd & 7) == 6) { l1 = z80r8_1 + 5 * ((*rcmd >> 3) & 7); break; }
385
            if((*rcmd & 0x38) == 0x30)
386
            {
387
                sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
388
                cm++;
389
            }
390
            else l1 = z80r8 + 5 * ((*rcmd >> 3) & 7);
391
            break;
716 lvd 392
            case _zr81: // in rcmd & 7
784 DimkaM 393
            if(z80p && (*rcmd & 7) == 6)
394
            {
395
                sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
396
                cm++;
397
            }
398
            else l1 = z80r8 + 5 * (*rcmd & 7);
399
            break;
716 lvd 400
            case _zr81_: // in rcmd & 7, in ld r8,r8
784 DimkaM 401
            if(!z80p || ((*rcmd & 0x38) == 0x30)) { l1 = z80r8_1 + 5 * (*rcmd & 7); break; }
402
            if((*rcmd & 7) == 6)
403
            {
404
                sprintf(ln, "(i%c%c%02X)", z80p == 0xDD ? 'x' : 'y', *(char*)cm >= 0 ? '+' : '-', abs(*(char*)cm));
405
                cm++;
406
            }
407
            else l1 = z80r8 + 5 * (*rcmd & 7);
408
            break;
716 lvd 409
            case _ld:
784 DimkaM 410
            l1 = "ld "; break;
716 lvd 411
            case _shrt: // short jump
784 DimkaM 412
            disasm_address(ln, unsigned(current + cm - st + *(signed char*)cm + 1), labels);
413
            cm++;
414
            break;
716 lvd 415
            case _ib: // immediate byte at cm
784 DimkaM 416
            sprintf(ln, "%02X", *cm++);
417
            break;
716 lvd 418
            case _iw: // immediate word at cm
784 DimkaM 419
            disasm_address(ln, *(unsigned short*)cm, labels); cm += 2;
420
            break;
716 lvd 421
            default:
784 DimkaM 422
            *(short*)ln = *pt;
423
            }
424
            strcat(asmbuf, l1);
425
        }
426
        // make tabulation between instruction and operands
427
        {
428
            //                        if( !cpu.logena ) //LVD
429
            {
430
                char b1[0x40], *p = asmbuf, *q = b1;
431
                while(*p != ' ' && *p) *q++ = *p++;
432
                *q++ = *p;
433
                if(*p)
434
                {
435
                    while(q < b1 + 5) *q++ = ' '; // +5 - tab size=5, was 4
436
                    while(*++p) *q++ = *p;
437
                }
438
                *q = 0;
439
                strcpy(asmbuf, b1);
440
            }
441
            return max(cm, cmd + *ptr);
442
        }
443
    nextcmd:
444
        ptr += (2 * *ptr) + 1; while(*ptr++); // skip mask,code and instruction
445
    }
446
    strcpy(asmbuf, "???"); return cmd + 1;
716 lvd 447
}
448
 
784 DimkaM 449
static int getindex(unsigned char **ptr, char *table, unsigned width, int size) {
450
   unsigned max = 0, imax; // find max match - fdiv and fdivr must be found as fdivr
451
   for (unsigned i = 0; i < unsigned(size); i++)
452
   {
453
       size_t ln = strlen(table + i * width);
454
       if(!strncmp((char*)*ptr, table + i * width, ln))
455
       {
456
           if(ln > max)
457
           {
458
               max = unsigned(ln);
459
               imax = i;
460
           }
461
       }
716 lvd 462
   }
463
   if (max) {
464
      (*ptr) += strlen(table + imax*width);
784 DimkaM 465
      return int(imax);
716 lvd 466
   }
467
   return -1;
468
}
784 DimkaM 469
static int scanhex(unsigned char **ptr) {
716 lvd 470
   int r = 0, s = 1;
784 DimkaM 471
   if(**ptr == '-')
472
   {
473
       (*ptr)++;
474
       s = -1;
475
   }
716 lvd 476
   if (**ptr == '+') (*ptr)++;
784 DimkaM 477
   while(isdigit(**ptr) || (**ptr >= 'a' && **ptr <= 'f'))
478
   {
479
       r = 16 * r + hexdigit(**ptr);
480
       (*ptr)++;
481
   }
716 lvd 482
   return r*s;
483
}
784 DimkaM 484
static unsigned char cmdb[16];
716 lvd 485
unsigned char asmresult[24];
784 DimkaM 486
static unsigned char z80p;
487
static unsigned char a_command[0x40];
716 lvd 488
 
784 DimkaM 489
static int z80scanr8(unsigned char **ptr, unsigned char **cm) {
716 lvd 490
   int in = getindex(ptr, z80r8_1, 5, 8);
491
   if (in >= 0) return in;
492
   char *r8 = z80r8_1;
493
   if (z80p == 0xDD) r8 = z80r8_2;
494
   if (z80p == 0xFD) r8 = z80r8_3;
495
   in = getindex(ptr, r8, 5, 8);
496
   if (!z80p) return in;
497
   if (*(unsigned short*)(*ptr) != WORD2('(','i')) return in;
498
   (*ptr) += 3;
784 DimkaM 499
   char c = char(*(*ptr - 1));
716 lvd 500
   if ((z80p == 0xDD && c != 'x') || (z80p == 0xFD && c != 'y')) return -1;
501
   int ofs = (**ptr == ')') ? 0 : scanhex(ptr);
502
   if (ofs > 127 || ofs < -128) return -1;
503
   if (*((*ptr)++) != ')') return -1;
504
   *(signed char*)(*cm)++ = (signed char)ofs;
505
   return 6;
506
}
507
 
784 DimkaM 508
static unsigned assemble(unsigned addr)
716 lvd 509
{
510
   char *z80r16 = z80r16_1;
511
   if (z80p == 0xDD) z80r16 = z80r16_2;
512
   if (z80p == 0xFD) z80r16 = z80r16_3;
513
 
514
   for (unsigned char *p1 = asm_tab_z80; *p1; ) {
515
      memset(cmdb, 0, sizeof(cmdb));
516
      unsigned char *cc = a_command; memcpy(cmdb, p1+1, *p1);
517
      unsigned char *cmd = cmdb;
518
      unsigned char *rcmd = cmd;
519
      unsigned char *cm;
520
      if (*cmd == 0xED) { rcmd++; if (z80p) goto nextcmd; }
521
      cm = rcmd+1;
522
 
523
      int in;
524
          unsigned char *ptr; //Alone Coder
525
      for (/*unsigned char * */ptr = p1+2 * *p1+1; *ptr; ptr++) {
526
         switch (*ptr) {
527
            case _zr16: // in rcmd & 0x30
528
               if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd;
529
               *rcmd |= (in << 4);
530
               break;
531
            case _zr16a: // in rcmd & 0x30
532
               if (*(unsigned short*)cc == WORD2('a','f')) {
533
                  cc += 2;
534
                  in = 3;
535
               } else {
536
                  if ((in = getindex(&cc, z80r16, 3, 4)) < 0) goto nextcmd;
537
               }
538
               *rcmd |= (in << 4);
539
               break;
540
            case _zjr: // relative jumps
541
               if ((in = getindex(&cc, zjr, 7, 8)) < 0) goto nextcmd;
542
               *rcmd |= (in << 3);
543
               break;
544
            case _zop: // z80 ops
545
               if ((in = getindex(&cc, zop, 8, 8)) < 0) goto nextcmd;
546
               *rcmd |= (in << 3);
547
               break;
548
            case _zf: // z80 flags
549
               if ((in = getindex(&cc, zf, 3, 8)) < 0) goto nextcmd;
550
               *rcmd |= (in << 3);
551
               break;
552
            case _hl: // hl/ix/iy
553
               if ((in = getindex(&cc, z80r16, 3, 4)) != 2) goto nextcmd;
554
               break;
555
            case _cb: // all CB-opcodes
556
            {
557
               if ((in = getindex(&cc, cbtab, 7, 32)) < 0) goto nextcmd;
558
               int in1 = getindex(&cc, z80r8_1, 5, 8);
559
               if (!z80p) {
560
                  if (in1 < 0) goto nextcmd;
561
               } else {
562
                  if (in1 < 0) {
563
                     in1 = z80scanr8(&cc, &cm);
564
                     if (in1 < 0) goto nextcmd;
565
                  } else {
566
                     if (*cc++ != ',' || z80scanr8(&cc, &cm) != 6) goto nextcmd;
567
                  }
568
               }
784 DimkaM 569
               *cm++ = u8(in*8+in1);
716 lvd 570
               break;
571
            }
572
            case _zr8: // r8 in *rcmd & 0x38
573
            case _zr8_: // r8 in *rcmd & 0x38, in ld r8,r8
574
               if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd;
575
               *rcmd |= in<<3;
576
               break;
577
            case _zr81: // r8 in *rcmd & 7
578
            case _zr81_: // r8 in *rcmd & 7, in ld r8,r8
579
               if ((in = z80scanr8(&cc, &cm)) < 0) goto nextcmd;
580
               *rcmd |= in;
581
               break;
582
            case _ld:
583
               if ((*(unsigned*)cc & 0xFFFFFF) != WORD4('l','d',' ',0)) goto nextcmd;
584
               cc += 3; break;
585
            case _shrt: // short jump
586
            {
784 DimkaM 587
               if (!ishex(char(*cc))) goto nextcmd;
716 lvd 588
               in = scanhex(&cc);
589
               int x = i16(in-(int)addr+cmdb-cm-1);
590
               if (x > 0x7F || x < -0x80) goto nextcmd;
784 DimkaM 591
               *(char*)cm = char(x); cm++;
716 lvd 592
               break;
593
            }
594
            case _ib: // immediate byte at cm
595
               if (*cc == '\'' && cc[2] == '\'') { in = cc[1]; cc+=3; goto imm; }
784 DimkaM 596
               if (!ishex(char(*cc))) goto nextcmd;
716 lvd 597
               in = scanhex(&cc);
598
               if ((unsigned)in > 0xFF) goto nextcmd;
599
imm:
600
               *(char*)cm++ = (char)in;
601
               break;
602
            case _iw: // immediate word at cm
784 DimkaM 603
               if (!ishex(char(*cc))) goto nextcmd;
716 lvd 604
               in = scanhex(&cc);
605
               if ((unsigned)in > 0xFFFF) goto nextcmd;
606
               *(unsigned short*)cm = (unsigned short)in; cm += 2;
607
               break;
608
            default:
609
               if (*ptr != *cc++) goto nextcmd;
610
         }
611
      }
612
      if (!*cc) return max(unsigned(cm-cmdb), unsigned(*p1));
613
nextcmd:
614
      p1 += (2 * *p1) + 1; while (*p1++);
615
   }
616
   return 0;
617
}
618
 
784 DimkaM 619
unsigned assemble_cmd(unsigned char *cmd, unsigned addr)
716 lvd 620
{
621
   unsigned char *res = a_command;
622
   unsigned char bf[0x40]; strcpy((char*)bf, (char*)cmd);
623
   for (res = bf; *res; res++) { // don't allow to kill space befor (# - place 0x01
624
      if (*(short*)res == WORD2(' ','(')) *(short*)res = WORD2(1,'(');
625
      if (*(short*)res == WORD2(' ','#')) *(short*)res = WORD2(1,'#');
626
   }
627
   res = a_command; cmd = bf;
628
   while (*cmd == ' ') cmd++;
784 DimkaM 629
   while (*cmd && *cmd != ' ') *res++ = u8(tolower(*cmd++));
716 lvd 630
   while (*cmd) {
631
      while (*cmd == ' ' && (!isalnum(cmd[1]) || !isalnum(res[-1]))) cmd++;
784 DimkaM 632
      *res++ = (cmd[-1] == '\'') ? *cmd : u8(tolower(*cmd));
716 lvd 633
      cmd++;
634
   }
635
   if (res[-1] == ' ') res[-1] = 0;
636
   *res = 0;
637
   // replace 0x01 to space again
638
   for (res = a_command; *res; res++) if (!(*res-1)) *res = ' ';
639
 
640
   unsigned r;
641
   z80p = 0;    if ((r = assemble(addr))) goto inspref1;
642
   z80p = 0xDD; if ((r = assemble(addr))) goto inspref1;
643
   z80p = 0xFD; if ((r = assemble(addr))) goto inspref1;
644
   return 0;
645
inspref1:
646
   unsigned char *p = asmresult;
647
   if (z80p) *p++ = z80p;
648
   for (unsigned i=0; i < r; i++) *p++ = cmdb[i];
649
   return r + (z80p ? 1 : 0);
650
}