PageRenderTime 59ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Tools/zmac/src/zmac.y

https://bitbucket.org/tim_ring/tz80-1
Happy | 7298 lines | 6532 code | 766 blank | 0 comment | 0 complexity | 95f9f1c4a1a8aec4e9cc5592fd34d0ab MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. %{
  2. // GWP - keep track of version via hand-maintained date stamp.
  3. #define VERSION "3dec2014"
  4. /*
  5. * zmac -- macro cross-assembler for the Zilog Z80 microprocessor
  6. *
  7. * Bruce Norskog 4/78
  8. *
  9. * Last modification 1-18-87 by cdk
  10. * This assembler is modeled after the Intel 8080 macro cross-assembler
  11. * for the Intel 8080 by Ken Borgendale. The major features are:
  12. * 1. Full macro capabilities
  13. * 2. Conditional assembly
  14. * 3. A very flexible set of listing options and pseudo-ops
  15. * 4. Symbol table output
  16. * 5. Error report
  17. * 6. Elimination of sequential searching
  18. * 7. Commenting of source
  19. * 8. Facilities for system definiton files
  20. *
  21. * Revision History:
  22. *
  23. * jrp 3-8-82 Converted to run on Vax, updated syntax to conform better
  24. * to the Zilog standard.
  25. *
  26. * jrp 3-15-82 Added underscore as a character type in the lex table
  27. * 'numpart' (0x5F).
  28. *
  29. * Changed maximum number of characters in a label to 15
  30. * from 7. Note that 'putsymtab' uses this value inside
  31. * of a quoted string, so we use 15.
  32. *
  33. * jrp 2-15-83 Fixed 'getlocal' to return better local labels. It used
  34. * to crash after 6 invocations.
  35. *
  36. * jrp 6-7-83 Fixed bug in the ADD IX,... instruction.
  37. *
  38. * jrp 5-11-84 Added code to print unused labels out with the symbol table
  39. * Also sped up the macro processor by using stdio.
  40. *
  41. * jrp 5-22-84 Added include files ala ormac
  42. *
  43. * jrp 8-27-84 Added PHASE/DEPHASE commands
  44. *
  45. * cdk 9-20-86 Converted to run on a Pyramid. This meant changing yylval
  46. * to be a %union, and then putting in the appropriate
  47. * typecasts where ints are pointers are used interchangeably.
  48. * The current version still probably won't run on machines where
  49. * sizeof(int) != sizeof(char *).
  50. * Also changed emit() to use varargs, and got rid of the
  51. * old style = in front of yacc action code.
  52. * -Colin Kelley vu-vlsi!colin
  53. *
  54. * cdk 10-2-86 Added some more typecasts to keep lint a little happier.
  55. * Removed several unused variables. Changed most vars
  56. * declared as char to int, since many of them were being
  57. * compared with -1! I still don't know what's going on with
  58. * est[][] being malloc'd and free'd everywhere...it looks pretty
  59. * fishy...
  60. *
  61. * cdk 1-18-87 Added MIO code to emulate 'mfile' using malloc()'d memory.
  62. * This was needed to get the code to work when compiled under
  63. * MSC 4.0 on a PC, and it's probably faster anyway.
  64. *
  65. * cdk 2-5-87 Added 'cmp' as a synonym for 'cp', 'jmp' as a synonym for
  66. * 'jp', and added tolerance of accumulator specification for arithmetic
  67. * and logical instructions. (For example, 'or a,12' is now accepted,
  68. * same as 'or 12'.)
  69. *
  70. * gwp 12-29-08 Changes to allow compilation with modern C compiler and using bison
  71. * as the .y to .c converter. assert, tstate pseudo-ops.
  72. * t(), tilo(), tihi() functions. ==, <=, >=, !=, !, <, > operators.
  73. * -c to turn cycle counts off in listing. Usage, -h and version.
  74. *
  75. * gwp 9-26-10 Add ocf() and setocf to track and set op code fetch counts.
  76. * Add sett as an alias for tstate
  77. *
  78. * gwp 12-30-11 Add undocumented instructions sl1, pfix, pfiy, in (c), out (c),0
  79. * bit/set/res (ixy+d),reg and ld/inc/dec ixylh.
  80. *
  81. * gwp 2-8-12 Increase MAXIFS massively due to massive lowt macro
  82. *
  83. * gwp 2-11-12 Support 32 bit constants. '%' alias for MOD. Add defd, dword.
  84. * lo(x) and hi(x) for easy low and high byte extraction. Allow
  85. * filenames longer than 15 characters. All output to "zout" subdirectory
  86. * of source file.
  87. *
  88. * gwp 2-15-12 Perform multiple passes while equates are changing. Support
  89. * .label for temporary label definitions and _label for file
  90. * scoped labels. Allow '.' within labels. Assert listing bugfix.
  91. *
  92. * gwp 4-27-12 Implement $ prefixed hex constants and double-quoted strings.
  93. *
  94. * gwp 6-30-12 Minor changes to allow compilation with gcc.
  95. *
  96. * gwp 9-05-12 incbin added.
  97. *
  98. * gwp 11-24-12 Fix macro expansion bug when symbol larger than MAXSYMBOLSIZE
  99. * due to file name prepending when symbol starts with '_'.
  100. *
  101. * gwp 12-04-12 Optional JR promotion and JP demotion errors. Output a warning
  102. * if no execute address given. Output ".bds" file to enable easy
  103. * simple source level debugging.
  104. *
  105. * gwp 4-14-13 Parens in expressions, else, .pseudo, full set of C operators
  106. * with conventional precedence and various aliases and code
  107. * changes to make source similar to zmac 1.3 on internet.
  108. *
  109. * gwp 5-5-13 .cmd,.cas,.lcas,.bin output. dc (both MACRO-80 and EDAS types).
  110. * lo, hi renamed to low, high and make unary operators. Allow
  111. * label::, placeholder public, extern declarations. Bug fixes
  112. * in defs, t, ocf, tihi, tilo in phase mode. Initial support
  113. * for -I include directories. 0x hex constants. --mras flag for
  114. * limited MRAS compatibility (allows $ in labels, $? to start
  115. * labels).
  116. *
  117. * gwp 4-6-13 --rel for .rel (Microsoft linker) output and extern, public,
  118. * aseg, cseg, dseg in support (big emit + expression revamp).
  119. * -I follows C preprocessor convention, output relative to
  120. * current directory. 8080 mnemonics, .z80, .8080, -z, -8.
  121. * Change .bin to .cim. Warn on labels not in first column.
  122. *
  123. * gwp 8-11-13 Allow $ to start identifiers and do '$' dropping when macro
  124. * parsed so we no longer need to drop '$' in identifiers.
  125. * Even $FCB allowed, with warning. Add --zmac for backwards
  126. * compatibility with zmac. ` now used for joining in macros.
  127. * Most reserved words can be used as labels or variables.
  128. * Free-form title, name, comment, subttl parsing. Allow #arg
  129. * for macro arguments (in --mras mode). Support <CR> delimited
  130. * files. Add .ams output. Integrate documentation (--doc).
  131. *
  132. * gwp 3-12-14 Emit jr even if out of range. z80.lib support.
  133. * Warning and bug fixes from Mark Galanger.
  134. * Macros can override built-ins and are no longer listed
  135. * in symbol table. A, B, C, D, E, H, L, M, PSW, SP are
  136. * pre-defined values which can be used in data statements
  137. * (db, dw, dd). Reserved words can be equated but are only
  138. * accessbile in data. SET can be used in place of DEFL
  139. * (MAC and MACRO-80 agree on this). '=' can be used in place
  140. * of EQU. 'maclib file' includes 'file.lib'. Bug fix in "dw 0,$".
  141. * Removed error flagging in expressions which could cause parse
  142. * to fail from that point onwards.
  143. * expression(ix) equivalent to (ix + expression).
  144. * Macro expanded lines didn't go through the line analyzer.
  145. * Empty macro arguments (e.g., mac 1,,2)
  146. * Implemented rept, irp, irpc, exitm. Add more detail on phase
  147. * errors. '' is an empty string in db/ascii/etc, 0 otherwise.
  148. * Almost any name can be used as a macro parameter name.
  149. * Allow 'if' in first column.
  150. * Fix .rel mode bug in dc, incbin.
  151. * Emit .bds output for dc, incbin.
  152. * Allow assembly to wrap past end of memory.
  153. * "pragma bds" for raw output to .bds file. Also output equates
  154. * to .bds file.
  155. * Macro bug fix from Sergey Erokhin.
  156. */
  157. #define MIO /* use emulation routines from mio.c */
  158. #include <stdio.h>
  159. #include <string.h>
  160. #include <stdlib.h>
  161. #include <stdarg.h>
  162. #include <time.h>
  163. #include <sys/stat.h>
  164. #ifdef WIN32
  165. #include <windows.h> // just for colouring the output
  166. #endif
  167. #include "zi80dis.h"
  168. #ifdef vax11c
  169. #define unlink(filename) delete(filename)
  170. #endif
  171. #ifdef MIO
  172. #include "mio.h"
  173. FILE *mfopen();
  174. #else
  175. #define mfopen(filename,mode) fopen(filename,mode)
  176. #define mfclose(filename,mode) fclose(filename,mode)
  177. #define mfputc(c,f) putc(c,f)
  178. #define mfgetc(f) getc(f)
  179. #define mfseek(f,loc,origin) fseek(f,loc,origin)
  180. #define mfread(ptr,size,nitems,f) fread(ptr,size,nitems,f)
  181. #define mfwrite(ptr,size,nitems,f) fread(ptr,size,nitems,f)
  182. #endif /* MIO */
  183. /*
  184. * DEBUG turns on pass reporting.
  185. * DBUG enables -d to allow yacc/bison yydebug increment (but must be passed
  186. * on the command line)
  187. * Macro debug and Token debug enables.
  188. #define DEBUG
  189. #define M_DEBUG
  190. #define T_DEBUG
  191. */
  192. #ifdef DBUG
  193. #define YYDEBUG 1
  194. #endif
  195. #define ITEMTABLESIZE 100000
  196. #define TEMPBUFSIZE (1000+MAXSYMBOLSIZE)
  197. #define LINEBUFFERSIZE 1000
  198. #define EMITBUFFERSIZE 200
  199. #define MAXSYMBOLSIZE 40
  200. #define IFSTACKSIZE 20
  201. // GWP - I use lots of if's with my lowt macro
  202. #define MAXIFS 65536
  203. #define TITLELEN 50
  204. #define BINPERLINE 16
  205. #define PARMMAX 25
  206. #define MAXEXP 25
  207. #define SYMMAJIC 07203
  208. #define NEST_IN 32
  209. #define MAXPASS 32
  210. #define MAXINCPATH 32
  211. int iflist();
  212. int yylex();
  213. int phaseaddr(int addr);
  214. int nextchar();
  215. int getcol();
  216. int skipline(int ac);
  217. int tokenofitem(int deftoken, int keyexclude, int keyinclude);
  218. int getm();
  219. int counterr();
  220. int countwarn();
  221. void yyerror(char *err)
  222. {} /* we will do our own error printing */
  223. struct argparse {
  224. char *arg; // output buffer for argument
  225. int argsize; // size of output buffer
  226. int (*getch)(struct argparse *); // get next character
  227. int *peek; // pointer single item pushback buffer
  228. int macarg; // working on macro arguments
  229. char *user_ptr; // state for getch
  230. int user_int; // state for getch
  231. int user_peek; // state for getch
  232. int didarg; // internal parsing state
  233. int numarg; // internal parsing state
  234. };
  235. int getarg(struct argparse *ap);
  236. struct item {
  237. char *i_string;
  238. int i_value;
  239. int i_token;
  240. int i_uses;
  241. int i_scope;
  242. int i_chain;
  243. };
  244. void itemcpy(struct item *dst, struct item *src);
  245. struct item *keyword(char *name);
  246. #define SCOPE_NONE (0)
  247. #define SCOPE_PROGRAM (1)
  248. #define SCOPE_DATA (2)
  249. #define SCOPE_PUBLIC (4)
  250. #define SCOPE_EXTERNAL (8)
  251. #define SCOPE_NORELOC (16)
  252. #define SCOPE_BUILTIN (32) /* abuse */
  253. #define SCOPE_SEGMASK (3)
  254. #define SCOPE_SEG(s) ((s) & SCOPE_SEGMASK)
  255. struct expr {
  256. int e_value;
  257. int e_scope;
  258. int e_token;
  259. struct item *e_item;
  260. struct expr *e_left;
  261. struct expr *e_right;
  262. };
  263. #define EXPR_SEG(e) SCOPE_SEG(e->e_scope)
  264. FILE *fout,
  265. *fbuf,
  266. *fbds,
  267. *fcmd,
  268. *fcas,
  269. *flcas,
  270. *fcim,
  271. *fams,
  272. *frel,
  273. *fin[NEST_IN],
  274. *now_file ;
  275. int pass2; /*set when pass one completed*/
  276. int outpass; // set when we decide to stop doing passes */
  277. int passfail; // set when an error means passes should not continue
  278. int passretry; // set when an inconsistency will require another pass
  279. int dollarsign ; /* location counter */
  280. int olddollar ; /* kept to put out binary */
  281. int oldothdollar; // output address of next .cmd/.cas/.lcas block
  282. int emit_addr; // were code and data are being placed in memory
  283. int tstates; // cumulative T-states
  284. int ocf; // cumulative op code fetches
  285. int llseq; // local label sequence number
  286. int mras; // MRAS semi-compatibility mode
  287. int zcompat; // Original zmac compatibility mode
  288. char modstr[8]; // Replacement string for '?' in labels when MRAS compatible
  289. int relopt; // Only output .rel files.
  290. char progname[8]; // Program name for .rel output
  291. int note_depend; // Print names of files included
  292. int firstcol;
  293. int logcol;
  294. int coloncnt;
  295. int full_exprs; // expression parsing mode allowing almost any identifier
  296. struct item *label, pristine_label; //
  297. int list_dollarsign;// flag used to change list output for some operations
  298. int list_addr; // address to display for operation if !list_dollarsign
  299. // Include file search path
  300. char *incpath[MAXINCPATH];
  301. int incpath_cnt;
  302. /* program counter save for PHASE/DEPHASE */
  303. int phdollar, phbegin, phaseflag ;
  304. char *src_name[NEST_IN] ;
  305. int linein[NEST_IN] ;
  306. int now_in ;
  307. // These first 5 errors are singled out in lsterr1() for reasons I don't
  308. // quite understand.
  309. #define bflag 0 /* balance error */
  310. #define eflag 1 /* expression error */
  311. #define fflag 2 /* syntax error */
  312. #define iflag 3 /* bad digits */
  313. #define mflag 4 /* multiply defined */
  314. #define pflag 5 /* phase error */
  315. #define uflag 6 /* undeclared used */
  316. #define vflag 7 /* value out of range */
  317. #define oflag 8 /* phase/dephase error */
  318. #define aflag 9 /* assert failed */
  319. #define jflag 10 /* JP could be JR */
  320. #define rflag 11 /* expression not relocatable */
  321. #define gflag 12 /* incorrect register */
  322. #define zflag 13 /* Z-80 instruction */
  323. #define FIRSTWARN warn_hex
  324. #define warn_hex 14
  325. #define warn_notimpl 15
  326. #define warn_general 16
  327. #define FLAGS 17 /* number of errors and warnings */
  328. char err[FLAGS];
  329. int keeperr[FLAGS];
  330. char errlet[FLAGS]="BEFIMPUVOAJRGZHNW";
  331. char *errname[FLAGS]={
  332. "Balance",
  333. "Expression",
  334. "Syntax",
  335. "Digit",
  336. "Mult. def.",
  337. "Phase",
  338. "Undeclared",
  339. "Value",
  340. "Phase/Dephase",
  341. "Assertion failure",
  342. "Use JR",
  343. "Not relocatable",
  344. "Register usage",
  345. "Z-80 instruction in 8080 mode",
  346. "$hex constant interpreted as symbol",
  347. "Not implemented",
  348. "General"
  349. };
  350. char errdetail[FLAGS][1024];
  351. char detail[1024];
  352. unsigned char inpbuf[LINEBUFFERSIZE];
  353. unsigned char *inpptr;
  354. char linebuf[LINEBUFFERSIZE];
  355. char *lineptr;
  356. char *linemax = linebuf+LINEBUFFERSIZE;
  357. char outbin[BINPERLINE];
  358. char *outbinp = outbin;
  359. char *outbinm = outbin+BINPERLINE;
  360. char outoth[256];
  361. int outoth_cnt = 0;
  362. unsigned char emitbuf[EMITBUFFERSIZE];
  363. unsigned char *emitptr;
  364. char ifstack[IFSTACKSIZE];
  365. char *ifptr;
  366. char *ifstmax = ifstack+IFSTACKSIZE-1;
  367. char hexadec[] = "0123456789ABCDEF" ;
  368. int nitems;
  369. int linecnt;
  370. int nbytes;
  371. int invented;
  372. int npass;
  373. int njrpromo;
  374. char tempbuf[TEMPBUFSIZE];
  375. char *tempmax = tempbuf+TEMPBUFSIZE-1;
  376. char arg_flag;
  377. struct argparse arg_state;
  378. void arg_start();
  379. void arg_reset();
  380. int str_getch(struct argparse *ap);
  381. char inmlex;
  382. char mlex_list_on;
  383. int parm_number;
  384. int exp_number;
  385. char symlong[] = "Symbol/number too long";
  386. int raw;
  387. int disp;
  388. int param_parse;
  389. #define PARAMTABSIZE (PARMMAX * 2)
  390. struct item paramtab[PARAMTABSIZE];
  391. #define FLOC PARMMAX
  392. #define TEMPNUM PARMMAX+1
  393. #define REPNUM PARMMAX+2
  394. #define MSTART PARMMAX+3
  395. #define MSTR PARMMAX+4
  396. #define MARGP PARMMAX+5
  397. #define MIF PARMMAX+6
  398. #define PAREXT 7
  399. union exprec {
  400. char *param;
  401. int value;
  402. struct argparse *ap;
  403. };
  404. union exprec *est;
  405. union exprec *est2;
  406. union exprec *expstack[MAXEXP];
  407. int expptr;
  408. int floc;
  409. int mfptr;
  410. FILE *mfile;
  411. char *writesyms;
  412. char *title;
  413. char titlespace[TITLELEN];
  414. char *timp;
  415. char *sourcef;
  416. /* changed to cope with filenames longer than 14 chars -rjm 1998-12-15 */
  417. char src[1024];
  418. char bin[1024];
  419. char mtmp[1024];
  420. char listf[1024];
  421. char bds[1024];
  422. char oth[1024];
  423. char bopt = 1,
  424. copt = 1, /* cycle counts in listings by default */
  425. edef = 1,
  426. eopt = 1,
  427. fdef = 0,
  428. fopt = 0,
  429. gdef = 1,
  430. gopt = 1,
  431. iopt = 0 , /* list include files */
  432. jopt = 0,
  433. JPopt = 0,
  434. lstoff = 0,
  435. lston = 0, /* flag to force listing on */
  436. lopt = 0,
  437. mdef = 0,
  438. mopt = 0,
  439. nopt = 1 , /* line numbers on as default */
  440. oopt = 0,
  441. popt = 1, /* form feed as default page eject */
  442. sopt = 0, /* turn on symbol table listing */
  443. topt = 1, /* terse, only error count to terminal */
  444. printer_output = 0, // GWP - printer style output
  445. z80,
  446. saveopt;
  447. char default_jopt, default_JPopt, default_z80 = 1;
  448. char xeq_flag = 0;
  449. int xeq;
  450. time_t now;
  451. int line;
  452. int page = 1;
  453. struct stab {
  454. char t_name[MAXSYMBOLSIZE+1];
  455. int t_value;
  456. int t_token;
  457. };
  458. // GWP - support for cycle count tracking (and opens door for efficient .cmd, etc. output)
  459. unsigned char memory[1 << 16];
  460. char memflag[1 << 16];
  461. enum {
  462. MEM_DATA = 1,
  463. MEM_INST = 2,
  464. MEM_T_SET = 4
  465. };
  466. int tstatesum[1 << 16];
  467. int ocfsum[1 << 16];
  468. // GWP - expression handling extensions for .rel output.
  469. void advance_segment(int step);
  470. void expr_reloc_check(struct expr *ex);
  471. void expr_number_check(struct expr *ex);
  472. void expr_scope_same(struct expr *ex1, struct expr *ex2);
  473. void expr_word_check(struct expr *ex);
  474. int is_number(struct expr *ex);
  475. int is_external(struct expr *ex);
  476. struct expr *expr_num(int value);
  477. struct expr *expr_alloc(void);
  478. struct expr *expr_op(struct expr *left, int token, struct expr *right, int value);
  479. struct expr *expr_op_sc(struct expr *left, int token, struct expr *right, int value);
  480. void expr_free(struct expr *ex);
  481. int can_extend_link(struct expr *ex);
  482. void extend_link(struct expr *ex);
  483. void putrelop(int op);
  484. #define RELOP_BYTE (1)
  485. #define RELOP_WORD (2)
  486. #define RELOP_HIGH (3)
  487. #define RELOP_LOW (4)
  488. #define RELOP_NOT (5)
  489. #define RELOP_NEG (6)
  490. #define RELOP_SUB (7)
  491. #define RELOP_ADD (8)
  492. #define RELOP_MUL (9)
  493. #define RELOP_DIV (10)
  494. #define RELOP_MOD (11)
  495. struct item *item_lookup(char *name, struct item *table, int table_size);
  496. struct item *locate(char *name);
  497. // Data descriptions for emit()
  498. #define E_CODE (0)
  499. #define E_DATA (1)
  500. #define E_CODE8 (2)
  501. #define E_CODE16 (3)
  502. int segment;
  503. #define SEGCHAR(s) " '\"!"[s]
  504. #define SEG_ABS (0)
  505. #define SEG_CODE (1)
  506. #define SEG_DATA (2)
  507. int seg_pos[4]; // may eventually support SEG_COMMON
  508. int seg_size[4];
  509. int rel_main;
  510. int segchange;
  511. void putout(int value);
  512. int outrec;
  513. int outlen;
  514. unsigned char outbuf[1024 * 1024];
  515. /*
  516. * push back character
  517. */
  518. int peekc;
  519. int nextline_peek;
  520. /* function prototypes */
  521. void error(char *as);
  522. void usage(char *msg, char *param);
  523. void help();
  524. void erreport();
  525. void errorprt(int errnum);
  526. void errwarn(int errnum, char *message);
  527. void mlex(char *look);
  528. void popsi();
  529. void suffix(char *str, char *suff);
  530. char *basename(char *filename);
  531. char *getsuffix(char *str);
  532. void outpath(char *out, char *src, char *suff);
  533. void casname(char *out, char *src);
  534. void putm(int c);
  535. void insymtab(char *name);
  536. void outsymtab(char *name);
  537. void compactsymtab();
  538. void putsymtab();
  539. void clear();
  540. void setmem(int addr, int value, int type);
  541. void setvars();
  542. void flushbin();
  543. void flushoth();
  544. void lineout();
  545. void puthex(int byte, FILE *buf);
  546. void putcas(int byte);
  547. void putrelbits(int count, int bits);
  548. void putrel(int byte);
  549. void putrelname(char *str);
  550. void putrelextaddr(int extaddr);
  551. void putrelcmd(int cmd);
  552. void putrelsegref(int scope, int addr);
  553. void flushrel(void);
  554. void lsterr1();
  555. void lsterr2(int lst);
  556. void copyname(char *st1, char *st2);
  557. void next_source(char *sp);
  558. void incbin(char *filename);
  559. void dc(int count, int value);
  560. char *getmraslocal();
  561. #define RELCMD_PUBLIC (0)
  562. #define RELCMD_COMMON (1)
  563. #define RELCMD_PROGNAME (2)
  564. #define RELCMD_LIBLOOK (3)
  565. #define RELCMD_EXTLINK (4)
  566. #define RELCMD_COMSIZE (5)
  567. #define RELCMD_EXTCHAIN (6)
  568. #define RELCMD_PUBVALUE (7)
  569. #define RELCMD_EXTMINUS (8)
  570. #define RELCMD_EXTPLUS (9)
  571. #define RELCMD_DATASIZE (10)
  572. #define RELCMD_SETLOC (11)
  573. #define RELCMD_CODESIZE (13)
  574. #define RELCMD_ENDMOD (14)
  575. #define RELCMD_ENDPROG (15)
  576. /*
  577. * add a character to the output line buffer
  578. */
  579. void addtoline(int ac)
  580. {
  581. /* check for EOF from stdio */
  582. if (ac == -1)
  583. ac = 0 ;
  584. if (lineptr >= linemax)
  585. error("line buffer overflow");
  586. *lineptr++ = ac;
  587. }
  588. /*
  589. * put values in buffer for outputing
  590. */
  591. void emit(int bytes, int desc, struct expr *data, ...)
  592. {
  593. int type, i, args, dsize;
  594. va_list ap;
  595. if (relopt && segchange) {
  596. segchange = 0;
  597. putrelcmd(RELCMD_SETLOC);
  598. putrelsegref(segment, seg_pos[segment]);
  599. }
  600. // External references only supported in .rel output.
  601. if (!relopt && data && (data->e_scope & SCOPE_EXTERNAL)) {
  602. sprintf(detail, "External references only allowed in .rel output\n");
  603. errwarn(uflag, detail);
  604. }
  605. va_start(ap, data);
  606. type = desc == E_DATA ? MEM_DATA : MEM_INST;
  607. // Check emit is not adding instructions to the buffer.
  608. if (desc != E_DATA && emitptr != emitbuf)
  609. fprintf(stderr, "internal inconsistency in t-state counting\n");
  610. dsize = 0;
  611. args = bytes;
  612. if (desc == E_DATA) {
  613. args = 0;
  614. dsize = bytes;
  615. }
  616. else if (desc == E_CODE16)
  617. dsize = 2;
  618. else if (desc == E_CODE8)
  619. dsize = 1;
  620. for (i = 0; i < args; i++)
  621. {
  622. if (emitptr >= &emitbuf[EMITBUFFERSIZE])
  623. error("emit buffer overflow");
  624. else {
  625. int addr = (emit_addr + (emitptr - emitbuf)) & 0xffff;
  626. *emitptr = va_arg(ap, int);
  627. if (segment == SEG_CODE)
  628. setmem(addr, *emitptr, type);
  629. putrel(*emitptr);
  630. putout(*emitptr);
  631. emitptr++;
  632. }
  633. }
  634. va_end(ap);
  635. for (i = 0; i < dsize; i++) {
  636. int addr = (emit_addr + (emitptr - emitbuf)) & 0xffff;
  637. *emitptr = data->e_value >> (i * 8);
  638. if (segment == SEG_CODE)
  639. setmem(addr, *emitptr, type);
  640. putout(*emitptr);
  641. emitptr++;
  642. }
  643. if (desc != E_DATA)
  644. {
  645. int eaddr = emit_addr, low, fetch, low8080, addr_after;
  646. // emitbuf is OK since this only happens with single emits
  647. if (!z80) {
  648. // Check for invalid 8080 instructions.
  649. int op = emitbuf[0] & 0xff;
  650. if (op == 0x08 || op == 0x10 || op == 0x18 ||
  651. op == 0x20 || op == 0x28 || op == 0x30 ||
  652. op == 0x38 || op == 0xCB || op == 0xD9 ||
  653. op == 0xDD || op == 0xED || op == 0xFD)
  654. {
  655. err[zflag]++;
  656. }
  657. }
  658. zi_tstates(emitbuf, &low, 0, &fetch, &low8080, 0);
  659. if (!z80)
  660. low = low8080;
  661. // Sanity check
  662. if (low <= 0)
  663. {
  664. fprintf(stderr, "undefined instruction on %02x %02x (assembler or diassembler broken)\n",
  665. emitbuf[0], emitbuf[1]);
  666. }
  667. // Special case to catch promotion of djnz to DEC B JP NZ
  668. // Even update the tstatesum[] counter though that seems to
  669. // me to be above and beyond.
  670. if (emitbuf[0] == 5 && args == 2) {
  671. tstatesum[eaddr] = tstates;
  672. ocfsum[eaddr] = ocf;
  673. memflag[eaddr] |= MEM_T_SET;
  674. eaddr++;
  675. tstates += low;
  676. ocf += fetch;
  677. low = 10;
  678. // still 1 fetch
  679. }
  680. // Double setting of both sides of tstatesum[] seems like too
  681. // much, but must be done in the isolated instruction case:
  682. // org x ; inc a ; org y
  683. tstatesum[eaddr] = tstates;
  684. ocfsum[eaddr] = ocf;
  685. memflag[eaddr] |= MEM_T_SET;
  686. // Well, OK, should we default to high or low???
  687. // Guess it should be whatever makes sense for you
  688. // to get here which, generally, is the low.
  689. // low it is.
  690. tstates += low;
  691. ocf += fetch;
  692. addr_after = (emit_addr + (emitptr - emitbuf)) & 0xffff;
  693. tstatesum[addr_after] = tstates;
  694. ocfsum[addr_after] = ocf;
  695. memflag[addr_after] |= MEM_T_SET;
  696. }
  697. if (relopt && outpass && dsize > 0) {
  698. if (dsize == 1) {
  699. if (is_number(data))
  700. putrel(data->e_value);
  701. else if (can_extend_link(data)) {
  702. extend_link(data);
  703. putrelop(RELOP_BYTE);
  704. putrel(0);
  705. }
  706. else {
  707. err[rflag]++;
  708. putrel(0);
  709. }
  710. }
  711. else if (dsize == 2) {
  712. int handled = 0;
  713. if (data->e_scope & SCOPE_EXTERNAL) {
  714. struct item *var = 0;
  715. int offset = 0;
  716. // Simple external reference.
  717. if (is_external(data))
  718. var = data->e_item;
  719. else if (is_external(data->e_left) &&
  720. data->e_token == '+' &&
  721. is_number(data->e_right))
  722. {
  723. var = data->e_left->e_item;
  724. offset = data->e_right->e_value;
  725. }
  726. else if (is_number(data->e_left) &&
  727. data->e_token == '+' &&
  728. is_external(data->e_right))
  729. {
  730. offset = data->e_left->e_value;
  731. var = data->e_right->e_item;
  732. }
  733. else if (is_external(data->e_left) &&
  734. data->e_token == '-' &&
  735. is_number(data->e_right))
  736. {
  737. var = data->e_left->e_item;
  738. offset = data->e_right->e_value;
  739. }
  740. if (var && offset) {
  741. putrelcmd(data->e_token == '-' ?
  742. RELCMD_EXTMINUS : RELCMD_EXTPLUS);
  743. // Theoretically we could put a
  744. // program or data relative value here...
  745. putrelsegref(SEG_ABS, offset);
  746. }
  747. if (var) {
  748. if (var->i_chain == 0) {
  749. putrel(0);
  750. putrel(0);
  751. }
  752. else {
  753. putrelbits(1, 1);
  754. putrelextaddr(var->i_chain);
  755. }
  756. var->i_chain = (segment << 16) |
  757. ((dollarsign + args) & 0xffff);
  758. handled = 1;
  759. }
  760. }
  761. else if ((data->e_scope & ~SCOPE_PUBLIC) == 0) {
  762. // nice constant value
  763. putrel(data->e_value);
  764. putrel(data->e_value >> 8);
  765. handled = 1;
  766. }
  767. else if (!(data->e_scope & SCOPE_NORELOC)) {
  768. // relocatable value
  769. putrelbits(1, 1);
  770. putrelbits(2, data->e_scope);
  771. putrelbits(8, data->e_value);
  772. putrelbits(8, data->e_value >> 8);
  773. handled = 1;
  774. }
  775. if (!handled) {
  776. if (can_extend_link(data)) {
  777. extend_link(data);
  778. putrelop(RELOP_WORD);
  779. putrel(0);
  780. putrel(0);
  781. }
  782. else {
  783. err[rflag]++;
  784. putrel(data->e_value);
  785. putrel(data->e_value >> 8);
  786. }
  787. }
  788. }
  789. else if (dsize == 4) {
  790. // Only numbers are allowed.
  791. if (data->e_scope != 0) {
  792. err[vflag]++;
  793. if (data->e_scope & SCOPE_NORELOC)
  794. err[rflag]++;
  795. }
  796. for (i = 0; i < dsize; i++)
  797. putrel(data->e_value >> (i * 8));
  798. }
  799. else
  800. error("internal dsize error");
  801. }
  802. }
  803. #define ET_NOARG_DISP (0)
  804. #define ET_NOARG (1)
  805. #define ET_BYTE (2)
  806. #define ET_WORD (5)
  807. void emit1(int opcode, int regvalh, struct expr *data, int type)
  808. {
  809. if (type == ET_BYTE && (data->e_value < -128 || data->e_value > 255))
  810. err[vflag]++;
  811. if (regvalh & 0x10000) {
  812. switch (type) {
  813. case ET_NOARG_DISP:
  814. emit(2, E_CODE, 0, regvalh >> 8, opcode);
  815. break;
  816. case ET_BYTE:
  817. emit(2, E_CODE8, data, regvalh >> 8, opcode);
  818. break;
  819. }
  820. }
  821. else if (regvalh & 0x8000) {
  822. switch (type) {
  823. case ET_NOARG_DISP:
  824. if (opcode & 0x8000)
  825. emit(4, E_CODE, 0, regvalh >> 8, opcode >> 8, disp, opcode);
  826. else
  827. emit(3, E_CODE, 0, regvalh >> 8, opcode, disp);
  828. break;
  829. case ET_NOARG:
  830. emit(2, E_CODE, 0, regvalh >> 8, opcode);
  831. break;
  832. case ET_BYTE:
  833. emit(3, E_CODE8, data, regvalh >> 8, opcode, disp);
  834. break;
  835. case ET_WORD:
  836. emit(2, E_CODE16, data, regvalh >> 8, opcode);
  837. }
  838. } else
  839. switch(type) {
  840. case ET_NOARG_DISP:
  841. case ET_NOARG:
  842. if (opcode & 0100000)
  843. emit(2, E_CODE, 0, opcode >> 8, opcode);
  844. else
  845. emit(1, E_CODE, 0, opcode);
  846. break;
  847. case ET_BYTE:
  848. emit(1, E_CODE8, data, opcode);
  849. break;
  850. case ET_WORD:
  851. if (opcode & 0100000)
  852. emit(2, E_CODE16, data, opcode >> 8, opcode);
  853. else
  854. emit(1, E_CODE16, data, opcode);
  855. }
  856. }
  857. void emitdad(int rp1,int rp2)
  858. {
  859. if (rp1 & 0x8000)
  860. emit(2, E_CODE, 0, rp1 >> 8, rp2 + 9);
  861. else
  862. emit(1, E_CODE, 0, rp2 + 9);
  863. }
  864. void emitjr(int opcode, struct expr *dest)
  865. {
  866. int disp = dest->e_value - dollarsign - 2;
  867. if (dest->e_scope & SCOPE_NORELOC)
  868. err[rflag]++;
  869. // Can't relative jump to other segments or an external
  870. // However, without .rel output we default to the code segment
  871. // for various reasons thus we let "jr 0" (and such) be acceptable
  872. // in those cases.
  873. if (((relopt && (dest->e_scope & SCOPE_SEGMASK) != segment) ||
  874. (dest->e_scope & SCOPE_EXTERNAL) ||
  875. disp > 127 || disp < -128) && z80)
  876. {
  877. if (jopt) {
  878. njrpromo++;
  879. switch (opcode) {
  880. case 0x10: // DJNZ
  881. emit(2, E_CODE16, dest, 0x05, 0xC2); // DEC B, JP NZ
  882. break;
  883. case 0x18: // JR
  884. emit(1, E_CODE16, dest, 0xC3); // JP
  885. break;
  886. case 0x20: // JR NZ
  887. emit(1, E_CODE16, dest, 0xC2); // JP NZ
  888. break;
  889. case 0x28: // JR Z
  890. emit(1, E_CODE16, dest, 0xCA); // JP Z
  891. break;
  892. case 0x30: // JR NC
  893. emit(1, E_CODE16, dest, 0xD2); // JP NC
  894. break;
  895. case 0x38: // JR C
  896. emit(1, E_CODE16, dest, 0xDA); // JP C
  897. break;
  898. default:
  899. err[vflag]++; // shouldn't happen!
  900. expr_free(dest);
  901. break;
  902. }
  903. }
  904. else {
  905. emit(2, E_CODE, 0, opcode, -2); // branch to itself
  906. err[vflag]++;
  907. expr_free(dest);
  908. }
  909. }
  910. else {
  911. emit(2, E_CODE, 0, opcode, disp);
  912. expr_free(dest);
  913. }
  914. }
  915. void checkjp(int op, struct expr *dest)
  916. {
  917. op &= 0x030;
  918. // Only applies to Z-80 output and if JP optimization checking is on.
  919. // JR only has z, nz, nc, c
  920. // A jump to the current segment might have been optimizable
  921. if (z80 && JPopt && (op == 0 || op == 010 || op == 020 || op == 030) &&
  922. (dest->e_scope & (SCOPE_SEGMASK | SCOPE_EXTERNAL)) == segment)
  923. {
  924. int disp = dest->e_value - dollarsign - 2;
  925. if (disp >= -128 && disp <= 127)
  926. err[jflag]++;
  927. }
  928. }
  929. /*
  930. * put out a byte of binary
  931. */
  932. void putbin(int v)
  933. {
  934. if(!outpass || !bopt) return;
  935. *outbinp++ = v;
  936. if (outbinp >= outbinm) flushbin();
  937. outoth[outoth_cnt++] = v;
  938. if (outoth_cnt == 256) flushoth();
  939. }
  940. /*
  941. * output one line of binary in INTEL standard form
  942. */
  943. void flushbin()
  944. {
  945. char *p;
  946. int check=outbinp-outbin;
  947. if (!outpass || !bopt)
  948. return;
  949. nbytes += check;
  950. if (check) {
  951. putc(':', fbuf);
  952. puthex(check, fbuf);
  953. puthex(olddollar>>8, fbuf);
  954. puthex(olddollar, fbuf);
  955. puthex(0, fbuf);
  956. check += (olddollar >> 8) + olddollar;
  957. olddollar += (outbinp-outbin);
  958. for (p=outbin; p<outbinp; p++) {
  959. puthex(*p, fbuf);
  960. check += *p;
  961. }
  962. puthex(256-check, fbuf);
  963. putc('\n', fbuf);
  964. outbinp = outbin;
  965. }
  966. }
  967. /*
  968. * put out one byte of hex
  969. */
  970. void puthex(int byte, FILE *buf)
  971. {
  972. putc(hexadec[(byte >> 4) & 017], buf);
  973. putc(hexadec[byte & 017], buf);
  974. }
  975. // Case-independent strcmp()
  976. int ci_strcmp(char *s1, char *s2)
  977. {
  978. int c1, c2;
  979. do {
  980. c1 = *s1++;
  981. if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A';
  982. c2 = *s2++;
  983. if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A';
  984. if (c1 != c2)
  985. return c1 - c2;
  986. } while (c1 && c2);
  987. return 0;
  988. }
  989. void flushoth()
  990. {
  991. int i, checksum;
  992. if (!outpass || !bopt || outoth_cnt == 0)
  993. return;
  994. fprintf(fcmd, "%c%c%c%c", 1, outoth_cnt + 2, oldothdollar, oldothdollar >> 8);
  995. fwrite(outoth, outoth_cnt, 1, fcmd);
  996. putcas(0x3c);
  997. putcas(outoth_cnt);
  998. putcas(oldothdollar);
  999. putcas(oldothdollar >> 8);
  1000. checksum = oldothdollar + (oldothdollar >> 8);
  1001. for (i = 0; i < outoth_cnt; i++) {
  1002. putcas(outoth[i]);
  1003. checksum += outoth[i];
  1004. }
  1005. putcas(checksum);
  1006. oldothdollar += outoth_cnt;
  1007. outoth_cnt = 0;
  1008. }
  1009. int casbit, casbitcnt = 0;
  1010. void putcas(int byte)
  1011. {
  1012. fputc(byte, flcas);
  1013. // Buffer 0 stop bit and the 8 data bits.
  1014. casbit = (casbit << 9) | (byte & 0xff);
  1015. casbitcnt += 9;
  1016. while (casbitcnt >= 8) {
  1017. casbitcnt -= 8;
  1018. fputc(casbit >> casbitcnt, fcas);
  1019. }
  1020. }
  1021. void casname(char *out, char *src)
  1022. {
  1023. char *base = basename(src);
  1024. int i;
  1025. out[0] = 'N';
  1026. for (i = 1; i < 6; i++)
  1027. out[i] = ' ';
  1028. for (i = 0; *base && i < 6; base++) {
  1029. if (ci_strcmp(base, ".z") == 0)
  1030. break;
  1031. if (*base >= 'a' && *base <= 'z') {
  1032. *out++ = *base - ('a' - 'A');
  1033. i++;
  1034. }
  1035. else if (*base >= 'A' && *base <= 'Z') {
  1036. *out++ = *base;
  1037. i++;
  1038. }
  1039. }
  1040. }
  1041. int relbit, relbitcnt = 0;
  1042. void putrelbits(int count, int bits)
  1043. {
  1044. if (!outpass || !relopt)
  1045. return;
  1046. relbit <<= count;
  1047. relbit |= bits & ((1 << count) - 1);
  1048. relbitcnt += count;
  1049. while (relbitcnt >= 8) {
  1050. relbitcnt -= 8;
  1051. fputc(relbit >> relbitcnt, frel);
  1052. }
  1053. }
  1054. void putrel(int byte)
  1055. {
  1056. // Add 0 bit indicating byte to load at next counter
  1057. putrelbits(1, 0);
  1058. // Add byte to load
  1059. putrelbits(8, byte);
  1060. }
  1061. void putrelname(char *str)
  1062. {
  1063. int len = strlen(str);
  1064. // .rel file format can do strings 7 long but for compatibility
  1065. // we restrict them to 6. I believe this is important because
  1066. // extended link functions require a character when they wish to
  1067. // operate on an external symbol.
  1068. if (len > 6)
  1069. len = 6;
  1070. putrelbits(3, len);
  1071. while (len-- > 0) {
  1072. int ch = *str++;
  1073. if (ch >= 'a' && ch <= 'z')
  1074. ch -= 'a' - 'A';
  1075. putrelbits(8, ch);
  1076. }
  1077. }
  1078. void putrelsegref(int scope, int addr)
  1079. {
  1080. putrelbits(2, scope);
  1081. putrelbits(8, addr);
  1082. putrelbits(8, addr >> 8);
  1083. }
  1084. void putrelextaddr(int extaddr)
  1085. {
  1086. putrelsegref(extaddr >> 16, extaddr);
  1087. }
  1088. void putrelcmd(int relcmd)
  1089. {
  1090. putrelbits(1, 1);
  1091. putrelbits(2, 0);
  1092. putrelbits(4, relcmd);
  1093. }
  1094. void flushrel(void)
  1095. {
  1096. if (relbitcnt > 0)
  1097. putrelbits(8 - relbitcnt, 0);
  1098. if (relopt)
  1099. fflush(frel);
  1100. }
  1101. /*
  1102. * put out a line of output -- also put out binary
  1103. */
  1104. void list(int optarg)
  1105. {
  1106. unsigned char * p;
  1107. int i;
  1108. int lst;
  1109. char seg = ' ';
  1110. if (!expptr)
  1111. linecnt++;
  1112. addtoline('\0');
  1113. if (outpass) {
  1114. lst = iflist();
  1115. if (lst) {
  1116. lineout();
  1117. if (nopt)
  1118. fprintf(fout, "%4d:", linein[now_in]);
  1119. if (copt)
  1120. {
  1121. if (emitptr > emitbuf && (memflag[emit_addr] & MEM_INST))
  1122. {
  1123. int low, high, fetch, low8080, high8080;
  1124. zi_tstates(memory + emit_addr, &low, &high, &fetch, &low8080, &high8080);
  1125. if (!z80) {
  1126. low = low8080;
  1127. high = high8080;
  1128. }
  1129. // Special case to catch promotion of djnz to DEC B JP NZ
  1130. if (memory[emit_addr] == 5 && emitptr - emitbuf == 4) {
  1131. low += 10;
  1132. high += 10;
  1133. }
  1134. fprintf(fout, nopt ? "%5d" : "%4d", tstatesum[emit_addr]);
  1135. fprintf(fout, "+%d", low);
  1136. if (low != high)
  1137. fprintf(fout, "+%d", high - low);
  1138. }
  1139. else
  1140. {
  1141. fprintf(fout, nopt ? "%5s-" : "%4s-", "");
  1142. }
  1143. }
  1144. if (nopt || copt)
  1145. fprintf(fout, "\t");
  1146. puthex(optarg >> 8, fout);
  1147. puthex(optarg, fout);
  1148. if (relopt)
  1149. seg = SEGCHAR(segment);
  1150. fputc(seg, fout);
  1151. fputc(' ', fout);
  1152. for (p = emitbuf; (p < emitptr) && (p - emitbuf < 4); p++) {
  1153. puthex(*p, fout);
  1154. }
  1155. for (i = 4 - (p-emitbuf); i > 0; i--)
  1156. fputs(" ", fout);
  1157. putc('\t', fout);
  1158. fputs(linebuf, fout);
  1159. }
  1160. if (bopt) {
  1161. if (emitptr > emitbuf) {
  1162. fprintf(fbds, "%04x %04x d ", dollarsign, emit_addr);
  1163. for (p = emitbuf; p < emitptr; p++)
  1164. fprintf(fbds, "%02x", *p & 0xff);
  1165. fprintf(fbds, "\n");
  1166. }
  1167. fprintf(fbds, "%04x %04x s %s", dollarsign, emit_addr, linebuf);
  1168. for (p = emitbuf; p < emitptr; p++)
  1169. putbin(*p);
  1170. }
  1171. p = emitbuf+4;
  1172. while (lst && gopt && p < emitptr) {
  1173. lineout();
  1174. if (nopt) putc('\t', fout);
  1175. fputs(" ", fout);
  1176. for (i = 0; (i < 4) && (p < emitptr);i++) {
  1177. puthex(*p, fout);
  1178. p++;
  1179. }
  1180. putc('\n', fout);
  1181. }
  1182. lsterr2(lst);
  1183. } else
  1184. lsterr1();
  1185. dollarsign += emitptr - emitbuf;
  1186. emit_addr += emitptr - emitbuf;
  1187. dollarsign &= 0xffff;
  1188. emit_addr &= 0xffff;
  1189. emitptr = emitbuf;
  1190. lineptr = linebuf;
  1191. }
  1192. /*
  1193. * keep track of line numbers and put out headers as necessary
  1194. */
  1195. void lineout()
  1196. {
  1197. if (!printer_output)
  1198. return;
  1199. if (line == 60) {
  1200. if (popt)
  1201. putc('\014', fout); /* send the form feed */
  1202. else
  1203. fputs("\n\n\n\n\n", fout);
  1204. line = 0;
  1205. }
  1206. if (line == 0) {
  1207. fprintf(fout, "\n\n%s %s\t%s\t Page %d\n\n\n",
  1208. &timp[4], &timp[20], title, page++);
  1209. line = 4;
  1210. }
  1211. line++;
  1212. }
  1213. /*
  1214. * cause a page eject
  1215. */
  1216. void eject()
  1217. {
  1218. if (printer_output)
  1219. return;
  1220. if (outpass && iflist()) {
  1221. if (popt) {
  1222. putc('\014', fout); /* send the form feed */
  1223. } else {
  1224. while (line < 65) {
  1225. line++;
  1226. putc('\n', fout);
  1227. }
  1228. }
  1229. }
  1230. line = 0;
  1231. }
  1232. /*
  1233. * space n lines on the list file
  1234. */
  1235. void space(int n)
  1236. {
  1237. int i ;
  1238. if (outpass && iflist())
  1239. for (i = 0; i<n; i++) {
  1240. lineout();
  1241. putc('\n', fout);
  1242. }
  1243. }
  1244. /*
  1245. * Error handling - pass 1
  1246. */
  1247. void lsterr1()
  1248. {
  1249. int i;
  1250. for (i = 0; i <= mflag; i++)
  1251. if (err[i]) {
  1252. if (topt)
  1253. errorprt(i);
  1254. passfail = 1;
  1255. err[i] = 0;
  1256. }
  1257. }
  1258. /*
  1259. * Error handling - pass 2.
  1260. */
  1261. void lsterr2(int lst)
  1262. {
  1263. int i;
  1264. for (i=0; i<FLAGS; i++)
  1265. if (err[i]) {
  1266. if (i < FIRSTWARN)
  1267. passfail = 1;
  1268. if (lst) {
  1269. char *desc = errname[i];
  1270. char *type = i < FIRSTWARN ? " error" : " warning";
  1271. if (errdetail[i][0]) {
  1272. desc = errdetail[i];
  1273. type = "";
  1274. }
  1275. lineout();
  1276. fprintf(fout, "%c %s%s\n",
  1277. errlet[i], desc, type);
  1278. }
  1279. err[i] = 0;
  1280. keeperr[i]++;
  1281. if (i > mflag && topt)
  1282. errorprt(i);
  1283. }
  1284. fflush(fout); /*to avoid putc(har) mix bug*/
  1285. }
  1286. /*
  1287. * print diagnostic to error terminal
  1288. */
  1289. void errorprt(int errnum)
  1290. {
  1291. char *desc = errname[errnum];
  1292. char *type = errnum < FIRSTWARN ? " error" : " warning";
  1293. if (errdetail[errnum][0]) {
  1294. desc = errdetail[errnum];
  1295. type = "";
  1296. }
  1297. fprintf(stderr, "%s(%d) : %s%s",
  1298. src_name[now_in], linein[now_in], desc, type);
  1299. errdetail[errnum][0] = '\0';
  1300. fprintf(stderr, "\n");
  1301. fprintf(stderr, "%s\n", linebuf);
  1302. fflush(stderr) ;
  1303. }
  1304. void errwarn(int errnum, char *message)
  1305. {
  1306. err[errnum]++;
  1307. strcpy(errdetail[errnum], message);
  1308. }
  1309. /*
  1310. * list without address -- for comments and if skipped lines
  1311. */
  1312. void list1()
  1313. {
  1314. int lst;
  1315. addtoline('\0');
  1316. lineptr = linebuf;
  1317. if (!expptr) linecnt++;
  1318. if (outpass) {
  1319. if ((lst = iflist())) {
  1320. lineout();
  1321. if (nopt)
  1322. fprintf(fout, "%4d:\t", linein[now_in]);
  1323. if (copt)
  1324. fprintf(fout, "\t");
  1325. fprintf(fout, "\t\t%s", linebuf);
  1326. lsterr2(lst);
  1327. }
  1328. if (bopt)
  1329. fprintf(fbds, "%04x %04x s %s", dollarsign, emit_addr, linebuf);
  1330. }
  1331. else
  1332. lsterr1();
  1333. }
  1334. /*
  1335. * see if listing is desired
  1336. */
  1337. int iflist()
  1338. {
  1339. int i, j;
  1340. if (inmlex)
  1341. return mlex_list_on;
  1342. if (lston)
  1343. return(1) ;
  1344. if (lopt)
  1345. return(0);
  1346. if (*ifptr && !fopt)
  1347. return(0);
  1348. if (!lstoff && !expptr)
  1349. return(1);
  1350. j = 0;
  1351. for (i=0; i<FLAGS; i++)
  1352. if (err[i])
  1353. j++;
  1354. if (expptr)
  1355. return(mopt || j);
  1356. if (eopt && j)
  1357. return(1);
  1358. return(0);
  1359. }
  1360. void do_equ(struct item *sym, struct expr *val, int call_list);
  1361. void do_defl(struct item *sym, struct expr *val, int call_list);
  1362. // GWP - This avoids an apparent bug in bison as it tries to start out the
  1363. // Not needed under gcc which defines __STDC__ so I guard it to prevent
  1364. // warnings.
  1365. // yyparse() function with yyparse() ; { }.
  1366. #ifndef __STDC__
  1367. #define __STDC__
  1368. #endif
  1369. #define PSTITL (0) /* title */
  1370. #define PSRSYM (1) /* rsym */
  1371. #define PSWSYM (2) /* wsym */
  1372. #define PSINC (3) /* include file */
  1373. #define PSMACLIB (4) /* maclib (similar to include) */
  1374. #define SPTITL (0) /* title */
  1375. #define SPSBTL (1) /* sub title */
  1376. #define SPNAME (2) /* name */
  1377. #define SPCOM (3) /* comment */
  1378. #define SPPRAGMA (4) /* pragma */
  1379. %}
  1380. %union {
  1381. struct expr *exprptr;
  1382. struct item *itemptr;
  1383. int ival;
  1384. char *cval;
  1385. }
  1386. %token <cval> STRING
  1387. %token <itemptr> NOOPERAND
  1388. %token <itemptr> ARITHC
  1389. %token ADD
  1390. %token <itemptr> LOGICAL
  1391. %token <itemptr> AND
  1392. %token <itemptr> OR
  1393. %token <itemptr> XOR
  1394. %token <ival> ANDAND
  1395. %token <ival> OROR
  1396. %token <itemptr> BIT
  1397. %token CALL
  1398. %token <itemptr> INCDEC
  1399. %token <itemptr> DJNZ
  1400. %token EX
  1401. %token <itemptr> IM
  1402. %token PHASE
  1403. %token DEPHASE
  1404. %token <itemptr> TK_IN
  1405. %token <itemptr> JR
  1406. %token LD
  1407. %token <itemptr> TK_OUT
  1408. %token <itemptr> PUSHPOP
  1409. %token <itemptr> RET
  1410. %token <itemptr> SHIFT
  1411. %token <itemptr> RST
  1412. %token <itemptr> REGNAME
  1413. %token <itemptr> IXYLH
  1414. %token <itemptr> ACC
  1415. %token <itemptr> C
  1416. %token <itemptr> RP
  1417. %token <itemptr> HL
  1418. %token <itemptr> INDEX
  1419. %token <itemptr> AF
  1420. %token AFp
  1421. %token <itemptr> SP
  1422. %token <itemptr> MISCREG
  1423. %token <itemptr> COND
  1424. %token <itemptr> SPCOND
  1425. %token <ival> NUMBER
  1426. %token <itemptr> UNDECLARED
  1427. %token END
  1428. %token ORG
  1429. %token ASSERT
  1430. %token TSTATE
  1431. %token <ival> T
  1432. %token <ival> TILO
  1433. %token <ival> TIHI
  1434. %token SETOCF
  1435. %token <ival> OCF
  1436. %token <ival> LOW
  1437. %token <ival> HIGH
  1438. %token DC
  1439. %token DEFB
  1440. %token DEFD
  1441. %token DEFS
  1442. %token DEFW
  1443. %token EQU
  1444. %token DEFL
  1445. %token <itemptr> LABEL
  1446. %token <itemptr> EQUATED
  1447. %token <itemptr> WASEQUATED
  1448. %token <itemptr> DEFLED
  1449. %token <itemptr> MULTDEF
  1450. %token <ival> MOD
  1451. %token <ival> SHL
  1452. %token <ival> SHR
  1453. %token <ival> NOT
  1454. %token <ival> LT
  1455. %token <ival> GT
  1456. %token <ival> LE
  1457. %token <ival> GE
  1458. %token <ival> NE
  1459. %token IF_TK
  1460. %token ELSE_TK
  1461. %token ENDIF_TK
  1462. %token <itemptr> ARGPSEUDO
  1463. %token <itemptr> INCBIN
  1464. %token <itemptr> LIST
  1465. %token <itemptr> MINMAX
  1466. %token MACRO
  1467. %token <itemptr> MNAME
  1468. %token ARG
  1469. %token ENDM
  1470. %token <ival> ONECHAR
  1471. %token <ival> TWOCHAR
  1472. %token JRPROMOTE
  1473. %token JPERROR
  1474. %token PUBLIC
  1475. %token EXTRN
  1476. %token MRAS_MOD
  1477. %token <itemptr> SETSEG INSTSET
  1478. %token LXI DAD STAX STA SHLD LDAX LHLD LDA MVI MOV
  1479. %token <itemptr> INXDCX INRDCR PSW JUMP8 JP CALL8 ALUI8
  1480. %token <itemptr> SPECIAL
  1481. %token RAWTOKEN LOCAL
  1482. // New token types for ZNONSTD support
  1483. %token <itemptr> LD_XY ST_XY MV_XY ALU_XY BIT_XY SHIFT_XY INP OUTP JR_COND
  1484. %token <itemptr> LDST16 ARITH16
  1485. // Tokens for improved macro support
  1486. %token REPT IRPC IRP EXITM
  1487. %token NUL
  1488. %token <itemptr> MPARM
  1489. %type <itemptr> label.part symbol
  1490. %type <ival> allreg reg evenreg ixylhreg realreg mem memxy pushable bcdesp bcdehlsp mar condition
  1491. %type <ival> spcondition
  1492. %type <exprptr> noparenexpr parenexpr expression lxexpression
  1493. %type <ival> maybecolon maybeocto
  1494. %type <ival> evenreg8 reg8 m pushable8
  1495. // Types for improved macro support
  1496. %type <cval> locals
  1497. %right '?' ':'
  1498. %left OROR
  1499. %left ANDAND
  1500. %left '|' OR
  1501. %left '^' XOR
  1502. %left '&' AND
  1503. %left '=' NE
  1504. %left '<' '>' LT GT LE GE
  1505. %left SHL SHR
  1506. %left '+' '-'
  1507. %left '*' '/' '%' MOD
  1508. %right '!' '~' NOT UNARY
  1509. %{
  1510. char *cp;
  1511. int i;
  1512. void do_equ(struct item *sym, struct expr *val, int call_list)
  1513. {
  1514. expr_reloc_check(val);
  1515. switch(sym->i_token) {
  1516. case UNDECLARED: case WASEQUATED:
  1517. if (sym->i_token == WASEQUATED &&
  1518. (sym->i_value != val->e_value ||
  1519. ((sym->i_scope ^ val->e_scope) & SCOPE_SEGMASK)))
  1520. {
  1521. if (outpass) {
  1522. if (sym->i_value != val->e_value)
  1523. sprintf(detail, "%s error - %s went from $%04x to $%04x",
  1524. errname[pflag], sym->i_string, sym->i_value, val->e_value);
  1525. else
  1526. sprintf(detail, "%s error - %s changed scope",
  1527. errname[pflag], sym->i_string);
  1528. errwarn(pflag, detail);
  1529. }
  1530. else
  1531. passretry = 1;
  1532. }
  1533. sym->i_token = EQUATED;
  1534. sym->i_value = val->e_value;
  1535. sym->i_scope |= val->e_scope;
  1536. break;
  1537. default:
  1538. // m80 allows multiple equates as long as the value
  1539. // does not change. So does newer zmac.
  1540. if (sym->i_value != val->e_value ||
  1541. ((sym->i_scope ^ val->e_scope) & SCOPE_SEGMASK))
  1542. {
  1543. err[mflag]++;
  1544. sym->i_token = MULTDEF;
  1545. }
  1546. }
  1547. sym->i_scope &= ~SCOPE_BUILTIN;
  1548. if (call_list)
  1549. list(val->e_value);
  1550. expr_free(val);
  1551. }
  1552. void do_defl(struct item *sym, struct expr *val, int call_list)
  1553. {
  1554. expr_reloc_check(val);
  1555. switch(sym->i_token) {
  1556. case UNDECLARED: case DEFLED:
  1557. sym->i_token = DEFLED;
  1558. sym->i_value = val->e_value;
  1559. sym->i_scope = (sym->i_scope & SCOPE_SEGMASK) | val->e_scope;
  1560. break;
  1561. default:
  1562. err[mflag]++;
  1563. sym->i_token = MULTDEF;
  1564. }
  1565. if (call_list)
  1566. list(val->e_value);
  1567. expr_free(val);
  1568. }
  1569. %}
  1570. %%
  1571. statements:
  1572. /* Empty file! */
  1573. |
  1574. statements statement
  1575. ;
  1576. statement:
  1577. label.part '\n' {
  1578. // An identfier without a colon all by itself on a line
  1579. // will be interpreted as a label. But there's a very
  1580. // good chance it is a misspelling of an instruction or
  1581. // pseudo-op name creating silent errors. Since the condition
  1582. // is unusual we print a warning. Unless it is followed by
  1583. // a colon in which case there's no ambiguity.
  1584. if ($1 && !firstcol && coloncnt == 0 && outpass) {
  1585. fprintf(stderr, "%s(%d): warning: '%s' treated as label (instruction typo?)\n",
  1586. src_name[now_in], linein[now_in], $1->i_string);
  1587. fprintf(stderr, "\tAdd a colon or move to first column to stop this warning.\n");
  1588. }
  1589. if ($1) list(dollarsign);
  1590. else list1();
  1591. }
  1592. |
  1593. label.part { list_dollarsign = 1; } operation '\n' {
  1594. list(list_dollarsign ? dollarsign : list_addr);
  1595. }
  1596. |
  1597. symbol EQU expression '\n' {
  1598. do_equ($1, $3, 1);
  1599. }
  1600. |
  1601. symbol '=' expression '\n' {
  1602. do_equ($1, $3, 1); // TODO: is '=' equate or defl?
  1603. }
  1604. |
  1605. symbol DEFL expression '\n' {
  1606. do_defl($1, $3, 1);
  1607. }
  1608. |
  1609. symbol MINMAX expression ',' expression '\n' {
  1610. int val3 = $3->e_value;
  1611. int val5 = $5->e_value;
  1612. expr_reloc_check($3);
  1613. expr_reloc_check($5);
  1614. expr_scope_same($3, $5);
  1615. switch ($1->i_token) {
  1616. case UNDECLARED: case DEFLED:
  1617. $1->i_token = DEFLED;
  1618. $1->i_scope |= $3->e_scope;
  1619. if ($2->i_value) /* max */
  1620. list($1->i_value = (val3 > val5? val3:val5));
  1621. else list($1->i_value = (val3 < val5? val3:val5));
  1622. break;
  1623. default:
  1624. err[mflag]++;
  1625. $1->i_token = MULTDEF;
  1626. list($1->i_value);
  1627. }
  1628. expr_free($3);
  1629. expr_free($5);
  1630. }
  1631. |
  1632. IF_TK expression '\n' {
  1633. expr_number_check($2);
  1634. if (ifptr >= ifstmax)
  1635. error("Too many ifs");
  1636. else
  1637. *++ifptr = !($2->e_value);
  1638. saveopt = fopt;
  1639. fopt = 1;
  1640. list($2->e_value);
  1641. fopt = saveopt;
  1642. expr_free($2);
  1643. }
  1644. |
  1645. ELSE_TK '\n' {
  1646. /* FIXME: it would be nice to spot repeated ELSEs, but how? */
  1647. *ifptr = !*ifptr;
  1648. saveopt = fopt;
  1649. fopt = 1;
  1650. list1();
  1651. fopt = saveopt;
  1652. }
  1653. |
  1654. ENDIF_TK '\n' {
  1655. if (ifptr == ifstack) err[bflag]++;
  1656. else --ifptr;
  1657. list1();
  1658. }
  1659. |
  1660. label.part END '\n' {
  1661. list(dollarsign);
  1662. peekc = 0;
  1663. }
  1664. |
  1665. label.part END expression '\n' {
  1666. expr_reloc_check($3);
  1667. xeq_flag++;
  1668. xeq = $3->e_value & 0xffff;
  1669. list($3->e_value);
  1670. peekc = 0;
  1671. rel_main = (($3->e_scope & SCOPE_SEGMASK) << 16) | xeq;
  1672. expr_free($3);
  1673. }
  1674. |
  1675. label.part DEFS expression '\n' {
  1676. expr_number_check($3);
  1677. if ($3->e_value < 0) err[vflag]++;
  1678. if ($3->e_value > 0) {
  1679. if (!phaseflag) {
  1680. list(dollarsign);
  1681. flushbin();
  1682. flushoth();
  1683. dollarsign += $3->e_value;
  1684. olddollar += $3->e_value;
  1685. oldothdollar += $3->e_value;
  1686. emit_addr += $3->e_value;
  1687. advance_segment($3->e_value);
  1688. putrelcmd(RELCMD_SETLOC);
  1689. putrelsegref(segment, seg_pos[segment]);
  1690. }
  1691. else
  1692. dc($3->e_value, 0);
  1693. }
  1694. else
  1695. list1();
  1696. expr_free($3);
  1697. }
  1698. |
  1699. label.part DEFS expression ',' expression '\n' {
  1700. expr_number_check($3);
  1701. expr_number_check($5);
  1702. if ($3->e_value < 0) err[vflag]++;
  1703. if ($5->e_value < -128 || $5->e_value > 127) err[vflag]++;
  1704. if ($3->e_value > 0) {
  1705. dc($3->e_value, $5->e_value);
  1706. }
  1707. else
  1708. list1();
  1709. expr_free($3);
  1710. expr_free($5);
  1711. }
  1712. |
  1713. label.part DC ONECHAR '\n' { emit(1, E_DATA, expr_num($3 | 0x80)); list(dollarsign); }
  1714. |
  1715. label.part DC TWOCHAR '\n' { emit(1, E_DATA, expr_num($3)); emit(1, E_DATA, expr_num(($3 >> 8) | 0x80)); list(dollarsign); }
  1716. |
  1717. label.part DC STRING '\n'
  1718. {
  1719. for (cp = $3; *cp != '\0'; cp++)
  1720. if (!cp[1])
  1721. emit(1, E_DATA, expr_num(*cp | 0x80));
  1722. else
  1723. emit(1, E_DATA, expr_num(*cp));
  1724. list(dollarsign);
  1725. }
  1726. |
  1727. label.part DC expression ',' expression '\n'
  1728. {
  1729. expr_number_check($3);
  1730. expr_number_check($5);
  1731. dc($3->e_value, $5->e_value);
  1732. expr_free($3);
  1733. expr_free($5);
  1734. }
  1735. |
  1736. ARGPSEUDO arg_on ARG arg_off '\n' {
  1737. list1();
  1738. switch ($1->i_value) {
  1739. case PSTITL: /* title */
  1740. lineptr = linebuf;
  1741. cp = tempbuf;
  1742. title = titlespace;
  1743. while ((*title++ = *cp++) && (title < &titlespace[TITLELEN]));
  1744. *title = 0;
  1745. title = titlespace;
  1746. break;
  1747. case PSRSYM: /* rsym */
  1748. if (pass2) break;
  1749. insymtab(tempbuf);
  1750. break;
  1751. case PSWSYM: /* wsym */
  1752. writesyms = malloc(strlen(tempbuf)+1);
  1753. strcpy(writesyms, tempbuf);
  1754. break;
  1755. case PSINC: /* include file */
  1756. next_source(tempbuf) ;
  1757. break ;
  1758. case PSMACLIB:
  1759. strcat(tempbuf, ".lib");
  1760. next_source(tempbuf);
  1761. break;
  1762. }
  1763. }
  1764. |
  1765. ARGPSEUDO arg_on arg_off '\n' {
  1766. fprintf(stderr, "Missing argument of '%s'\n", $1->i_string);
  1767. err[fflag]++;
  1768. list(dollarsign);
  1769. }
  1770. |
  1771. label.part INCBIN arg_on ARG arg_off '\n' {
  1772. incbin(tempbuf);
  1773. }
  1774. |
  1775. SPECIAL { raw = 1; } RAWTOKEN {
  1776. int quote = 0;
  1777. char *p, *q;
  1778. switch ($1->i_value) {
  1779. case SPTITL:
  1780. cp = tempbuf;
  1781. title = titlespace;
  1782. if (*cp == '\'' || *cp == '"')
  1783. quote = *cp++;
  1784. while ((*title++ = *cp++) && (title < &titlespace[TITLELEN]));
  1785. if (quote && title > titlespace + 1 && title[-2] == quote)
  1786. title[-2] = '\0';
  1787. title = titlespace;
  1788. list1();
  1789. break;
  1790. case SPSBTL:
  1791. err[warn_notimpl]++;
  1792. list1();
  1793. break;
  1794. case SPNAME:
  1795. // Drop surrounding ('') if present
  1796. p = tempbuf;
  1797. q = strchr(tempbuf, '\0') - 1;
  1798. if (*p == '(' && *q == ')' && q > p) p++, q--;
  1799. if (*p == '\'' && *q == '\'' && q > p) p++, q--;
  1800. q[1] = '\0';
  1801. strncpy(progname, p, sizeof progname);
  1802. progname[sizeof progname - 1] = '\0';
  1803. list1();
  1804. break;
  1805. case SPCOM:
  1806. quote = *tempbuf;
  1807. list1();
  1808. for (;;) {
  1809. raw = 1;
  1810. yychar = yylex();
  1811. list1();
  1812. if (yychar == 0)
  1813. break;
  1814. if (*tempbuf == quote) {
  1815. yychar = yylex();
  1816. break;
  1817. }
  1818. }
  1819. break;
  1820. case SPPRAGMA:
  1821. if (strncmp(tempbuf, "bds", 3) == 0 && bopt && outpass) {
  1822. fprintf(fbds, "%s\n", tempbuf + 4);
  1823. }
  1824. list1();
  1825. break;
  1826. }
  1827. }
  1828. |
  1829. LIST '\n' {
  1830. goto dolopt; }
  1831. |
  1832. LIST expression '\n' {
  1833. int enable = $2->e_value;
  1834. expr_number_check($2);
  1835. expr_free($2);
  1836. goto doloptA;
  1837. dolopt:
  1838. enable = 1;
  1839. doloptA:
  1840. linecnt++;
  1841. if (outpass) {
  1842. lineptr = linebuf;
  1843. switch ($1->i_value) {
  1844. case 0: /* list */
  1845. if (enable < 0) lstoff = 1;
  1846. if (enable > 0) lstoff = 0;
  1847. break;
  1848. case 1: /* eject */
  1849. if (enable) eject();
  1850. break;
  1851. case 2: /* space */
  1852. if ((line + enable) > 60) eject();
  1853. else space(enable);
  1854. break;
  1855. case 3: /* elist */
  1856. eopt = edef;
  1857. if (enable < 0) eopt = 0;
  1858. if (enable > 0) eopt = 1;
  1859. break;
  1860. case 4: /* fopt */
  1861. fopt = fdef;
  1862. if (enable < 0) fopt = 0;
  1863. if (enable > 0) fopt = 1;
  1864. break;
  1865. case 5: /* gopt */
  1866. gopt = gdef;
  1867. if (enable < 0) gopt = 1;
  1868. if (enable > 0) gopt = 0;
  1869. break;
  1870. case 6: /* mopt */
  1871. mopt = mdef;
  1872. if (enable < 0) mopt = 0;
  1873. if (enable > 0) mopt = 1;
  1874. }
  1875. }
  1876. }
  1877. |
  1878. JRPROMOTE expression '\n' {
  1879. expr_number_check($2);
  1880. jopt = !!$2->e_value;
  1881. list1();
  1882. expr_free($2);
  1883. }
  1884. |
  1885. JPERROR expression '\n' {
  1886. expr_number_check($2);
  1887. JPopt = !!$2->e_value;
  1888. list1();
  1889. expr_free($2);
  1890. }
  1891. |
  1892. PUBLIC public.list '\n' {
  1893. list1();
  1894. }
  1895. |
  1896. EXTRN extrn.list '\n' {
  1897. list1();
  1898. }
  1899. |
  1900. MRAS_MOD '\n' {
  1901. char *p = strchr(modstr, '\0') - 1;
  1902. for (; p >= modstr; p--) {
  1903. (*p)++;
  1904. if (*p < 'Z')
  1905. break;
  1906. *p = 'A';
  1907. }
  1908. list1();
  1909. }
  1910. |
  1911. SETSEG '\n'

Large files files are truncated, but you can click here to view the full file