#endif
extern int address_long INIT(1), operand_long INIT(1);
+extern int use32 INIT(1);
+
+/* For 16-bit addressing: copied from i86 assembler */
+#ifndef extern
+extern char sr_m[8];
+#else
+char sr_m[8] = {
+ -1, -1, -1, 7, -1, 6, 4, 5
+};
+#endif
+
+#ifndef extern
+extern char dr_m[8][8];
+#else
+char dr_m[8][8] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 0, 1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2, 3,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+#endif
* INTEL 80386 tokens
*/
+%token <y_word> ATOGGLE
+%token <y_word> OTOGGLE
+%token <y_word> USE16
+%token <y_word> USE32
%token <y_word> R32
%token <y_word> R16
%token <y_word> R8
* No system registers for now ...
*/
+0, USE16, 0, ".use16",
+0, USE32, 0, ".use32",
0, R32, 0, "ax",
0, R32, 1, "cx",
0, R32, 2, "dx",
0, NOTOP, 071, "idiv",
0, PREFIX, 0144, "fseg",
0, PREFIX, 0145, "gseg",
-0, PREFIX, 0146, "o16", /* operand size toggle */
-0, PREFIX, 0146, "o32", /* operand size toggle */
-0, PREFIX, 0147, "a16", /* address size toggle */
-0, PREFIX, 0147, "a32", /* address size toggle */
+0, OTOGGLE, 0146, "o16", /* operand size toggle */
+0, OTOGGLE, 0346, "o32", /* operand size toggle */
+0, ATOGGLE, 0147, "a16", /* address size toggle */
+0, ATOGGLE, 0347, "a32", /* address size toggle */
0, PREFIX, 0360, "lock",
0, PREFIX, 0362, "rep",
0, PREFIX, 0362, "repne",
operation
:
- prefix oper
- { address_long = 1; operand_long = 1; }
+ 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
- { if ($2 == 0146) operand_long = ! operand_long;
- if ($2 == 0147) address_long = ! address_long;
- emit1($2);
- }
+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);}
;
mem : '(' expr ')'
- { rm_2 = 05; exp_2 = $2; reg_2 = 05; mod_2 = 0;
+ { if (address_long) {
+ rm_2 = 05; reg_2 = 05; mod_2 = 0;
+ }
+ else {
+ reg_2 = 06;
+ }
+ exp_2 = $2;
RELOMOVE(rel_2, relonami);
+
}
| bases
{ exp_2.val = 0; exp_2.typ = S_ABS; indexed();}
}
;
bases : '(' R32 ')'
- { reg_2 = $2; sib_2 = 0; rm_2 = 0;}
+ { if (address_long) {
+ reg_2 = $2; sib_2 = 0; rm_2 = 0;
+ }
+ else reg_2 = sr_m[$2];
+ }
| '(' R32 ')' '(' R32 scale ')'
- { rm_2 = 04; sib_2 |= regindex_ind[$2][$5];
- reg_2 = $2;
+ { if (address_long) {
+ rm_2 = 04;
+ sib_2 |= regindex_ind[$2][$5];
+ reg_2 = $2;
+ }
+ else {
+ reg_2 = dr_m[$2][$5];
+ }
}
| '(' R32 '*' absexp ')'
{ if ($4 == 1) {
* INTEL 80386 special routines
*/
+ea_1_16(param)
+{
+ if ((reg_1 & 070) || (param & ~070)) {
+ serror("bad operand");
+ }
+ emit1(reg_1 | param);
+ switch(reg_1 >> 6) {
+ case 0:
+ if (reg_1 == 6 || (reg_1 & 040)) {
+#ifdef RELOCATION
+ RELOMOVE(relonami, rel_1);
+ newrelo(exp_1.typ, RELO2);
+#endif
+ emit2(exp_1.val);
+ }
+ break;
+ case 1:
+ emit1(exp_1.val);
+ break;
+ case 2:
+#ifdef RELOCATION
+ RELOMOVE(relonami, rel_1);
+ newrelo(exp_1.typ, RELO2);
+#endif
+ emit2(exp_1.val);
+ break;
+ }
+}
+
ea_1(param) {
+ if (! address_long) {
+ ea_1_16(param);
+ return;
+ }
if (is_expr(reg_1)) {
serror("bad operand");
return;
{
int v = val;
+ if (! address_long) {
+ serror("scaling not allowed in 16-bit mode");
+ return 0;
+ }
if (v != val) v = 0;
switch(v) {
case 1:
}
indexed() {
- mod_2 = 0;
- if (sib_2 == -1)
- serror("register error");
- if (rm_2 == 0 && reg_2 == 4) {
- /* base register sp, no index register; use
- indexed mode without index register
- */
- rm_2 = 04;
- sib_2 = 044;
+ if (address_long) {
+ mod_2 = 0;
+ if (sib_2 == -1)
+ serror("register error");
+ if (rm_2 == 0 && reg_2 == 4) {
+ /* base register sp, no index register; use
+ indexed mode without index register
+ */
+ rm_2 = 04;
+ sib_2 = 044;
+ }
+ if (reg_2 == 015) {
+ reg_2 = 05;
+ return;
+ }
+ if (exp_2.typ != S_ABS || fitb(exp_2.val) == 0)
+ mod_2 = 02;
+ else if (exp_2.val != 0 || reg_2 == 5)
+ mod_2 = 01;
}
- if (reg_2 == 015) {
- reg_2 = 05;
- return;
+ else {
+ if (reg_2 & ~7)
+ serror("register error");
+ if (exp_2.typ != S_ABS || fitb(exp_2.val) == 0)
+ reg_2 |= 0200;
+ else if (exp_2.val != 0 || reg_2 == 6)
+ reg_2 |= 0100;
}
- if (exp_2.typ != S_ABS || fitb(exp_2.val) == 0)
- mod_2 = 02;
- else if (exp_2.val != 0 || reg_2 == 5)
- mod_2 = 01;
}
ebranch(opc,exp)
emit4((long)(exp.val));
}
else {
- if (! fitw(exp.val)) {
+ if (! fitw(exp.val) && pass == PASS_3) {
warning("offset does not fit in 2 bytes; remove prefix");
}
#ifdef RELOCATION