X386 problem: Xaw i/make cannot find _divsi3. What/where is it?

James Van Artsdalen james at bigtex.cactus.org
Thu May 16 14:23:39 AEST 1991


In <1991May15.153752.6208 at thyme.jpl.nasa.gov>, kaleb at thyme.jpl.nasa.gov
	(Kaleb Keithley) wrote:

> In article holtt at jacobs.CS.ORST.EDU (Tim Holt) writes:

| I get 3 undefined symbols:  _divsi3, _fxdfsi (both in libXaw.a),
| and _udivsi3 (in libXt.a).

> These are long long arithmetic functions from gnulib.

Actually, _divsi3 is signed 32 bit division, _udivsi3 is unsigned 32 bit
division, and _fixdfsi is double->int conversion.  gcc version 1 has
little if any long long support in i386.md.  gcc version 2 will support
it better.

I'm not sure why the divide patterns are being used from gnulib - gcc
has patterns for divmodsi4 & udivmodsi4.  If someone can induce gcc 1.39
to call _divsi3 or _udivsi3, I'd like to know how as I think it is a bug.

As for converting double to int, that change probably won't be made to
gcc version 1 unless there is a strong need.  But, here are the
changes to do it if you like.  Don't report bugs to gnu.gcc.bug: mail
them to me.

First, add these three patterns to i386.md:

(define_expand "fix_truncdfdi2"
  [(parallel [(set (match_operand:DI 0 "general_operand" "")
		   (fix:DI
		    (fix:DF (match_operand:DF 1 "general_operand" ""))))
	      (clobber (match_dup 2))])]
  "TARGET_80387"
  "operands[2] = gen_reg_rtx (HImode);")

(define_expand "fixuns_truncdfdi2"
  [(parallel [(set (match_operand:DI 0 "general_operand" "")
		   (fix:DI
		    (fix:DF (match_operand:DF 1 "general_operand" ""))))
	      (clobber (match_dup 2))])]
  "TARGET_80387"
  "operands[2] = gen_reg_rtx (HImode);")

(define_insn "fix_truncdfdi2_1"
  [(set (match_operand:DI 0 "general_operand" "=m,?*r")
	(fix:DI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))
   (clobber (match_operand:HI 2 "register_operand" "=r,r"))]
  "TARGET_80387"
  "*output_fix_trunc (operands); RET;")

=====

Then, in out-i386.c, in print_operand(), add the two lines marked below:

>>	case 'D':
>>	  PUT_OP_SIZE (code, 'l', file);
	case 'L':
	  PUT_OP_SIZE (code, 'l', file);
	  return;

=====

Also in out-i386.c, replace fp_pop_int() with this and remove the #if 0 /
#endif that surrounds the function:

/* Pop the fp stack, convert value to integer and store in TARGET.
   TARGET may be memory or register, and may have QI, HI or SImode.  */

void
fp_pop_int (target)
     rtx target;
{
  if (REG_P (target))
    {
      rtx xops[3];

      xops[0] = stack_pointer_rtx;
      xops[1] = gen_rtx (CONST_INT, VOIDmode,
			  GET_MODE_SIZE (GET_MODE (target)));

      output_asm_insn (AS2 (sub%L0,%1,%0), xops);
      /* fp_pop_level--; */

      xops[0] = AT_SP (Pmode);

      if (GET_MODE (target) == SImode)
	{
	  output_asm_insn (AS1 (fistp%L0,%0), xops);
	  output_asm_insn (AS1 (pop%L0,%0), &target);
	}
      else if (GET_MODE (target) == DImode)
	{
	  xops[1] = gen_rtx (REG, SImode, REGNO (target));
	  xops[2] = gen_rtx (REG, SImode, REGNO (target) + 1);

	  output_asm_insn (AS1 (fistp%D0,%0), xops);
	  output_asm_insn (AS1 (pop%L1,%1), xops);
	  output_asm_insn (AS1 (pop%L2,%2), xops);
	}
      else
	abort();
    }
  else if (GET_CODE (target) == MEM)
    {
      if (GET_MODE (target) == DImode)
	output_asm_insn (AS1 (fistp%D0,%0), &target);
      else if (GET_MODE (target) == SImode)
	output_asm_insn (AS1 (fistp%L0,%0), &target);
      else
	abort();
    }
  else
    abort ();
}

=====

Lastly, add this to the end of out-i386.c:

void
output_fix_trunc (operands)
     rtx *operands;
{
  rtx xops[6];

  if (!FP_REG_P (operands[1]))
    abort ();

  xops[0] = stack_pointer_rtx;
  xops[1] = AT_SP (HImode);
  xops[2] = adj_offsettable_operand (xops[1], 2);
  xops[3] = gen_rtx (CONST_INT, VOIDmode, 4);
  xops[4] = gen_rtx (CONST_INT, VOIDmode, 0xc00);
  xops[5] = operands[2];

  output_asm_insn (AS2 (sub%L0,%3,%0), xops);
  output_asm_insn ("fnstcw %1", xops);
  output_asm_insn (AS2 (mov%W5,%1,%5), xops);
  output_asm_insn (AS2 (or%W5,%4,%5), xops);
  output_asm_insn (AS2 (mov%W5,%5,%2), xops);
  output_asm_insn ("fldcw %2", xops);

  fp_pop_int (operands[0]);

  output_asm_insn ("fldcw %1", xops);
  output_asm_insn (AS2 (add%L0,%3,%0), xops);
}

-- 
James R. Van Artsdalen          james at bigtex.cactus.org   "Live Free or Die"
Dell Computer Co    9505 Arboretum Blvd Austin TX 78759         512-338-8789



More information about the Comp.unix.sysv386 mailing list