1 /*****************************************************************************/
5 /* Pseudo instructions for the ca65 macroassembler */
9 /* (C) 1998-2000 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
69 /*****************************************************************************/
71 /*****************************************************************************/
75 /* Keyword we're about to handle */
76 static char Keyword [sizeof (SVal)+1] = ".";
80 /*****************************************************************************/
82 /*****************************************************************************/
86 static void DoUnexpected (void);
87 /* Got an unexpected keyword */
89 static void DoInvalid (void);
90 /* Handle a token that is invalid here, since it should have been handled on
91 * a much lower level of the expression hierarchy. Getting this sort of token
92 * means that the lower level code has bugs.
93 * This function differs to DoUnexpected in that the latter may be triggered
94 * by the user by using keywords in the wrong location. DoUnexpected is not
95 * an error in the assembler itself, while DoInvalid is.
100 /*****************************************************************************/
101 /* Helper functions */
102 /*****************************************************************************/
106 static void SetBoolOption (unsigned char* Flag)
107 /* Read a on/off/+/- option and set flag accordingly */
109 static const char* Keys[] = {
114 if (Tok == TOK_PLUS) {
117 } else if (Tok == TOK_MINUS) {
120 } else if (Tok == TOK_IDENT) {
121 /* Map the keyword to a number */
122 switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
123 case 0: *Flag = 0; NextTok (); break;
124 case 1: *Flag = 1; NextTok (); break;
125 default: ErrorSkip (ERR_ONOFF_EXPECTED); break;
127 } else if (Tok == TOK_SEP || Tok == TOK_EOF) {
128 /* Without anything assume switch on */
131 ErrorSkip (ERR_ONOFF_EXPECTED);
137 static void ExportImport (void (*SymFunc) (const char*, int), int ZP)
138 /* Export or import symbols */
141 if (Tok != TOK_IDENT) {
142 ErrorSkip (ERR_IDENT_EXPECTED);
147 if (Tok == TOK_COMMA) {
157 static long IntArg (long Min, long Max)
158 /* Read an integer argument and check a range. Accept the token "unlimited"
159 * and return -1 in this case.
162 if (Tok == TOK_IDENT && strcmp (SVal, "unlimited") == 0) {
166 long Val = ConstExpression ();
167 if (Val < Min || Val > Max) {
177 static void ConDes (const char* Name, unsigned Type)
178 /* Parse remaining line for constructor/destructor of the remaining type */
182 /* Optional constructor priority */
183 if (Tok == TOK_COMMA) {
184 /* Priority value follows */
186 Prio = ConstExpression ();
187 if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) {
188 /* Value out of range */
193 /* Use the default priority value */
197 /* Define the symbol */
198 SymConDes (Name, Type, (unsigned) Prio);
203 /*****************************************************************************/
204 /* Handler functions */
205 /*****************************************************************************/
209 static void DoA16 (void)
210 /* Switch the accu to 16 bit mode (assembler only) */
212 if (GetCPU() != CPU_65816) {
213 Error (ERR_816_MODE_ONLY);
215 /* Immidiate mode has two extension bytes */
216 ExtBytes [AMI_IMM_ACCU] = 2;
222 static void DoA8 (void)
223 /* Switch the accu to 8 bit mode (assembler only) */
225 if (GetCPU() != CPU_65816) {
226 Error (ERR_816_MODE_ONLY);
228 /* Immidiate mode has one extension byte */
229 ExtBytes [AMI_IMM_ACCU] = 1;
235 static void DoAddr (void)
236 /* Define addresses */
239 if (GetCPU() == CPU_65816) {
240 EmitWord (ForceWordExpr (Expression ()));
242 /* Do a range check */
243 EmitWord (Expression ());
245 if (Tok != TOK_COMMA) {
255 static void DoAlign (void)
256 /* Align the PC to some boundary */
262 /* Read the alignment value */
263 Align = ConstExpression ();
264 if (Align <= 0 || Align > 0x10000) {
265 ErrorSkip (ERR_RANGE);
269 /* Optional value follows */
270 if (Tok == TOK_COMMA) {
272 Val = ConstExpression ();
273 /* We need a byte value here */
274 if (!IsByteRange (Val)) {
275 ErrorSkip (ERR_RANGE);
282 /* Check if the alignment is a power of two */
283 Bit = BitFind (Align);
284 if (Align != (0x01L << Bit)) {
287 SegAlign (Bit, (int) Val);
293 static void DoASCIIZ (void)
294 /* Define text with a zero terminator */
297 if (Tok != TOK_STRCON) {
298 ErrorSkip (ERR_STRCON_EXPECTED);
301 /* Translate into target charset and emit */
302 TgtTranslateStr (SVal);
303 EmitData ((unsigned char*) SVal, strlen (SVal));
305 if (Tok == TOK_COMMA) {
316 static void DoAutoImport (void)
317 /* Mark unresolved symbols as imported */
319 SetBoolOption (&AutoImport);
324 static void DoBss (void)
325 /* Switch to the BSS segment */
332 static void DoByte (void)
336 if (Tok == TOK_STRCON) {
337 /* A string, translate into target charset and emit */
338 TgtTranslateStr (SVal);
339 EmitData ((unsigned char*) SVal, strlen (SVal));
342 EmitByte (Expression ());
344 if (Tok != TOK_COMMA) {
348 /* Do smart handling of dangling comma */
349 if (Tok == TOK_SEP) {
350 Error (ERR_UNEXPECTED_EOL);
359 static void DoCase (void)
360 /* Switch the IgnoreCase option */
362 SetBoolOption (&IgnoreCase);
363 IgnoreCase = !IgnoreCase;
368 static void DoCode (void)
369 /* Switch to the code segment */
376 static void DoConDes (void)
377 /* Export a symbol as constructor/destructor */
379 static const char* Keys[] = {
383 char Name [sizeof (SVal)];
386 /* Symbol name follows */
387 if (Tok != TOK_IDENT) {
388 ErrorSkip (ERR_IDENT_EXPECTED);
394 /* Type follows. May be encoded as identifier or numerical */
396 if (Tok == TOK_IDENT) {
398 /* Map the following keyword to a number, then skip it */
399 Type = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
402 /* Check if we got a valid keyword */
411 /* Read the type as numerical value */
412 Type = ConstExpression ();
413 if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
414 /* Value out of range */
421 /* Parse the remainder of the line and export the symbol */
422 ConDes (Name, (unsigned) Type);
427 static void DoConstructor (void)
428 /* Export a symbol as constructor */
430 char Name [sizeof (SVal)];
432 /* Symbol name follows */
433 if (Tok != TOK_IDENT) {
434 ErrorSkip (ERR_IDENT_EXPECTED);
440 /* Parse the remainder of the line and export the symbol */
441 ConDes (Name, CD_TYPE_CON);
446 static void DoData (void)
447 /* Switch to the data segment */
454 static void DoDbg (void)
455 /* Add debug information from high level code */
457 static const char* Keys[] = {
465 /* We expect a subkey */
466 if (Tok != TOK_IDENT) {
467 ErrorSkip (ERR_IDENT_EXPECTED);
471 /* Map the following keyword to a number */
472 Key = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
474 /* Skip the subkey */
477 /* Parameters are separated by a comma */
480 /* Check the key and dispatch to a handler */
482 case 0: DbgInfoFile (); break;
483 case 1: DbgInfoLine (); break;
484 case 2: DbgInfoSym (); break;
485 default: ErrorSkip (ERR_SYNTAX); break;
491 static void DoDByt (void)
492 /* Output double bytes */
495 EmitWord (SwapExpr (Expression ()));
496 if (Tok != TOK_COMMA) {
506 static void DoDebugInfo (void)
507 /* Switch debug info on or off */
509 SetBoolOption (&DbgSyms);
514 static void DoDefine (void)
515 /* Define a one line macro */
517 MacDef (MAC_STYLE_DEFINE);
522 static void DoDestructor (void)
523 /* Export a symbol as destructor */
525 char Name [sizeof (SVal)];
527 /* Symbol name follows */
528 if (Tok != TOK_IDENT) {
529 ErrorSkip (ERR_IDENT_EXPECTED);
535 /* Parse the remainder of the line and export the symbol */
536 ConDes (Name, CD_TYPE_DES);
541 static void DoDWord (void)
545 EmitDWord (Expression ());
546 if (Tok != TOK_COMMA) {
556 static void DoEnd (void)
557 /* End of assembly */
564 static void DoEndProc (void)
565 /* Leave a lexical level */
572 static void DoError (void)
575 if (Tok != TOK_STRCON) {
576 ErrorSkip (ERR_STRCON_EXPECTED);
578 Error (ERR_USER, SVal);
585 static void DoExitMacro (void)
586 /* Exit a macro expansion */
588 if (!InMacExpansion ()) {
589 /* We aren't expanding a macro currently */
598 static void DoExport (void)
599 /* Export a symbol */
601 ExportImport (SymExport, 0);
606 static void DoExportZP (void)
607 /* Export a zeropage symbol */
609 ExportImport (SymExport, 1);
614 static void DoFarAddr (void)
615 /* Define far addresses (24 bit) */
618 EmitFarAddr (Expression ());
619 if (Tok != TOK_COMMA) {
629 static void DoFeature (void)
630 /* Switch the Feature option */
632 /* Allow a list of comma separated keywords */
635 /* We expect an identifier */
636 if (Tok != TOK_IDENT) {
637 ErrorSkip (ERR_IDENT_EXPECTED);
641 /* Make the string attribute lower case */
644 /* Set the feature and check for errors */
645 if (SetFeature (SVal) == FEAT_UNKNOWN) {
647 ErrorSkip (ERR_ILLEGAL_FEATURE);
650 /* Skip the keyword */
654 /* Allow more than one keyword */
655 if (Tok == TOK_COMMA) {
665 static void DoFileOpt (void)
666 /* Insert a file option */
670 /* The option type may be given as a keyword or as a number. */
671 if (Tok == TOK_IDENT) {
673 /* Option given as keyword */
674 static const char* Keys [] = {
675 "AUTHOR", "COMMENT", "COMPILER"
678 /* Map the option to a number */
679 OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
682 ErrorSkip (ERR_OPTION_KEY_EXPECTED);
686 /* Skip the keyword */
689 /* Must be followed by a comma */
692 /* We accept only string options for now */
693 if (Tok != TOK_STRCON) {
694 ErrorSkip (ERR_STRCON_EXPECTED);
698 /* Insert the option */
717 Internal ("Invalid OptNum: %l", OptNum);
726 /* Option given as number */
727 OptNum = ConstExpression ();
728 if (!IsByteRange (OptNum)) {
729 ErrorSkip (ERR_RANGE);
733 /* Must be followed by a comma */
736 /* We accept only string options for now */
737 if (Tok != TOK_STRCON) {
738 ErrorSkip (ERR_STRCON_EXPECTED);
742 /* Insert the option */
743 OptStr ((unsigned char) OptNum, SVal);
752 static void DoGlobal (void)
753 /* Declare a global symbol */
755 ExportImport (SymGlobal, 0);
760 static void DoGlobalZP (void)
761 /* Declare a global zeropage symbol */
763 ExportImport (SymGlobal, 1);
768 static void DoI16 (void)
769 /* Switch the index registers to 16 bit mode (assembler only) */
771 if (GetCPU() != CPU_65816) {
772 Error (ERR_816_MODE_ONLY);
774 /* Immidiate mode has two extension bytes */
775 ExtBytes [AMI_IMM_INDEX] = 2;
781 static void DoI8 (void)
782 /* Switch the index registers to 16 bit mode (assembler only) */
784 if (GetCPU() != CPU_65816) {
785 Error (ERR_816_MODE_ONLY);
787 /* Immidiate mode has one extension byte */
788 ExtBytes [AMI_IMM_INDEX] = 1;
794 static void DoImport (void)
795 /* Import a symbol */
797 ExportImport (SymImport, 0);
802 static void DoImportZP (void)
803 /* Import a zero page symbol */
805 ExportImport (SymImport, 1);
810 static void DoIncBin (void)
811 /* Include a binary file */
813 /* Name must follow */
814 if (Tok != TOK_STRCON) {
815 ErrorSkip (ERR_STRCON_EXPECTED);
817 /* Try to open the file */
818 FILE* F = fopen (SVal, "rb");
820 Error (ERR_CANNOT_OPEN_INCLUDE, SVal, strerror (errno));
822 unsigned char Buf [1024];
824 /* Read chunks and insert them into the output */
825 while ((Count = fread (Buf, 1, sizeof (Buf), F)) > 0) {
826 EmitData (Buf, Count);
828 /* Close the file, ignore errors since it's r/o */
838 static void DoInclude (void)
839 /* Include another file */
841 char Name [MAX_STR_LEN+1];
843 /* Name must follow */
844 if (Tok != TOK_STRCON) {
845 ErrorSkip (ERR_STRCON_EXPECTED);
855 static void DoInvalid (void)
856 /* Handle a token that is invalid here, since it should have been handled on
857 * a much lower level of the expression hierarchy. Getting this sort of token
858 * means that the lower level code has bugs.
859 * This function differs to DoUnexpected in that the latter may be triggered
860 * by the user by using keywords in the wrong location. DoUnexpected is not
861 * an error in the assembler itself, while DoInvalid is.
864 Internal ("Unexpected token: %s", Keyword);
869 static void DoLineCont (void)
870 /* Switch the use of line continuations */
872 SetBoolOption (&LineCont);
877 static void DoList (void)
878 /* Enable/disable the listing */
880 /* Get the setting */
882 SetBoolOption (&List);
884 /* Manage the counter */
894 static void DoListBytes (void)
895 /* Set maximum number of bytes to list for one line */
897 SetListBytes (IntArg (MIN_LIST_BYTES, MAX_LIST_BYTES));
902 static void DoLocalChar (void)
903 /* Define the character that starts local labels */
905 if (Tok != TOK_CHARCON) {
906 ErrorSkip (ERR_CHARCON_EXPECTED);
908 if (IVal != '@' && IVal != '?') {
909 Error (ERR_ILLEGAL_LOCALSTART);
911 LocalStart = (char) IVal;
919 static void DoMacPack (void)
920 /* Insert a macro package */
922 /* Macro package names */
923 static const char* Keys [] = {
930 /* We expect an identifier */
931 if (Tok != TOK_IDENT) {
932 ErrorSkip (ERR_IDENT_EXPECTED);
936 /* Map the keyword to a number */
937 Package = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
940 ErrorSkip (ERR_ILLEGAL_MACPACK);
944 /* Skip the package name */
947 /* Insert the package */
948 InsertMacPack (Package);
953 static void DoMacro (void)
954 /* Start a macro definition */
956 MacDef (MAC_STYLE_CLASSIC);
961 static void DoNull (void)
962 /* Switch to the NULL segment */
969 static void DoOrg (void)
970 /* Start absolute code */
972 long PC = ConstExpression ();
973 if (PC < 0 || PC > 0xFFFFFF) {
982 static void DoOut (void)
983 /* Output a string */
985 if (Tok != TOK_STRCON) {
986 ErrorSkip (ERR_STRCON_EXPECTED);
988 /* Output the string and be sure to flush the output to keep it in
989 * sync with any error messages if the output is redirected to a file.
991 printf ("%s\n", SVal);
999 static void DoP02 (void)
1000 /* Switch to 6502 CPU */
1007 static void DoPC02 (void)
1008 /* Switch to 65C02 CPU */
1015 static void DoP816 (void)
1016 /* Switch to 65816 CPU */
1023 static void DoPageLength (void)
1024 /* Set the page length for the listing */
1026 PageLength = IntArg (MIN_PAGE_LEN, MAX_PAGE_LEN);
1031 static void DoProc (void)
1032 /* Start a new lexical scope */
1034 if (Tok == TOK_IDENT) {
1035 /* The new scope has a name */
1036 SymDef (SVal, CurrentPC (), IsZPSeg ());
1044 static void DoReloc (void)
1045 /* Enter relocatable mode */
1052 static void DoRepeat (void)
1053 /* Repeat some instruction block */
1060 static void DoRes (void)
1061 /* Reserve some number of storage bytes */
1066 Count = ConstExpression ();
1067 if (Count > 0xFFFF || Count < 0) {
1068 ErrorSkip (ERR_RANGE);
1071 if (Tok == TOK_COMMA) {
1073 Val = ConstExpression ();
1074 /* We need a byte value here */
1075 if (!IsByteRange (Val)) {
1076 ErrorSkip (ERR_RANGE);
1080 /* Emit constant values */
1082 Emit0 ((unsigned char) Val);
1086 /* Emit fill fragments */
1093 static void DoROData (void)
1094 /* Switch to the r/o data segment */
1101 static void DoSegment (void)
1102 /* Switch to another segment */
1104 static const char* AttrTab [] = {
1105 "ZEROPAGE", "DIRECT",
1109 char Name [sizeof (SVal)];
1112 if (Tok != TOK_STRCON) {
1113 ErrorSkip (ERR_STRCON_EXPECTED);
1116 /* Save the name of the segment and skip it */
1117 strcpy (Name, SVal);
1120 /* Check for an optional segment attribute */
1121 SegType = SEGTYPE_DEFAULT;
1122 if (Tok == TOK_COMMA) {
1124 if (Tok != TOK_IDENT) {
1125 ErrorSkip (ERR_IDENT_EXPECTED);
1127 int Attr = GetSubKey (AttrTab, sizeof (AttrTab) / sizeof (AttrTab [0]));
1133 SegType = SEGTYPE_ZP;
1138 SegType = SEGTYPE_ABS;
1144 SegType = SEGTYPE_FAR;
1148 Error (ERR_ILLEGAL_SEG_ATTR);
1154 /* Set the segment */
1155 UseSeg (Name, SegType);
1161 static void DoSmart (void)
1162 /* Smart mode on/off */
1164 SetBoolOption (&SmartMode);
1169 static void DoSunPlus (void)
1170 /* Switch to the SUNPLUS CPU */
1172 SetCPU (CPU_SUNPLUS);
1177 static void DoUnexpected (void)
1178 /* Got an unexpected keyword */
1180 Error (ERR_UNEXPECTED, Keyword);
1186 static void DoWarning (void)
1189 if (Tok != TOK_STRCON) {
1190 ErrorSkip (ERR_STRCON_EXPECTED);
1192 Warning (WARN_USER, SVal);
1199 static void DoWord (void)
1203 EmitWord (Expression ());
1204 if (Tok != TOK_COMMA) {
1214 static void DoZeropage (void)
1215 /* Switch to the zeropage segment */
1222 /*****************************************************************************/
1224 /*****************************************************************************/
1228 /* Control commands flags */
1230 ccNone = 0x0000, /* No special flags */
1231 ccKeepToken = 0x0001 /* Do not skip the current token */
1234 /* Control command table */
1236 unsigned Flags; /* Flags for this directive */
1237 void (*Handler) (void); /* Command handler */
1239 typedef struct CtrlDesc_ CtrlDesc;
1241 #define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0]))
1242 static CtrlDesc CtrlCmdTab [] = {
1245 { ccNone, DoAddr }, /* .ADDR */
1246 { ccNone, DoAlign },
1247 { ccNone, DoASCIIZ },
1248 { ccNone, DoAutoImport },
1249 { ccNone, DoUnexpected }, /* .BLANK */
1254 { ccNone, DoUnexpected, }, /* .CONCAT */
1255 { ccNone, DoConDes },
1256 { ccNone, DoUnexpected }, /* .CONST */
1257 { ccNone, DoConstructor },
1258 { ccNone, DoUnexpected }, /* .CPU */
1262 { ccNone, DoDebugInfo },
1263 { ccNone, DoDefine },
1264 { ccNone, DoUnexpected }, /* .DEFINED */
1265 { ccNone, DoDestructor },
1266 { ccNone, DoDWord },
1267 { ccKeepToken, DoConditionals }, /* .ELSE */
1268 { ccKeepToken, DoConditionals }, /* .ELSEIF */
1270 { ccKeepToken, DoConditionals }, /* .ENDIF */
1271 { ccNone, DoUnexpected }, /* .ENDMACRO */
1272 { ccNone, DoEndProc },
1273 { ccNone, DoUnexpected }, /* .ENDREPEAT */
1274 { ccNone, DoError },
1275 { ccNone, DoExitMacro },
1276 { ccNone, DoExport },
1277 { ccNone, DoExportZP },
1278 { ccNone, DoFarAddr },
1279 { ccNone, DoFeature },
1280 { ccNone, DoFileOpt },
1281 { ccNone, DoUnexpected }, /* .FORCEWORD */
1282 { ccNone, DoGlobal },
1283 { ccNone, DoGlobalZP },
1286 { ccKeepToken, DoConditionals }, /* .IF */
1287 { ccKeepToken, DoConditionals }, /* .IFBLANK */
1288 { ccKeepToken, DoConditionals }, /* .IFCONST */
1289 { ccKeepToken, DoConditionals }, /* .IFDEF */
1290 { ccKeepToken, DoConditionals }, /* .IFNBLANK */
1291 { ccKeepToken, DoConditionals }, /* .IFNCONST */
1292 { ccKeepToken, DoConditionals }, /* .IFNDEF */
1293 { ccKeepToken, DoConditionals }, /* .IFNREF */
1294 { ccKeepToken, DoConditionals }, /* .IFP02 */
1295 { ccKeepToken, DoConditionals }, /* .IFP816 */
1296 { ccKeepToken, DoConditionals }, /* .IFPC02 */
1297 { ccKeepToken, DoConditionals }, /* .IFREF */
1298 { ccNone, DoImport },
1299 { ccNone, DoImportZP },
1300 { ccNone, DoIncBin },
1301 { ccNone, DoInclude },
1302 { ccNone, DoInvalid }, /* .LEFT */
1303 { ccNone, DoLineCont },
1305 { ccNone, DoListBytes },
1306 { ccNone, DoUnexpected }, /* .LOCAL */
1307 { ccNone, DoLocalChar },
1308 { ccNone, DoMacPack },
1309 { ccNone, DoMacro },
1310 { ccNone, DoUnexpected }, /* .MATCH */
1311 { ccNone, DoInvalid }, /* .MID */
1317 { ccNone, DoPageLength },
1318 { ccNone, DoUnexpected }, /* .PARAMCOUNT */
1321 { ccNone, DoUnexpected }, /* .REFERENCED */
1322 { ccNone, DoReloc },
1323 { ccNone, DoRepeat },
1325 { ccNone, DoInvalid }, /* .RIGHT */
1326 { ccNone, DoROData },
1327 { ccNone, DoSegment },
1328 { ccNone, DoSmart },
1329 { ccNone, DoUnexpected }, /* .STRAT */
1330 { ccNone, DoUnexpected }, /* .STRING */
1331 { ccNone, DoUnexpected }, /* .STRLEN */
1332 { ccNone, DoSunPlus },
1333 { ccNone, DoUnexpected }, /* .TCOUNT */
1334 { ccNone, DoWarning },
1336 { ccNone, DoUnexpected }, /* .XMATCH */
1337 { ccNone, DoZeropage },
1342 /*****************************************************************************/
1344 /*****************************************************************************/
1348 int TokIsPseudo (unsigned Tok)
1349 /* Return true if the given token is a pseudo instruction token */
1351 return (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO);
1356 void HandlePseudo (void)
1357 /* Handle a pseudo instruction */
1361 /* Calculate the index into the table */
1362 unsigned Index = Tok - TOK_FIRSTPSEUDO;
1365 if (PSEUDO_COUNT != (TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1)) {
1366 Internal ("Pseudo mismatch: PSEUDO_COUNT = %u, actual count = %u\n",
1367 PSEUDO_COUNT, TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1);
1369 CHECK (Index < PSEUDO_COUNT);
1371 /* Get the pseudo intruction descriptor */
1372 D = &CtrlCmdTab [Index];
1374 /* Remember the instruction, then skip it if needed */
1375 if ((D->Flags & ccKeepToken) == 0) {
1376 strcpy (Keyword+1, SVal);
1380 /* Call the handler */