pkgsrc-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
pkg/34690: TME sun3 emulator incorrectly performs: movel sp,-(sp)
>Number: 34690
>Category: pkg
>Synopsis: TME sun3 emulator incorrectly performs: movel sp,-(sp)
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: pkg-manager
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Oct 01 19:15:00 +0000 2006
>Originator: Arthur Townsend
>Release: 3.0
>Organization:
>Environment:
3.0 for i386
>Description:
When performing the m68k instruction: movel sp,-(sp), TME (incorrectly) puts
the predecremented sp value on the stack. Using this m68k instruction seems a
little silly, but it needs to work for a variety of programs to run (such as
any code compiled with verdix ada that raises an ada exception, handled or
not), and gcc-3.2.3 running on sunos 4.1.1 to be able to correctly preprocess
the gcc-3.2.3 testcases 981001-3.c, c94-digraph-1.c, strp2.c and two dozen
others.
>How-To-Repeat:
assemble the following test code with gcc-3.3.3 on netbsd 3.0. It prints the
same two numbers on a real sun3, but different numbers in TME.
#NO_APP
.globl _i
.data
.even
.text
LC0:
.ascii "%d\12\0"
.even
.globl _main
_main:
link a6,#0
jbsr ___main
movel sp,a0
movel a0,sp@-
pea LC0
jbsr _printf
addql #8,sp
movel sp,sp@-
pea LC0
jbsr _printf
addql #8,sp
unlk a6
rts
>Fix:
I made the following changes to m68k-insns-auto.c.
This file is automatically generated by m68k-insns-auto.sh, so these changes
should somehow be put in that script.
I updated the code so that for any move instruction with the same address
register in both the source and destination, with either a
predecrement/postincrement in the source or a predecrement in the destination,
fix instructions of the format
move.l sp,-(sp)
ignore (as tested successfully) instructions of the type
move.l (sp)+,(028,sp)
move.l (028,sp),-(sp)
and generate a warning for any others. I've been running both NetBSD and SunOS
operating systems inside TME for a few days and no other instructions have been
flagged. If one pops up, it should be checked to ensure that it is being
performed correctly. The BEST fix would be to modify the code so that the move
function gets the correct information without needing to add four back, but
that appears to be difficult to implement. I went for the low-risk fix.
--- m68k-insns-auto.c.orig 2006-10-01 08:37:12.000000000 -0400
+++ m68k-insns-auto.c 2006-10-01 08:42:12.000000000 -0400
@@ -2,8 +2,73 @@
_TME_RCSID("$Id: m68k-insns-auto.sh,v 1.23 2005/03/10 13:26:23 fredette Exp
$");
#include "m68k-impl.h"
+#include <stdio.h>
+/* following are to fix the movel sp,-(sp) problem (of the value being pushed
+ on the stack being off by four) and to warn if there are other possible
+ problems that haven't been tested */
+
+#define PREDEC_POSTINC_CONCERN \
+\
+/* if source and destination register are the same number */ \
+ ( \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3) == \
+ TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,9,3)) && \
+ \
+/* and neither is a data register */ \
+ ( \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) != 0) && \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) != 0) \
+ ) && \
+ \
+/* and there is a predec or postinc in the src, or a predec in dest */ \
+ ( \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 3) || \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 4) || \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 4) \
+ ) \
+ )
+
+
+#define DEST_IS_PREDEC_SRC_IS_REG_BOTH_SP \
+ ( \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 4) && \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 1) && \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3) == 7) && \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,9,3) == 7) \
+ ) \
+
+/* following modes test ok */
+#define MODE35_OR_MODE54_BOTH_SP \
+ ( \
+ ( \
+ \
+/* src/dest mode 3,5 : this is move.l (sp)+,(028,sp) */ \
+ ( \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 3) && \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 5) \
+ ) || \
+ \
+/* or src/dest mode 5,4 : this is move.l (028,sp),-(sp) */ \
+ ( \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3) == 5) && \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3) == 4) \
+ ) \
+ ) && \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3) == 7) && \
+ (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,9,3) == 7) \
+ ) \
+
+
+#define PRINT_WEIRD_SRC_DST_REG_MODE \
+printf ("src reg: %x src mode: %x dest reg: %x dest mode %x at pc:%x\n", \
+ TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3), \
+ TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,3,3), \
+ TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,9,3), \
+ TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,6,3), \
+ ic->tme_m68k_ireg_pc);
+
/* this does a 8-bit "add SRC, DST": */
TME_M68K_INSN(tme_m68k_add8)
{
@@ -237,6 +302,16 @@
/* perform the operation: */
res = op1;
+ if PREDEC_POSTINC_CONCERN {
+ if DEST_IS_PREDEC_SRC_IS_REG_BOTH_SP {
+ printf("ERROR: move8: how can addr/addr be 8 bits? at
pc:%x\n",ic->tme_m68k_ireg_pc);
+ } else {
+ printf("WEIRD: move8");
+ PRINT_WEIRD_SRC_DST_REG_MODE
+ }
+ }
+
+
/* store the result: */
*((tme_uint8_t *) _op0) = res;
@@ -1281,6 +1356,17 @@
/* perform the operation: */
res = op1;
+ if PREDEC_POSTINC_CONCERN {
+ if DEST_IS_PREDEC_SRC_IS_REG_BOTH_SP {
+ printf("move16: chg predec dest res from:%x to %x for register %d at pc
%x\n", res, res+2, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3),
ic->tme_m68k_ireg_pc);
+ res = res + 2;
+ } else {
+ printf("WEIRD: move16");
+ PRINT_WEIRD_SRC_DST_REG_MODE
+ }
+ }
+
+
/* store the result: */
*((tme_uint16_t *) _op0) = res;
@@ -2578,6 +2664,17 @@
/* perform the operation: */
res = op1;
+ if PREDEC_POSTINC_CONCERN {
+ if DEST_IS_PREDEC_SRC_IS_REG_BOTH_SP {
+ printf("move32: chg predec dest res from:%x to %x for register %d at pc
%x\n", res, res+4, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE,0,3),
ic->tme_m68k_ireg_pc);
+ res = res + 4;
+ } else if (!(MODE35_OR_MODE54_BOTH_SP)) {
+ printf("WEIRD: move32");
+ PRINT_WEIRD_SRC_DST_REG_MODE
+ }
+ }
+
+
/* store the result: */
*((tme_uint32_t *) _op0) = res;
Home |
Main Index |
Thread Index |
Old Index