Subversion Repositories pentevo

Rev

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