123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- #define RCSID4 "$Id$"
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- *
- */
- operation
- :
- USE16
- { use32 = 0; address_long = 0; operand_long = 0; }
- |
- USE32
- { use32 = 1; address_long = 1; operand_long = 1; }
- | prefix oper
- { address_long = use32; operand_long = use32; }
- | prefix1 /* to allow for only prefixes on a line */
- ;
- prefix : /* empty */
- | prefix1
- ;
- prefix1: prefix PREFIX { emit1($2); }
- |
- prefix ATOGGLE
- { if ((($2&0200) >> 7) == address_long) {
- if (pass == PASS_3) warning("address size toggle ignored");
- } else {
- emit1($2 & 0177);
- address_long = ! address_long;
- }
- }
- |
- prefix OTOGGLE
- { if ((($2&0200) >> 7) == operand_long) {
- if (pass == PASS_3) warning("operand size toggle ignored");
- } else {
- emit1($2 & 0177);
- operand_long = ! operand_long;
- }
- }
- ;
- oper : NOOP_1
- { emit1($1);}
- | NOOP_2
- { emit2($1);}
- | JOP expr
- { branch($1,$2);}
- | JOP2 expr
- { ebranch($1,$2);}
- | PUSHOP ea_1
- { pushop($1);}
- | IOOP absexp
- { emit1($1);
- fit(ufitb($2));
- emit1((int)$2);
- }
- | IOOP R32
- { if ($2!=2) serror("register error");
- emit1($1+010);
- }
- | BITTEST ea_ea
- { bittestop($1);}
- | ADDOP ea_ea
- { addop($1);}
- | ROLOP ea_ea
- { rolop($1);}
- | INCOP ea_1
- { incop($1);}
- | NOTOP ea_1
- { regsize($1); emit1(0366|($1&1)); ea_1($1&070);}
- | CALLOP ea_1
- { callop($1&0xFFFF);}
- | CALFOP expr ':' expr
- { emit1($1>>8);
- adsize_exp($4, 0);
- #ifdef RELOCATION
- newrelo($2.typ, RELO2);
- #endif
- emit2((int)($2.val));
- }
- | CALFOP mem
- { emit1(0377); ea_2($1&0xFF);}
- | ENTER absexp ',' absexp
- { fit(fitw($2)); fit(fitb($4));
- emit1($1); emit2((int)$2); emit1((int)$4);
- }
- | LEAOP R32 ',' mem
- { emit1($1); ea_2($2<<3);}
- | LEAOP2 R32 ',' mem
- { emit1(0xF); emit1($1); ea_2($2<<3);}
- | ARPLOP ea_2 ',' R32
- { emit1($1); ea_2($4<<3);}
- | LSHFT ea_1 ',' R32 ',' ea_2
- { extshft($1, $4);}
- | EXTEND R32 ',' ea_2
- { emit1(0xF); emit1($1); ea_2($2<<3);}
- | EXTOP R32 ',' ea_2
- { emit1(0xF); emit1($1); ea_2($2<<3);}
- | EXTOP1 ea_1
- { emit1(0xF); emit1($1&07); ea_1($1&070);}
- | IMULB ea_1
- { regsize(0); emit1(0366); ea_1($1&070);}
- | IMUL ea_2
- { reg_1 = IS_R32 | (address_long ? 0 : 0310);
- imul(0);
- }
- | IMUL R32 ',' ea_2
- { reg_1 = $2 | IS_R32 | (address_long ? 0 : 0310);
- imul($2|0x10);
- }
- | IMUL R32 ',' ea_ea
- { imul($2|0x10);}
- | INT absexp
- { if ($2==3)
- emit1(0314);
- else {
- fit(ufitb($2));
- emit1(0315); emit1((int)$2);
- }
- }
- | RET
- { emit1($1);}
- | RET expr
- { emit1($1-1);
- #ifdef RELOCATION
- newrelo($2.typ, RELO2);
- #endif
- emit2((int)($2.val));
- }
- | SETCC ea_2
- { if (reg_2 & (IS_R32|IS_RSEG)) {
- serror("register error");
- }
- emit1(0xF); emit1($1|0x90); ea_2(0);
- }
- | XCHG ea_ea
- { xchg($1);}
- | TEST ea_ea
- { test($1);}
- | MOV ea_ea
- { mov($1);}
- | /* What is really needed is just
- MOV R32 ',' RSYSCR
- but this gives a bad yacc conflict
- */
- MOV ea_1 ',' RSYSCR
- {
- if ($1 != 1 || !(reg_1 & IS_R32))
- serror("syntax error");
- emit1(0xF); emit1(0x20); emit1(0300|($4<<3)|(reg_1&07));}
- | MOV ea_1 ',' RSYSDR
- {
- if ($1 != 1 || !(reg_1 & IS_R32))
- serror("syntax error");
- emit1(0xF); emit1(0x21); emit1(0300|($4<<3)|(reg_1&07));}
- | MOV ea_1 ',' RSYSTR
- {
- if ($1 != 1 || !(reg_1 & IS_R32))
- serror("syntax error");
- emit1(0xF); emit1(0x24); emit1(0300|($4<<3)|(reg_1&07));}
- | MOV RSYSCR ',' R32
- {
- if ($1 != 1) serror("syntax error");
- emit1(0xF); emit1(0x22); emit1(0300|($2<<3)|$4);}
- | MOV RSYSDR ',' R32
- {
- if ($1 != 1) serror("syntax error");
- emit1(0xF); emit1(0x23); emit1(0300|($2<<3)|$4);}
- | MOV RSYSTR ',' R32
- {
- if ($1 != 1) serror("syntax error");
- emit1(0xF); emit1(0x26); emit1(0300|($2<<3)|$4);}
- /* Intel 80[23]87 coprocessor instructions */
- | FNOOP
- { emit1($1); emit1($1>>8);}
- | FMEM mem
- { emit1($1); ea_2(($1>>8)&070);}
- | FMEM_AX mem
- { emit1($1); ea_2(($1>>8)&070);}
- | FMEM_AX R32
- { if ($2 != 0) {
- serror("illegal register");
- }
- emit1(FESC|7); emit1(7<<5);
- }
- | FST_I st_i
- { emit1($1); emit1(($1>>8)|$2); }
- | FST_I ST
- { emit1($1); emit1($1>>8); }
- | FST_ST ST ',' st_i
- { emit1($1); emit1(($1>>8)|$4); }
- | FST_ST2 ST ',' st_i
- { emit1($1); emit1(($1>>8)|$4); }
- | FST_ST st_i ',' ST
- { emit1($1|4); emit1((($1>>8)|$2)); }
- | FST_ST2 st_i ',' ST
- { emit1($1|4); emit1((($1>>8)|$2)^010); }
- /* 486 instructions */
- | BSWAP R32
- { emit1(0xF); emit1($1|$2); }
- | EXTOPBW ea_2 ',' reg
- { regsize($1);
- emit1(0xF); emit1($1); ea_2($4<<3);
- }
- ;
- st_i : ST '(' absexp ')'
- { if (!fit3($3)) {
- serror("illegal index in FP stack");
- }
- $$ = $3;
- }
- ;
- ;
- mem : '(' expr ')'
- { if (address_long) reg_2 = 05;
- else reg_2 = 06;
- mod_2 = 0;
- rm_2 = 05;
- exp_2 = $2;
- RELOMOVE(rel_2, relonami);
-
- }
- | bases
- { exp_2.val = 0; exp_2.typ = S_ABS; indexed();}
- | expr bases
- { exp_2 = $1; indexed();
- RELOMOVE(rel_2, relonami);
- }
- ;
- bases : '(' R32 ')'
- { if (address_long) reg_2 = $2;
- else reg_2 = sr_m[$2];
- sib_2 = 0; rm_2 = 0;
- }
- | '(' R32 ')' '(' R32 scale ')'
- { if (address_long) reg_2 = $2;
- else reg_2 = dr_m[$2][$5];
- rm_2 = 04;
- sib_2 |= regindex_ind[$2][$5];
- }
- | '(' R32 '*' absexp ')'
- { if ($4 == 1) {
- reg_2 = $2; sib_2 = 0; rm_2 = 0;
- }
- else {
- rm_2 = 04;
- sib_2 = checkscale($4) | regindex_ind[05][$2];
- reg_2 = 015;
- }
- }
- ;
- scale : /* empty */
- { sib_2 = 0;}
- | '*' absexp
- { sib_2 = checkscale($2);}
- ;
- ea_2 : mem
- | R8
- { reg_2 = ($1 | IS_R8) | (address_long ? 0 : 0300);
- rm_2 = 0;
- }
- | R32
- { reg_2 = ($1 | IS_R32) | (address_long ? 0 : 0310);
- rm_2 = 0;
- }
- | RSEG
- { reg_2 = ($1 | IS_RSEG) | (address_long ? 0 : 020);
- rm_2 = 0;
- }
- | expr
- { reg_2 = IS_EXPR | (address_long ? 0 : 040);
- exp_2 = $1; rm_2 = 0;
- RELOMOVE(rel_2, relonami);
- }
- ;
- reg : R8 { reg_1 = ($1 | IS_R8) | (address_long ? 0 : 0300);
- rm_1 = 0;
- $$ = $1;
- }
- | R32
- { reg_1 = ($1 | IS_R32) | (address_long ? 0 : 0310);
- rm_1 = 0;
- $$ = $1;
- }
- ;
- ea_1 : ea_2
- { op_1 = op_2;
- RELOMOVE(rel_1, rel_2);
- }
- ;
- ea_ea : ea_1 ',' ea_2
- ;
|