www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2001/06/08/11:44:03

X-Authentication-Warning: kendall.sfbr.org: jeffw set sender to jeffw AT darwin DOT sfbr DOT org using -f
Date: Fri, 8 Jun 2001 10:46:57 -0500
From: JT Williams <jeffw AT darwin DOT sfbr DOT org>
To: djgpp-workers AT delorie DOT com
Subject: patch for djasm.y (double-precision instructions)
Message-ID: <20010608104657.A21101@kendall.sfbr.org>
Mail-Followup-To: djgpp-workers AT delorie DOT com
Mime-Version: 1.0
User-Agent: Mutt/1.2.5i
Reply-To: djgpp-workers AT delorie DOT com

Below is the last patch currently in the queue for djasm.y.

This patch (re-)implements the double-precision shift instructions, and
traps any obsolete usage of `sh[lr]d' to denote double-precision shifts.
(Recall, `sh[lr]d' are now the mnemonics for basic left/right shifts of a
double-word operand.)  For example, here are some (obsolete) instructions
and the resulting error messages:

shld	ax,bx,4
shrd	ax,bx,4
shld	eax,ebx,4
shrd	eax,ebx,4

% djasm shifty.asm shifty.exe shifty.map
shifty.asm:11: Obsolete use of `shld' detected.  Use `dshl' instead.
shifty.asm:12: Obsolete use of `shrd' detected.  Use `dshr' instead.
shifty.asm:19: Obsolete use of `shld' detected.  Use `dshl' instead.
shifty.asm:20: Obsolete use of `shrd' detected.  Use `dshr' instead.
shifty.asm: 4 errors

Documentation patches can be finalized and committed when the final form
of this patch is known.

This patch is a considerably simplified implementation of Bill Currie's
original scheme for double-precision shifts.  Bill used the mnemonics
`sh[lr]d[dq]', interpreted as follows:

sh	[sh]ift
lr	[l]eft/[r]ight
d	[d]ouble-precision
dq	[d]ouble-word operands/[q]uad-word (double double-word) operands

I have two problems with this:

(1) the double-precision shifts are *not* equivalent to shifts of a
double-wide operand.  See the Intel documentation, or confirm this using
small test programs (I did both).  Therefore the `d' and `q' suffixes
are IMHO misleading, because they suggest monolithic shifts of 32- and
64-bit operands.

(2) the double-precision shift instructions do *not* require a suffix
to denote the operand size.  Further explanation is given in the patch.

For our implementation, I chose the mnemonics `dsh[lr]'.

(I didn't plan it this way, but it turns out that *if* anyone ever did
use `shld' or `shrd' for a double-precision shift, all they have to do
is rewrite these instructions as `dshl' or `dshr'.)


--- djasm.y.old	Thu May 24 16:46:49 2001
+++ djasm.y	Fri Jun  8 10:01:57 2001
@@ -36,6 +36,7 @@
 
 void djerror(char *s);
 void yyerror(char *s);
+void shd_error(int opcode, int b32);
 
 #define OUT_exe 0
 #define OUT_com 1
@@ -230,7 +231,7 @@
 %token <i> ARITH2 ARITH2B ARITH2D ARITH2W
 %token <i> LXS MOVSZX MOVSZXB MOVSZXW
 %token <i> JCC JCCL JCXZ LOOP SETCC
-%token <i> SHIFT SHIFTB SHIFTD SHIFTW
+%token <i> SHIFT SHIFTB SHIFTD SHIFTW DPSHIFT
 %token <i> ONEBYTE TWOBYTE ASCADJ
 %token <i> BITTEST GROUP3 GROUP3B GROUP3D GROUP3W GROUP6 GROUP7 STRUCT
 %token ALIGN ARPL
@@ -592,10 +593,12 @@
   {"shlb", SHIFTB, 4},
   {"shld", SHIFTD, 4},
   {"shlw", SHIFTW, 4},
+  {"dshl", DPSHIFT, 0xa4},
   {"shr", SHIFT, 5},
   {"shrb", SHIFTB, 5},
   {"shrd", SHIFTD, 5},
   {"shrw", SHIFTW, 5},
+  {"dshr", DPSHIFT, 0xac},
   {"smsw", GROUP7, 4},
   {"str", GROUP6, 1},
   {"sub", ARITH2, 5},
@@ -1031,6 +1034,7 @@
 	| SETCC REG8			{ emitb(0x0f); emitb(0x90+$1); modrm(3, 0, $2); }
 	| SETCC regmem			{ emitb(0x0f); emitb(0x90+$1); reg(0); }
 
