%{
-/* This file is part of Paul's XA51 Assembler, Copyright 1997,2002 Paul Stoffregen
- *
- * Paul's XA51 Assembler is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2.
- *
- * Paul's XA51 Assembler is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+/* xa_rasm.y - This file is part of Paul's XA51 Assembler
+
+ Copyright 1997,2002 Paul Stoffregen (paul at pjrc dot com)
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Author contact: paul@pjrc.com */
int rlist_reg_bank, rlist_bitmask, rlist_size;
int db_count, dw_count, i;
char symbol_name[MAX_SYMBOL], base_symbol_name[MAX_SYMBOL]={'\0'};
-char expr_var[2][MAX_SYMBOL]={{'\0'},{'\0'}};
+char operand[2][MAX_SYMBOL]={{'\0'},{'\0'}};
extern char lex_sym_name[];
extern int yylex();
void RELOC_FF(unsigned where, unsigned pc, short rl) {
// pc = PC of the next instruction
struct symbol *sym;
- if ((sym=findSymbol(yytext))) {
- if (sym->mode=='X') {
+ if ((sym=findSymbol(operand[0]))) {
+ if (sym->mode=='X' || sym->area!=current_area) {
sprintf (rel_line[rl], "R %04x REL_FF %s %04x",
where, sym->name, pc);
}
void RELOC_FFFF(unsigned where, unsigned pc, short rl) {
struct symbol *sym;
- if ((sym=findSymbol(yytext))) {
- if (sym->mode=='X') {
+ if ((sym=findSymbol(operand[0]))) {
+ if (sym->mode=='X' || sym->area!=current_area) {
sprintf (rel_line[rl], "R %04x REL_FFFF %s %04x",
where, sym->name, pc);
}
}
}
-void RELOC_ABS_0F(unsigned where, int expr) {
+void RELOC_ABS_0F(unsigned where, int seq) {
struct symbol *sym;
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_0F %s 0", where, sym->name);
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x ABS_0F %s 0", where, sym->name);
}
}
-void RELOC_ABS_FF(unsigned where, int expr) {
+void RELOC_BIT_03FF(unsigned where, int seq) {
struct symbol *sym;
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_FF %s 0", where, sym->name);
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x BIT_03FF %s 0", where, sym->name);
}
}
-void RELOC_ABS_03FF(unsigned where, int expr) {
+void RELOC_DIR_07FF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_03FF %s 0", where, sym->name);
- }
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x DIR_07FF %s 0", where, sym->name);
}
}
-void RELOC_ABS_07ff(unsigned where, int expr) {
+void RELOC_DIR_70FF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_07ff %s 0", where, sym->name);
- }
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x DIR_70FF %s 0", where, sym->name);
}
}
-void RELOC_ABS_F0FF(unsigned where, int expr) {
+void RELOC_ABS_FF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_F0FF %s", where, sym->name);
- }
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x DIR_FF %s 0", where, sym->name);
}
}
-
-void RELOC_ABS_FFFF(unsigned where, int expr) {
+
+void RELOC_ABS_FFFF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_FFFF %s 0", where, sym->name);
- }
+ if ((sym=findSymbol(operand[seq]))) {
+ switch (sym->mode) {
+ case 'A':
+ // sfr or sbit, already in instruction
+ case '=':
+ // equat, already in instruction
+ break;
+ case 'X':
+ // external reference
+ sprintf (rel_line[seq], "R %04x ABS_FFFF %s %04x", where, sym->name,
+ sym->value);
+ break;
+ case 'R':
+ // absolute in current segment
+ sprintf (rel_line[seq], "R %04x ABS_PC PC %04x", where, sym->value);
+ break;
+ default:
+ fprintf (stderr, "unknown ABS_FFFF\n");
+ exit (1);
}
}
}
-void RELOC_ABS_0F00FF(unsigned where, int expr) {
+void RELOC_DIR_0700FF(unsigned where, int seq) {
struct symbol *sym;
- if (expr_var[0]) {
- if ((sym=findSymbol(expr_var[expr]))) {
- if (sym->mode=='X') {
- sprintf (rel_line[expr], "R %04x ABS_0F00FF %s", where, sym->name);
- }
- }
+ if ((sym=findSymbol(operand[seq])) && sym->mode!='A') {
+ sprintf (rel_line[seq], "R %04x ABS_0700FF %s 0", where, sym->name);
}
}
%nonassoc UNARY
%%
-
all: line
| line all;
MEM_POS += $3;
}
| linenosym {
- MEM_POS += $1;
+ if (!is_abs(symbol_name)) {
+ MEM_POS += $1;
+ }
}
linenosym: directive EOL {
value: NUMBER {$$ = $1;}
| CHAR {$$ = $1;}
- | WORD {
- $$ = $1;
- if (expr_var[0][0]=='\0') {
- strcpy(expr_var[0], yytext);
- } else {
- strcpy(expr_var[1], yytext);
- }
- }
-
+ | WORD { $$ = $1;}
rlist: REG {
rlist_bitmask = 1<<(reg($1) % 8);
op[0] = arith_opcode * 16 + size * 8 + 6;
op[1] = reg($4) * 16 + 8 + msb(direct_addr($2));
op[2] = lsb(direct_addr($2));
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| arith_inst REG ',' WORD {
$$ = 3;
op[0] = arith_opcode * 16 + size * 8 + 6;
op[1] = reg($2) * 16 + msb(direct_addr($4));
op[2] = lsb(direct_addr($4));
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| arith_inst REG ',' '#' expr {
size = find_size1(inst_size, $2);
op[1] = msb(direct_addr($2)) * 16 + arith_opcode;
op[2] = lsb(direct_addr($2));
op[3] = imm_data8($5);
- RELOC_ABS_F0FF(MEM_POS+1,0);
+ RELOC_DIR_70FF(MEM_POS+1,0);
RELOC_ABS_FF(MEM_POS+3,1);
} else {
$$ = 5;
op[2] = lsb(direct_addr($2));
op[3] = msb(imm_data16($5));
op[4] = lsb(imm_data16($5));
- RELOC_ABS_F0FF(MEM_POS+1,0);
+ RELOC_DIR_70FF(MEM_POS+1,0);
RELOC_ABS_FFFF (MEM_POS+3,1);
}
}
op[0] = 0xA0 + size * 8;
op[1] = 128 + reg_indirect($5) * 16 + msb(direct_addr($2));
op[2] = lsb(direct_addr($2));
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| arith_inst '[' REG ']' ',' WORD {
/* this addr mode is only valid for MOV */
op[0] = 0xA0 + size * 8;
op[1] = reg_indirect($3) * 16 + msb(direct_addr($6));
op[2] = lsb(direct_addr($6));
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| arith_inst WORD ',' WORD {
/* this addr mode is only valid for MOV */
op[1] = msb(direct_addr($2)) * 16 + msb(direct_addr($4));
op[2] = lsb(direct_addr($2));
op[3] = lsb(direct_addr($4));
- RELOC_ABS_F0FF(MEM_POS+1, 0);
- RELOC_ABS_0F00FF(MEM_POS+1, 1);
+ RELOC_DIR_70FF(MEM_POS+1, 0);
+ RELOC_DIR_0700FF(MEM_POS+1, 1);
}
| arith_inst REG ',' USP {
/* this addr mode is only valid for MOV */
op[0] = 0x08;
op[1] = 0x20 + msb(bit_addr($4));
op[2] = lsb(bit_addr($4));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| arith_inst bit ',' C {
/* this addr mode is only valid for MOV */
op[0] = 0x08;
op[1] = 0x30 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| MOVC REG ',' '[' REG '+' ']' {
op[0] = 0xA0 + size * 8;
op[1] = reg($2) * 16 + msb(direct_addr($4));
op[2] = lsb(direct_addr($4));
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| short_data_inst REG ',' '#' expr {
$$ = 2;
op[0] = 0x08;
op[1] = 0x40 + msb(bit_addr($4));
op[2] = lsb(bit_addr($4));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| ANL C ',' '/' bit {
$$ = 3;
op[0] = 0x08;
op[1] = 0x50 + msb(bit_addr($5));
op[2] = lsb(bit_addr($5));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| ORL C ',' bit {
op[0] = 0x08;
op[1] = 0x60 + msb(bit_addr($4));
op[2] = lsb(bit_addr($4));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| ORL C ',' '/' bit {
$$ = 3;
op[0] = 0x08;
op[1] = 0x70 + msb(bit_addr($5));
op[2] = lsb(bit_addr($5));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| CLR bit {
$$ = 3;
op[0] = 0x08;
op[1] = msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| SETB bit {
$$ = 3;
op[0] = 0x08;
op[1] = 0x10 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
}
| logical_shift_inst REG ',' REG {
size = find_size1(inst_size, $2);
op[0] = msb(stack_addr_opcode) + size * 8;
op[1] = lsb(stack_addr_opcode) + msb(direct_addr($2));
op[2] = lsb(direct_addr($2));
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
}
| stack_inst rlist {
$$ = 2;
size = find_size2(inst_size, $2, $4);
switch (size) {
case SIZE8:
- error("Singed DIV can't be 8 bit size"); break;
+ error("Signed DIV can't be 8 bit size"); break;
case SIZE16:
op[0] = 0xE7;
op[1] = reg($2) * 16 + reg($4);
op[1] = reg($2) * 16 + msb(direct_addr($4));
op[2] = lsb(direct_addr($4));
op[3] = rel8(MEM_POS + $$, $6);
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
}
| CJNE REG ',' '#' expr ',' jmpaddr {
op[1] = msb(direct_addr($2)) + 8;
op[2] = lsb(direct_addr($2));
op[3] = rel8(MEM_POS + $$, $4);
- RELOC_ABS_07ff(MEM_POS+1, 0);
+ RELOC_DIR_07FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1)
}
op[1] = 0x80 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
op[3] = rel8(MEM_POS + $$, $4);
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
}
op[1] = 0xC0 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
op[3] = rel8(MEM_POS + $$, $4);
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
}
op[1] = 0xA0 + msb(bit_addr($2));
op[2] = lsb(bit_addr($2));
op[3] = rel8(MEM_POS + $$, $4);
- RELOC_ABS_03FF(MEM_POS+1, 0);
+ RELOC_BIT_03FF(MEM_POS+1, 0);
RELOC_FF(MEM_POS+3, MEM_POS + $$, 1);
}