Implemented fgetman,fscale,fsincos, and partial-fixed a softfloat bug

- fgetman, fscale, and fsincos are implemented but not tested at all

- fixed part of a softbug float when converting subnormal numbers between
  floatx80 and float128

- also, I checked in the wrong core/Makefile with the last commit.
  Re-committing the correct Makefile
This commit is contained in:
Peter Rutenbar 2014-11-22 16:47:49 -05:00
parent f04e039dca
commit 8142098fa1
3 changed files with 199 additions and 16 deletions

View File

@ -1,18 +1,85 @@
CC = clang
CFLAGS = -O3 -ggdb -flto -Wno-deprecated-declarations
# CFLAGS = -O0 -ggdb -Wno-deprecated-declarations
all: shoebill
shoebill: make_gui debugger
DEPS = mc68851.h shoebill.h Makefile macro.pl
NEED_DECODER = cpu dis
NEED_PREPROCESSING = adb mc68851 mem via floppy core_api fpu
NEED_NOTHING = atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer sound ethernet SoftFloat/softfloat
make_gui: make_core
xcodebuild -project gui/Shoebill.xcodeproj SYMROOT=build
# Object files that can be compiled directly from the source
OBJ_NEED_NOTHING = $(patsubst %,$(TEMP)/%.o,$(NEED_NOTHING))
debugger: make_core
$(MAKE) -C debugger
# Object files than need preprocessing with macro.pl
OBJ_NEED_PREPROCESSING = $(patsubst %,$(TEMP)/%.o,$(NEED_PREPROCESSING))
make_core:
$(MAKE) -C core -j 4
# Object files that depend on the instruction decoder
OBJ_NEED_DECODER = $(patsubst %,$(TEMP)/%.o,$(NEED_DECODER))
# Files that NEED_DECODER also NEED_PREPROCESSING
POST_PREPROCESSING = $(patsubst %,$(TEMP)/%.post.c,$(NEED_PREPROCESSING)) $(patsubst %,$(TEMP)/%.post.c,$(NEED_DECODER))
# All the object files compiled for x86_64
OBJ_x86_64 = $(OBJ_NEED_NOTHING) $(OBJ_NEED_PREPROCESSING) $(OBJ_NEED_DECODER)
# The object files compiled for i386 (the same as x86_64 files, but with .i386 appended)
OBJ_i386 = $(patsubst %,%.i386,$(OBJ_x86_64))
MACRO = perl macro.pl
TEMP = ../intermediates
all: $(TEMP)/libshoebill_core.a
$(TEMP)/libshoebill_core.a: $(TEMP) $(DEPS) $(OBJ_x86_64)
libtool -static -v -o $(TEMP)/libshoebill_core.a.x86_64 $(OBJ_x86_64)
libtool -static -v -o $(TEMP)/libshoebill_core.a.i386 $(OBJ_i386)
lipo -create -output $(TEMP)/libshoebill_core.a $(TEMP)/libshoebill_core.a.x86_64 $(TEMP)/libshoebill_core.a.i386
# Split object files into i386/x86_64 versions, since it seems that libtool is unable to
# link a static universal library for -O4 object files.
# x86_64 object files have the form "intermediates/<file_name>.o
# i386 object files have the form "intermediates/<file_name>.o.i386
# Build object files
$(OBJ_NEED_NOTHING): $(TEMP)/%.o: %.c $(DEPS)
$(CC) -c -arch x86_64 $(CFLAGS) $< -o $@
$(CC) -c -arch i386 $(CFLAGS) $< -o $@.i386
$(OBJ_NEED_PREPROCESSING): $(TEMP)/%.o: $(TEMP)/%.post.c $(DEPS)
$(CC) -c -arch x86_64 $(CFLAGS) $< -o $@
$(CC) -c -arch i386 $(CFLAGS) $< -o $@.i386
$(OBJ_NEED_DECODER): $(TEMP)/%.o: $(TEMP)/%.post.c $(DEPS) $(TEMP)/dis_decoder_guts.c $(TEMP)/inst_decoder_guts.c
$(CC) -c -arch x86_64 $(CFLAGS) $< -o $@
$(CC) -c -arch i386 $(CFLAGS) $< -o $@.i386
# Preprocess C files
$(POST_PREPROCESSING): $(TEMP)/%.post.c: %.c $(DEPS)
$(MACRO) $< $@
# Generate instruction decoders
$(TEMP)/inst_decoder_guts.c: $(TEMP)/decoder_gen $(DEPS)
$(TEMP)/decoder_gen inst $(TEMP)/
$(TEMP)/dis_decoder_guts.c: $(TEMP)/decoder_gen $(DEPS)
$(TEMP)/decoder_gen dis $(TEMP)/
# Compile the decoder generator
$(TEMP)/decoder_gen: decoder_gen.c $(DEPS)
$(CC) decoder_gen.c -o $(TEMP)/decoder_gen
$(TEMP):
mkdir -p $(TEMP)
mkdir -p $(TEMP)/SoftFloat
clean:
rm -rf intermediates gui/build
rm -rf $(TEMP)

View File

@ -3321,7 +3321,11 @@ float128 floatx80_to_float128( floatx80 a )
if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
return commonNaNToFloat128( floatx80ToCommonNaN( a ) );
}
shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
if (aExp == 0)
shift128Right( aSig, 0, 16, &zSig0, &zSig1 );
else
shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
return packFloat128( aSign, aExp, zSig0, zSig1 );
}

