From 2c7496a5256d9ad3b15f4a7c3c238f1aabd84d50 Mon Sep 17 00:00:00 2001 From: ceriel Date: Mon, 12 Mar 1990 16:24:58 +0000 Subject: [PATCH] Added 16-bit mode --- mach/i386/as/mach1.c | 25 ++++++++++++++ mach/i386/as/mach2.c | 4 +++ mach/i386/as/mach3.c | 10 +++--- mach/i386/as/mach4.c | 58 +++++++++++++++++++++++++------ mach/i386/as/mach5.c | 81 ++++++++++++++++++++++++++++++++++---------- 5 files changed, 146 insertions(+), 32 deletions(-) diff --git a/mach/i386/as/mach1.c b/mach/i386/as/mach1.c index 910a3b93d..5ecaad7f2 100644 --- a/mach/i386/as/mach1.c +++ b/mach/i386/as/mach1.c @@ -75,3 +75,28 @@ char regindex_ind[8][8] = { #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 diff --git a/mach/i386/as/mach2.c b/mach/i386/as/mach2.c index 18c16fc55..3f899b9d5 100644 --- a/mach/i386/as/mach2.c +++ b/mach/i386/as/mach2.c @@ -8,6 +8,10 @@ * INTEL 80386 tokens */ +%token ATOGGLE +%token OTOGGLE +%token USE16 +%token USE32 %token R32 %token R16 %token R8 diff --git a/mach/i386/as/mach3.c b/mach/i386/as/mach3.c index eca3888f4..f3c06c625 100644 --- a/mach/i386/as/mach3.c +++ b/mach/i386/as/mach3.c @@ -10,6 +10,8 @@ * 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", @@ -213,10 +215,10 @@ 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", diff --git a/mach/i386/as/mach4.c b/mach/i386/as/mach4.c index 019765178..5e273e806 100644 --- a/mach/i386/as/mach4.c +++ b/mach/i386/as/mach4.c @@ -8,18 +8,37 @@ 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);} @@ -177,8 +196,15 @@ st_i : ST '(' absexp ')' ; 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();} @@ -188,10 +214,20 @@ mem : '(' expr ')' } ; 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) { diff --git a/mach/i386/as/mach5.c b/mach/i386/as/mach5.c index 88b74c8f8..bdd15afc0 100644 --- a/mach/i386/as/mach5.c +++ b/mach/i386/as/mach5.c @@ -8,7 +8,40 @@ * 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; @@ -49,6 +82,10 @@ checkscale(val) { 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: @@ -93,24 +130,34 @@ regsize(sz) } 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) @@ -245,7 +292,7 @@ adsize_exp(exp, relpc) 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 -- 2.34.1