Fix PPC simulator fdiv insn

Andrew Cagney cagney@tpgi.com.au
Wed Feb 11 02:54:00 GMT 1998


Jason,

Probably interested in the below.

	Andrew

Mon Feb  9 14:13:14 1998  Andrew Cagney  <cagney@b1.cygnus.com>

	* ppc-instructions (fdiv, fdivs): Check for divide by zero.
	(is_invalid_zero_divide, invalid_zero_divide_operation): New
 	functions.
	
*** ./sim/ppc/ppc-instructions.orig	Wed Feb 11 21:54:54 1998
--- ./sim/ppc/ppc-instructions	Mon Feb  9 17:27:39 1998
***************
*** 1384,1389 ****
--- 1384,1429 ----
  
  
  
+ # detect divide by zero
+ int::function::is_invalid_zero_divide:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, int single
+ 	int fail = 0;
+ 	if (is_zero (frb)) {
+ 	  FPSCR_SET_ZX (1);
+ 	  fail = 1;
+ 	}
+ 	return fail;
+ 
+ 
+ 
+ 
+ # handle case of invalid operation
+ void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, int single
+ 	if (FPSCR & fpscr_ze) {
+ 	  /* zero-divide exception enabled */
+ 	  /* FRT unchaged */
+ 	  FPSCR_SET_FR(0);
+ 	  FPSCR_SET_FI(0);
+ 	  /* fpscr_FPRF unchanged */
+ 	}
+ 	else {
+ 	  /* zero-divide exception disabled */
+ 	  FPSCR_SET_FR(0);
+ 	  FPSCR_SET_FI(0);
+ 	  if ((sign (fra) < 0 && sign (frb) < 0)
+ 	      || (sign (fra) > 0 && sign (frb) > 0)) {
+ 	    *frt = MASK64 (1, 11); /* 0 : 2047 : 0..0 */
+ 	    FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
+ 	  }
+ 	  else {
+ 	    *frt = MASK64 (0, 11); /* 1 : 2047 : 0..0 */
+ 	    FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
+ 	  }
+ 	}
+ 
+ 
+ 
+ 
+ 
  #
  # 0.0.0.0 Illegal instruction used for kernel mode emulation
  #
***************
*** 3758,3763 ****
--- 3798,3810 ----
  	                                0, /*instruction_is_convert_to_32bit*/
  	                                0); /*single-precision*/
  	}
+ 	else if (is_invalid_zero_divide (processor, cia,
+ 	                                 *frA, *frB,
+ 	                                 0 /*single?*/)) {
+ 	  invalid_zero_divide_operation (processor, cia,
+ 	                                 frT, *frA, *frB,
+ 	                                 0 /*single?*/);
+ 	}
  	else {
  	  /*HACK!*/
  	  double s = *(double*)frA / *(double*)frB;
***************
*** 3783,3788 ****
--- 3830,3842 ----
  	                                0, /*instruction_is_convert_to_64bit*/
  	                                0, /*instruction_is_convert_to_32bit*/
  	                                1); /*single-precision*/
+ 	}
+ 	else if (is_invalid_zero_divide (processor, cia,
+ 	                                 *frA, *frB,
+ 	                                 1 /*single?*/)) {
+ 	  invalid_zero_divide_operation (processor, cia,
+ 	                                 frT, *frA, *frB,
+ 	                                 1 /*single?*/);
  	}
  	else {
  	  /*HACK!*/



More information about the Gdb mailing list