mirror of
https://github.com/pruten/shoebill.git
synced 2024-09-27 09:55:14 +00:00
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:
parent
f04e039dca
commit
8142098fa1
@ -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)
|
||||
|
||||
|
@ -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 );
|
||||
|
||||
}
|
||||
|
124
core/fpu.c
124
core/fpu.c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user