#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 reg ',' ea_2 { regsize($1); emit1(0xF); emit1($1); ea_2($2<<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 ;