View File

@ -132,6 +132,7 @@ typedef struct {
// State for the static fmath instruction implementations
float128 source, dest, result;
_Bool write_back;
uint16_t extension_word; // only set in inst_fmath(), only used by fsincos
uint8_t fmath_op;
} fpu_state_t;
@ -1522,7 +1523,29 @@ static void inst_fmath_fgetman ()
{
fpu_get_state_ptr();
assert(!"fmath: fgetman not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
/* If source is inf, set operr, result is nan */
if (source_inf) {
fpu->result = _nan128;
es_operr = 1;
return;
}
/* If source is zero, result is source */
else if (source_zero) {
fpu->result = fpu->source;
return;
}
/*
* fgetman "returns" the value of the source's mantissa,
* which I think just means it resets the exponent to 0x3fff (biased 0)
* FIXME: test this
*/
fpu->result = fpu->source;
fpu->result.high &= 0x8000ffffffffffffULL;
fpu->result.high |= 0x3fff000000000000ULL;
}
static void inst_fmath_fint ()
@ -1847,7 +1870,62 @@ static void inst_fmath_fscale ()
{
fpu_get_state_ptr();
assert(!"fmath: fscale not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
const _Bool source_sign = _float128_is_neg(fpu->source);
const _Bool dest_zero = _float128_is_zero(fpu->dest);
const _Bool dest_inf = _float128_is_infinity(fpu->dest);
int32_t factor, exponent;
/* If the source is inf, the result is nan and set operr */
if (source_inf) {
fpu->result = _nan128;
es_operr = 1;
return ;
}
/* Else, if dest is inf or zero, the result is dest */
else if (dest_inf || dest_zero) {
fpu->result = fpu->dest;
return ;
}
/*
* If the source has a huge magnitude, it's definitely
* going to over/underflow
*/
if (float128_le(int32_to_float128(65536), fpu->source))
goto overflow;
else if (float128_le(fpu->source, int32_to_float128(-65536)))
goto underflow;
/* Find the scaling factor. This shoudn't raise any exceptions */
factor = float128_to_int32_round_to_zero(fpu->source);
assert(float_exception_flags == 0);
exponent = factor + (int32_t)((fpu->dest.high >> 48) & 0x7fff);
if (exponent <= 0) /* not precisely correct, I think - should be '< 0' */
goto underflow;
else if (exponent >= 0x7fff)
goto overflow;
fpu->result = fpu->dest;
fpu->result.high &= 0x8000ffffffffffffULL;
fpu->result.high |= (((uint64_t)exponent) << 48);
return ;
overflow:
/* result is +-inf, set overflow */
fpu->result = _assemble_float128(source_sign, 0x7fff, 0, 0);
es_ovfl = 1;
return ;
underflow:
/* result is +-zero, set underflow */
fpu->result = _assemble_float128(source_sign, 0, 0, 0);
es_unfl = 1;
return ;
}
static void inst_fmath_fsgldiv ()
@ -1954,7 +2032,38 @@ static void inst_fmath_fsincos ()
{
fpu_get_state_ptr();
assert(!"fmath: fsincos not implemented");
const _Bool source_zero = _float128_is_zero(fpu->source);
const _Bool source_inf = _float128_is_infinity(fpu->source);
const uint16_t cos_reg = fpu->extension_word & 0x7;
float128 cos_result;
/*
* This is incredibly inefficient, but it's fine for now
* floatx80 -> float128 -> float64 -> native -> sin -> float128 -> floatx80
* floatx80 -> float128 -> float64 -> native -> cos -> float128 -> floatx80
*/
/* If source is inf, result is nan, and set operr */
if (source_inf) {
fpu->result = _nan128;
cos_result = _nan128;
es_operr = 1;
goto write_cos;
}
/* If the source is zero, cos is +1.0, sin is +-0.0 */
else if (source_zero) {
fpu->result = fpu->source;
cos_result = _one128;
goto write_cos;
}
fpu->result = _hack_sin(fpu->source);
cos_result = _hack_cos(fpu->source);
write_cos:
/* FIXME: 68kprm doesn't clarify how the cosine result is rounded */
fpu->fp[cos_reg] = float128_to_floatx80(cos_result);
}
static void inst_fmath_fsinh ()
@ -2411,9 +2520,6 @@ static void inst_fmath (const uint16_t ext)
*/
_set_rounding_mode(mode_nearest);
/* Reset softfloat's exception flags */
float_exception_flags = 0;
/* Reset fpsr's exception flags */
es_inex1 = 0; // this is only set for imprecisely-rounded packed inputs (not implemented)
es_inex2 = 0; // set if we ever lose precision (during the op or during rounding)
@ -2459,6 +2565,9 @@ static void inst_fmath (const uint16_t ext)
printf("%Lf,fp%u\n", tmp, dest_register);
}
/* fsincos needs this to know which register to write cos */
fpu->extension_word = ext;
/*
* If the source is NaN, or this is a dyadic (two-operand)
* instruction, and the second operand (fpu->dest) is NaN,
@ -2471,6 +2580,9 @@ static void inst_fmath (const uint16_t ext)
goto computation_done;
}
/* Reset softfloat's exception flags */
float_exception_flags = 0;
/*
* Otherwise, call the extension-specific helper function.
* Guarantees: Neither source nor dest are NaN