+	/* basic shift of byte/word/double operand */
 	| SHIFT REG8 ',' const		{ emitb($4 == 1 ? 0xd0 : 0xc0); modrm(3, $1, $2); if ($4 != 1) emitb($4); }
 	| SHIFT REG8 ',' REG8		{ if ($4 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0xd2); modrm(3, $1, $2); }
 	| SHIFTB regmem ',' const	{ emitb($4 == 1 ? 0xd0 : 0xc0); reg($1); if ($4 != 1) emitb($4); }
@@ -1044,6 +1048,40 @@
 	| SHIFTD regmem ',' const	{ emitb(0x66); emitb($4 == 1 ? 0xd1 : 0xc1); reg($1); if ($4 != 1) emitb($4); }
 	| SHIFTD regmem ',' REG8	{ if ($4 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0x66); emitb(0xd3); reg($1); }
 
+	/* Trap any use of `sh[lr]d' to denote a double-precision shift.
+	This trap is not strictly necessary, because writing `sh[lr]d'
+	with three operands would generate a parse error anyway.  However,
+	there _was_ a time when djasm did use `sh[lr]d' as the mnemonics
+	for the double-precision shifts.  This usage was later removed
+	(it interfered with subsequent implementation of the basic shift
+	instructions).  (jtw) */
+
+	| SHIFTD REG16 ',' REG16 ',' const	{ shd_error($1,0); }
+	| SHIFTD REG16 ',' REG16 ',' REG8	{ shd_error($1,0); }
+	| SHIFTD regmem ',' REG16 ',' const	{ shd_error($1,0); }
+	| SHIFTD regmem ',' REG16 ',' REG8	{ shd_error($1,0); }
+	| SHIFTD REG32 ',' REG32 ',' const	{ shd_error($1,1); }
+	| SHIFTD REG32 ',' REG32 ',' REG8	{ shd_error($1,1); }
+	| SHIFTD regmem ',' REG32 ',' const	{ shd_error($1,1); }
+	| SHIFTD regmem ',' REG32 ',' REG8	{ shd_error($1,1); }
+
+	/* These double-precision shift instructions do *not* require an
+	operand-size suffix.  The size of the memory operand must agree
+	with the size of the register, hence the allowable combinations
+	of operands are completely unambiguous. (jtw) */
+
+	/* 16-bit double-precision shift */
+	| DPSHIFT REG16 ',' REG16 ',' const	{ emitb(0x0f); emitb($1); modrm(3, $4, $2); emitb($6); }
+	| DPSHIFT REG16 ',' REG16 ',' REG8	{ if ($6 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0x0f); emitb($1+1); modrm(3, $4, $2); }
+	| DPSHIFT regmem ',' REG16 ',' const	{ emitb(0x0f); emitb($1); reg($4); emitb($6); }
+	| DPSHIFT regmem ',' REG16 ',' REG8	{ if ($6 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0x0f); emitb($1+1); reg($4); }
+
+	/* 32-bit double-precision shift */
+	| DPSHIFT REG32 ',' REG32 ',' const	{ emitb(0x66); emitb(0x0f); emitb($1); modrm(3, $4, $2); emitb($6); }
+	| DPSHIFT REG32 ',' REG32 ',' REG8	{ if ($6 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0x66); emitb(0x0f); emitb($1+1); modrm(3, $4, $2); }
+	| DPSHIFT regmem ',' REG32 ',' const	{ emitb(0x66); emitb(0x0f); emitb($1); reg($4); emitb($6); }
+	| DPSHIFT regmem ',' REG32 ',' REG8	{ if ($6 != 1) djerror ("Non-constant shift count must be `cl'"); emitb(0x66); emitb(0x0f); emitb($1+1); reg($4); }
+
 	| STACK				{ stack_ptr = pc; }
 	| START				{ start_ptr = pc; main_obj=1; }
 
@@ -1628,6 +1666,35 @@
 {
   djerror(s);
   fprintf(stderr, "%s:%d: Last token was `%s' (%s)\n", inname, lineno, last_token, yytname[(unsigned char)yytranslate[last_tret]]);
+}
+
+void
+shd_error(int opcode, int b32)
+{
+  char *bad_op;
+  char *good_op;
+  char msg[80];
+
+  if (opcode == 4)
+  {
+    bad_op = "`shld'";
+    good_op = "`dshl'";
+    /* good_op = b32 ? "`shldd' or `shldq'" : "`shldd'"; */
+  }
+  else
+  {
+    bad_op = "`shrd'";
+    good_op = "`dshr'";
+    /* good_op = b32 ? "`shrdd' or `shrdq'" : "`shrdd'"; */
+  }
+  sprintf(msg, "Obsolete use of %s detected.  Use %s instead.", bad_op, good_op);
+  djerror(msg);
+/*
+  sprintf(msg, "Attempted obsolete use of %s detected.", bad_op);
+  djerror(msg);
+  sprintf(msg, "Use %s instead.", good_op);
+  djerror(msg);
+*/
 }
 
 Symbol *get_symbol(char *name, int create)

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019