]> Shamusworld >> Repos - rmac/blob - procln.c
Version bump for last commit. :-)
[rmac] / procln.c
1 //
2 // RMAC - Renamed Macro Assembler for all Atari computers
3 // PROCLN.C - Line Processing
4 // Copyright (C) 199x Landon Dyer, 2011-2022 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
7 //
8
9 #include "procln.h"
10 #include "6502.h"
11 #include "amode.h"
12 #include "direct.h"
13 #include "dsp56k_amode.h"
14 #include "dsp56k_mach.h"
15 #include "error.h"
16 #include "expr.h"
17 #include "listing.h"
18 #include "mach.h"
19 #include "macro.h"
20 #include "op.h"
21 #include "riscasm.h"
22 #include "sect.h"
23 #include "symbol.h"
24
25 #define DEF_KW                                  // Declare keyword values
26 #include "kwtab.h"                              // Incl generated keyword tables & defs
27
28 #define DEF_MN                                  // Incl 68k keyword definitions
29 #define DECL_MN                                 // Incl 68k keyword state machine tables
30 #include "mntab.h"
31 #define DEF_REG68                               // Incl 68k register definitions
32 #include "68kregs.h"
33
34 #define DEF_MR
35 #define DECL_MR
36 #include "risckw.h"
37
38 #define DEF_MP                                  // Include 6502 keyword definitions
39 #define DECL_MP                                 // Include 6502 keyword state machine tables
40 #include "6502kw.h"
41
42 #define DEF_MO                                  // Include OP keyword definitions
43 #define DECL_MO                                 // Include OP keyword state machine tables
44 #include "opkw.h"
45
46 #define DEF_DSP                                 // Include DSP56K keywords definitions
47 #define DECL_DSP                                // Include DSP56K keyword state machine tables
48 #include "dsp56kkw.h"
49 #define DEF_REG56                               // Include DSP56K register definitions
50 #include "56kregs.h"
51
52 IFENT * ifent;                                  // Current ifent
53 static IFENT ifent0;                    // Root ifent
54 IFENT * f_ifent;                                // Freelist of ifents
55 int disabled;                                   // Assembly conditionally disabled
56 int just_bss;                                   // 1, ds.b in microprocessor mode
57 uint32_t pcloc;                                 // Value of "PC" at beginning of line
58 SYM * lab_sym;                                  // Label on line (or NULL)
59 char * label_defined;                   // The name of the last label defined in current line (if any)
60
61 const char extra_stuff[] = "extra (unexpected) text found after addressing mode";
62 const char comma_error[] = "missing comma";
63 const char syntax_error[] = "syntax error";
64 const char locgl_error[] = "cannot GLOBL local symbol";
65 const char lab_ignored[] = "label ignored";
66
67 // Table to convert an addressing-mode number to a bitmask.
68 LONG amsktab[0124] = {
69         M_DREG, M_DREG, M_DREG, M_DREG,
70         M_DREG, M_DREG, M_DREG, M_DREG,
71
72         M_AREG, M_AREG, M_AREG, M_AREG,
73         M_AREG, M_AREG, M_AREG, M_AREG,
74
75         M_AIND, M_AIND, M_AIND, M_AIND,
76         M_AIND, M_AIND, M_AIND, M_AIND,
77
78         M_APOSTINC, M_APOSTINC, M_APOSTINC, M_APOSTINC,
79         M_APOSTINC, M_APOSTINC, M_APOSTINC, M_APOSTINC,
80
81         M_APREDEC, M_APREDEC, M_APREDEC, M_APREDEC,
82         M_APREDEC, M_APREDEC, M_APREDEC, M_APREDEC,
83
84         M_ADISP, M_ADISP, M_ADISP, M_ADISP,
85         M_ADISP, M_ADISP, M_ADISP, M_ADISP,
86
87         M_AINDEXED, M_AINDEXED, M_AINDEXED, M_AINDEXED,
88         M_AINDEXED, M_AINDEXED, M_AINDEXED, M_AINDEXED,
89
90         M_ABSW,                 // 070
91         M_ABSL,                 // 071
92         M_PCDISP,               // 072
93         M_PCINDEXED,    // 073
94         M_IMMED,                // 074
95         0L,                             // 075
96         0L,                             // 076
97         0L,                             // 077
98         M_ABASE,                // 0100
99         M_MEMPOST,              // 0101
100         M_MEMPRE,               // 0102
101         M_PCBASE,               // 0103
102         M_PCMPOST,              // 0104
103         M_PCMPRE,               // 0105
104         M_AM_USP,               // 0106
105         M_AM_SR,                // 0107
106         M_AM_CCR,               // 0110
107         M_AM_NONE,              // 0111
108         0x30,                   // 0112
109         0x30,                   // 0113
110         0L,                             // 0114
111         0L,                             // 0115
112         0L,                             // 0116
113         0L,                             // 0117
114         M_CACHE40,              // 0120
115         M_CREG,                 // 0121
116         M_FREG,                 // 0122
117         M_FPSCR                 // 0123
118 };                                      // 0123 length
119
120 // Function prototypes
121 int HandleLabel(char *, int);
122
123 //
124 // Initialize line processor
125 //
126 void InitLineProcessor(void)
127 {
128         disabled = 0;
129         ifent = &ifent0;
130         f_ifent = ifent0.if_prev = NULL;
131         ifent0.if_state = 0;
132 }
133
134 //
135 // Line processor
136 //
137 void Assemble(void)
138 {
139         int state;                                      // Keyword machine state (output)
140         int j;                                          // Random int, must be fast
141         char * p;                                       // Random char ptr, must be fast
142         TOKEN * tk;                                     // First token in line
143         char * label;                           // Symbol (or NULL)
144         char * equate;                          // Symbol (or NULL)
145         int labtyp = 0;                         // Label type (':', DCOLON)
146         int equtyp = 0;                         // Equ type ('=', DEQUALS)
147         uint64_t eval;                          // Expression value
148         WORD eattr;                                     // Expression attributes
149         SYM * esym;                                     // External symbol involved in expr.
150         WORD siz = 0;                           // Size suffix to mnem/diretve/macro
151         LONG amsk0, amsk1;                      // Address-type masks for ea0, ea1
152         MNTAB * m;                                      // Code generation table pointer
153         SYM * sy, * sy2;                        // Symbol (temp usage)
154         char * opname = NULL;           // Name of dirctve/mnemonic/macro
155         int listflag;                           // 0: Don't call listeol()
156         WORD rmask;                                     // Register list, for REG
157         int equreg;                             // RISC register
158         listflag = 0;                           // Initialise listing flag
159
160 loop:                                                   // Line processing loop label
161
162         // Get another line of tokens
163         if (TokenizeLine() == TKEOF)
164         {
165 DEBUG { printf("Assemble: Found TKEOF flag...\n"); }
166                 if (list_flag && listflag)                      // Flush last line of source
167                         listeol();
168
169                 if (ifent->if_prev != NULL)                     // Check conditional token
170                         error("hit EOF without finding matching .endif");
171
172                 return;
173         }
174
175         DEBUG { DumpTokenBuffer(); }
176
177         if (list_flag)
178         {
179                 if (listflag && listing > 0)
180                         listeol();                                              // Tell listing generator about EOL
181
182                 lstout((char)(disabled ? '-' : lntag)); // Prepare new line for listing
183                 listflag = 1;                                           // OK to call `listeol' now
184                 just_bss = 0;                                           // Reset just_bss mode
185         }
186
187         state = -3;                                                             // No keyword (just EOL)
188         label = NULL;                                                   // No label
189         label_defined = NULL;                                   // No label defined yet
190         lab_sym = NULL;                                                 // No (exported) label
191         equate = NULL;                                                  // No equate
192         tk = tok;                                                               // Save first token in line
193         pcloc = (uint32_t)sloc;                                 // Set beginning-of-line PC
194
195 loop1:                                                                          // Internal line processing loop
196
197         if (*tok == EOL)                                                // Restart loop if end-of-line
198                 goto loop;
199
200         // First token MUST be a symbol (Shamus: not sure why :-/)
201         if (*tok != SYMBOL)
202         {
203                 error("syntax error; expected symbol");
204
205                 goto loop;
206         }
207
208         j = (int)tok[2];                                                // Skip equates (normal statements)
209
210         if (j == '=' || j == DEQUALS || j == SET || j == REG || j == EQUREG || j == CCDEF)
211         {
212                 equate = string[tok[1]];
213                 equtyp = j;
214                 tok += 3;
215                 goto normal;
216         }
217
218         // Skip past label (but record it)
219         if (j == ':' || j == DCOLON)
220         {
221                 label = string[tok[1]];                         // Get label name
222                 labtyp = tok[2];                                        // Get label type
223                 tok += 3;                                                       // Go to next line token
224         }
225
226         // EOL is legal here...
227         if (*tok == EOL)
228                 goto normal;
229
230         // First token MUST be a symbol (if we get here, tok didn't advance)
231         if (*tok++ != SYMBOL)
232         {
233                 error("syntax error; expected symbol");
234                 goto loop;
235         }
236
237         opname = p = string[*tok++];
238
239         // Check to see if the SYMBOL is a keyword (a mnemonic or directive).
240         // On output, `state' will have one of the values:
241         //    -3          there was no symbol (EOL)
242         //    -2..-1      the symbol didn't match any keyword
243         //    0..499      vanilla directives (dc, ds, etc.)
244         //    500..999    electric directives (macro, rept, etc.)
245         //    1000..+     mnemonics (move, lsr, etc.)
246         for(state=0; state>=0;)
247         {
248                 j = mnbase[state] + (int)tolowertab[*p];
249
250                 // Reject, character doesn't match
251                 if (mncheck[j] != state)
252                 {
253                         state = -1;                                             // No match
254                         break;
255                 }
256
257                 // Must accept or reject at EOS
258                 if (!*++p)
259                 {
260                         state = mnaccept[j];                    // (-1 on no terminal match)
261                         break;
262                 }
263
264                 state = mntab[j];
265         }
266
267         // Check for ".b" ".w" ".l" after directive, macro or mnemonic.
268         siz = SIZN;
269
270         switch (*tok)
271         {
272         case DOTW: siz = SIZW, tok++; break;
273         case DOTL: siz = SIZL, tok++; break;
274         case DOTB: siz = SIZB, tok++; break;
275         case DOTD: siz = SIZD, tok++; break;
276         case DOTP: siz = SIZP, tok++; break;
277         case DOTQ: siz = SIZQ, tok++; break;
278         case DOTS: siz = SIZS, tok++; break;
279         case DOTX: siz = SIZX, tok++; break;
280         }
281
282         // Do special directives (500..999) (These must be handled in "real time")
283         if (state >= 500 && state < 1000)
284         {
285                 switch (state)
286                 {
287                 case MN_IF:
288                         d_if();
289                         goto loop;
290
291                 case MN_ELSE:
292                         d_else();
293                         goto loop;
294
295                 case MN_ENDIF:
296                         d_endif();
297                         goto loop;
298
299                 case MN_IIF:                                            // .iif --- immediate if
300                         if (disabled || expr(exprbuf, &eval, &eattr, &esym) != OK)
301                                 goto loop;
302
303                         if (!(eattr & DEFINED))
304                         {
305                                 error(undef_error);
306                                 goto loop;
307                         }
308
309                         if (*tok++ != ',')
310                         {
311                                 error(comma_error);
312                                 goto loop;
313                         }
314
315                         if (eval == 0)
316                                 goto loop;
317
318                         goto loop1;
319
320                 case MN_MACRO:                                          // .macro --- macro definition
321                         if (!disabled)
322                         {
323                                 // Label on a macro definition is bad mojo... Warn the user
324                                 if (label != NULL)
325                                         warn(lab_ignored);
326
327                                 DefineMacro();
328                         }
329
330                         goto loop;
331
332                 case MN_EXITM:                                          // .exitm --- exit macro
333                 case MN_ENDM:                                           // .endm --- same as .exitm
334                         if (!disabled)
335                         {
336                                 if (label != NULL)
337                                         warn(lab_ignored);
338
339                                 ExitMacro();
340                         }
341
342                         goto loop;
343
344                 case MN_REPT:
345                         if (!disabled)
346                         {
347                                 // Handle labels on REPT directive lines...
348                                 if (label)
349                                 {
350                                         if (HandleLabel(label, labtyp) != 0)
351                                                 goto loop;
352
353                                         label_defined = label;
354                                 }
355
356                                 HandleRept();
357                         }
358
359                         goto loop;
360
361                 case MN_ENDR:
362                         if (!disabled)
363                                 error("mis-nested .endr");
364
365                         goto loop;
366                 }
367         }
368
369 normal:
370         if (disabled)                                                   // Conditionally disabled code
371                 goto loop;
372
373         // Do equates
374         if (equate != NULL)
375         {
376                 // Pick global or local symbol enviroment
377                 j = (*equate == '.' ? curenv : 0);
378                 sy = lookup(equate, LABEL, j);
379
380                 if (sy == NULL)
381                 {
382                         sy = NewSymbol(equate, LABEL, j);
383                         sy->sattr = 0;
384
385                         if (equtyp == DEQUALS)
386                         {
387                                 // Can't GLOBAL a local symbol
388                                 if (j)
389                                 {
390                                         error(locgl_error);
391                                         goto loop;
392                                 }
393
394                                 sy->sattr = GLOBAL;
395                         }
396                 }
397                 else if ((sy->sattr & DEFINED) && equtyp != SET)
398                 {
399                         if ((equtyp == EQUREG) && (sy->sattre & UNDEF_EQUR))
400                         {
401                                 sy->sattre &= ~UNDEF_EQUR;
402                                 sy->svalue = 0;
403                         }
404                         else if ((equtyp == CCDEF) && (sy->sattre & UNDEF_CC))
405                         {
406                                 sy->sattre &= ~UNDEF_CC;
407                                 sy->svalue = 0;
408                         }
409                         else
410                         {
411                                 error("multiple equate to '%s'", sy->sname);
412                                 goto loop;
413                         }
414                 }
415
416                 // Put symbol in "order of definition" list if it's not already there
417                 AddToSymbolDeclarationList(sy);
418
419                 // Parse value to equate symbol to;
420                 // o  .equr
421                 // o  .reg
422                 // o  everything else
423                 if (equtyp == EQUREG)
424                 {
425 //Linko's request to issue a warning on labels that equated to the same
426 //register would go here. Not sure how to implement it though. :-/
427 /*
428 Maybe like this way:
429 have an array of bools with 64 entries. Whenever a register is equated, set the
430 corresponding register bool to true. Whenever it's undef'ed, set it to false.
431 When checking to see if it's already been equated, issue a warning.
432 */
433
434                         // Check for register to equate to
435                         // This check will change once we split the registers per architecture into their own tables
436                         // and out of kw.tab. But for now it'll do...
437                         if ((*tok >= REG68_D0) && (*tok <= REG56_BA))
438                         {
439                                 sy->sattre = EQUATEDREG;        // Mark as equated register
440                                 equreg = *tok;
441                                 // Check for ",<bank #>" override notation and skip past it.
442                                 // It is ignored now. Was that ever useful anyway?
443                                 if ((rgpu ||rdsp) && (tok[1] == ',') && (tok[2] == CONST))
444                                 {
445                                         // Advance token pointer and skip everything
446                                         tok += 4;
447                                 }
448
449                                 eattr = ABS | DEFINED | GLOBAL;
450                                 eval = equreg;
451                                 tok++;
452                         }
453                         // Checking for a register symbol
454                         else if (tok[0] == SYMBOL)
455                         {
456                                 sy2 = lookup(string[tok[1]], LABEL, j);
457
458                                 // Make sure symbol is a valid equreg
459                                 if (!sy2 || !(sy2->sattre & EQUATEDREG))
460                                 {
461                                         error("invalid .equr/.regequ definition");
462                                         goto loop;
463                                 }
464                                 else
465                                 {
466                                         eattr = ABS | DEFINED | GLOBAL; // Copy symbol's attributes
467                                         sy->sattre = sy2->sattre;
468                                         eval = (sy2->svalue & 0xFFFFF0FF);
469                                         tok += 2;
470                                 }
471                         }
472                         else
473                         {
474                                 error("invalid .equr/.regequ definition");
475                                 goto loop;
476                         }
477                 }
478                 else if (equtyp == REG)
479                 {
480                         if (reglist(&rmask) < 0)
481                                 goto loop;
482
483                         eval = (uint32_t)rmask;
484                         eattr = ABS | DEFINED;
485                 }
486                 else if (equtyp == CCDEF)
487                 {
488                         sy->sattre |= EQUATEDCC;
489                         eattr = ABS | DEFINED | GLOBAL;
490
491                         if (tok[0] == SYMBOL)
492                         {
493                                 sy2 = lookup(string[tok[1]], LABEL, j);
494
495                                 if (!sy2 || !(sy2->sattre & EQUATEDCC))
496                                 {
497                                         error("invalid gpu/dsp .ccdef definition");
498                                         goto loop;
499                                 }
500                                 else
501                                 {
502                                         eattr = ABS | DEFINED | GLOBAL;
503                                         sy->sattre = sy2->sattre;
504                                         eval = sy2->svalue;
505                                         tok += 2;
506                                 }
507                         }
508                         else if (expr(exprbuf, &eval, &eattr, &esym) != OK)
509                                 goto loop;
510                 }
511                 // equ an equr
512                 else if (*tok == SYMBOL)
513                 {
514                         sy2 = lookup(string[tok[1]], LABEL, j);
515
516                         if (sy2 && (sy2->sattre & EQUATEDREG))
517                         {
518                                 sy->stype = sy2->stype;
519                                 sy->sattr = sy2->sattr;
520                                 sy->sattre = sy2->sattre;
521                                 sy->svalue = sy2->svalue;
522                                 goto loop;
523                         }
524                         else if (expr(exprbuf, &eval, &eattr, &esym) != OK)
525                                 goto loop;
526                 }
527                 else if (expr(exprbuf, &eval, &eattr, &esym) != OK)
528                         goto loop;
529
530                 if (!(eattr & DEFINED))
531                 {
532                         error(undef_error);
533                         goto loop;
534                 }
535
536                 sy->sattr |= eattr | EQUATED;   // Symbol inherits value and attributes
537                 sy->svalue = eval;
538
539                 if (list_flag)                                  // Put value in listing
540                         listvalue((uint32_t)eval);
541
542                 ErrorIfNotAtEOL();                              // Must be at EOL now
543                 goto loop;
544         }
545
546         // Do labels
547         if (label != NULL)
548         {
549                 // Non-zero == error occurred
550                 if (HandleLabel(label, labtyp) != 0)
551                         goto loop;
552
553                 label_defined = label;
554         }
555
556         // Punt on EOL
557         if (state == -3)
558                 goto loop;
559
560         // If we're in 6502 mode and are still in need of a mnemonic, then search
561         // for valid 6502 mnemonic.
562         if (m6502 && (state < 0 || state >= 1000))
563         {
564 #ifdef ST
565                 state = kmatch(opname, mpbase, mpcheck, mptab, mpaccept);
566 #else
567                 for(state=0, p=opname; state>= 0; )
568                 {
569                         j = mpbase[state] + tolowertab[*p];
570
571                         if (mpcheck[j] != state)        // Reject, character doesn't match
572                         {
573                                 state = -1;             // No match
574                                 break;
575                         }
576
577                         if (!*++p)
578                         {                       // Must accept or reject at EOS
579                                 state = mpaccept[j];    // (-1 on no terminal match)
580                                 break;
581                         }
582
583                         state = mptab[j];
584                 }
585 #endif
586
587                 // Call 6502 code generator if we found a mnemonic
588                 if (state >= 2000)
589                 {
590                         m6502cg(state - 2000);
591                         goto loop;
592                 }
593         }
594
595         // If we are in GPU or DSP mode and still in need of a mnemonic then search
596         // for one
597         if ((rgpu || rdsp) && (state < 0 || state >= 1000))
598         {
599                 for(state=0, p=opname; state>=0;)
600                 {
601                         j = mrbase[state] + (int)tolowertab[*p];
602
603                         // Reject, character doesn't match
604                         if (mrcheck[j] != state)
605                         {
606                                 state = -1;                                     // No match
607                                 break;
608                         }
609
610                         // Must accept or reject at EOS
611                         if (!*++p)
612                         {
613                                 state = mraccept[j];            // (-1 on no terminal match)
614                                 break;
615                         }
616
617                         state = mrtab[j];
618                 }
619
620                 // Call RISC code generator if we found a mnemonic
621                 if (state >= 3000)
622                 {
623                         GenerateRISCCode(state);
624                         goto loop;
625                 }
626         }
627
628         // If we are in OP mode and still in need of a mnemonic then search for one
629         if (robjproc && ((state < 0) || (state >= 1000)))
630         {
631                 for(state=0, p=opname; state>=0;)
632                 {
633                         j = mobase[state] + (int)tolowertab[*p];
634
635                         // Reject, character doesn't match
636                         if (mocheck[j] != state)
637                         {
638                                 state = -1;                                     // No match
639                                 break;
640                         }
641
642                         // Must accept or reject at EOS
643                         if (!*++p)
644                         {
645                                 state = moaccept[j];            // (-1 on no terminal match)
646                                 break;
647                         }
648
649                         state = motab[j];
650                 }
651
652                 // Call OP code generator if we found a mnemonic
653                 if (state >= 3100)
654                 {
655                         GenerateOPCode(state);
656                         goto loop;
657                 }
658         }
659
660         // If we are in 56K mode and still in need of a mnemonic then search for one
661         if (dsp56001 && ((state < 0) || (state >= 1000)))
662         {
663                 for(state=0, p=opname; state>=0;)
664                 {
665                         j = dspbase[state] + (int)tolowertab[*p];
666
667                         // Reject, character doesn't match
668                         if (dspcheck[j] != state)
669                         {
670                                 state = -1;                                     // No match
671                                 break;
672                         }
673
674                         // Must accept or reject at EOS
675                         if (!*++p)
676                         {
677                                 state = dspaccept[j];           // (-1 on no terminal match)
678                                 break;
679                         }
680
681                         state = dsptab[j];
682                 }
683
684                 // Call DSP code generator if we found a mnemonic
685                 if (state >= 2000)
686                 {
687                         LONG parcode;
688                         int operands;
689                         MNTABDSP * md = &dsp56k_machtab[state - 2000];
690                         deposit_extra_ea = 0;   // Assume no extra word needed
691
692                         if (md->mnfunc == dsp_mult)
693                         {
694                                 // Special case for multiplication instructions: they require
695                                 // 3 operands
696                                 if ((operands = dsp_amode(3)) == ERROR)
697                                         goto loop;
698                         }
699                         else if ((md->mnattr & PARMOVE) && md->mn0 != M_AM_NONE)
700                         {
701                                 if (dsp_amode(2) == ERROR)
702                                         goto loop;
703                         }
704                         else if ((md->mnattr & PARMOVE) && md->mn0 == M_AM_NONE)
705                         {
706                                 // Instructions that have parallel moves but use no operands
707                                 // (probably only move). In this case, don't parse addressing
708                                 // modes--just go straight to parallel parse
709                                 dsp_am0 = dsp_am1 = M_AM_NONE;
710                         }
711                         else
712                         {
713                                 // Non parallel move instructions can have up to 4 parameters
714                                 // (well, only tcc instructions really)
715                                 if ((operands = dsp_amode(4)) == ERROR)
716                                         goto loop;
717
718                                 if (operands == 4)
719                                 {
720                                         dsp_tcc4(md->mninst);
721                                         goto loop;
722                                 }
723                         }
724
725                         if (md->mnattr & PARMOVE)
726                         {
727                                 // Check for parallel moves
728                                 if ((parcode = parmoves(dsp_a1reg)) == ERROR)
729                                         goto loop;
730                         }
731                         else
732                         {
733                                 if (*tok != EOL)
734                                         error("parallel moves not allowed with this instruction");
735
736                                 parcode = 0;
737                         }
738
739                         while ((dsp_am0 & md->mn0) == 0 || (dsp_am1 & md->mn1) == 0)
740                                 md = &dsp56k_machtab[md->mncont];
741
742                         GENLINENOSYM();
743                         (*md->mnfunc)(md->mninst | (parcode << 8));
744                         goto loop;
745                 }
746         }
747
748         // Invoke macro or complain about bad mnemonic
749         if (state < 0)
750         {
751                 if ((sy = lookup(opname, MACRO, 0)) != NULL)
752                         InvokeMacro(sy, siz);
753                 else
754                         error("unknown op '%s'", opname);
755
756                 goto loop;
757         }
758
759         // Call directive handlers
760         if (state < 500)
761         {
762                 (*dirtab[state])(siz);
763                 goto loop;
764         }
765
766         // Do mnemonics
767         //  o  can't deposit instrs in BSS or ABS
768         //  o  do automatic .EVEN for instrs
769         //  o  allocate space for largest possible instr
770         //  o  can't do ".b" operations with an address register
771         if (scattr & SBSS)
772         {
773                 error("cannot initialize non-storage (BSS) section");
774                 goto loop;
775         }
776
777         if (sloc & 1)                                   // Automatic .even
778                 auto_even();
779
780         if (challoc - ch_size < 18)             // Make sure have space in current chunk
781                 chcheck(0);
782
783         m = &machtab[state - 1000];
784
785         // Call special-mode handler
786         if (m->mnattr & CGSPECIAL)
787         {
788                 GENLINENOSYM();
789                 (*m->mnfunc)(m->mninst, siz);
790                 goto loop;
791         }
792
793         if (amode(1) < 0)                               // Parse 0, 1 or 2 addr modes
794                 goto loop;
795
796         // Check that we're at EOL
797         // The only exception is ptestr/ptestw instructions
798         // that have 3 or 4 operands and are not handled by
799         // amode(). (yes, we're taking a performance hit here sadly)
800         if (m->mnfunc != m_ptestr && m->mnfunc != m_ptestw)
801                 if (*tok != EOL)
802                         error(extra_stuff);
803
804         amsk0 = amsktab[am0];
805         amsk1 = amsktab[am1];
806
807         // Catch attempts to use ".B" with an address register (yes, this check
808         // does work at this level)
809         if (siz == SIZB && (am0 == AREG || am1 == AREG))
810         {
811                 error("cannot use '.b' with an address register");
812                 goto loop;
813         }
814
815         // Keep a backup of chptr (used for optimisations during codegen)
816         chptr_opcode = chptr;
817
818         while (!(m->mnattr & siz) || (amsk0 & m->mn0) == 0 || (amsk1 & m->mn1) == 0)
819                 m = &machtab[m->mncont];
820
821         DEBUG { printf("    68K: mninst=$%X, siz=$%X, mnattr=$%X, amsk0=$%X, mn0=$%X, amsk1=$%X, mn1=$%X\n", m->mninst, siz, m->mnattr, amsk0, m->mn0, amsk1, m->mn1); }
822
823         GENLINENOSYM();
824         (*m->mnfunc)(m->mninst, siz);
825         goto loop;
826 }
827
828 //
829 // Handle the creation of labels
830 //
831 int HandleLabel(char * label, int labelType)
832 {
833         // Check for dot in front of label; means this is a local label if present
834         int environment = (*label == '.' ? curenv : 0);
835         SYM * symbol = lookup(label, LABEL, environment);
836
837         if (symbol == NULL)
838         {
839                 symbol = NewSymbol(label, LABEL, environment);
840                 symbol->sattr = 0;
841                 symbol->sattre = 0;
842         }
843         else if (symbol->sattr & DEFINED)
844                 return error("multiply-defined label '%s'", label);
845
846         // Put symbol in "order of definition" list if it's not already in it
847         AddToSymbolDeclarationList(symbol);
848
849         if (orgactive)
850         {
851                 symbol->svalue = orgaddr;
852                 symbol->sattr |= ABS | DEFINED | EQUATED;
853         }
854         else
855         {
856                 symbol->svalue = sloc;
857                 symbol->sattr |= DEFINED | cursect;
858         }
859
860         lab_sym = symbol;
861
862         // Yes, our CS professors told us to write checks for equality this way,
863         // but damn, it hurts my brain every time I look at it. :-/
864         if (0 == environment)
865                 curenv++;
866
867         // Make label global if it has a double colon
868         if (labelType == DCOLON)
869         {
870                 if (environment != 0)
871                         return error(locgl_error);
872
873                 symbol->sattr |= GLOBAL;
874         }
875
876         return 0;
877 }