X-Git-Url: https://jxself.org/git/?p=a56.git;a=blobdiff_plain;f=a56.y;fp=a56.y;h=0000000000000000000000000000000000000000;hp=9c3399b3bb724c8ffacafbde3c877b7971adc1a1;hb=34923afb4a618598083726717bf2f20d310f4f6e;hpb=c6db6f4c5cb82f5e09472163bf11be0c165965ee diff --git a/a56.y b/a56.y deleted file mode 100644 index 9c3399b..0000000 --- a/a56.y +++ /dev/null @@ -1,2114 +0,0 @@ -%{ -/******************************************************* - * - * a56 - a DSP56001 assembler - * - * Written by Quinn C. Jensen - * July 1990 - * - *******************************************************/ - -/* - * Copyright (C) 1990-1994 Quinn C. Jensen - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. The author makes no representations - * about the suitability of this software for any purpose. It is - * provided "as is" without express or implied warranty. - * - */ - -/* - * a56.y - The YACC grammar for the assembler. - * - * Note: This module requires a "BIG" version of YACC. I had to - * recompile YACC in the largest mode available. - * - * Other notes: - * - * MOVEC, MOVEM and MOVEP must be used explicitly--MOVE can't yet figure - * out which form to use. - * - */ - -#include "a56.h" -#include - -unsigned int w0, w1; /* workspace for the actual generated code */ -BOOL uses_w1; /* says whether w1 is alive */ -unsigned int pc; /* current program counter */ -int seg; /* current segment P: X: Y: or L: */ -int expr_seg; /* segment of current expression */ - -int just_rep = 0; /* keeps track of REP instruction */ -int hot_rreg = -1; /* rreg loaded by prev inst. or -1 */ -int hot_nreg = -1; /* nreg loaded by prev inst. or -1 */ -int hot_mreg = -1; /* mreg loaded by prev inst. or -1 */ -int prev_hot_rreg = -1; /* rreg loaded by prev inst. or -1 */ -int prev_hot_nreg = -1; /* nreg loaded by prev inst. or -1 */ -int prev_hot_mreg = -1; /* mreg loaded by prev inst. or -1 */ - -int substatement = 0; /* in a substatement */ -BOOL long_symbolic_expr = FALSE; /* a parser flag */ -char *new_include = NULL; /* file to be included */ - -/* listing stuff */ - -char segs[] = "uPXYL*"; -extern BOOL list_on_next; /* listing to turn on or off */ -BOOL list_on; /* listing on at the moment */ -extern char *cur_line; /* points to line being lex'd */ -char list_buf[1024 + 80]; /* listing buffer */ -char list_buf2[1024 + 80]; /* listing buffer for two-line code */ -BOOL uses_buf2 = FALSE; /* list_buf2 is alive */ -BOOL list_print_line = FALSE; /* whether or not to print line in listing */ -char *spaces(), *luntab(); - -struct n binary_op(); -struct n unary_op(); -struct n sym_ref(); - -#define R_R6 0x0001 -#define R_R5 0x0002 -#define R_R4 0x0004 -#define R_DATA_ALU_ACCUM 0x0008 -#define R_CTL_REG 0x0010 -#define R_FUNKY_CTL_REG 0x0020 -#define R_SDX 0x0040 -#define R_SDY 0x0080 -#define R_LSD 0x0100 -#define R_AB 0x0200 -#define R_XREG 0x0400 -#define R_YREG 0x0800 -/* registers to which short immediate move is an unsigned int */ -#define R_UINT 0x1000 -/* registers to which short immediate move is an signed frac */ -#define R_SFRAC 0x2000 -%} - -%union { - int ival; /* integer value */ - struct n n; /* just like in struct sym */ - double dval; /* floating point value */ - char *sval; /* string */ - int cval; /* character */ - char cond; /* condition */ - struct regs { - int r6, r5, r4, data_alu_accum, ctl_reg, funky_ctl_reg; - int sdx, sdy, lsd, ab, xreg, yreg; - int flags; - } regs; - struct ea { - int mode; - int ext; - int pp; - } ea; -} - -%token CHEX CDEC FRAC -%token AREG BREG MREG NREG RREG XREG YREG -%token OP OPA OPP -%token OP_JCC OP_JSCC OP_TCC -%token SYM -%token STRING -%token CHAR -%token XMEM -%token YMEM -%token LMEM -%token PMEM -%token AAAA -%token A10 -%token BBBB -%token B10 -%token AABB -%token BBAA -%token XXXX -%token YYYY -%token SR -%token MR -%token CCR -%token OMR -%token SP -%token SSH -%token SSL -%token LA -%token LC -%token EOL -%token EOS -%token LEXBAD - -%token OP_ABS -%token OP_ADC -%token OP_ADD -%token OP_ADDL -%token OP_ADDR -%token OP_ASL -%token OP_ASR -%token OP_CLR -%token OP_CMP -%token OP_CMPM -%token OP_DIV -%token OP_MAC -%token OP_MACR -%token OP_MPY -%token OP_MPYR -%token OP_NEG -%token OP_NORM -%token OP_RND -%token OP_SBC -%token OP_SUB -%token OP_SUBL -%token OP_SUBR -%token OP_TFR -%token OP_TST -%token OP_AND -%token OP_ANDI -%token OP_EOR -%token OP_LSL -%token OP_LSR -%token OP_NOT -%token OP_OR -%token OP_ORI -%token OP_ROL -%token OP_ROR -%token OP_BCLR -%token OP_BSET -%token OP_BCHG -%token OP_BTST -%token OP_DO -%token OP_ENDDO -%token OP_LUA -%token OP_MOVE -%token OP_MOVEC -%token OP_MOVEM -%token OP_MOVEP -%token OP_ILLEGAL -%token OP_INCLUDE -%token OP_JMP -%token OP_JCLR -%token OP_JSET -%token OP_JSR -%token OP_JSCLR -%token OP_JSSET -%token OP_NOP -%token OP_REP -%token OP_RESET -%token OP_RTI -%token OP_RTS -%token OP_STOP -%token OP_SWI -%token OP_WAIT -%token OP_EQU -%token OP_ORG -%token OP_DC -%token OP_DS -%token OP_DSM -%token OP_END -%token OP_PAGE -%token OP_PSECT -%token OP_ALIGN -%token OP_INT -%token SHL -%token SHR -%token OP_PI -%token OP_SIN -%token OP_COS -%token OP_TAN -%token OP_ATAN -%token OP_ASIN -%token OP_ACOS -%token OP_EXP -%token OP_LN -%token OP_LOG -%token OP_POW - -%type num num_or_sym -%type num_or_sym_expr -%type expr -%type ix -%type ix_long - -%type abs_addr abs_short_addr io_short_addr -%type a_b x_or_y ea b5_10111_max -%type p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12 -%type ea_short -%type prog_ctl_reg -%type op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8 -%type mpy_arg mpy_srcs plus_minus -%type sd3 -%type funky_ctl_reg tcc_sd space -%type opt_label - -%type regs -%type movep_ea_pp - -%left '|' -%left '^' -%left SHL SHR -%left '&' -%left '+' '-' -%left '*' '/' '%' -%right '~' - -%start input - -%% - -/*%%%********************* top syntax ***********************/ - -input : /* empty */ - | input statement - ; - -statement - : good_stuff EOL - { - if(pass == 2 && list_on && list_print_line) { - printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n", - list_buf, substatement == 0 ? luntab(cur_line) : ""); - if(uses_buf2) - printf(ldebug ? "\n(%s|)\n" : "%s\n", - list_buf2); - list_buf[0] = list_buf2[0] = '\0'; - } - curline++; - uses_buf2 = FALSE; - list_print_line = TRUE; - list_on = list_on_next; - substatement = 0; - if(NOT check_psect(seg, pc) && pass == 2) - yyerror("%04X: psect violation", pc); - } - | good_stuff EOS - { - if(pass == 2 && list_on && list_print_line) { - printf(ldebug ? "\n(%s" : "%s", list_buf); - if(substatement == 0) - printf(ldebug ? "|%s)\n" : "%s\n", luntab(cur_line)); - else - printf(ldebug ? ")\n" : "\n"); - if(uses_buf2) - printf(ldebug ? "\n(%s|)\n" : "%s\n", - list_buf2); - list_buf[0] = list_buf2[0] = '\0'; - } - substatement++; - uses_buf2 = FALSE; - list_print_line = TRUE; - list_on = list_on_next; - if(NOT check_psect(seg, pc) && pass == 2) - yyerror("%04X: psect violation", pc); - } - | error EOL - {curline++; substatement = 0;} - ; - -good_stuff - : /* empty */ - {sprintf(list_buf, "%s", spaces(0));} - | cpp_droppings - {list_print_line = FALSE;} - | assembler_ops - {long_symbolic_expr = FALSE;} - | label_field operation_field - {char *printcode(); - if(pass == 2) { - gencode(seg, pc, w0); - sprintf(list_buf, "%c:%04X %s ", segs[seg], pc, printcode(w0)); - pc++; - if(uses_w1) { - gencode(seg, pc, w1); - sprintf(list_buf2, "%c:%04X %s", segs[seg], pc, - printcode(w1 & 0xFFFFFF)); - uses_buf2++; - pc++; - } - } else { - pc++; - if(uses_w1) - pc++; - } - w0 = w1 = 0; uses_w1 = FALSE; - long_symbolic_expr = FALSE;} - | SYM - {sym_def($1, INT, seg, pc); - free($1); - if(pass == 2 && list_on) { - sprintf(list_buf, "%c:%04X%s", segs[seg], pc, spaces(14-8)); - long_symbolic_expr = FALSE; - }} - ; - -cpp_droppings - : '#' num STRING - {if(strlen($3) > 0) - curfile = $3; - else - curfile = ""; - curline = $2.val.i - 1;} - ; - -assembler_ops - : SYM OP_EQU expr - {sym_def($1, $3.type, ANY, $3.val.i, $3.val.f); - free($1); - if(pass == 2 && list_on) { - if($3.type == INT) - sprintf(list_buf, "%06X%s", - $3.val.i & 0xFFFFFF, - spaces(14-8)); - else - sprintf(list_buf, "%10g%s", $3.val.f, - spaces(14-4)); - }} - | OP_ALIGN expr - {int ival = n2int($2); - if($2.type == UNDEF) { - yyerror("illegal forward reference"); - } else if (ival <= 1) { - yyerror("%d: illegal alignment", ival); - } else { - if(pc % ival != 0) - pc += ival - pc % ival; - } - if(pass == 2 && list_on) - sprintf(list_buf, "%c:%04X%s", segs[seg], pc, - spaces(14-8)); - } - | OP_PSECT SYM - {struct psect *pp = find_psect($2); - if(NOT pp) { - if(pass == 2) - yyerror("%s: undefined psect", $2); - } else { - seg = pp->seg; - pc = pp->pc; - set_psect(pp); - if(pass == 2 && list_on) - sprintf(list_buf, "%c:%04X%s", segs[seg], pc, - spaces(14-8)); - } - free($2);} - | OP_PSECT SYM space expr ':' expr - {new_psect($2, $3, n2int($4), n2int($6)); - if(pass == 2 && list_on) - sprintf(list_buf, "%c:%04X %04X%s", - segs[$3], n2int($4), n2int($6), spaces(14-8+4+1)); - } - | OP_ORG space expr - {pc = n2int($3); - seg = $2; - if(pass == 2 && list_on) - sprintf(list_buf, "%c:%04X%s", segs[seg], pc, - spaces(14-8)); - } - | OP_ORG space expr ',' space expr - {pc = n2int($3); - seg = $2; - if(pass == 2 && list_on) - sprintf(list_buf, "%c:%04X%s", segs[seg], pc, - spaces(14-8)); - } - | label_field OP_DC dc_list - | label_field OP_DS expr - {pc += n2int($3); - if(pass == 2 && list_on) - sprintf(list_buf, "%c:%04X%s", segs[seg], pc, - spaces(14-8)); - } - | opt_label OP_DSM expr - {int size = n2int($3); - if(size) - { int align = 1; - while(align < size) - align <<= 1; - pc += (align - (pc % align)); - } - if($1) - { sym_def($1, INT, seg, pc); - free($1); - } - pc += size; - } - | OP_PAGE num ',' num ',' num ',' num - {if(pass == 2 && list_on) { - sprintf(list_buf, "%s", spaces(0)); - }} - | OP_INCLUDE STRING - {if(pass == 2 && list_on) { - printf(ldebug ? "\n(%s|%s)\n" : "%s%s\n", - spaces(0), luntab(cur_line)); - list_print_line = FALSE; - } - include($2); /* free($2); */ - } - | OP_END - {if(pass == 2 && list_on) { - sprintf(list_buf, "%s", spaces(0)); - }} - ; - -dc_list - : dc_list ',' dc_stuff - | dc_stuff - ; - -dc_stuff - : STRING - {int len = strlen($1), i; char *cp; w0 = 0; - if(len % 3 == 2) - len++; /* force empty word */ - for(i = 0, cp = $1; i < len; i++, cp++) { - w0 |= (*cp & 0xFF) << (2 - (i % 3)) * 8; - if(i % 3 == 2 || i == len - 1) { - if(pass == 2) { - if(list_on) sprintf(list_buf, "%c:%04X %06X%s", - segs[seg], pc, w0, - spaces(14-6+5)); - gencode(seg, pc, w0); - } - pc++; w0 = 0; - } - } - free($1);} - | expr - {int frac = n2frac($1); - if(pass == 2) { - if(list_on) { - sprintf(list_buf, "%c:%04X %06X%s", segs[seg], pc, - frac & 0xFFFFFF, spaces(14-6+5)); - } - gencode(seg, pc, frac); - } - pc++;} - -space - : PMEM - {$$ = PROG;} - | XMEM - {$$ = XDATA;} - | YMEM - {$$ = YDATA;} - | LMEM - {$$ = LDATA;} - ; - -label_field - : SYM - {sym_def($1, INT, seg, pc); - free($1);} - | /* empty */ - ; - -opt_label - : SYM {$$ = $1;} - | /* empty */ {$$ = NULL;} - ; - -operation_field - : operation - {prev_hot_rreg = hot_rreg; - prev_hot_nreg = hot_nreg; - prev_hot_mreg = hot_mreg; - hot_rreg = hot_nreg = hot_mreg = -1; - if(just_rep) - just_rep--;} - ; - -operation - : no_parallel - | parallel_ok - {w0 |= 0x200000;} - | parallel_ok parallel_move - ; - -/*%%%************* instructions that allow parallel moves ****************/ - -parallel_ok - : - OP_MPY mpy_arg - {w0 |= 0x80 | $2 << 2;} - | OP_MPYR mpy_arg - {w0 |= 0x81 | $2 << 2;} - | OP_MAC mpy_arg - {w0 |= 0x82 | $2 << 2;} - | OP_MACR mpy_arg - {w0 |= 0x83 | $2 << 2;} - - | OP_SUB op8_1 - {w0 |= 0x04 | $2 << 3;} - | OP_ADD op8_1 - {w0 |= 0x00 | $2 << 3;} - | OP_MOVE - {w0 |= 0x00;} - - | OP_TFR op8_2 - {w0 |= 0x01 | $2 << 3;} - | OP_CMP op8_2 - {w0 |= 0x05 | $2 << 3;} - | OP_CMPM op8_2 - {w0 |= 0x07 | $2 << 3;} - - | OP_RND op8_3 - {w0 |= 0x11 | $2 << 3;} - | OP_ADDL op8_3 - {w0 |= 0x12 | $2 << 3;} - | OP_CLR op8_3 - {w0 |= 0x13 | $2 << 3;} - | OP_SUBL op8_3 - {w0 |= 0x16 | $2 << 3;} - | OP_NOT op8_3 - {w0 |= 0x17 | $2 << 3;} - - | OP_ADDR op8_4 - {w0 |= 0x02 | $2 << 3;} - | OP_TST op8_4 - {w0 |= 0x03 | $2 << 3;} - | OP_SUBR op8_4 - {w0 |= 0x06 | $2 << 3;} - - | OP_AND op8_5 - {w0 |= 0x46 | $2 << 3;} - | OP_OR op8_5 - {w0 |= 0x42 | $2 << 3;} - | OP_EOR op8_5 - {w0 |= 0x43 | $2 << 3;} - - | OP_ASR op8_6 - {w0 |= 0x22 | $2 << 3;} - | OP_LSR op8_6 - {w0 |= 0x23 | $2 << 3;} - | OP_ABS op8_6 - {w0 |= 0x26 | $2 << 3;} - | OP_ROR op8_6 - {w0 |= 0x27 | $2 << 3;} - - | OP_ASL op8_7 - {w0 |= 0x32 | $2 << 3;} - | OP_LSL op8_7 - {w0 |= 0x33 | $2 << 3;} - | OP_NEG op8_7 - {w0 |= 0x36 | $2 << 3;} - | OP_ROL op8_7 - {w0 |= 0x37 | $2 << 3;} - - | OP_ADC op8_8 - {w0 |= 0x21 | $2 << 3;} - | OP_SBC op8_8 - {w0 |= 0x25 | $2 << 3;} - ; - -mpy_arg : plus_minus mpy_srcs ',' a_b - {$$ = $1 | $4 << 1 | $2 << 2;} - ; - -plus_minus - : '+' - {$$ = 0;} - | '-' - {$$ = 1;} - | - {$$ = 0;} - ; - -mpy_srcs - : XREG ',' XREG - {switch ($1 << 4 | $3) { - case 0x00: $$ = 0x0; break; - case 0x01: - case 0x10: $$ = 0x2; break; - case 0x11: - yyerror("illegal source operands"); - break; - }} - | YREG ',' YREG - {switch ($1 << 4 | $3) { - case 0x00: $$ = 0x1; break; - case 0x01: - case 0x10: $$ = 0x3; break; - case 0x11: - yyerror("illegal source operands"); - break; - }} - | XREG ',' YREG - {switch ($1 << 4 | $3) { - case 0x00: $$ = 0x5; break; - case 0x01: $$ = 0x4; break; - case 0x10: $$ = 0x6; break; - case 0x11: $$ = 0x7; break; - }} - | YREG ',' XREG - {switch ($1 << 4 | $3) { - case 0x00: $$ = 0x5; break; - case 0x01: $$ = 0x6; break; - case 0x10: $$ = 0x4; break; - case 0x11: $$ = 0x7; break; - }} - ; - -op8_1 : BBBB ',' AAAA - {$$ = 0x2;} - | AAAA ',' BBBB - {$$ = 0x3;} - | XXXX ',' a_b - {$$ = 0x4 | $3;} - | YYYY ',' a_b - {$$ = 0x6 | $3;} - | XREG ',' a_b - {$$ = 0x8 | $1 << 2 | $3;} - | YREG ',' a_b - {$$ = 0xA | $1 << 2 | $3;} - ; - -op8_2 : BBBB ',' AAAA - {$$ = 0x0;} - | AAAA ',' BBBB - {$$ = 0x1;} - | XREG ',' a_b - {$$ = 0x8 | $1 << 2 | $3;} - | YREG ',' a_b - {$$ = 0xA | $1 << 2 | $3;} - ; - -op8_3 : AAAA - {$$ = 0x0;} - | BBBB - {$$ = 0x1;} - | BBBB ',' AAAA - {$$ = 0x0;} - | AAAA ',' BBBB - {$$ = 0x1;} - ; - -op8_4 : op8_3 - {$$ = $1;} - ; - -op8_5 : XREG ',' a_b - {$$ = 0x0 | $1 << 2 | $3;} - | YREG ',' a_b - {$$ = 0x2 | $1 << 2 | $3;} - ; - -op8_6 : a_b - {$$ = $1;} - ; - -op8_7 : a_b - {$$ = $1;} - ; - -op8_8 : XXXX ',' a_b - {$$ = 0x0 | $3;} - | YYYY ',' a_b - {$$ = 0x2 | $3;} - ; - -a_b : AAAA - {$$ = 0;} - | BBBB - {$$ = 1;} - ; - -no_parallel - : control_inst - {if(just_rep == 1) - yyerror("instruction not allowed after REP");} - | bit_inst - | move_inst - | arith_inst - ; - -/*%%%************** non-parallel arithmetic and logical ********************/ - -arith_inst - : OP_NORM RREG ',' a_b - {w0 |= 0x01D815 | $2 << 8 | $4 << 3;} - | OP_DIV sd3 - {w0 |= 0x018040 | $2 << 3;} - | or_op ix ',' funky_ctl_reg - {w0 |= 0x0000F8 | (n2int($2) & 0xFF) << 8 | $4;} - | and_op ix ',' funky_ctl_reg - {w0 |= 0x0000B8 | (n2int($2) & 0xFF) << 8 | $4;} - ; - -or_op : OP_OR - | OP_ORI - ; - -and_op : OP_AND - | OP_ANDI - ; - -/*%%%******************************* control instructions **********************/ - -control_inst - : OP_JSCC ea_a12 - {if($2) { - w0 |= 0x0BC0A0 | $1 << 0; - } else { - w0 |= 0x0F0000 | $1 << 12; - }} - | OP_JCC ea_a12 - {if($2) { - w0 |= 0x0AC0A0 | $1 << 0; - } else { - w0 |= 0x0E0000 | $1 << 12; - }} - | OP_JSR ea_a12 - {if($2) { - w0 |= 0x0BC080; - } else { - w0 |= 0x0D0000; - }} - | OP_JMP ea_a12 - {if($2) { - w0 |= 0x0AC080; - } else { - w0 |= 0x0C0000; - }} - - | OP_JSSET control_args - {w0 |= 0x0B0020;} - | OP_JSCLR control_args - {w0 |= 0x0B0000;} - | OP_JSET control_args - {w0 |= 0x0A0020;} - | OP_JCLR control_args - {w0 |= 0x0A0000;} - - | OP_REP rep_args - {just_rep = 2;} - | OP_DO do_args - {uses_w1++;} - | OP_ENDDO - {w0 |= 0x00008C;} - | OP_STOP - {w0 |= 0x000087;} - | OP_WAIT - {w0 |= 0x000086;} - | OP_RESET - {w0 |= 0x000084;} - | OP_RTS - {w0 |= 0x00000C;} - | OP_SWI - {w0 |= 0x000006;} - | OP_ILLEGAL - {w0 |= 0x000005;} - | OP_RTI - {w0 |= 0x000004;} - | OP_NOP - {w0 |= 0x000000; - just_rep = 0;} - ; - -do_args - : ix ',' abs_addr - {int ival = n2int($1); - w0 |= 0x060080 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8; - if(ival > 0xFFF && pass == 2) { - yywarning("warning: immediate operand truncated"); - } - w1 |= $3-1;} - | regs ',' abs_addr - {w0 |= 0x06C000 | $1.r6 << 8; - hot_rreg = hot_nreg = hot_mreg = -1; - w1 |= $3-1;} - | x_or_y ea_no_ext ',' abs_addr - {w0 |= 0x064000 | $2 << 8 | $1 << 6; - w1 |= $4-1;} - | x_or_y abs_short_addr ',' abs_addr /* allow forced */ - {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6; - /* - * $$$ oops, can't check expr_seg because both abs_short_addr and - * abs_addr touch it - */ - if($2 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - w1 |= $4-1;} - | x_or_y abs_addr ',' abs_addr - {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6; - /* - * $$$ oops, can't check expr_seg because both abs_short_addr and - * abs_addr touch it - */ - if($2 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - w1 |= $4-1;} - ; - -rep_args - : ix - {int ival = n2int($1); - w0 |= 0x0600A0 | (ival & 0xFF) << 8 | (ival & 0xF00)>> 8; - if(ival > 0xFFF && pass == 2) { - yywarning("warning: immediate operand truncated"); - }} - | regs - {w0 |= 0x06C020 | $1.r6 << 8; - hot_rreg = hot_nreg = hot_mreg = -1;} - | x_or_y ea_no_ext - {w0 |= 0x064020 | $1 << 6 | $2 << 8;} - | x_or_y abs_addr - {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8; - if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || - $1 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($2 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - } - | x_or_y abs_short_addr /* forced */ - {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8; - if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || - $1 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($2 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - } - ; - -control_args - : b5_10111_max ',' x_or_y p6_ean_a6 ',' abs_addr - {w0 |= $1 << 0 | $3 << 6; - uses_w1++; - w1 = $6;} - | b5_10111_max ',' regs ',' abs_addr - {w0 |= 0x00C000 | $1 << 0 | $3.r6 << 8; - hot_rreg = hot_nreg = hot_mreg = -1; - uses_w1++; - w1 = $5;} - ; - -p6_ean_a6 - : abs_addr /* in pass 2 can always discern size. */ - /* Sometimes in pass one, too. But since */ - /* address extension is always used for the */ - /* branch target, pass 1 can assume the */ - /* symbol value will fit; warning in pass 2 */ - /* if it doesn't */ - {if($1 != -1) { /* symbol defined */ - w0 |= ($1 & 0x3F) << 8; - if($1 >= 0xFFC0) { - w0 |= 0x008080; - } else { - w0 |= 0x000080; - if($1 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - } - }} - | abs_short_addr - {if($1 != -1) { - if($1 > 0x3F && pass == 2) - yywarning("warning: address operand truncated"); - w0 |= 0x000080 | ($1 & 0x3F) << 8; - }} - | io_short_addr - {if($1 != -1) { - if($1 < 0xFFC0 && pass == 2) - yywarning("warning: address operand truncated"); - w0 |= 0x008080 | ($1 & 0x3F) << 8; - }} - | ea_no_ext - {w0 |= 0x004080 | $1 << 8;} - ; - -/*%%%**************************** bit instructions ***************************/ - -bit_inst - : OP_BTST bit_args - {w0 |= 0x0B0020;} - | OP_BCHG bit_args - {w0 |= 0x0B0000;} - | OP_BSET bit_args - {w0 |= 0x0A0020;} - | OP_BCLR bit_args - {w0 |= 0x0A0000;} - ; - -bit_args - : b5_10111_max ',' x_or_y p6_ea_a6 - {w0 |= $1 << 0 | $3 << 6; - } - | b5_10111_max ',' regs - {w0 |= 0x00C040 | $1 << 0 | $3.r6 << 8;} - ; - -p6_ea_a6 - : io_short_addr /* must be forced to tell from abs_addr */ - {if($1 != -1) { - w0 |= ($1 & 0x3F) << 8 | 0x008000; - if($1 < 0xFFC0 && pass == 2) - yywarning("warning: address operand truncated"); - }} - | abs_short_addr /* must be forced to tell from abs_addr */ - {if($1 != -1) { - w0 |= ($1 & 0x3F) << 8 | 0x000000; - if($1 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - }} - | ea /* can use abs_addr */ - {w0 |= 0x004000;} - ; - -/*%%%************************** move instructions **********************/ - -move_inst - : OP_MOVEP movep_args - | OP_MOVEM movem_args - | OP_MOVEC movec_args - | OP_LUA ea_short ',' regs - {w0 |= 0x044010 | $2 << 8 | $4.r4;} - | OP_TCC tcc_args - {w0 |= $1 << 12;} - ; - -tcc_args - : tcc_sd - {w0 |= 0x020000 | $1 << 3;} - | tcc_sd RREG ',' RREG - {w0 |= 0x030000 | $1 << 3 | $2 << 8 | $4;} - ; - -tcc_sd - : regs /* a_b */ ',' regs /* a_b */ - {hot_rreg = hot_nreg = hot_mreg = -1; - if($1.flags & R_AB && $3.flags & R_AB) { - if($1.ab == $3.ab) - yyerror("source and dest must be different"); - $$ = $3.ab; - } else if($1.flags & R_XREG && $3.flags & R_AB) { - $$ = 0x8 | $1.xreg << 2 | $3.ab; - } else if($1.flags & R_YREG && $3.flags & R_AB) { - $$ = 0xA | $1.yreg << 2 | $3.ab; - } else - yyerror("illegal TCC operands"); - } - ; - -sd3 : regs /* XREG */ ',' regs /* a_b */ - {hot_rreg = hot_nreg = hot_mreg = -1; - if($1.flags & R_XREG && $3.flags & R_AB) { - $$ = $1.xreg << 2 | $3.ab; - } else if($1.flags & R_YREG && $3.flags & R_AB) { - $$ = $1.yreg << 2 | 2 | $3.ab; - }} - ; - -movec_args - : x_or_y ea ',' regs /* ctl_reg */ - {if(NOT ($4.flags & R_CTL_REG)) - yyerror("bad MOVEC target register"); - if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || - $1 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($1 == 0) { - w0 |= 0x05C020 | $4.ctl_reg; - } else { - w0 |= 0x05C060 | $4.ctl_reg; - }} - | regs /* ctl_reg */ ',' x_or_y ea - {hot_rreg = hot_nreg = hot_mreg = -1; - if(NOT ($1.flags & R_CTL_REG)) - yyerror("bad MOVEC source register"); - if($3 == 0) { - w0 |= 0x054020 | $1.ctl_reg; - } else { - w0 |= 0x054060 | $1.ctl_reg; - }} - | ix ',' regs /* ctl_reg */ - {int ival = n2int($1); - if(NOT ($3.flags & R_CTL_REG)) - yyerror("bad MOVEC target register"); - if(ival < 256 && NOT long_symbolic_expr) { - w0 |= 0x0500A0 | (ival & 0xFF) << 8 | $3.ctl_reg; - } else { - w0 |= 0x05C020 | 0x003400 | $3.ctl_reg; - uses_w1++; w1 = ival & 0xFFFF; - }} - | x_or_y abs_short_addr ',' regs /* ctl_reg */ - {if($1 == 0) { - w0 |= 0x058020 | ($2 & 0x3F) << 8 | $4.ctl_reg; - } else { - w0 |= 0x058060 | ($2 & 0x3F) << 8 | $4.ctl_reg; - } - if(NOT ($4.flags & R_CTL_REG)) - yyerror("bad MOVEC target register"); - if($2 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - } - | regs /* ctl_reg */ ',' x_or_y abs_short_addr - {hot_rreg = hot_nreg = hot_mreg = -1; - if($3 == 0) { - w0 |= 0x050020 | ($4 & 0x3F) << 8 | $1.ctl_reg; - } else { - w0 |= 0x050060 | ($4 & 0x3F) << 8 | $1.ctl_reg; - } - if(NOT ($1.flags & R_CTL_REG)) - yyerror("bad MOVEC source register"); - if($4 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - } - | regs /* ctl_reg */ ',' regs - {if($1.flags & R_CTL_REG) { - w0 |= 0x0440A0 | $3.r6 << 8 | $1.ctl_reg; - } else if($3.flags & R_CTL_REG) { - w0 |= 0x04C0A0 | $1.r6 << 8 | $3.ctl_reg; - } else if($1.flags & $3.flags & R_CTL_REG) { - /* bogus? $$$ */ - w0 |= 0x04C0A0 | ($1.ctl_reg | 0x20) << 8 | - $3.ctl_reg; - } else { - yyerror("MOVEC must reference a control reg"); - }} - ; - -movep_args - : x_or_y movep_ea_pp ',' x_or_y movep_ea_pp - {w0 |= 0x084080; - switch($2.pp << 1 | $5.pp) { - case 0: case 3: - yyerror("illegal MOVEP; can't move EA to EA or IO to IO"); - break; - case 1: /* ea, pp */ - w0 |= $4 << 16 | 1 << 15 | $1 << 6 | - ($5.ext & 0x3F); - if($2.mode == 0x003000) { - w0 |= 0x003000; - uses_w1++; - w1 = $2.ext; - } else { - w0 |= $2.mode; - } - break; - case 2: /* pp, ea */ - w0 |= $1 << 16 | 0 << 15 | $4 << 6 | - ($2.ext & 0x3F); - if($5.mode == 0x003000) { - w0 |= 0x003000; - uses_w1++; - w1 = $5.ext; - } else { - w0 |= $5.mode; - } - break; - }} - | ix ',' x_or_y num_or_sym - {w0 |= 0x084080; - w0 |= $3 << 16 | 1 << 15 | 0x34 << 8 | - (n2int($4) & 0x3F); - uses_w1++; - w1 = n2int($1);} - | PMEM ea ',' x_or_y num_or_sym - {w0 |= 0x084040; - w0 |= $4 << 16 | 1 << 15 | (n2int($5) & 0x3F);} - | x_or_y movep_ea_pp ',' PMEM ea - {w0 |= 0x084040; - if($2.mode != 0x003000 && $2.mode != 0) - yyerror("illegal MOVEP"); - w0 |= $1 << 16 | 0 << 15 | ($2.ext & 0x3F);} - | regs ',' x_or_y num_or_sym - {hot_rreg = hot_nreg = hot_mreg = -1; - w0 |= 0x084000; - w0 |= $3 << 16 | 1 << 15 | $1.r6 << 8 | - (n2int($4) & 0x3F);} - | x_or_y movep_ea_pp ',' regs - {hot_rreg = hot_nreg = hot_mreg = -1; - w0 |= 0x084000; - if(!$2.pp) - yyerror("illegal MOVEP"); - w0 |= $1 << 16 | 0 << 15 | $4.r6 << 8 | ($2.ext & 0x3F);} - ; - -movep_ea_pp - : abs_addr - {if($1 != UNDEF && $1 >= 0xFFC0) { - /* defined symbol or constant, in i/o range */ - $$.pp = 1; - $$.mode = 0; - } else { - /* either out of i/o range or symbol not */ - /* yet defined: assume ea extension */ - $$.pp = 0; - $$.mode = 0x003000; - } - $$.ext = $1;} - | io_short_addr /* forced i/o short */ - {$$.pp = 1; - $$.mode = 0; - if($1 < 0xFFC0 && pass == 2) - yywarning("warning: address operand truncated"); - $$.ext = $1;} - | ea_no_ext - {$$.pp = 0; - $$.mode = $1 << 8; - $$.ext = $1;} - ; - -movem_args - : regs ',' PMEM ea_a6 - {w0 |= 0x070000 | 0 << 15 | $1.r6;} - | PMEM ea_a6 ',' regs - {hot_rreg = hot_nreg = hot_mreg = -1; - w0 |= 0x070000 | 1 << 15 | $4.r6;} - ; - -/*%%%**************** memory reference fields ************************/ - -b5_10111_max - : ix - {int ival = n2int($1); - $$ = ival; if(ival > 0x17) - yyerror("%d: illegal bit number", ival);} - ; - -x_or_y - : XMEM - {$$ = 0;} - | YMEM - {$$ = 1;} - ; - -/*%%%**************** effective address fields ************************/ - -ea_a6 - : ea - {w0 |= 0x004080;} - | abs_short_addr - {w0 |= ($1 & 0x3F) << 8; - if($1 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - } - ; - -ea_a12 - : ea - {$$ = 1;} - | abs_short_addr - {w0 |= $1 & 0xFFF; $$ = 0; - if($1 > 0x0FFF && pass == 2) - yywarning("warning: address operand truncated"); - } - ; - -ea : abs_addr - {w0 |= 0x003000; - uses_w1++; - w1 |= $1; - $$ = 0x003000;} - | ea_no_ext - {w0 |= $1 << 8; - $$ = $1 << 8; - expr_seg = ANY;} - ; - -ea_no_ext - : ea_short - {$$ = $1;} - | '(' RREG ')' - {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); - $$ = 4 << 3 | $2;} - | '(' RREG '+' NREG ')' - {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); - if($4 == prev_hot_nreg) yywarning("warning: n%d just loaded", $4); - if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); - $$ = 5 << 3 | $2; - if($2 != $4) yyerror("Rn and Nn must be same number");} - | '-' '(' RREG ')' - {if($3 == prev_hot_rreg) yywarning("warning: r%d just loaded", $3); - if($3 == prev_hot_mreg) yywarning("warning: m%d just loaded", $3); - $$ = 7 << 3 | $3;} - ; - -ea_short - : '(' RREG ')' '-' NREG - {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); - if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5); - if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); - $$ = 0 << 3 | $2; - expr_seg = ANY; - if($2 != $5) yyerror("Rn and Nn must be same number");} - | '(' RREG ')' '+' NREG - {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); - if($5 == prev_hot_nreg) yywarning("warning: n%d just loaded", $5); - if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); - $$ = 1 << 3 | $2; - expr_seg = ANY; - if($2 != $5) yyerror("Rn and Nn must be same number");} - | '(' RREG ')' '-' - {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); - if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); - expr_seg = ANY; - $$ = 2 << 3 | $2;} - | '(' RREG ')' '+' - {if($2 == prev_hot_rreg) yywarning("warning: r%d just loaded", $2); - if($2 == prev_hot_mreg) yywarning("warning: m%d just loaded", $2); - expr_seg = ANY; - $$ = 3 << 3 | $2;} - ; - -/*%%%******************* register fields ******************************/ - -regs - : XREG - {$$.r6 = $$.r5 = 0x04 | $1; - $$.sdx = $1; - $$.xreg = $1; - $$.flags = R_R6|R_R5|R_XREG|R_SDX|R_SFRAC;} - | YREG - {$$.r6 = $$.r5 = 0x06 | $1; - $$.sdy = $1; - $$.yreg = $1; - $$.flags = R_R6|R_R5|R_SDY|R_YREG|R_SFRAC;} - | AREG - {switch($1) { - case 0: - $$.r6 = $$.r5 = 0x08 | 0; - break; - case 1: - $$.r6 = $$.r5 = 0x08 | 4; - break; - case 2: - $$.r6 = $$.r5 = 0x08 | 2; - break; - } - $$.flags = R_R6|R_R5|R_UINT;} - | BREG - {switch($1) { - case 0: - $$.r6 = $$.r5 = 0x08 | 1; break; - case 1: - $$.r6 = $$.r5 = 0x08 | 5; break; - case 2: - $$.r6 = $$.r5 = 0x08 | 3; break; - } - $$.flags = R_R6|R_R5|R_UINT;} - | AAAA - {$$.r6 = $$.r5 = 0x0E; - $$.sdx = $$.sdy = 0x2; - $$.ab = 0; - $$.lsd = 4; - $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;} - | BBBB - {$$.r6 = $$.r5 = 0x0F; - $$.sdx = $$.sdy = 0x3; - $$.ab = 1; - $$.lsd = 5; - $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD|R_SFRAC;} - | RREG - {$$.r6 = $$.r5 = 0x10 | $1; - $$.r4 = 0x00 | $1; - $$.flags = R_R6|R_R5|R_R4|R_UINT; - hot_rreg = $1;} - | NREG - {$$.r6 = $$.r5 = 0x18 | $1; - $$.r4 = 0x08 | $1; - $$.flags = R_R6|R_R5|R_R4|R_UINT; - hot_nreg = $1;} - | MREG - {$$.r6 = 0x20 | $1; - $$.r5 = -1; - $$.ctl_reg = $1; - $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT; - hot_mreg = $1;} - | prog_ctl_reg - {$$.r6 = 0x38 | $1; - $$.r5 = -1; - $$.ctl_reg = 0x18 | $1; - $$.flags = R_R6|R_R5|R_CTL_REG|R_UINT;} - | A10 - {$$.lsd = 0; - $$.flags = R_LSD;} - | B10 - {$$.lsd = 1; - $$.flags = R_LSD;} - | XXXX - {$$.lsd = 2; - $$.flags = R_LSD;} - | YYYY - {$$.lsd = 3; - $$.flags = R_LSD;} - | AABB - {$$.lsd = 6; - $$.flags = R_LSD;} - | BBAA - {$$.lsd = 7; - $$.flags = R_LSD;} - ; - -prog_ctl_reg - : SR - {$$ = 1;} - | OMR - {$$ = 2;} - | SP - {$$ = 3;} - | SSH - {$$ = 4;} - | SSL - {$$ = 5;} - | LA - {$$ = 6;} - | LC - {$$ = 7;} - ; - -funky_ctl_reg - : MR - {$$ = 0;} - | CCR - {$$ = 1;} - | OMR - {$$ = 2;} - ; - -/*%%%************************* parallel moves *************/ - -parallel_move - : i_move - | u_move - | x_or_y_move - | xr_move - | ry_move - | r_move - | xy_move - | l_move - ; - -i_move : ix ',' regs - {int ival = n2int($1); - int frac = n2frac($1); - int value; - BOOL shortform = FALSE; - if($3.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - if(($3.flags & R_SFRAC) && $1.type == FLT) { - if((frac & 0xFFFF) == 0 && - NOT long_symbolic_expr) { - value = frac >> 16; - shortform++; - } else { - value = frac; - } - } else { - if(ival <= 0xFF && ival >= -0xFF && NOT long_symbolic_expr) { - value = ival; - shortform++; - } else { - value = ival; - } - } - - if(shortform) { - w0 |= 0x200000 | (value & 0xFF) << 8 | - $3.r5 << 16; - } else { - w0 |= 0x400000 | 0x00F400 | - ($3.r5 >> 3 & 3) << 20 | - ($3.r5 & 7) << 16; - uses_w1++; w1 = value; - }} - ; - -r_move : regs ',' regs - { - if($3.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - if($1.flags & R_R5 & $3.flags) - w0 |= 0x200000 | $3.r5 << 8 | $1.r5 << 13; - else - yyerror("illegal R move"); - } - ; - -u_move : ea_short - {w0 |= 0x204000 | $1 << 8;} - ; - -x_or_y_move - : x_or_y ea ',' regs - {w0 |= 0x40C000 | $1 << 19; - if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || - $1 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($4.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - w0 |= ($4.r5 >> 3 & 3) << 20 | ($4.r5 & 7) << 16;} - | x_or_y abs_short_addr ',' regs - {w0 |= 0x408000 | $1 << 19 | ($2 & 0x3F) << 8; - if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || - $1 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($4.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - if($2 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - w0 |= ($4.r5>> 3 & 3) << 20 | ($4.r5 & 7) << 16;} - | regs ',' x_or_y ea - {hot_rreg = hot_nreg = hot_mreg = -1; - w0 |= 0x404000 | $3 << 19; - if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA || - $3 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($1.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;} - | regs ',' x_or_y abs_short_addr - {hot_rreg = hot_nreg = hot_mreg = -1; - w0 |= 0x400000 | $3 << 19 | ($4 & 0x3F) << 8; - if($1.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA || - $3 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($4 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;} - | ix_long ',' regs - {w0 |= 0x400000 | 0x00F400 | ($3.r5 >> 3 & 3) << 20 | - ($3.r5 & 7) << 16; - if($3.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - uses_w1++; w1 = n2frac($1); - } - ; - -xr_move - : x_or_y /* XMEM */ ea ',' regs regs /* a_b */ ',' YREG - {hot_rreg = hot_nreg = hot_mreg = -1; - if(expr_seg != ANY && ($1 == 0 && expr_seg != XDATA || - $1 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($1 == 0 && $5.flags & R_AB) { - w0 |= 0x108000 | $4.sdx << 18 | $5.ab << 17 | - $7 << 16; - } else { - yyerror("illegal X:R move"); - }} - | ix ',' regs regs /* a_b */ ',' YREG - {hot_rreg = hot_nreg = hot_mreg = -1; - if($4.flags & R_AB) { - w0 |= 0x10B400 | $3.sdx << 18 | $4.ab << 17 | - $6 << 16; - uses_w1++; - w1 |= n2frac($1) & 0xFFFFFF; - } else { - yyerror("illegal X:R move"); - }} - | regs ',' x_or_y /* XMEM */ ea regs /* a_b */ ',' regs/*YREG*/ - {hot_rreg = hot_nreg = hot_mreg = -1; - if(expr_seg != ANY && ($3 == 0 && expr_seg != XDATA || - $3 == 1 && expr_seg != YDATA)) - yywarning("warning: space mismatch"); - if($1.flags & R_SDX && $3 == 0 && $5.flags & R_AB && - $7.flags & R_YREG) { - w0 |= 0x100000 | $1.sdx << 18 | $5.ab << 17 | - $7.yreg << 16; - } else if($1.flags & R_AB && $3 == 0 && - $5.flags & R_XREG && $7.flags & R_AB) { - if($5.xreg != 0) yyerror("must use X0"); - if($1.ab == 0 && $7.ab == 0) - w0 |= 0x080000; - else if($1.ab == 1 && $7.ab == 1) - w0 |= 0x090000; - else - yyerror("illegal X:R move"); - } else { - yyerror("illegal X:R move"); - }} - ; - -ry_move : regs /* a_b */ ',' regs /* XREG */ YMEM ea ',' regs - {hot_rreg = hot_nreg = hot_mreg = -1; - if($3.flags & R_XREG && $7.flags & (R_YREG|R_AB)) { - w0 |= 0x10C000 | $1.ab << 19 | $3.xreg << 18 | - $7.sdy << 16; - } else { - yyerror("illegal R:Y move"); - }} - | regs /* a_b */ ',' regs /* XREG */ ix ',' regs - {hot_rreg = hot_nreg = hot_mreg = -1; - if($3.flags & R_XREG && $6.flags & (R_YREG|R_AB)) { - w0 |= 0x10F400 | $1.ab << 19 | $3.xreg << 18 | - $6.sdy << 16; - uses_w1++; - w1 |= n2frac($4) & 0xFFFFFF; - } else { - yyerror("illegal R:Y move"); - }} - | regs /* a_b */ ',' regs /* XREG */ regs ',' YMEM ea - {hot_rreg = hot_nreg = hot_mreg = -1; - if($1.flags & R_AB && $3.flags & R_XREG) { - w0 |= 0x104000 | $1.ab << 19 | $3.xreg << 18 | - $4.sdy << 16; - } else if ($1.flags & R_YREG && $3.flags & R_AB && - $4.flags & R_AB) { - if($1.yreg != 0) yyerror("must use Y0"); - if($3.ab == 0 && $4.ab == 0) - w0 |= 0x088000; - else if($3.ab == 1 && $4.ab == 1) - w0 |= 0x098000; - else - yyerror("illegal R:Y move"); - } else { - yyerror("illegal R:Y move"); - }} - ; - -l_move - : LMEM ea ',' regs /* lsd */ - {if($4.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - w0 |= 0x40C000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;} - | regs /* lsd */ ',' LMEM ea - {hot_rreg = hot_nreg = hot_mreg = -1; - if($1.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - w0 |= 0x404000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;} - | LMEM abs_short_addr ',' regs /* lsd */ - {w0 |= 0x408000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19; - if($4.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - if($2 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - w0 |= ($2 & 0x3F) << 8;} - | regs /* lsd */ ',' LMEM abs_short_addr - {hot_rreg = hot_nreg = hot_mreg = -1; - w0 |= 0x400000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19; - if($1.flags & R_CTL_REG) { - yyerror("please use MOVEC for control register moves"); - break; - } - if($4 > 0x003F && pass == 2) - yywarning("warning: address operand truncated"); - w0 |= ($4 & 0x3F) << 8;} - ; - -xy_move - : x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs YMEM ea /*ea_strange*/ ',' regs - {int eax = $2, eay = $6, - regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg, - regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg; - hot_rreg = hot_nreg = hot_mreg = -1; - if((eax & 0x400) == (eay & 0x400)) - yyerror("registers must be in opposite halves"); - if(!($4.flags & (R_AB | R_XREG))) - yyerror("invalid X move register"); - if(!($8.flags & (R_AB | R_YREG))) - yyerror("invalid Y move register"); - if($4.flags & R_AB && - $8.flags & R_AB && - $4.ab == $8.ab) - yyerror("duplicate destination register"); - w0 = w0 & 0xFF | 0xC08000; /* both write */ - w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;} - | x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs regs ',' YMEM ea /*ea_strange*/ - {int eax = $2, eay = $8, - regx = ($4.flags & R_AB) ? $4.ab | 2 : $4.xreg, - regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg; - hot_rreg = hot_nreg = hot_mreg = -1; - if((eax & 0x400) == (eay & 0x400)) - yyerror("registers must be in opposite halves"); - if(!($4.flags & (R_AB | R_XREG))) - yyerror("invalid X move register"); - if(!($5.flags & (R_AB | R_YREG))) - yyerror("invalid Y move register"); - w0 = w0 & 0xFF | 0x808000; /* X:write, Y:read */ - w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;} - | regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/ YMEM ea /*ea_strange*/ ',' regs - {int eax = $4, eay = $6, - regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg, - regy = ($8.flags & R_AB) ? $8.ab | 2 : $8.yreg; - hot_rreg = hot_nreg = hot_mreg = -1; - if((eax & 0x400) == (eay & 0x400)) - yyerror("registers must be in opposite halves"); - if(!($1.flags & (R_AB | R_XREG))) - yyerror("invalid X move register"); - if(!($8.flags & (R_AB | R_YREG))) - yyerror("invalid Y move register"); - w0 = w0 & 0xFF | 0xC00000; /* X:read, Y:write */ - w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;} - | regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/ regs ',' YMEM ea /*ea_strange*/ - {int eax = $4, eay = $8, - regx = ($1.flags & R_AB) ? $1.ab | 2 : $1.xreg, - regy = ($5.flags & R_AB) ? $5.ab | 2 : $5.yreg; - hot_rreg = hot_nreg = hot_mreg = -1; - if((eax & 0x400) == (eay & 0x400)) - yyerror("registers must be in opposite halves"); - if(!($1.flags & (R_AB | R_XREG))) - yyerror("invalid X move register"); - if(!($5.flags & (R_AB | R_YREG))) - yyerror("invalid Y move register"); - w0 = w0 & 0xFF | 0x800000; /* both read */ - w0 |= eax & 0x1f00 | (eay & 0x300) << 5 | (eay & 0x1800) << 9 | regx << 18 | regy << 16;} - ; - -/*%%%******* absolute address and immediate data fields ************/ - -num : CHEX - {$$ = $1;} - | CDEC - {$$ = $1;} - | FRAC - {$$ = $1;} - ; - -ix : '#' expr - {$$ = $2; expr_seg = ANY;} - | '#' '<' expr - {$$.val.i = n2int($3) & 0xFF; - $$.type = INT; - expr_seg = ANY; - long_symbolic_expr = FALSE;} - ; - -ix_long : '#' '>' expr - {$$ = $3; expr_seg = ANY;} - ; - -abs_addr - : expr - {$$ = n2int($1); - expr_seg = $1.seg;} - ; - -abs_short_addr - : '<' expr - {$$ = n2int($2); - expr_seg = $2.seg;} - ; - -io_short_addr - : SHL expr - {$$ = n2int($2); - expr_seg = $2.seg;} - ; - -num_or_sym - : num - {$$ = $1;} - | SYM - {$$ = sym_ref($1); free($1);} - | io_short_addr - {$$.type = INT; $$.val.i = $1; $$.seg = expr_seg;} - ; - -num_or_sym_expr - : num - {$$ = $1; expr_seg = $1.seg;} - | SYM - {$$ = sym_ref($1); - free($1); - long_symbolic_expr++; - expr_seg = $$.seg; - } - | CHAR - {$$.type = INT; $$.val.i = $1 & 0xFFFFFF; expr_seg = $$.seg = ANY;} - | '*' - {$$.type = INT; $$.val.i = pc; expr_seg = $$.seg = ANY;} - | OP_PI - {$$.type = FLT; $$.val.f = acos(-1.0); expr_seg = $$.seg = ANY;} - ; - -expr - : OP_INT '(' expr ')' - {$$.type = INT; - if($3.type == INT) - $$.val.i = $3.val.i; - else - $$.val.i = $3.val.f; - $$.seg = $3.seg; - } - | expr '|' expr - {$$ = binary_op($1, '|', $3);} - | expr '^' expr - {$$ = binary_op($1, '^', $3);} - | expr '&' expr - {$$ = binary_op($1, '&', $3);} - | expr SHR expr - {$$ = binary_op($1, SHR, $3);} - | expr SHL expr - {$$ = binary_op($1, SHL, $3);} - | expr '-' expr - {$$ = binary_op($1, '-', $3);} - | expr '+' expr - {$$ = binary_op($1, '+', $3);} - | expr '%' expr - {$$ = binary_op($1, '%', $3);} - | expr '/' expr - {$$ = binary_op($1, '/', $3);} - | expr '*' expr - {$$ = binary_op($1, '*', $3);} - | '-' expr %prec '~' - {$$ = unary_op('-', $2);} - | '~' expr - {$$ = unary_op('~', $2);} - | OP_SIN '(' expr ')' - {$$ = unary_op('s', $3);} - | OP_COS '(' expr ')' - {$$ = unary_op('c', $3);} - | OP_TAN '(' expr ')' - {$$ = unary_op('t', $3);} - | OP_ASIN '(' expr ')' - {$$ = unary_op('S', $3);} - | OP_ACOS '(' expr ')' - {$$ = unary_op('C', $3);} - | OP_ATAN '(' expr ')' - {$$ = unary_op('T', $3);} - | OP_EXP '(' expr ')' - {$$ = unary_op('e', $3);} - | OP_LN '(' expr ')' - {$$ = unary_op('l', $3);} - | OP_LOG '(' expr ')' - {$$ = unary_op('L', $3);} - | OP_ABS '(' expr ')' - {$$ = unary_op('a', $3);} - | OP_POW '(' expr ',' expr ')' - {$$ = binary_op($3, 'p', $5);} - | '(' expr ')' - {$$ = $2;} - | num_or_sym_expr - {$$ = $1;} - ; - -/*%%%****************** end ******************************/ - -%% - -#include -#include -#include - -int yydebug; - -struct n binary_op(a1, op, a2) -struct n a1, a2; -int op; -{ - struct n result; - int iarg1, iarg2; - double farg1, farg2; - - if(a1.type == UNDEF || a2.type == UNDEF) { - result.type = UNDEF; - return result; - } - - iarg1 = a1.type == INT ? a1.val.i : a1.val.f; - iarg2 = a2.type == INT ? a2.val.i : a2.val.f; - - farg1 = a1.type == INT ? a1.val.i : a1.val.f; - farg2 = a2.type == INT ? a2.val.i : a2.val.f; - - /* figure out target segment */ - - if(a1.seg == a2.seg) - result.seg = a1.seg; - else if(a1.seg == ANY) - result.seg = a2.seg; - else if(a2.seg == ANY) - result.seg = a1.seg; - else - result.seg = NONE; - - /* promote to float automatically */ - - if(a1.type != a2.type) { - if(a1.type == INT) { - a1.val.f = a1.val.i; /* truncate */ - a1.type = FLT; - } else { - a2.val.f = a2.val.i; /* truncate */ - } - } - result.type = a1.type; - - /* do the op */ - - switch(op) { - case '+': - if(result.type == INT) result.val.i = a1.val.i + a2.val.i; - else result.val.f = a1.val.f + a2.val.f; - break; - case '-': - if(result.type == INT) result.val.i = a1.val.i - a2.val.i; - else result.val.f = a1.val.f - a2.val.f; - break; - case '*': - if(result.type == INT) result.val.i = a1.val.i * a2.val.i; - else result.val.f = a1.val.f * a2.val.f; - break; - case '/': - if(result.type == INT) result.val.i = a1.val.i / a2.val.i; - else result.val.f = a1.val.f / a2.val.f; - break; - case '%': - result.val.i = iarg1 % iarg2; - result.type = INT; - break; - case SHL: - result.val.i = iarg1 << iarg2; - result.type = INT; - break; - case SHR: - result.val.i = iarg1 >> iarg2; - result.type = INT; - break; - case '|': - result.val.i = iarg1 | iarg2; - result.type = INT; - break; - case '&': - result.val.i = iarg1 & iarg2; - result.type = INT; - break; - case '^': - result.val.i = iarg1 ^ iarg2; - result.type = INT; - break; - case 'p': - result.val.f = pow(farg1, farg2); - result.type = FLT; - } - - return result; -} - -jmp_buf unary_env; - -void -sigfpu() -{ - longjmp(unary_env, 1); -} - -char *unary_name(op) -{ - switch(op) { - case 's': return "sin"; - case 'c': return "cos"; - case 't': return "tan"; - case 'S': return "asin"; - case 'C': return "acos"; - case 'T': return "atan"; - case 'e': return "exp"; - case 'l': return "ln"; - case 'L': return "log"; - case 'a': return "abs"; - } -} - -struct n unary_op(op, a1) -int op; -struct n a1; -{ - struct n result; - void (*orig)(); - double farg; - - if(a1.type == UNDEF) { - result.type = UNDEF; - return result; - } - - result.seg = a1.seg; - - /* do the op */ - - orig = signal(SIGFPE, sigfpu); - if(setjmp(unary_env)) { - yyerror("floating point exception in function %s", unary_name(op)); - result.val.i = result.val.f = 0; - } else { - farg = a1.type == INT ? (double)a1.val.i : a1.val.f; - switch(op) { - case '-': - result.type = a1.type; - if(a1.type == INT) result.val.i = -a1.val.i; - else result.val.f = -a1.val.f; - break; - case '~': - result.type = a1.type; - if(a1.type == INT) result.val.i = ~a1.val.i; - else result.val.f = ~(int)a1.val.f; - break; - case 'a': - result.type = a1.type; - if(a1.type == INT) result.val.i = a1.val.i < 0 ? -a1.val.i : a1.val.i; - else result.val.f = result.val.f = a1.val.f < 0 ? -a1.val.f : a1.val.f; - break; - case 's': - result.type = FLT; - result.val.f = sin(farg); - break; - case 'c': - result.type = FLT; - result.val.f = cos(farg); - break; - case 't': - result.type = FLT; - result.val.f = tan(farg); - break; - case 'S': - result.type = FLT; - result.val.f = asin(farg); - break; - case 'C': - result.type = FLT; - result.val.f = acos(farg); - break; - case 'T': - result.type = FLT; - result.val.f = atan(farg); - break; - case 'e': - result.type = FLT; - result.val.f = exp(farg); - break; - case 'l': - result.type = FLT; - result.val.f = log(farg); - break; - case 'L': - result.type = FLT; - result.val.f = log10(farg); - break; - } - } - signal(SIGFPE, orig); - - return result; -} - -n2int(n) -struct n n; -{ - if(n.type == UNDEF) - return UNDEF; - else if(n.type == INT) - return n.val.i; - else - return n.val.f; -} - -n2frac(n) -struct n n; -{ - double adval = n.val.f >= 0.0 ? n.val.f : -n.val.f; - - if(n.type == UNDEF) - return UNDEF; - else if(n.type == INT) - return n.val.i; - else if(n.val.f == -1.0) - return 0x800000; - - adval -= (double)(int)adval; - adval *= (double)0x800000; - adval += 0.5; - - if(n.val.f >= 0.0) - return adval; - else - return -adval; -} - -extern struct {int n; char *name;} tok_tab[]; -extern int n_tok; - -char *tok_print(tok) -int tok; -{ - int i; - static char buf[32]; - - if(tok == '1') { - i = 1; - } - - if(tok < 256) { - sprintf(buf, tok < ' ' ? "\\z%02X" : "%c", tok & 0xFF); - return buf; - } else { - for(i = 0; i < n_tok; i++) { - if(tok == tok_tab[i].n) - return tok_tab[i].name; - } - } - return "*bogus*"; -} - -yyerror(s, a0, a1, a2, a3) -char *s, *a0, *a1, *a2, *a3; -{ - extern int error; - char buf[1024]; - - error++; - sprintf(buf, s, a0, a1, a2, a3); - - if(pass == 2) { - fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline, - buf, tok_print(yychar)); - fprintf(stderr, "%s\n", cur_line); - printf("%s: line %d: %s (tok=%s)\n", curfile, curline, - buf, tok_print(yychar)); - } -} - -yywarning(s, a0, a1, a2, a3) -char *s, *a0, *a1, *a2, *a3; -{ - extern int warning; - char buf[1024]; - - warning++; - sprintf(buf, s, a0, a1, a2, a3); - - if(pass == 2) { - fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline, - buf, tok_print(yychar)); - fprintf(stderr, "%s\n", cur_line); - printf("%s: line %d: %s (tok=%s)\n", curfile, curline, - buf, tok_print(yychar)); - } -} - -char *luntab(s) -char *s; -{ - static char buf[1024]; - int p; - - strcpy(buf, s); - - untab(buf); - p = strlen(buf); - - if(buf[p - 1] == '\n') - buf[p - 1] = '\0'; - - return buf; -}