byte {LIST; return DB;}
bit {LIST; return BITDEF;}
reg {LIST; return REGDEF;}
+area {LIST; return AREA;}
+ds {LIST; return DS;}
+DSEG {LIST; yylval = AREA_DSEG; return AREA_NAME;}
+OSEG {LIST; yylval = AREA_OSEG; return AREA_NAME;}
+ISEG {LIST; yylval = AREA_ISEG; return AREA_NAME;}
+BSEG {LIST; yylval = AREA_BSEG; return AREA_NAME;}
+XSEG {LIST; yylval = AREA_XSEG; return AREA_NAME;}
+XISEG {LIST; yylval = AREA_XISEG; return AREA_NAME;}
+GSINIT {LIST; yylval = AREA_GSINIT; return AREA_NAME;}
+GSFINAL {LIST; yylval = AREA_GSFINAL; return AREA_NAME;}
+HOME {LIST; yylval = AREA_HOME; return AREA_NAME;}
+CSEG {LIST; yylval = AREA_CSEG; return AREA_NAME;}
+module {LIST; return MODULE;}
+globl {LIST; return GLOBL;}
+\(DATA\) {LIST; return AREA_DESC;}
+\(OVR,DATA\) {LIST; return AREA_DESC;}
+\(BIT\) {LIST; return AREA_DESC;}
+\(XDATA\) {LIST; return AREA_DESC;}
+\(CODE\) {LIST; return AREA_DESC;}
low {LIST; return LOW;}
high {LIST; return HIGH;}
>> {LIST; return RSHIFT;}
%token WORD BIT NUMBER CHAR STRING EOL LOCAL_LABEL
%token ORG EQU DB DW BITDEF REGDEF LOW HIGH
%token RSHIFT LSHIFT
+%token AREA AREA_NAME AREA_DESC DS
+%token MODULE GLOBL
%left '&' '|' '^'
%left RSHIFT LSHIFT
| line all;
line: linesymbol ':' linenosym {
- if (p1) build_sym_list(symbol_name);
- if (p2) assign_value(symbol_name, mem);
- mem += $3; }
- | linenosym {mem += $1;}
+ if (p1) {
+ build_sym_list(symbol_name);
+ if (current_area == AREA_BSEG) {
+ mk_bit(symbol_name);
+ }
+ }
+ if (p1 || p2) assign_value(symbol_name, MEM_POS);
+ MEM_POS += $3;
+ }
+ | linenosym {
+ MEM_POS += $1;
+ }
linenosym: directive EOL {
if (p3) out(op, $1);
}
| error EOL /* try to recover from any parse error */
+
directive: '.' ORG expr {
- mem = $3;
+ MEM_POS = $3;
$$ = 0;
}
| ORG expr {
- mem = $2;
+ MEM_POS = $2;
$$ = 0;
}
| '.' EQU symbol ',' expr {
| dw_directive words {
$$ = dw_count;
}
+ | '.' AREA AREA_NAME AREA_DESC {
+ if ($3 < 0 || $3 >= NUM_AREAS) {
+ error("Illegal Area Directive");
+ }
+ symbol_name[0] = '\0';
+ current_area = $3;
+ $$ = 0;
+ }
+ | '.' MODULE WORD {
+ /* ignore module definition */
+ $$ = 0;
+ }
+ | '.' GLOBL WORD {
+ /* ignore global symbol declaration */
+ $$ = 0;
+ }
+ | '.' DS expr {
+ /* todo: if CSEG, emit some filler bytes */
+ $$ = $3;
+ }
db_directive: DB {db_count = 0;}
+
+linesymbol: WORD {
+ strcpy(symbol_name, lex_sym_name);
+ if (!strchr(lex_sym_name, ':')) {
+ /* non-local label, remember base name */
+ strcpy(base_symbol_name, lex_sym_name);
+ }
+ if (is_target(symbol_name)) pad_with_nop();
+ }
+
bytes: byte_element
| bytes ',' byte_element
}
-linesymbol: WORD {
- strcpy(symbol_name, lex_sym_name);
- if (!strchr(lex_sym_name, ':')) {
- /* non-local label, remember base name */
- strcpy(base_symbol_name, lex_sym_name);
- }
- if (is_target(symbol_name)) pad_with_nop();
- }
symbol: WORD {
strcpy(symbol_name, lex_sym_name);
| JMP jmpaddr {
$$ = 3;
op[0] = 0xD5;
- op[1] = msb(rel16(mem + $$, $2));
- op[2] = lsb(rel16(mem + $$, $2));
+ op[1] = msb(rel16(MEM_POS + $$, $2));
+ op[2] = lsb(rel16(MEM_POS + $$, $2));
}
| CALL jmpaddr {
$$ = 3;
op[0] = 0xC5;
- op[1] = msb(rel16(mem + $$, $2));
- op[2] = lsb(rel16(mem + $$, $2));
+ op[1] = msb(rel16(MEM_POS + $$, $2));
+ op[2] = lsb(rel16(MEM_POS + $$, $2));
}
| branch_inst jmpaddr {
$$ = 2;
op[0] = branch_opcode;
- op[1] = rel8(mem + $$, $2);
+ op[1] = rel8(MEM_POS + $$, $2);
}
| CJNE REG ',' expr ',' jmpaddr {
$$ = 4;
op[0] = 0xE2 + size * 8;
op[1] = reg($2) * 16 + msb(direct_addr($4));
op[2] = lsb(direct_addr($4));
- op[3] = rel8(mem + $$, $6);
+ op[3] = rel8(MEM_POS + $$, $6);
}
| CJNE REG ',' '#' expr ',' jmpaddr {
size = find_size1(inst_size, $2);
$$ = 4;
op[0] = 0xE3;
op[1] = reg($2) * 16;
- op[2] = rel8(mem + $$, $7);
+ op[2] = rel8(MEM_POS + $$, $7);
op[3] = imm_data8($5);
} else {
$$ = 5;
op[0] = 0xEB;
op[1] = reg($2) * 16;
- op[2] = rel8(mem + $$, $7);
+ op[2] = rel8(MEM_POS + $$, $7);
op[3] = msb(imm_data16($5));
op[4] = lsb(imm_data16($5));
}
$$ = 4;
op[0] = 0xE3;
op[1] = reg_indirect($3) * 16 + 8;
- op[2] = rel8(mem + $$, $9);
+ op[2] = rel8(MEM_POS + $$, $9);
op[3] = imm_data8($7);
} else {
$$ = 5;
op[0] = 0xEB;
op[1] = reg_indirect($3) * 16 + 8;
- op[2] = rel8(mem + $$, $9);
+ op[2] = rel8(MEM_POS + $$, $9);
op[3] = msb(imm_data16($7));
op[4] = lsb(imm_data16($7));
}
size = find_size1(inst_size, $2);
op[0] = 0x87 + size * 8;
op[1] = reg($2) * 16 + 8;
- op[2] = rel8(mem + $$, $4);
+ op[2] = rel8(MEM_POS + $$, $4);
}
op[0] = 0xE2 + size * 8;
op[1] = msb(direct_addr($2)) + 8;
op[2] = lsb(direct_addr($2));
- op[3] = rel8(mem + $$, $4);
+ op[3] = rel8(MEM_POS + $$, $4);
}
| JB bit ',' jmpaddr {
op[0] = 0x97;
op[1] = 0x80 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
- op[3] = rel8(mem + $$, $4);
+ op[3] = rel8(MEM_POS + $$, $4);
}
| JBC bit ',' jmpaddr {
op[0] = 0x97;
op[1] = 0xC0 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
- op[3] = rel8(mem + $$, $4);
+ op[3] = rel8(MEM_POS + $$, $4);
}
| JNB bit ',' jmpaddr {
op[0] = 0x97;
op[1] = 0xA0 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
- op[3] = rel8(mem + $$, $4);
+ op[3] = rel8(MEM_POS + $$, $4);
}
extern char last_line_text[];
struct symbol *sym_list=NULL;
struct target *targ_list=NULL;
-int lineno=1, mem=0; /* mem is location in memory */
+int lineno=1;
int p1=0, p2=0, p3=0;
int expr_result, expr_ok, jump_dest, inst;
int opcode, operand;
char symbol_name[1000];
+struct area_struct area[NUM_AREAS];
+int current_area=AREA_CSEG;
+/* "mem" is replaced by area[current_area].alloc_position */
+/* int mem=0; */ /* mem is location in memory */
+
/* add symbols to list when we find their definition in pass #1 */
/* we will evaluate their values in pass #2, and figure out if */
/* they are branch targets betweem passes 1 and 2. Every symbol */
{
int i, first=1;
- if (num > 0) fprintf(list_fp, "%06X: ", mem);
+ if (num > 0) fprintf(list_fp, "%06X: ", MEM_POS);
else fprintf(list_fp, "\t");
for (i=0; i<num; i++) {
- hexout(byte_list[i], mem+i, 0);
+ hexout(byte_list[i], MEM_POS + i, 0);
if (!first && (i % 4) == 0) fprintf(list_fp, "\t");
fprintf(list_fp, "%02X", byte_list[i]);
if ((i+1) % 4 == 0) {
last_line_text[0] = '\0';
- for(num=0; (mem + num) % BRANCH_SPACING; num++) ;
+ for(num=0; (MEM_POS + num) % BRANCH_SPACING; num++) ;
if (p3) out(nops, num);
- mem += num;
+ MEM_POS += num;
}
/* print branch out of bounds error */
}
/* output the jump either direction on carry */
-/* jump_dest and mem must have the proper values */
+/* jump_dest and MEM_POS must have the proper values */
/*
void do_jump_on_carry()
{
if (p3) {
- operand = REL4(jump_dest, mem);
+ operand = REL4(jump_dest, MEM_POS);
if (operand < 0) {
operand *= -1;
operand -= 1;
void print_usage();
+
+/* todo: someday this will allow the user to control where the */
+/* various memory areas go, and it will take care of assigning */
+/* positions to area which follow others (such as OSEG getting */
+/* set just after DSEG on the 2nd and 3rd passes when we have */
+/* leared the size needed for each segment */
+
+void init_areas(void)
+{
+ area[AREA_CSEG].alloc_position = 0;
+ area[AREA_DSEG].alloc_position = 0x30;
+ area[AREA_OSEG].alloc_position = 0x80;
+ area[AREA_ISEG].alloc_position = 0;
+ area[AREA_BSEG].alloc_position = 0;
+ area[AREA_XSEG].alloc_position = 0;
+ area[AREA_XISEG].alloc_position = 0;
+ area[AREA_GSINIT].alloc_position = 0;
+ area[AREA_GSFINAL].alloc_position = 0;
+ area[AREA_HOME].alloc_position = 0;
+}
+
+
/* pass #1 (p1=1) find all symbol defs and branch target names */
/* pass #2 (p2=1) align branch targets, evaluate all symbols */
/* pass #3 (p3=1) produce object code */
printf(" Building Symbol Table:\n");
p1 = 1;
- mem = 0;
+ //mem = 0;
+ init_areas();
yyparse();
flag_targets();
- // print_symbol_table();
+ print_symbol_table();
check_redefine();
p1 = 0;
p2 = 1;
yyrestart(yyin);
lineno = 1;
printf(" Aligning Branch Targets:\n");
- mem = 0;
+ //mem = 0;
+ init_areas();
yyparse();
// print_symbol_table();
p2 = 0;
yyrestart(yyin);
lineno = 1;
printf(" Generating Object Code:\n");
- mem = 0;
+ //mem = 0;
+ init_areas();
yyparse();
fclose(yyin);
hexout(0, 0, 1); /* flush and close intel hex file output */