📄 fpa_recompute.c
字号:
#if !defined(lint) && defined(SCCSIDS)static char sccsid[] = "@(#)fpa_recompute.c 1.1 92/07/30 SMI";#endif/* * Copyright (c) 1989 by Sun Microsystems, Inc. */#include <signal.h>#include <stdio.h>#include "fpa_support.h"extern double fabs(); /* Inline expansion actually takes care of * this. */STATICextended_precision()/* Forces extended precision expression evaluation */{ int oldmode, newmode;#ifdef F68881 newmode = 0; oldmode = Wmode(newmode); newmode = oldmode & ~0xc0; /* Force extended */ Wmode(newmode);#endif}STATIC longread_msw(n) int n;{ /* read most significant 32 bits of FPA reg n */ long *fpa_pointer; fpa_pointer = (long *) (FPABASE + 0xc00 + 8 * n); return (*fpa_pointer);}STATIC longread_lsw(n) int n;{ /* read least significant 32 bits of FPA reg * n */ long *fpa_pointer; fpa_pointer = (long *) (FPABASE + 0xc04 + 8 * n); return (*fpa_pointer);}STATIC voidwrite_msw(n, data) int n; long data;{ /* write most significant 32 bits of FPA reg * n */ long *fpa_pointer; fpa_pointer = (long *) (FPABASE + 0xc00 + 8 * n); *fpa_pointer = data;}STATIC voidwrite_lsw(n, data) int n; long data;{ /* write most significant 32 bits of FPA reg * n */ long *fpa_pointer; fpa_pointer = (long *) (FPABASE + 0xc04 + 8 * n); *fpa_pointer = data;}STATIC doubleread_single(n) int n;{ /* read FPA register n as single */ union singlekluge k; union doublekluge dk; k.i[0] = read_msw(n); dk.x = (double) k.x; /* * Conversion of single to double causes no exception except possibly * converting a signalling NaN to quiet. The following code undoes * that. */ if (Wstatus(0) & 0x80) {/* Wstatus(0) clears fpsr. */ dk.i[0] = dk.i[0] & ~0x00080000; /* Convert quiet back to * signalling. */ } return (dk.x);}STATIC doubleread_long(n) int n;{ /* read FPA register n as long */ union singlekluge k; k.x = read_msw(n); return (k.x);}STATIC doubleread_double(n) int n;{ /* read FPA register n as double */ union doublekluge k; k.i[0] = read_msw(n); k.i[1] = read_lsw(n); return (k.x);}STATIC voidwrite_long(n, data) int n; double data;{ /* write FPA register n as long */ union singlekluge k; k.i[0] = data; write_msw(n, k.i[0]);}STATIC voidwrite_single(n, data) int n; double data;{ /* write FPA register n as single */ union singlekluge k; k.x = data; write_msw(n, k.i[0]);}STATIC voidwrite_double(n, data) int n; double data;{ /* write FPA register n as double */ union doublekluge k; k.x = data; write_msw(n, k.i[0]); write_lsw(n, k.i[1]);}STATIC doubleread_2_single(data) long data;/* * returns FPA register defined in the reg_2 field of data from command * format. */{ long *fpa_pointer; int reg_1; double reg_1_op, reg_2_op; reg_1 = data & 0x1f; reg_1_op = read_single(reg_1); fpa_pointer = (long *) (FPABASE + 0x880); *fpa_pointer = data; /* reg_1 gets reg_2 contents */ reg_2_op = read_single(reg_1); write_single(reg_1, reg_1_op); return (reg_2_op);}STATIC doubleread_2_double(data) long data;/* * returns FPA register defined in the reg_2 field of data from command * format. */{ long *fpa_pointer; int reg_1; double reg_1_op, reg_2_op; reg_1 = data & 0x1f; reg_1_op = read_double(reg_1); fpa_pointer = (long *) (FPABASE + 0x884); *fpa_pointer = data; /* reg_1 gets reg_2 contents */ reg_2_op = read_double(reg_1); write_double(reg_1, reg_1_op); return (reg_2_op);}STATIC doubleread_3_single(data) long data;/* * returns FPA register defined in the reg_3 field of data from command * format, wiping out reg_1 in the process. */{ long *fpa_pointer, reg_1; double reg_1_op, reg_2_op; reg_1 = data & 0x1f; reg_1_op = read_single(reg_1); fpa_pointer = (long *) (FPABASE + 0x880); *fpa_pointer = ((data >> 10) & ~0x1f) | reg_1; /* reg_1 gets reg_3 * contents */ reg_2_op = read_single(reg_1); write_single(reg_1, reg_1_op); return (reg_2_op);}STATIC doubleread_3_double(data) long data;/* * returns FPA register defined in the reg_3 field of data from command * format. */{ long *fpa_pointer, reg_1; double reg_1_op, reg_2_op; reg_1 = data & 0x1f; reg_1_op = read_double(reg_1); fpa_pointer = (long *) (FPABASE + 0x884); *fpa_pointer = ((data >> 10) & ~0x1f) | reg_1; /* reg_1 gets reg_3 * contents */ reg_2_op = read_double(reg_1); write_double(reg_1, reg_1_op); return (reg_2_op);}STATIC doubleread_4_single(data) long data;/* * returns FPA register defined in the reg_4 field of data from command * format. */{ long *fpa_pointer, reg_1; double reg_1_op, reg_2_op; reg_1 = data & 0x1f; reg_1_op = read_single(reg_1); fpa_pointer = (long *) (FPABASE + 0x880); *fpa_pointer = ((data >> 20) & 0x7c0) | reg_1; /* reg_1 gets reg_4 * contents */ reg_2_op = read_single(reg_1); write_single(reg_1, reg_1_op); return (reg_2_op);}STATIC doubleread_4_double(data) long data;/* * returns FPA register defined in the reg_4 field of data from command * format. */{ long *fpa_pointer, reg_1; double reg_1_op, reg_2_op; reg_1 = data & 0x1f; reg_1_op = read_double(reg_1); fpa_pointer = (long *) (FPABASE + 0x884); *fpa_pointer = ((data >> 20) & 0x7c0) | reg_1; /* reg_1 gets reg_4 * contents */ reg_2_op = read_double(reg_1); write_double(reg_1, reg_1_op); return (reg_2_op);}STATIC voidfpa_compare(x, y, pc) double x, y; unsigned short *pc;/* Procedure to recompute Weitek status for x compare y - always unord. */{ long *fpa_pointer; int i, cc; /* * Following code attempts to determine if compare was for == != or * for an ordered comparison < <= > >=. The way it works is the * instruction stream is followed from pc+6 to find a bcc, dbcc, or * scc instruction: * * fpcmps@1 a0@,fpa2 pc-> fpmove@1 fpastatus,d0 pc+4-> movw d0,cc pc+6-> seq d0 * * A bcc looks like 6cXX. A dbcc or scc looks like 5cXX with bits 6 and 7 * on. * * Obviously this code can be fooled so we allow at most 100 * instructions. * * This only matters if... 1) neither operand is a signaling nan 2) the * comparison is == or !=. When both conditions hold, IEEE invalid * should not be signaled. */ pc = (unsigned short *) ((int) pc + 6); i = 0; while (((*pc & 0xf000) != 0x6000) && ((*pc & 0xf0c0) != 0x50c0) && (i < 100)) { i++; pc++; } if (((*pc & 0xf000) != 0x6000) || ((*pc & 0xf0c0) != 0x50c0)) { /* cc op code found */ cc = (*pc & 0x0f00) >> 8; if ((cc == 6) || (cc == 7)) cc = (x == y); /* == or !=, don't signal. */ else cc = (x >= y); /* Unordered, always signal. */ } else { /* no cc op code found */ printf(" no cc op code found \n") ; cc = x >= y; /* Assume unordered, always signal. */ } if (!cc) { /* cc is always false! But we need to fool * the optimizer! */ fpa_pointer = (long *) (FPABASE + 0x958); *fpa_pointer = 0xf00; /* Set unordered. */ }}STATIC intshort_single(a1, pc) struct fpa_access *a1; unsigned short *pc;/* Procedure to recompute short single format instructions. */{ struct fpa_access ap0; int opcode, src, dest, found; double reg, operand, result; union singlekluge sk; found = 1; ap0 = *a1; opcode = ap0.kluge.kis.op; src = ap0.kluge.kis.reg1; dest = ap0.kluge.kis.reg1; reg = read_single(src); sk.i[0] = ap0.data; operand = sk.x; switch (opcode) { case 1: result = -(operand); break; case 2: result = fabs(operand); break; case 3: result = sk.i[0]; break; case 4: result = fpa_tolong(operand); write_long(dest, result); goto pastwrites; case 5: result = operand; write_double(dest, result); goto pastwrites; case 6: result = (float) (operand * operand); break; case 7: result = (float) (reg + operand); break; case 8: result = (float) (reg - operand); break; case 9: result = (float) (reg * operand); break; case 10: result = (float) (reg / operand); break; case 11: result = (float) (operand - reg); break; case 12: result = (float) (operand / reg); break; case 13: fpa_compare(operand, 0.0, pc); goto pastwrites; case 14: fpa_compare(operand, reg, pc); goto pastwrites; case 15: fpa_compare(fabs(operand), fabs(reg), pc); goto pastwrites; default: found = 0; goto pastwrites; } write_single(dest, result);pastwrites:; if (!found) fprintf(stderr, "\n Invalid result from failed FPA short single format instruction:\n operand %g reg_1 %g \n", operand, reg); return (found);}STATIC intshort_double(a1, a2, pc) struct fpa_access *a1, *a2; unsigned short *pc;/* Procedure to recompute short double format instructions. */{ struct fpa_access ap0, ap1; int opcode, src, dest, found; double reg, operand, result; union doublekluge dk; found = 1; ap0 = *a1; ap1 = *a2; opcode = ap0.kluge.kis.op; src = ap0.kluge.kis.reg1; dest = ap0.kluge.kis.reg1; reg = read_double(src); dk.i[0] = ap0.data; dk.i[1] = ap1.data; operand = dk.x; switch (opcode) { case 1: result = -(operand); break; case 2: result = fabs(operand); break; case 3: result = dk.i[0]; break; case 4: result = fpa_tolong(operand); write_long(dest, result); goto pastwrited; case 5: result = (double) (float) operand; write_single(dest, result); goto pastwrited; case 6: result = operand * operand; break; case 7: result = reg + operand; break; case 8: result = reg - operand; break; case 9: result = reg * operand; break; case 10: result = reg / operand; break; case 11: result = operand - reg; break; case 12: result = operand / reg; break; case 13: fpa_compare(operand, 0.0, pc); goto pastwrited; case 14: fpa_compare(operand, reg, pc); goto pastwrited; case 15: fpa_compare(fabs(operand), fabs(reg), pc); goto pastwrited; default: found = 0; goto pastwrited; } write_double(dest, result);pastwrited: if (!found) fprintf(stderr, "\n Invalid result from failed FPA short double format instruction:\n operand %g reg_1 %g \n", operand, reg); return (found);}STATIC intextended_semantics(opcode, reg_1, prec, mem_op, mem_2_op, reg_2_op, reg_3_op) int opcode, prec, reg_1; double mem_op, mem_2_op, reg_2_op, reg_3_op;{ int found; double result; complexunion complex1, complex2, complex3; double d1, d2; pdoublekluge pdk; found = 1; switch (opcode) { case 0: extended_precision(); result = mem_2_op + (reg_2_op * mem_op); break; case 1: extended_precision(); result = mem_2_op - (reg_2_op * mem_op); break; case 2: extended_precision(); result = (reg_2_op * mem_op) - mem_2_op; break; case 3: extended_precision(); result = mem_2_op * (reg_2_op + mem_op); break; case 4: extended_precision(); result = mem_2_op * (reg_2_op - mem_op); break; case 5: extended_precision(); result = mem_2_op * (mem_op - reg_2_op); break; case 6: result = reg_2_op + mem_op; break; case 7: result = reg_2_op - mem_op; break; case 8: result = reg_2_op * mem_op; break; case 9: result = reg_2_op / mem_op; break; case 10: result = mem_op - reg_2_op; break; case 11: result = mem_op / reg_2_op; break; case 12: /* sqrt */ result = fpa_transcendental(8, mem_op); break; case 13: /* hypot */ extended_precision(); pdk.pd[0] = (double *)&mem_op; pdk.pd[1] = (double *)®_2_op; result = fpa_transcendental(9, pdk.d); break; case 14: /* complex negation */ complex3.d = mem_op; complex1.f[0] = -complex3.f[0]; complex1.f[1] = -complex3.f[1]; result = complex1.d; break; case 15: /* complex absolute value */ extended_precision(); complex3.d = mem_op; d1=complex3.f[0]; d2=complex3.f[1]; pdk.pd[0] = (double *)&d1; pdk.pd[1] = (double *)&d2; result = (double) (float) fpa_transcendental(9, pdk.d); write_single(reg_1, result); goto pastwrite; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -