/* * Z80 - Assembler * Copyright (C) 1987-1992 by Udo Munk * * History: * 17-SEP-1987 Development under Digital Research CP/M 2.2 * 28-JUN-1988 Switched to Unix System V.3 */ /* * Dieses Modul enthaelt die Funktionen zur Bearbeitung * aller Pseudo-Op-Codes */ #include #include #include "z80a.h" #include "z80aglb.h" /* * Diese Funktion behandelt den Pseudo-Op-Code ORG */ op_org() { register int i; if (!gencode) return(0); i = eval(operand); if (i < pc) { asmerr(E_MEMOVR); return(0); } if (pass == 1) { /* PASS 1 */ if (!prg_flag) { prg_adr = i; prg_flag++; } } else { /* PASS 2 */ if (++prg_flag > 2) obj_fill(i - pc); sd_flag = 2; } pc = i; return(0); } /* * Diese Funktion behandelt den Pseudo-Op-Code EQU */ op_equ() { struct sym *get_sym(); if (!gencode) return(0); if (pass == 1) { /* Pass 1 */ if (get_sym(label) == NULL) { sd_val = eval(operand); if (put_sym(label, sd_val)) fatal(F_OUTMEM, "symbols"); } else asmerr(E_MULSYM); } else { /* Pass 2 */ sd_flag = 1; sd_val = eval(operand); } return(0); } /* * Diese Funktion behandelt den Pseudo-Op-Code DEFL */ op_dl() { if (!gencode) return(0); sd_flag = 1; sd_val = eval(operand); if (put_sym(label, sd_val)) fatal(F_OUTMEM, "symbols"); return(0); } /* * Diese Funktion behandelt den Pseudo-Op-Code DEFS */ op_ds() { register int val; if (!gencode) return(0); if (pass == 1) if (*label) put_label(); sd_val = pc; sd_flag = 3; val = eval(operand); if (pass == 2) obj_fill(val); pc += val; return(0); } /* * Diese Funktion behandelt den Pseudo-Op-Code DEFB */ op_db() { register int i; register char *p; register char *s; if (!gencode) return(0); i = 0; p = operand; if (pass == 1) if (*label) put_label(); while (*p) { if (*p == STRSEP) { p++; while (*p != STRSEP) { if (*p == '\n' || *p == '\0') { asmerr(E_MISHYP); goto hyp_error; } ops[i++] = *p++; if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } p++; } else { s = tmp; while (*p != ',' && *p != '\0') *s++ = *p++; *s = '\0'; ops[i++] = eval(tmp); if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } if (*p == ',') p++; } hyp_error: return(i); } /* * Diese Funktion behandelt den Pseudo-Op-Code DEFM */ op_dm() { register int i; register char *p; if (!gencode) return(0); i = 0; p = operand; if (pass == 1) if (*label) put_label(); if (*p != STRSEP) { asmerr(E_MISHYP); return(0); } p++; while (*p != STRSEP) { if (*p == '\n' || *p == '\0') { asmerr(E_MISHYP); break; } ops[i++] = *p++; if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } return(i); } /* * Diese Funktion behandelt den Pseudo-Op-Code DEFW */ op_dw() { register int i, len, temp; register char *p; register char *s; if (!gencode) return(0); p = operand; i = len = 0; if (pass == 1) if (*label) put_label(); while (*p) { s = tmp; while (*p != ',' && *p != '\0') *s++ = *p++; *s = '\0'; if (pass == 2) { temp = eval(tmp); ops[i++] = temp & 0xff; ops[i++] = temp >> 8; if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } len += 2; if (*p == ',') p++; } return(len); } /* * Diese Funktion behandelt die Pseudo-Op-Codes * EJECT, LIST, NOLIST, PAGE, PRINT, TITLE, INCLUDE */ op_misc(op_code, dummy) int op_code, dummy; { register char *p, *d; static char fn[LENFN]; static int incnest; static struct inc incl[INCNEST]; if (!gencode) return(0); sd_flag = 2; switch(op_code) { case 1: /* EJECT */ if (pass == 2) p_line = ppl; break; case 2: /* LIST */ if (pass == 2) list_flag = 1; break; case 3: /* NOLIST */ if (pass == 2) list_flag = 0; break; case 4: /* PAGE */ if (pass == 2) ppl = eval(operand); break; case 5: /* PRINT */ if (pass == 1) { p = operand; while (*p) { if (*p != STRSEP) putchar(*p++); else p++; } putchar('\n'); } break; case 6: /* INCLUDE */ if (incnest >= INCNEST) { asmerr(E_INCNEST); break; } incl[incnest].inc_line = c_line; incl[incnest].inc_fn = srcfn; incl[incnest].inc_fp = srcfp; incnest++; p = line; d = fn; while(isspace(*p)) /* white space bis INCLUDE ueberlesen */ p++; while(!isspace(*p)) /* INCLUDE ueberlesen */ p++; while(isspace(*p)) /* white space bis Filename ueberlesen */ p++; while(!isspace(*p) && *p != COMMENT) /* Filename uebernehmen */ *d++ = *p++; *d = '\0'; if (pass == 1) { /* PASS 1 */ if (!ver_flag) printf(" Include %s\n", fn); p1_file(fn); } else { /* PASS 2 */ sd_flag = 2; lst_line(0, 0); if (!ver_flag) printf(" Include %s\n", fn); p2_file(fn); } incnest--; c_line = incl[incnest].inc_line; srcfn = incl[incnest].inc_fn; srcfp = incl[incnest].inc_fp; printf(" Resume %s\n", srcfn); if (list_flag && (pass == 2)) { lst_header(); lst_attl(); } sd_flag = 4; break; case 7: /* TITLE */ if (pass == 2) { p = line; d = title; while (isspace(*p)) /* white space bis TITLE ueberlesen */ p++; while (!isspace(*p)) /* TITLE ueberlesen */ p++; while (isspace(*p)) /* white space bis Titel ueberlesen */ p++; if (*p == STRSEP) p++; while (*p != '\n' && *p != STRSEP && *p != COMMENT) *d++ = *p++; *d = '\0'; } break; default: fatal(F_INTERN, "illegal opcode for function op_misc"); break; } return(0); } /* * Diese Funktion behandelt die Pseudo-Op-Codes * IFDEF, IFNDEF, IFEQ, IFNEQ, ELSE, ENDIF */ op_cond(op_code, dummy) int op_code, dummy; { register char *p, *p1, *p2; static int condnest[IFNEST]; struct sym *get_sym(); char *strchr(); switch(op_code) { case 1: /* IFDEF */ if (iflevel >= IFNEST) { asmerr(E_IFNEST); break; } condnest[iflevel++] = gencode; if (gencode) if (get_sym(operand) == NULL) gencode = 0; break; case 2: /* IFNDEF */ if (iflevel >= IFNEST) { asmerr(E_IFNEST); break; } condnest[iflevel++] = gencode; if (gencode) if (get_sym(operand) != NULL) gencode = 0; break; case 3: /* IFEQ */ if (iflevel >= IFNEST) { asmerr(E_IFNEST); break; } condnest[iflevel++] = gencode; p = operand; if (!*p || !(p1 = strchr(operand, ','))) { asmerr(E_MISOPE); break; } if (gencode) { p2 = tmp; while (*p != ',') *p2++ = *p++; *p2 = '\0'; if (eval(tmp) != eval(++p1)) gencode = 0; } break; case 4: /* IFNEQ */ if (iflevel >= IFNEST) { asmerr(E_IFNEST); break; } condnest[iflevel++] = gencode; p = operand; if (!*p || !(p1 = strchr(operand, ','))) { asmerr(E_MISOPE); break; } if (gencode) { p2 = tmp; while (*p != ',') *p2++ = *p++; *p2 = '\0'; if (eval(tmp) == eval(++p1)) gencode = 0; } break; case 98: /* ELSE */ if (!iflevel) asmerr(E_MISIFF); else if ((iflevel == 0) || (condnest[iflevel - 1] == 1)) gencode = !gencode; break; case 99: /* ENDIF */ if (!iflevel) asmerr(E_MISIFF); else gencode = condnest[--iflevel]; break; default: fatal(F_INTERN, "illegal opcode for function op_cond"); break; } sd_flag = 2; return(0); } /* * Diese Funktion behandelt die Pseudo-Op-Codes * EXTRN und PUBLIC */ op_glob(op_code, dummy) int op_code, dummy; { if (!gencode) return(0); sd_flag = 2; switch(op_code) { case 1: /* EXTRN */ break; case 2: /* PUBLIC */ break; default: fatal(F_INTERN, "illegal opcode for function op_glob"); break; } return(0); }