From 6f535fd5b5dd864e862609e05648ba5a2fbd5727 Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Mon, 31 Jan 2005 23:44:35 +0000 Subject: [PATCH] Remove GPLed fpemulation, old rp, old awe and pcic. dgb is still in, until the persons having the hardware decide that digi(4) works for them. Correct spelling of deprecation. --- sys/bus/isa/i386/isa_compat.h | 8 +- sys/conf/files | 4 +- sys/conf/files.amd64 | 4 +- sys/conf/files.i386 | 35 +- sys/conf/files.pc98 | 34 +- sys/conf/options | 4 +- sys/conf/options.amd64 | 5 +- sys/conf/options.i386 | 5 +- sys/conf/options.pc98 | 5 +- sys/config/LINT | 18 +- sys/dev/pccard/pcic/Makefile | 8 - sys/dev/pccard/pcic/i82365.c | 1526 ------ sys/dev/pccard/pcic/i82365_isa.c | 405 -- sys/dev/pccard/pcic/i82365reg.h | 366 -- sys/dev/pccard/pcic/i82365var.h | 170 - sys/dev/serial/rp2/rp.c | 1973 ------- sys/dev/serial/rp2/rpreg.h | 1046 ---- sys/dev/serial/rp2/rpvar.h | 94 - sys/dev/sound/isa/i386/dev_table.h | 5 +- sys/dev/sound/isa/i386/sound_calls.h | 6 +- sys/dev/sound/isa/i386/soundcard.c | 5 +- sys/i386/conf/LINT | 18 +- sys/i386/gnu/fpemul/Changelog | 39 - sys/i386/gnu/fpemul/README | 279 - sys/i386/gnu/fpemul/control_w.h | 96 - sys/i386/gnu/fpemul/div_small.s | 98 - sys/i386/gnu/fpemul/errors.c | 609 --- sys/i386/gnu/fpemul/exception.h | 106 - sys/i386/gnu/fpemul/fpu_arith.c | 234 - sys/i386/gnu/fpemul/fpu_asm.h | 84 - sys/i386/gnu/fpemul/fpu_aux.c | 236 - sys/i386/gnu/fpemul/fpu_emu.h | 189 - sys/i386/gnu/fpemul/fpu_entry.c | 525 -- sys/i386/gnu/fpemul/fpu_etc.c | 177 - sys/i386/gnu/fpemul/fpu_proto.h | 115 - sys/i386/gnu/fpemul/fpu_system.h | 98 - sys/i386/gnu/fpemul/fpu_trig.c | 1372 ----- sys/i386/gnu/fpemul/get_address.c | 203 - sys/i386/gnu/fpemul/load_store.c | 274 - sys/i386/gnu/fpemul/math_emu.h | 48 - sys/i386/gnu/fpemul/poly_2xm1.c | 140 - sys/i386/gnu/fpemul/poly_atan.c | 252 - sys/i386/gnu/fpemul/poly_div.s | 139 - sys/i386/gnu/fpemul/poly_l2.c | 317 -- sys/i386/gnu/fpemul/poly_mul64.s | 123 - sys/i386/gnu/fpemul/poly_sin.c | 196 - sys/i386/gnu/fpemul/poly_tan.c | 228 - sys/i386/gnu/fpemul/polynomial.s | 191 - sys/i386/gnu/fpemul/reg_add_sub.c | 301 -- sys/i386/gnu/fpemul/reg_compare.c | 386 -- sys/i386/gnu/fpemul/reg_constant.c | 167 - sys/i386/gnu/fpemul/reg_constant.h | 83 - sys/i386/gnu/fpemul/reg_div.s | 291 -- sys/i386/gnu/fpemul/reg_ld_str.c | 1389 ----- sys/i386/gnu/fpemul/reg_mul.c | 160 - sys/i386/gnu/fpemul/reg_norm.s | 177 - sys/i386/gnu/fpemul/reg_round.s | 651 --- sys/i386/gnu/fpemul/reg_u_add.s | 241 - sys/i386/gnu/fpemul/reg_u_div.s | 502 -- sys/i386/gnu/fpemul/reg_u_mul.s | 195 - sys/i386/gnu/fpemul/reg_u_sub.s | 358 -- sys/i386/gnu/fpemul/status_w.h | 107 - sys/i386/gnu/fpemul/version.h | 62 - sys/i386/gnu/fpemul/wm_shrx.s | 259 - sys/i386/gnu/fpemul/wm_sqrt.s | 493 -- sys/i386/gnu/isa/dgb.c | 6 +- sys/i386/gnu/isa/sound/awe_compat.h | 220 - sys/i386/gnu/isa/sound/awe_config.h | 151 - sys/i386/gnu/isa/sound/awe_hw.h | 100 - sys/i386/gnu/isa/sound/awe_version.h | 35 - sys/i386/gnu/isa/sound/awe_voice.h | 490 -- sys/i386/gnu/isa/sound/awe_wave.c | 4581 ----------------- sys/i386/i386/userconfig.c | 3 +- sys/i386/isa/ic/i82365.h | 192 - sys/i386/isa/npx.c | 4 +- sys/i386/isa/sound/local.h | 7 +- sys/platform/pc32/gnu/fpemul/Changelog | 39 - sys/platform/pc32/gnu/fpemul/README | 279 - sys/platform/pc32/gnu/fpemul/control_w.h | 96 - sys/platform/pc32/gnu/fpemul/div_small.s | 98 - sys/platform/pc32/gnu/fpemul/errors.c | 609 --- sys/platform/pc32/gnu/fpemul/exception.h | 106 - sys/platform/pc32/gnu/fpemul/fpu_arith.c | 234 - sys/platform/pc32/gnu/fpemul/fpu_asm.h | 84 - sys/platform/pc32/gnu/fpemul/fpu_aux.c | 236 - sys/platform/pc32/gnu/fpemul/fpu_emu.h | 189 - sys/platform/pc32/gnu/fpemul/fpu_entry.c | 525 -- sys/platform/pc32/gnu/fpemul/fpu_etc.c | 177 - sys/platform/pc32/gnu/fpemul/fpu_proto.h | 115 - sys/platform/pc32/gnu/fpemul/fpu_system.h | 98 - sys/platform/pc32/gnu/fpemul/fpu_trig.c | 1372 ----- sys/platform/pc32/gnu/fpemul/get_address.c | 203 - sys/platform/pc32/gnu/fpemul/load_store.c | 274 - sys/platform/pc32/gnu/fpemul/math_emu.h | 48 - sys/platform/pc32/gnu/fpemul/poly_2xm1.c | 140 - sys/platform/pc32/gnu/fpemul/poly_atan.c | 252 - sys/platform/pc32/gnu/fpemul/poly_div.s | 139 - sys/platform/pc32/gnu/fpemul/poly_l2.c | 317 -- sys/platform/pc32/gnu/fpemul/poly_mul64.s | 123 - sys/platform/pc32/gnu/fpemul/poly_sin.c | 196 - sys/platform/pc32/gnu/fpemul/poly_tan.c | 228 - sys/platform/pc32/gnu/fpemul/polynomial.s | 191 - sys/platform/pc32/gnu/fpemul/reg_add_sub.c | 301 -- sys/platform/pc32/gnu/fpemul/reg_compare.c | 386 -- sys/platform/pc32/gnu/fpemul/reg_constant.c | 167 - sys/platform/pc32/gnu/fpemul/reg_constant.h | 83 - sys/platform/pc32/gnu/fpemul/reg_div.s | 291 -- sys/platform/pc32/gnu/fpemul/reg_ld_str.c | 1389 ----- sys/platform/pc32/gnu/fpemul/reg_mul.c | 160 - sys/platform/pc32/gnu/fpemul/reg_norm.s | 177 - sys/platform/pc32/gnu/fpemul/reg_round.s | 651 --- sys/platform/pc32/gnu/fpemul/reg_u_add.s | 241 - sys/platform/pc32/gnu/fpemul/reg_u_div.s | 502 -- sys/platform/pc32/gnu/fpemul/reg_u_mul.s | 195 - sys/platform/pc32/gnu/fpemul/reg_u_sub.s | 358 -- sys/platform/pc32/gnu/fpemul/status_w.h | 107 - sys/platform/pc32/gnu/fpemul/version.h | 62 - sys/platform/pc32/gnu/fpemul/wm_shrx.s | 259 - sys/platform/pc32/gnu/fpemul/wm_sqrt.s | 493 -- sys/platform/pc32/gnu/isa/dgb.c | 6 +- sys/platform/pc32/gnu/isa/sound/awe_compat.h | 220 - sys/platform/pc32/gnu/isa/sound/awe_config.h | 151 - sys/platform/pc32/gnu/isa/sound/awe_hw.h | 100 - sys/platform/pc32/gnu/isa/sound/awe_version.h | 35 - sys/platform/pc32/gnu/isa/sound/awe_voice.h | 490 -- sys/platform/pc32/gnu/isa/sound/awe_wave.c | 4581 ----------------- sys/platform/pc32/i386/userconfig.c | 3 +- sys/platform/pc32/isa/ic/i82365.h | 192 - sys/platform/pc32/isa/npx.c | 4 +- sys/platform/pc32/isa/sound/local.h | 7 +- 130 files changed, 34 insertions(+), 41668 deletions(-) delete mode 100644 sys/dev/pccard/pcic/Makefile delete mode 100644 sys/dev/pccard/pcic/i82365.c delete mode 100644 sys/dev/pccard/pcic/i82365_isa.c delete mode 100644 sys/dev/pccard/pcic/i82365reg.h delete mode 100644 sys/dev/pccard/pcic/i82365var.h delete mode 100644 sys/dev/serial/rp2/rp.c delete mode 100644 sys/dev/serial/rp2/rpreg.h delete mode 100644 sys/dev/serial/rp2/rpvar.h delete mode 100644 sys/i386/gnu/fpemul/Changelog delete mode 100644 sys/i386/gnu/fpemul/README delete mode 100644 sys/i386/gnu/fpemul/control_w.h delete mode 100644 sys/i386/gnu/fpemul/div_small.s delete mode 100644 sys/i386/gnu/fpemul/errors.c delete mode 100644 sys/i386/gnu/fpemul/exception.h delete mode 100644 sys/i386/gnu/fpemul/fpu_arith.c delete mode 100644 sys/i386/gnu/fpemul/fpu_asm.h delete mode 100644 sys/i386/gnu/fpemul/fpu_aux.c delete mode 100644 sys/i386/gnu/fpemul/fpu_emu.h delete mode 100644 sys/i386/gnu/fpemul/fpu_entry.c delete mode 100644 sys/i386/gnu/fpemul/fpu_etc.c delete mode 100644 sys/i386/gnu/fpemul/fpu_proto.h delete mode 100644 sys/i386/gnu/fpemul/fpu_system.h delete mode 100644 sys/i386/gnu/fpemul/fpu_trig.c delete mode 100644 sys/i386/gnu/fpemul/get_address.c delete mode 100644 sys/i386/gnu/fpemul/load_store.c delete mode 100644 sys/i386/gnu/fpemul/math_emu.h delete mode 100644 sys/i386/gnu/fpemul/poly_2xm1.c delete mode 100644 sys/i386/gnu/fpemul/poly_atan.c delete mode 100644 sys/i386/gnu/fpemul/poly_div.s delete mode 100644 sys/i386/gnu/fpemul/poly_l2.c delete mode 100644 sys/i386/gnu/fpemul/poly_mul64.s delete mode 100644 sys/i386/gnu/fpemul/poly_sin.c delete mode 100644 sys/i386/gnu/fpemul/poly_tan.c delete mode 100644 sys/i386/gnu/fpemul/polynomial.s delete mode 100644 sys/i386/gnu/fpemul/reg_add_sub.c delete mode 100644 sys/i386/gnu/fpemul/reg_compare.c delete mode 100644 sys/i386/gnu/fpemul/reg_constant.c delete mode 100644 sys/i386/gnu/fpemul/reg_constant.h delete mode 100644 sys/i386/gnu/fpemul/reg_div.s delete mode 100644 sys/i386/gnu/fpemul/reg_ld_str.c delete mode 100644 sys/i386/gnu/fpemul/reg_mul.c delete mode 100644 sys/i386/gnu/fpemul/reg_norm.s delete mode 100644 sys/i386/gnu/fpemul/reg_round.s delete mode 100644 sys/i386/gnu/fpemul/reg_u_add.s delete mode 100644 sys/i386/gnu/fpemul/reg_u_div.s delete mode 100644 sys/i386/gnu/fpemul/reg_u_mul.s delete mode 100644 sys/i386/gnu/fpemul/reg_u_sub.s delete mode 100644 sys/i386/gnu/fpemul/status_w.h delete mode 100644 sys/i386/gnu/fpemul/version.h delete mode 100644 sys/i386/gnu/fpemul/wm_shrx.s delete mode 100644 sys/i386/gnu/fpemul/wm_sqrt.s delete mode 100644 sys/i386/gnu/isa/sound/awe_compat.h delete mode 100644 sys/i386/gnu/isa/sound/awe_config.h delete mode 100644 sys/i386/gnu/isa/sound/awe_hw.h delete mode 100644 sys/i386/gnu/isa/sound/awe_version.h delete mode 100644 sys/i386/gnu/isa/sound/awe_voice.h delete mode 100644 sys/i386/gnu/isa/sound/awe_wave.c delete mode 100644 sys/i386/isa/ic/i82365.h delete mode 100644 sys/platform/pc32/gnu/fpemul/Changelog delete mode 100644 sys/platform/pc32/gnu/fpemul/README delete mode 100644 sys/platform/pc32/gnu/fpemul/control_w.h delete mode 100644 sys/platform/pc32/gnu/fpemul/div_small.s delete mode 100644 sys/platform/pc32/gnu/fpemul/errors.c delete mode 100644 sys/platform/pc32/gnu/fpemul/exception.h delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_arith.c delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_asm.h delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_aux.c delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_emu.h delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_entry.c delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_etc.c delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_proto.h delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_system.h delete mode 100644 sys/platform/pc32/gnu/fpemul/fpu_trig.c delete mode 100644 sys/platform/pc32/gnu/fpemul/get_address.c delete mode 100644 sys/platform/pc32/gnu/fpemul/load_store.c delete mode 100644 sys/platform/pc32/gnu/fpemul/math_emu.h delete mode 100644 sys/platform/pc32/gnu/fpemul/poly_2xm1.c delete mode 100644 sys/platform/pc32/gnu/fpemul/poly_atan.c delete mode 100644 sys/platform/pc32/gnu/fpemul/poly_div.s delete mode 100644 sys/platform/pc32/gnu/fpemul/poly_l2.c delete mode 100644 sys/platform/pc32/gnu/fpemul/poly_mul64.s delete mode 100644 sys/platform/pc32/gnu/fpemul/poly_sin.c delete mode 100644 sys/platform/pc32/gnu/fpemul/poly_tan.c delete mode 100644 sys/platform/pc32/gnu/fpemul/polynomial.s delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_add_sub.c delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_compare.c delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_constant.c delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_constant.h delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_div.s delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_ld_str.c delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_mul.c delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_norm.s delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_round.s delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_u_add.s delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_u_div.s delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_u_mul.s delete mode 100644 sys/platform/pc32/gnu/fpemul/reg_u_sub.s delete mode 100644 sys/platform/pc32/gnu/fpemul/status_w.h delete mode 100644 sys/platform/pc32/gnu/fpemul/version.h delete mode 100644 sys/platform/pc32/gnu/fpemul/wm_shrx.s delete mode 100644 sys/platform/pc32/gnu/fpemul/wm_sqrt.s delete mode 100644 sys/platform/pc32/gnu/isa/sound/awe_compat.h delete mode 100644 sys/platform/pc32/gnu/isa/sound/awe_config.h delete mode 100644 sys/platform/pc32/gnu/isa/sound/awe_hw.h delete mode 100644 sys/platform/pc32/gnu/isa/sound/awe_version.h delete mode 100644 sys/platform/pc32/gnu/isa/sound/awe_voice.h delete mode 100644 sys/platform/pc32/gnu/isa/sound/awe_wave.c delete mode 100644 sys/platform/pc32/isa/ic/i82365.h diff --git a/sys/bus/isa/i386/isa_compat.h b/sys/bus/isa/i386/isa_compat.h index cac9c6c92b..47d5c23d28 100644 --- a/sys/bus/isa/i386/isa_compat.h +++ b/sys/bus/isa/i386/isa_compat.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/isa/isa_compat.h,v 1.27.2.11 2002/10/05 18:31:48 scottl Exp $ - * $DragonFly: src/sys/bus/isa/i386/isa_compat.h,v 1.6 2004/02/21 06:37:05 dillon Exp $ + * $DragonFly: src/sys/bus/isa/i386/isa_compat.h,v 1.7 2005/01/31 23:44:34 joerg Exp $ */ #include "use_vt.h" @@ -38,7 +38,6 @@ #include "use_sb.h" #include "use_sbxvi.h" #include "use_sbmidi.h" -#include "use_awe.h" #include "use_gus.h" #include "use_mss.h" #include "use_css.h" @@ -58,7 +57,6 @@ #include "use_dgb.h" #include "use_labpc.h" #include "use_rc.h" -#include "use_rp.h" #include "use_tw.h" #include "use_asc.h" #include "use_stl.h" @@ -80,7 +78,6 @@ extern struct isa_driver pasdriver; extern struct isa_driver sbdriver; extern struct isa_driver sbxvidriver; extern struct isa_driver sbmididriver; -extern struct isa_driver awedriver; extern struct isa_driver gusdriver; extern struct isa_driver mssdriver; extern struct isa_driver cssdriver; @@ -205,9 +202,6 @@ static struct old_isa_driver old_drivers[] = { #if NSBMIDI > 0 { INTR_TYPE_MISC, &sbmididriver }, #endif -#if NAWE > 0 - { INTR_TYPE_MISC, &awedriver }, -#endif #if NGUS > 0 { INTR_TYPE_MISC, &gusdriver }, #endif diff --git a/sys/conf/files b/sys/conf/files index 36f9e1f40f..a6717a6ed7 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/sys/conf/files,v 1.84 2005/01/14 03:25:31 dillon Exp $ +# $DragonFly: src/sys/conf/files,v 1.85 2005/01/31 23:44:34 joerg Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -253,8 +253,6 @@ dev/pccard/pccbb/pccbb.c optional cbb dev/pccard/cardbus/cardbus.c optional cardbus dev/pccard/cardbus/cardbus_cis.c optional cardbus dev/pccard/exca/exca.c optional cbb -dev/pccard/pcic/i82365.c optional pcic pccard -dev/pccard/pcic/i82365_isa.c optional pcic pccard isa dev/disk/advansys/adv_eisa.c optional adv eisa dev/disk/advansys/adv_pci.c optional adv pci diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 0f843c50c5..bb234c0476 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -2,7 +2,7 @@ # files marked standard are always included. # # $FreeBSD: src/sys/conf/files.i386,v 1.307.2.38 2003/01/02 20:41:33 kan Exp $ -# $DragonFly: src/sys/conf/Attic/files.amd64,v 1.3 2004/04/29 12:11:15 joerg Exp $ +# $DragonFly: src/sys/conf/Attic/files.amd64,v 1.4 2005/01/31 23:44:34 joerg Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -125,7 +125,6 @@ vfs/smbfs/smbfs_subr.c optional smbfs vfs/smbfs/smbfs_vfsops.c optional smbfs vfs/smbfs/smbfs_vnops.c optional smbfs i386/gnu/isa/dgb.c optional dgb -i386/gnu/isa/sound/awe_wave.c optional awe i386/apm/apm.c optional apm i386/i386/atomic.c standard \ compile-with "${CC} -c ${CFLAGS} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}" @@ -212,7 +211,6 @@ i386/isa/pmtimer.c optional acpica # XXX drhodus i386/isa/prof_machdep.c optional profiling-routine dev/serial/rc/rc.c optional rc -dev/serial/rp2/rp.c optional rp dev/disk/scd/scd.c optional scd dev/sound/isa/i386/ad1848.c optional css dev/sound/isa/i386/ad1848.c optional gus diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 2126fe35be..6621f3affe 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -2,7 +2,7 @@ # files marked standard are always included. # # $FreeBSD: src/sys/conf/files.i386,v 1.307.2.38 2003/01/02 20:41:33 kan Exp $ -# $DragonFly: src/sys/conf/Attic/files.i386,v 1.26 2004/07/27 08:09:55 asmodai Exp $ +# $DragonFly: src/sys/conf/Attic/files.i386,v 1.27 2005/01/31 23:44:34 joerg Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -145,39 +145,7 @@ vfs/smbfs/smbfs_smb.c optional smbfs vfs/smbfs/smbfs_subr.c optional smbfs vfs/smbfs/smbfs_vfsops.c optional smbfs vfs/smbfs/smbfs_vnops.c optional smbfs -i386/gnu/fpemul/div_small.s optional gpl_math_emulate -i386/gnu/fpemul/errors.c optional gpl_math_emulate -i386/gnu/fpemul/fpu_arith.c optional gpl_math_emulate -i386/gnu/fpemul/fpu_aux.c optional gpl_math_emulate -i386/gnu/fpemul/fpu_entry.c optional gpl_math_emulate -i386/gnu/fpemul/fpu_etc.c optional gpl_math_emulate -i386/gnu/fpemul/fpu_trig.c optional gpl_math_emulate -i386/gnu/fpemul/get_address.c optional gpl_math_emulate -i386/gnu/fpemul/load_store.c optional gpl_math_emulate -i386/gnu/fpemul/poly_2xm1.c optional gpl_math_emulate -i386/gnu/fpemul/poly_atan.c optional gpl_math_emulate -i386/gnu/fpemul/poly_div.s optional gpl_math_emulate -i386/gnu/fpemul/poly_l2.c optional gpl_math_emulate -i386/gnu/fpemul/poly_mul64.s optional gpl_math_emulate -i386/gnu/fpemul/poly_sin.c optional gpl_math_emulate -i386/gnu/fpemul/poly_tan.c optional gpl_math_emulate -i386/gnu/fpemul/polynomial.s optional gpl_math_emulate -i386/gnu/fpemul/reg_add_sub.c optional gpl_math_emulate -i386/gnu/fpemul/reg_compare.c optional gpl_math_emulate -i386/gnu/fpemul/reg_constant.c optional gpl_math_emulate -i386/gnu/fpemul/reg_div.s optional gpl_math_emulate -i386/gnu/fpemul/reg_ld_str.c optional gpl_math_emulate -i386/gnu/fpemul/reg_mul.c optional gpl_math_emulate -i386/gnu/fpemul/reg_norm.s optional gpl_math_emulate -i386/gnu/fpemul/reg_round.s optional gpl_math_emulate -i386/gnu/fpemul/reg_u_add.s optional gpl_math_emulate -i386/gnu/fpemul/reg_u_div.s optional gpl_math_emulate -i386/gnu/fpemul/reg_u_mul.s optional gpl_math_emulate -i386/gnu/fpemul/reg_u_sub.s optional gpl_math_emulate -i386/gnu/fpemul/wm_shrx.s optional gpl_math_emulate -i386/gnu/fpemul/wm_sqrt.s optional gpl_math_emulate i386/gnu/isa/dgb.c optional dgb -i386/gnu/isa/sound/awe_wave.c optional awe i386/apm/apm.c optional apm i386/i386/atomic.c standard \ compile-with "${CC} -c ${CFLAGS} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}" @@ -292,7 +260,6 @@ i386/isa/pmtimer.c optional acpica pmtimer # XXX drhodus i386/isa/prof_machdep.c optional profiling-routine dev/serial/rc/rc.c optional rc -dev/serial/rp2/rp.c optional rp dev/disk/scd/scd.c optional scd dev/sound/isa/i386/ad1848.c optional css dev/sound/isa/i386/ad1848.c optional gus diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index e54c3ba3ad..6cb6ef4774 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -4,7 +4,7 @@ # modified for PC-9801 # # $FreeBSD: src/sys/conf/files.pc98,v 1.140.2.44 2003/02/10 13:11:50 nyan Exp $ -# $DragonFly: src/sys/conf/Attic/files.pc98,v 1.6 2004/04/29 12:11:15 joerg Exp $ +# $DragonFly: src/sys/conf/Attic/files.pc98,v 1.7 2005/01/31 23:44:34 joerg Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -124,39 +124,7 @@ fs/smbfs/smbfs_smb.c optional smbfs fs/smbfs/smbfs_subr.c optional smbfs fs/smbfs/smbfs_vfsops.c optional smbfs fs/smbfs/smbfs_vnops.c optional smbfs -gnu/i386/fpemul/div_small.s optional gpl_math_emulate -gnu/i386/fpemul/errors.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_arith.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_aux.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_entry.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_etc.c optional gpl_math_emulate -gnu/i386/fpemul/fpu_trig.c optional gpl_math_emulate -gnu/i386/fpemul/get_address.c optional gpl_math_emulate -gnu/i386/fpemul/load_store.c optional gpl_math_emulate -gnu/i386/fpemul/poly_2xm1.c optional gpl_math_emulate -gnu/i386/fpemul/poly_atan.c optional gpl_math_emulate -gnu/i386/fpemul/poly_div.s optional gpl_math_emulate -gnu/i386/fpemul/poly_l2.c optional gpl_math_emulate -gnu/i386/fpemul/poly_mul64.s optional gpl_math_emulate -gnu/i386/fpemul/poly_sin.c optional gpl_math_emulate -gnu/i386/fpemul/poly_tan.c optional gpl_math_emulate -gnu/i386/fpemul/polynomial.s optional gpl_math_emulate -gnu/i386/fpemul/reg_add_sub.c optional gpl_math_emulate -gnu/i386/fpemul/reg_compare.c optional gpl_math_emulate -gnu/i386/fpemul/reg_constant.c optional gpl_math_emulate -gnu/i386/fpemul/reg_div.s optional gpl_math_emulate -gnu/i386/fpemul/reg_ld_str.c optional gpl_math_emulate -gnu/i386/fpemul/reg_mul.c optional gpl_math_emulate -gnu/i386/fpemul/reg_norm.s optional gpl_math_emulate -gnu/i386/fpemul/reg_round.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_add.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_div.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_mul.s optional gpl_math_emulate -gnu/i386/fpemul/reg_u_sub.s optional gpl_math_emulate -gnu/i386/fpemul/wm_shrx.s optional gpl_math_emulate -gnu/i386/fpemul/wm_sqrt.s optional gpl_math_emulate gnu/i386/isa/dgb.c optional dgb -gnu/i386/isa/sound/awe_wave.c optional awe pc98/apm/apm.c optional apm pc98/apm/apm_bioscall.s optional apm i386/i386/atomic.c standard \ diff --git a/sys/conf/options b/sys/conf/options index 1539328a3d..072bf399e9 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/options,v 1.191.2.53 2003/06/04 17:56:58 sam Exp $ -# $DragonFly: src/sys/conf/options,v 1.28 2004/12/08 20:36:39 joerg Exp $ +# $DragonFly: src/sys/conf/options,v 1.29 2005/01/31 23:44:34 joerg Exp $ # # On the handling of kernel options # @@ -531,4 +531,4 @@ DCONS_FORCE_CONSOLE opt_dcons.h DCONS_FORCE_GDB opt_dcons.h # depricated drivers and options -I_WANT_DEPRICATED_STUFF opt_depricated.h +I_WANT_DEPRECATED_STUFF opt_deprecated.h diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64 index e6ff8f1570..ac09a79fe8 100644 --- a/sys/conf/options.amd64 +++ b/sys/conf/options.amd64 @@ -1,10 +1,9 @@ # $FreeBSD: src/sys/conf/options.i386,v 1.132.2.18 2003/03/14 21:22:35 jhb Exp $ -# $DragonFly: src/sys/conf/Attic/options.amd64,v 1.2 2004/04/29 12:11:15 joerg Exp $ +# $DragonFly: src/sys/conf/Attic/options.amd64,v 1.3 2005/01/31 23:44:34 joerg Exp $ DISABLE_PSE IDE_DELAY MATH_EMULATE opt_math_emulate.h -GPL_MATH_EMULATE opt_math_emulate.h PMAP_SHPGPERPROC opt_pmap.h PPC_PROBE_CHIPSET opt_ppc.h PPC_DEBUG opt_ppc.h @@ -103,8 +102,6 @@ PSM_HOOKRESUME opt_psm.h PSM_RESETAFTERSUSPEND opt_psm.h PSM_DEBUG opt_psm.h -PCIC_RESUME_RESET opt_pcic.h - PUC_FASTINTR opt_puc.h ATKBD_DFLT_KEYMAP opt_atkbd.h diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index 6102186632..8c5d365ba1 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -1,10 +1,9 @@ # $FreeBSD: src/sys/conf/options.i386,v 1.132.2.18 2003/03/14 21:22:35 jhb Exp $ -# $DragonFly: src/sys/conf/Attic/options.i386,v 1.8 2004/09/21 13:02:51 joerg Exp $ +# $DragonFly: src/sys/conf/Attic/options.i386,v 1.9 2005/01/31 23:44:34 joerg Exp $ DISABLE_PSE IDE_DELAY MATH_EMULATE opt_math_emulate.h -GPL_MATH_EMULATE opt_math_emulate.h PMAP_SHPGPERPROC opt_pmap.h PPC_PROBE_CHIPSET opt_ppc.h PPC_DEBUG opt_ppc.h @@ -108,8 +107,6 @@ PSM_HOOKRESUME opt_psm.h PSM_RESETAFTERSUSPEND opt_psm.h PSM_DEBUG opt_psm.h -PCIC_RESUME_RESET opt_pcic.h - PUC_FASTINTR opt_puc.h ATKBD_DFLT_KEYMAP opt_atkbd.h diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98 index a14b2d0286..c68e6b334f 100644 --- a/sys/conf/options.pc98 +++ b/sys/conf/options.pc98 @@ -1,10 +1,9 @@ # $FreeBSD: src/sys/conf/options.pc98,v 1.103.2.17 2003/03/14 21:22:35 jhb Exp $ -# $DragonFly: src/sys/conf/Attic/options.pc98,v 1.6 2004/04/29 12:11:15 joerg Exp $ +# $DragonFly: src/sys/conf/Attic/options.pc98,v 1.7 2005/01/31 23:44:34 joerg Exp $ DISABLE_PSE IDE_DELAY MATH_EMULATE opt_math_emulate.h -GPL_MATH_EMULATE opt_math_emulate.h PMAP_SHPGPERPROC opt_pmap.h PPC_PROBE_CHIPSET opt_ppc.h PPC_DEBUG opt_ppc.h @@ -97,8 +96,6 @@ PSM_HOOKRESUME opt_psm.h PSM_RESETAFTERSUSPEND opt_psm.h PSM_DEBUG opt_psm.h -PCIC_RESUME_RESET opt_pcic.h - PUC_FASTINTR opt_puc.h KBD_DISABLE_KEYMAP_LOAD opt_kbd.h diff --git a/sys/config/LINT b/sys/config/LINT index c166ddca2b..07b04b8831 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -3,7 +3,7 @@ # as much of the source tree as it can. # # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $ -# $DragonFly: src/sys/config/LINT,v 1.45 2005/01/10 19:37:23 joerg Exp $ +# $DragonFly: src/sys/config/LINT,v 1.46 2005/01/31 23:44:35 joerg Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -268,14 +268,8 @@ options CYRIX_CACHE_REALLY_WORKS # # A math emulator is mandatory if you wish to run on hardware which -# does not have a floating-point processor. Pick either the original, -# bogus (but freely-distributable) math emulator, or a much more -# fully-featured but GPL-licensed emulator taken from Linux. -# +# does not have a floating-point processor. options MATH_EMULATE #Support for x87 emulation -# Don't enable both of these in a real config. -#options GPL_MATH_EMULATE #Support for x87 emulation via - #new math emulator ##################################################################### # COMPATIBILITY OPTIONS @@ -1537,7 +1531,6 @@ options NATM #native ATM #device sb0 at isa? port 0x220 irq 5 drq 1 #device sbxvi0 at isa? drq 5 #device sbmidi0 at isa? port 0x330 -#device awe0 at isa? port 0x620 #device gus0 at isa? port 0x220 irq 12 drq 1 ##device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 #device mss0 at isa? port 0x530 irq 10 drq 1 @@ -2084,15 +2077,10 @@ options BKTR_NEW_MSP34XX_DRIVER # PCCARD/PCMCIA # # pccard: pccard slots -# pcic: isa/pccard bridge (OLDCARD) -# cardbus/cbb: cardbus bridge (NEWCARD) +# cardbus/cbb: cardbus bridge device pccard device cardbus device cbb -#device pcic - -# You may need to reset all pccards after resuming -options PCIC_RESUME_RESET # reset after resume # # Laptop/Notebook options: diff --git a/sys/dev/pccard/pcic/Makefile b/sys/dev/pccard/pcic/Makefile deleted file mode 100644 index 12276f1325..0000000000 --- a/sys/dev/pccard/pcic/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $DragonFly: src/sys/dev/pccard/pcic/Attic/Makefile,v 1.1 2004/02/10 07:55:47 joerg Exp $ - -KMOD= pcic -SRCS= i82365.c i82365_isa.c \ - device_if.h bus_if.h isa_if.h power_if.h card_if.h -NOMAN= - -.include diff --git a/sys/dev/pccard/pcic/i82365.c b/sys/dev/pccard/pcic/i82365.c deleted file mode 100644 index 88aeb04285..0000000000 --- a/sys/dev/pccard/pcic/i82365.c +++ /dev/null @@ -1,1526 +0,0 @@ -/* $NetBSD: i82365.c,v 1.25 1999/10/15 06:07:27 haya Exp $ */ -/* $FreeBSD: src/sys/dev/pcic/i82365.c,v 1.37 2002/11/17 04:52:37 imp Exp $ */ -/* $DragonFly: src/sys/dev/pccard/pcic/Attic/i82365.c,v 1.2 2004/12/08 20:36:39 joerg Exp $ */ - -/* - * Copyright (c) 1997 Marc Horowitz. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Marc Horowitz. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "opt_depricated.h" -#ifndef I_WANT_DEPRICATED_STUFF -#error "Add options I_WANT_DEPRICATED_STUFF to your kernel config and send a mail to kernel@" -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -/* We shouldn't need to include the following, but sadly we do for now */ -/* XXX */ -#include -#include - -#include -#include - -#include "card_if.h" - -#define PCICDEBUG - -#ifdef PCICDEBUG -int pcic_debug = 1; -#define DPRINTF(arg) if (pcic_debug) printf arg; else ; -#define DEVPRINTF(arg) if (pcic_debug) device_printf arg; else ; -#else -#define DPRINTF(arg) -#define DEVPRINTF(arg) -#endif - -#define VERBOSE(arg) if (bootverbose) printf arg; else ; - -#define N(a) (sizeof(a)/sizeof(a[0])) - -#define PCIC_VENDOR_UNKNOWN 0 -#define PCIC_VENDOR_I82365SLR0 1 -#define PCIC_VENDOR_I82365SLR1 2 -#define PCIC_VENDOR_CIRRUS_PD6710 3 -#define PCIC_VENDOR_CIRRUS_PD672X 4 - -#define PCIC_H2SOFTC(h) ((struct pcic_softc *)h->sc) -/* - * Individual drivers will allocate their own memory and io regions. Memory - * regions must be a multiple of 4k, aligned on a 4k boundary. - */ - -#define PCIC_MEM_ALIGN PCIC_MEM_PAGESIZE - -static void pcic_init_socket(struct pcic_handle *); -static void pcic_intr_socket(struct pcic_handle *); - -static int pcic_activate(device_t dev); -static void pcic_intr(void *arg); - -static void pcic_attach_card(struct pcic_handle *); -static void pcic_detach_card(struct pcic_handle *); - -static void pcic_chip_do_mem_map(struct pcic_handle *, int); -static void pcic_chip_do_io_map(struct pcic_handle *, int); - -void pcic_create_event_thread(void *); -void pcic_event_thread(void *); - -void pcic_queue_event(struct pcic_handle *, int); - -static void pcic_wait_ready(struct pcic_handle *); - -static u_int8_t st_pcic_read(struct pcic_handle *, int); -static void st_pcic_write(struct pcic_handle *, int, u_int8_t); - -/* XXX Should really be dynamic XXX */ -static struct pcic_handle *handles[20]; -static struct pcic_handle **lasthandle = handles; - -static struct pcic_handle * -pcic_get_handle(device_t dev, device_t child) -{ - if (dev == child) - return NULL; - while (child && device_get_parent(child) != dev) - child = device_get_parent(child); - if (child == NULL) - return NULL; - return ((struct pcic_handle *) device_get_ivars(child)); -} - -int -pcic_ident_ok(int ident) -{ - /* this is very empirical and heuristic */ - - if ((ident == 0) || (ident == 0xff) || (ident & PCIC_IDENT_ZERO)) - return (0); - - if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) { -#ifdef DIAGNOSTIC - printf("pcic: does not support memory and I/O cards, " - "ignored (ident=%0x)\n", ident); -#endif - return (0); - } - return (1); -} - -int -pcic_vendor(struct pcic_handle *h) -{ - int reg; - - /* - * the chip_id of the cirrus toggles between 11 and 00 after a write. - * weird. - */ - - pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0); - reg = pcic_read(h, -1); - - if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == - PCIC_CIRRUS_CHIP_INFO_CHIP_ID) { - reg = pcic_read(h, -1); - if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) { - if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS) - return (PCIC_VENDOR_CIRRUS_PD672X); - else - return (PCIC_VENDOR_CIRRUS_PD6710); - } - } - - reg = pcic_read(h, PCIC_IDENT); - - if ((reg & PCIC_IDENT_REV_MASK) == PCIC_IDENT_REV_I82365SLR0) - return (PCIC_VENDOR_I82365SLR0); - else - return (PCIC_VENDOR_I82365SLR1); - - return (PCIC_VENDOR_UNKNOWN); -} - -char * -pcic_vendor_to_string(int vendor) -{ - switch (vendor) { - case PCIC_VENDOR_I82365SLR0: - return ("Intel 82365SL Revision 0"); - case PCIC_VENDOR_I82365SLR1: - return ("Intel 82365SL Revision 1"); - case PCIC_VENDOR_CIRRUS_PD6710: - return ("Cirrus PD6710"); - case PCIC_VENDOR_CIRRUS_PD672X: - return ("Cirrus PD672X"); - } - - return ("Unknown controller"); -} - -static int -pcic_activate(device_t dev) -{ - struct pcic_softc *sc = PCIC_SOFTC(dev); - int err; - - sc->port_rid = 0; - sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, - 0, ~0, PCIC_IOSIZE, RF_ACTIVE); - if (!sc->port_res) { - device_printf(dev, "Cannot allocate ioport\n"); - return ENOMEM; - } - - sc->irq_rid = 0; - sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, - 0, ~0, 1, RF_ACTIVE); - if (sc->irq_res) { - sc->irq = rman_get_start(sc->irq_res); - if ((err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, - pcic_intr, sc, &sc->intrhand)) != 0) { - device_printf(dev, "Cannot setup intr\n"); - pcic_deactivate(dev); - return err; - } - } else { - printf("Polling not supported\n"); - /* XXX Do polling */ - return (ENXIO); - } - - /* XXX This might not be needed in future, get it directly from - * XXX parent */ - sc->mem_rid = 0; - sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid, - 0, ~0, 1 << 13, RF_ACTIVE); - if (sc->mem_res == NULL) { - device_printf(dev, "Cannot allocate mem\n"); - pcic_deactivate(dev); - return ENOMEM; - } - - sc->iot = rman_get_bustag(sc->port_res); - sc->ioh = rman_get_bushandle(sc->port_res);; - sc->memt = rman_get_bustag(sc->mem_res); - sc->memh = rman_get_bushandle(sc->mem_res);; - - return (0); -} - -void -pcic_deactivate(device_t dev) -{ - struct pcic_softc *sc = PCIC_SOFTC(dev); - - if (sc->intrhand) - bus_teardown_intr(dev, sc->irq_res, sc->intrhand); - sc->intrhand = 0; - if (sc->port_res) - bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, - sc->port_res); - sc->port_res = 0; - if (sc->irq_res) - bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, - sc->irq_res); - sc->irq_res = 0; - if (sc->mem_res) - bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, - sc->mem_res); - sc->mem_res = 0; - return; -} - -int -pcic_attach(device_t dev) -{ - struct pcic_softc *sc = PCIC_SOFTC(dev); - struct pcic_handle *h; - int vendor, count, i, reg, error; - - sc->dev = dev; - - /* Activate our resources */ - if ((error = pcic_activate(dev)) != 0) { - printf("pcic_attach (active) returns %d\n", error); - return error; - } - - /* now check for each controller/socket */ - - /* - * this could be done with a loop, but it would violate the - * abstraction... --- unknown - * I don't see the abstraction... --imp - */ - - count = 0; - - VERBOSE(("pcic ident regs:")); - - sc->handle[0].sc = sc; - sc->handle[0].sock = C0SA; - /* initialise pcic_read and pcic_write functions */ - sc->handle[0].ph_read = st_pcic_read; - sc->handle[0].ph_write = st_pcic_write; - sc->handle[0].ph_bus_t = sc->iot; - sc->handle[0].ph_bus_h = sc->ioh; - if (pcic_ident_ok(reg = pcic_read(&sc->handle[0], PCIC_IDENT))) { - sc->handle[0].flags = PCIC_FLAG_SOCKETP; - count++; - } else { - sc->handle[0].flags = 0; - } - sc->handle[0].laststate = PCIC_LASTSTATE_EMPTY; - - VERBOSE((" 0x%02x", reg)); - - sc->handle[1].sc = sc; - sc->handle[1].sock = C0SB; - /* initialise pcic_read and pcic_write functions */ - sc->handle[1].ph_read = st_pcic_read; - sc->handle[1].ph_write = st_pcic_write; - sc->handle[1].ph_bus_t = sc->iot; - sc->handle[1].ph_bus_h = sc->ioh; - if (pcic_ident_ok(reg = pcic_read(&sc->handle[1], PCIC_IDENT))) { - sc->handle[1].flags = PCIC_FLAG_SOCKETP; - count++; - } else { - sc->handle[1].flags = 0; - } - sc->handle[1].laststate = PCIC_LASTSTATE_EMPTY; - - VERBOSE((" 0x%02x", reg)); - - /* - * The CL-PD6729 has only one controller and always returns 0 - * if you try to read from the second one. Maybe pcic_ident_ok - * shouldn't accept 0? - */ - sc->handle[2].sc = sc; - sc->handle[2].sock = C1SA; - /* initialise pcic_read and pcic_write functions */ - sc->handle[2].ph_read = st_pcic_read; - sc->handle[2].ph_write = st_pcic_write; - sc->handle[2].ph_bus_t = sc->iot; - sc->handle[2].ph_bus_h = sc->ioh; - if (pcic_vendor(&sc->handle[0]) != PCIC_VENDOR_CIRRUS_PD672X || - pcic_read(&sc->handle[2], PCIC_IDENT) != 0) { - if (pcic_ident_ok(reg = pcic_read(&sc->handle[2], - PCIC_IDENT))) { - sc->handle[2].flags = PCIC_FLAG_SOCKETP; - count++; - } else { - sc->handle[2].flags = 0; - } - sc->handle[2].laststate = PCIC_LASTSTATE_EMPTY; - - VERBOSE((" 0x%02x", reg)); - - sc->handle[3].sc = sc; - sc->handle[3].sock = C1SB; - /* initialise pcic_read and pcic_write functions */ - sc->handle[3].ph_read = st_pcic_read; - sc->handle[3].ph_write = st_pcic_write; - sc->handle[3].ph_bus_t = sc->iot; - sc->handle[3].ph_bus_h = sc->ioh; - if (pcic_ident_ok(reg = pcic_read(&sc->handle[3], - PCIC_IDENT))) { - sc->handle[3].flags = PCIC_FLAG_SOCKETP; - count++; - } else { - sc->handle[3].flags = 0; - } - sc->handle[3].laststate = PCIC_LASTSTATE_EMPTY; - - VERBOSE((" 0x%02x\n", reg)); - } else { - sc->handle[2].flags = 0; - sc->handle[3].flags = 0; - } - - if (count == 0) { - printf("pcic_attach: attach found no sockets\n"); - return (ENXIO); - } - - /* establish the interrupt */ - - /* XXX block interrupts? */ - - for (i = 0; i < PCIC_NSLOTS; i++) { - /* - * this should work, but w/o it, setting tty flags hangs at - * boot time. - */ - if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) - { - STAILQ_INIT(&sc->handle[i].events); - pcic_write(&sc->handle[i], PCIC_CSC_INTR, 0); - pcic_read(&sc->handle[i], PCIC_CSC); - } - } - - if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) || - (sc->handle[1].flags & PCIC_FLAG_SOCKETP)) { - vendor = pcic_vendor(&sc->handle[0]); - - device_printf(dev, "controller 0 (%s) has ", - pcic_vendor_to_string(vendor)); - - if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) && - (sc->handle[1].flags & PCIC_FLAG_SOCKETP)) - printf("sockets A and B\n"); - else if (sc->handle[0].flags & PCIC_FLAG_SOCKETP) - printf("socket A only\n"); - else - printf("socket B only\n"); - - if (sc->handle[0].flags & PCIC_FLAG_SOCKETP) - sc->handle[0].vendor = vendor; - if (sc->handle[1].flags & PCIC_FLAG_SOCKETP) - sc->handle[1].vendor = vendor; - } - if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) || - (sc->handle[3].flags & PCIC_FLAG_SOCKETP)) { - vendor = pcic_vendor(&sc->handle[2]); - - device_printf(dev, "controller 1 (%s) has ", - pcic_vendor_to_string(vendor)); - - if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) && - (sc->handle[3].flags & PCIC_FLAG_SOCKETP)) - printf("sockets A and B\n"); - else if (sc->handle[2].flags & PCIC_FLAG_SOCKETP) - printf("socket A only\n"); - else - printf("socket B only\n"); - - if (sc->handle[2].flags & PCIC_FLAG_SOCKETP) - sc->handle[2].vendor = vendor; - if (sc->handle[3].flags & PCIC_FLAG_SOCKETP) - sc->handle[3].vendor = vendor; - } - - for (i = 0; i < PCIC_NSLOTS; i++) { - if ((sc->handle[i].flags & PCIC_FLAG_SOCKETP) == 0) - continue; - h = &sc->handle[i]; - /* initialize the rest of the handle */ - h->shutdown = 0; - h->memalloc = 0; - h->ioalloc = 0; - h->ih_irq = 0; - h->sc = sc; - h->dev = device_add_child(dev, "pccard", -1); - device_set_ivars(h->dev, h); - pcic_init_socket(h); - } - - /* - * Probe and attach any children as were configured above. - */ - error = bus_generic_attach(dev); - if (error) - pcic_deactivate(dev); - return error; -} - -void -pcic_create_event_thread(void *arg) -{ - struct pcic_handle *h = arg; - const char *cs; - - switch (h->sock) { - case C0SA: - cs = "0,0"; - break; - case C0SB: - cs = "0,1"; - break; - case C1SA: - cs = "1,0"; - break; - case C1SB: - cs = "1,1"; - break; - default: - panic("pcic_create_event_thread: unknown pcic socket"); - } - - if (kthread_create(pcic_event_thread, h, &h->event_thread, - "%s,%s", device_get_name(PCIC_H2SOFTC(h)->dev), cs)) { - device_printf(PCIC_H2SOFTC(h)->dev, - "cannot create event thread for sock 0x%02x\n", h->sock); - panic("pcic_create_event_thread"); - } -} - -void -pcic_event_thread(void *arg) -{ - struct pcic_handle *h = arg; - struct pcic_event *pe; - int s; - struct pcic_softc *sc = h->sc; - - while (h->shutdown == 0) { - s = splhigh(); - if ((pe = STAILQ_FIRST(&h->events)) == NULL) { - splx(s); - (void) tsleep(&h->events, 0, "pcicev", 0); - continue; - } else { - splx(s); - /* sleep .25s to be enqueued chatterling interrupts */ - (void) tsleep((caddr_t)pcic_event_thread, 0, "pcicss", hz/4); - } - s = splhigh(); - STAILQ_REMOVE_HEAD_UNTIL(&h->events, pe, pe_q); - splx(s); - - switch (pe->pe_type) { - case PCIC_EVENT_INSERTION: - s = splhigh(); - while (1) { - struct pcic_event *pe1, *pe2; - - if ((pe1 = STAILQ_FIRST(&h->events)) == NULL) - break; - if (pe1->pe_type != PCIC_EVENT_REMOVAL) - break; - if ((pe2 = STAILQ_NEXT(pe1, pe_q)) == NULL) - break; - if (pe2->pe_type == PCIC_EVENT_INSERTION) { - STAILQ_REMOVE_HEAD_UNTIL(&h->events, pe1, pe_q); - free(pe1, M_TEMP); - STAILQ_REMOVE_HEAD_UNTIL(&h->events, pe2, pe_q); - free(pe2, M_TEMP); - } - } - splx(s); - - DEVPRINTF((h->dev, "insertion event\n")); - pcic_attach_card(h); - break; - - case PCIC_EVENT_REMOVAL: - s = splhigh(); - while (1) { - struct pcic_event *pe1, *pe2; - - if ((pe1 = STAILQ_FIRST(&h->events)) == NULL) - break; - if (pe1->pe_type != PCIC_EVENT_INSERTION) - break; - if ((pe2 = STAILQ_NEXT(pe1, pe_q)) == NULL) - break; - if (pe2->pe_type == PCIC_EVENT_REMOVAL) { - STAILQ_REMOVE_HEAD_UNTIL(&h->events, pe1, pe_q); - free(pe1, M_TEMP); - STAILQ_REMOVE_HEAD_UNTIL(&h->events, pe2, pe_q); - free(pe2, M_TEMP); - } - } - splx(s); - - DEVPRINTF((h->dev, "removal event\n")); - pcic_detach_card(h); - break; - - default: - panic("pcic_event_thread: unknown event %d", - pe->pe_type); - } - free(pe, M_TEMP); - } - - h->event_thread = NULL; - - /* In case parent is waiting for us to exit. */ - wakeup(sc); - - kthread_exit(); -} - -void -pcic_init_socket(struct pcic_handle *h) -{ - int reg; - struct pcic_softc *sc = h->sc; - - /* - * queue creation of a kernel thread to handle insert/removal events. - */ - *lasthandle++ = h; - - /* set up the card to interrupt on card detect */ - - pcic_write(h, PCIC_CSC_INTR, (sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) | - PCIC_CSC_INTR_CD_ENABLE); - pcic_write(h, PCIC_INTR, 0); - pcic_read(h, PCIC_CSC); - - /* unsleep the cirrus controller */ - - if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) || - (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) { - reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2); - if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) { - DEVPRINTF((sc->dev, "socket %02x was suspended\n", - h->sock)); - reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND; - pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg); - } - } - h->laststate = PCIC_LASTSTATE_EMPTY; - -#if 0 -/* XXX */ -/* Should do this later */ -/* maybe as part of interrupt routing verification */ - if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) == - PCIC_IF_STATUS_CARDDETECT_PRESENT) { - pcic_attach_card(h); - h->laststate = PCIC_LASTSTATE_PRESENT; - } else { - h->laststate = PCIC_LASTSTATE_EMPTY; - } -#endif -} - -static void -pcic_intr(void *arg) -{ - struct pcic_softc *sc = arg; - int i; - - for (i = 0; i < PCIC_NSLOTS; i++) - if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) - pcic_intr_socket(&sc->handle[i]); -} - -static void -pcic_intr_socket(struct pcic_handle *h) -{ - int cscreg; - - cscreg = pcic_read(h, PCIC_CSC); - - cscreg &= (PCIC_CSC_GPI | PCIC_CSC_CD | PCIC_CSC_READY | - PCIC_CSC_BATTWARN | PCIC_CSC_BATTDEAD); - - if (cscreg & PCIC_CSC_GPI) { - DEVPRINTF((h->dev, "%02x GPI\n", h->sock)); - } - if (cscreg & PCIC_CSC_CD) { - int statreg; - - statreg = pcic_read(h, PCIC_IF_STATUS); - - DEVPRINTF((h->dev, "%02x CD %x\n", h->sock, statreg)); - - if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == - PCIC_IF_STATUS_CARDDETECT_PRESENT) { - if (h->laststate != PCIC_LASTSTATE_PRESENT) { - DEVPRINTF((h->dev, - "enqueing INSERTION event\n")); - pcic_queue_event(h, PCIC_EVENT_INSERTION); - } - h->laststate = PCIC_LASTSTATE_PRESENT; - } else { - if (h->laststate == PCIC_LASTSTATE_PRESENT) { - /* Deactivate the card now. */ - DEVPRINTF((h->dev, "detaching card\n")); - pcic_detach_card(h); - DEVPRINTF((h->dev,"enqueing REMOVAL event\n")); - pcic_queue_event(h, PCIC_EVENT_REMOVAL); - } - h->laststate = ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == 0) - ? PCIC_LASTSTATE_EMPTY : PCIC_LASTSTATE_HALF; - } - } - if (cscreg & PCIC_CSC_READY) { - DEVPRINTF((h->dev, "%02x READY\n", h->sock)); - /* shouldn't happen */ - } - if (cscreg & PCIC_CSC_BATTWARN) { - DEVPRINTF((h->dev, "%02x BATTWARN\n", h->sock)); - } - if (cscreg & PCIC_CSC_BATTDEAD) { - DEVPRINTF((h->dev, "%02x BATTDEAD\n", h->sock)); - } -} - -void -pcic_queue_event(struct pcic_handle *h, int event) -{ - struct pcic_event *pe; - int s; - - pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT); - if (pe == NULL) - panic("pcic_queue_event: can't allocate event"); - - pe->pe_type = event; - s = splhigh(); - STAILQ_INSERT_TAIL(&h->events, pe, pe_q); - splx(s); - wakeup(&h->events); -} - -static void -pcic_attach_card(struct pcic_handle *h) -{ - if (!(h->flags & PCIC_FLAG_CARDP)) { - /* call the MI attach function */ - CARD_ATTACH_CARD(h->dev); - h->flags |= PCIC_FLAG_CARDP; - } else { - DPRINTF(("pcic_attach_card: already attached\n")); - } -} - -static void -pcic_detach_card(struct pcic_handle *h) -{ - if (h->flags & PCIC_FLAG_CARDP) { - h->flags &= ~PCIC_FLAG_CARDP; - /* call the MI detach function */ - CARD_DETACH_CARD(h->dev); - } -} - -static int -pcic_chip_mem_alloc(struct pcic_handle *h, struct resource *r, bus_size_t size, - struct pccard_mem_handle *pcmhp) -{ - bus_space_handle_t memh; - bus_addr_t addr; - bus_size_t sizepg; - int mask; - struct pcic_softc *sc = h->sc; - - /* out of sc->memh, allocate as many pages as necessary */ - - /* convert size to PCIC pages */ - sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN; - if (sizepg > PCIC_MAX_MEM_PAGES) - return (1); - - mask = (1 << sizepg) - 1; - - addr = rman_get_start(r); - memh = addr; - pcmhp->memt = sc->memt; - pcmhp->memh = memh; - pcmhp->addr = addr; - pcmhp->size = size; - pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE; - return (0); -} - -static void -pcic_chip_mem_free(struct pcic_handle *h, struct pccard_mem_handle *pcmhp) -{ -} - -static struct mem_map_index_st { - int sysmem_start_lsb; - int sysmem_start_msb; - int sysmem_stop_lsb; - int sysmem_stop_msb; - int cardmem_lsb; - int cardmem_msb; - int memenable; -} mem_map_index[] = { - { - PCIC_SYSMEM_ADDR0_START_LSB, - PCIC_SYSMEM_ADDR0_START_MSB, - PCIC_SYSMEM_ADDR0_STOP_LSB, - PCIC_SYSMEM_ADDR0_STOP_MSB, - PCIC_CARDMEM_ADDR0_LSB, - PCIC_CARDMEM_ADDR0_MSB, - PCIC_ADDRWIN_ENABLE_MEM0, - }, - { - PCIC_SYSMEM_ADDR1_START_LSB, - PCIC_SYSMEM_ADDR1_START_MSB, - PCIC_SYSMEM_ADDR1_STOP_LSB, - PCIC_SYSMEM_ADDR1_STOP_MSB, - PCIC_CARDMEM_ADDR1_LSB, - PCIC_CARDMEM_ADDR1_MSB, - PCIC_ADDRWIN_ENABLE_MEM1, - }, - { - PCIC_SYSMEM_ADDR2_START_LSB, - PCIC_SYSMEM_ADDR2_START_MSB, - PCIC_SYSMEM_ADDR2_STOP_LSB, - PCIC_SYSMEM_ADDR2_STOP_MSB, - PCIC_CARDMEM_ADDR2_LSB, - PCIC_CARDMEM_ADDR2_MSB, - PCIC_ADDRWIN_ENABLE_MEM2, - }, - { - PCIC_SYSMEM_ADDR3_START_LSB, - PCIC_SYSMEM_ADDR3_START_MSB, - PCIC_SYSMEM_ADDR3_STOP_LSB, - PCIC_SYSMEM_ADDR3_STOP_MSB, - PCIC_CARDMEM_ADDR3_LSB, - PCIC_CARDMEM_ADDR3_MSB, - PCIC_ADDRWIN_ENABLE_MEM3, - }, - { - PCIC_SYSMEM_ADDR4_START_LSB, - PCIC_SYSMEM_ADDR4_START_MSB, - PCIC_SYSMEM_ADDR4_STOP_LSB, - PCIC_SYSMEM_ADDR4_STOP_MSB, - PCIC_CARDMEM_ADDR4_LSB, - PCIC_CARDMEM_ADDR4_MSB, - PCIC_ADDRWIN_ENABLE_MEM4, - }, -}; - -static void -pcic_chip_do_mem_map(struct pcic_handle *h, int win) -{ - int reg; - - pcic_write(h, mem_map_index[win].sysmem_start_lsb, - (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); - pcic_write(h, mem_map_index[win].sysmem_start_msb, - ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & - PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK)); - -#if 0 - /* XXX do I want 16 bit all the time? */ - PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT; -#endif - - pcic_write(h, mem_map_index[win].sysmem_stop_lsb, - ((h->mem[win].addr + h->mem[win].size) >> - PCIC_SYSMEM_ADDRX_SHIFT) & 0xff); - pcic_write(h, mem_map_index[win].sysmem_stop_msb, - (((h->mem[win].addr + h->mem[win].size) >> - (PCIC_SYSMEM_ADDRX_SHIFT + 8)) & - PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) | - PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2); - - pcic_write(h, mem_map_index[win].cardmem_lsb, - (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff); - pcic_write(h, mem_map_index[win].cardmem_msb, - ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) & - PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) | - ((h->mem[win].kind == PCCARD_MEM_ATTR) ? - PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0)); - - reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); - reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16); - pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); - - DELAY(100); - -#ifdef PCICDEBUG - { - int r1, r2, r3, r4, r5, r6; - - r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb); - r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb); - r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb); - r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb); - r5 = pcic_read(h, mem_map_index[win].cardmem_msb); - r6 = pcic_read(h, mem_map_index[win].cardmem_lsb); - - DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x " - "%02x%02x\n", win, r1, r2, r3, r4, r5, r6)); - } -#endif -} - -static int -pcic_chip_mem_map(struct pcic_handle *h, int kind, bus_addr_t card_addr, - bus_size_t size, struct pccard_mem_handle *pcmhp, bus_addr_t *offsetp, - int *windowp) -{ - bus_addr_t busaddr; - long card_offset; - int i, win; - - win = -1; - for (i = 0; i < N(mem_map_index); i++) { - if ((h->memalloc & (1 << i)) == 0) { - win = i; - h->memalloc |= (1 << i); - break; - } - } - - if (win == -1) - return (1); - - *windowp = win; - busaddr = pcmhp->addr; - - /* - * compute the address offset to the pccard address space for the - * pcic. this is intentionally signed. The masks and shifts below - * will cause TRT to happen in the pcic registers. Deal with making - * sure the address is aligned, and return the alignment offset. - */ - - *offsetp = card_addr % PCIC_MEM_ALIGN; - card_addr -= *offsetp; - - DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr " - "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size, - (u_long) card_addr)); - - /* - * include the offset in the size, and decrement size by one, since - * the hw wants start/stop - */ - size += *offsetp - 1; - - card_offset = (((long) card_addr) - ((long) busaddr)); - - h->mem[win].addr = busaddr; - h->mem[win].size = size; - h->mem[win].offset = card_offset; - h->mem[win].kind = kind; - - pcic_chip_do_mem_map(h, win); - - return (0); -} - -static void -pcic_chip_mem_unmap(struct pcic_handle *h, int window) -{ - int reg; - - if (window >= N(mem_map_index)) - panic("pcic_chip_mem_unmap: window out of range"); - - reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); - reg &= ~mem_map_index[window].memenable; - pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); - - h->memalloc &= ~(1 << window); -} - -static int -pcic_chip_io_alloc(struct pcic_handle *h, bus_addr_t start, bus_size_t size, - bus_size_t align, struct pccard_io_handle *pcihp) -{ - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_addr_t ioaddr; - int flags = 0; - - /* - * Allocate some arbitrary I/O space. - */ - iot = h->ph_bus_t; - ioaddr = start; - if (start) { - ioh = start; - DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n", - (u_long) ioaddr, (u_long) size)); - } else { - flags |= PCCARD_IO_ALLOCATED; - ioh = start; - DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n", - (u_long) ioaddr, (u_long) size)); - } - - pcihp->iot = iot; - pcihp->ioh = ioh; - pcihp->addr = ioaddr; - pcihp->size = size; - pcihp->flags = flags; - - return (0); -} - -static void -pcic_chip_io_free(struct pcic_handle *h, struct pccard_io_handle *pcihp) -{ -} - - -static struct io_map_index_st { - int start_lsb; - int start_msb; - int stop_lsb; - int stop_msb; - int ioenable; - int ioctlmask; - int ioctlbits[3]; /* indexed by PCCARD_WIDTH_* */ -} io_map_index[] = { - { - PCIC_IOADDR0_START_LSB, - PCIC_IOADDR0_START_MSB, - PCIC_IOADDR0_STOP_LSB, - PCIC_IOADDR0_STOP_MSB, - PCIC_ADDRWIN_ENABLE_IO0, - PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT | - PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK, - { - PCIC_IOCTL_IO0_IOCS16SRC_CARD, - PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | - PCIC_IOCTL_IO0_DATASIZE_8BIT, - PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | - PCIC_IOCTL_IO0_DATASIZE_16BIT, - }, - }, - { - PCIC_IOADDR1_START_LSB, - PCIC_IOADDR1_START_MSB, - PCIC_IOADDR1_STOP_LSB, - PCIC_IOADDR1_STOP_MSB, - PCIC_ADDRWIN_ENABLE_IO1, - PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT | - PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK, - { - PCIC_IOCTL_IO1_IOCS16SRC_CARD, - PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | - PCIC_IOCTL_IO1_DATASIZE_8BIT, - PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | - PCIC_IOCTL_IO1_DATASIZE_16BIT, - }, - }, -}; - -static void -pcic_chip_do_io_map(struct pcic_handle *h, int win) -{ - int reg; - - DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n", - win, (long) h->io[win].addr, (long) h->io[win].size, - h->io[win].width * 8)); - - pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff); - pcic_write(h, io_map_index[win].start_msb, - (h->io[win].addr >> 8) & 0xff); - - pcic_write(h, io_map_index[win].stop_lsb, - (h->io[win].addr + h->io[win].size - 1) & 0xff); - pcic_write(h, io_map_index[win].stop_msb, - ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff); - - reg = pcic_read(h, PCIC_IOCTL); - reg &= ~io_map_index[win].ioctlmask; - reg |= io_map_index[win].ioctlbits[h->io[win].width]; - pcic_write(h, PCIC_IOCTL, reg); - - reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); - reg |= io_map_index[win].ioenable; - pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); -} - -static int -pcic_chip_io_map(struct pcic_handle *h, int width, bus_addr_t offset, - bus_size_t size, struct pccard_io_handle *pcihp, int *windowp) -{ - bus_addr_t ioaddr = pcihp->addr + offset; - int i, win; -#ifdef PCICDEBUG - static char *width_names[] = { "auto", "io8", "io16" }; -#endif - - /* XXX Sanity check offset/size. */ - - win = -1; - for (i = 0; i < N(io_map_index); i++) { - if ((h->ioalloc & (1 << i)) == 0) { - win = i; - h->ioalloc |= (1 << i); - break; - } - } - - if (win == -1) - return (1); - - *windowp = win; - - DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n", - win, width_names[width], (u_long) ioaddr, (u_long) size)); - - h->io[win].addr = ioaddr; - h->io[win].size = size; - h->io[win].width = width; - - pcic_chip_do_io_map(h, win); - - return (0); -} - -static void -pcic_chip_io_unmap(struct pcic_handle *h, int window) -{ - int reg; - - if (window >= N(io_map_index)) - panic("pcic_chip_io_unmap: window out of range"); - - reg = pcic_read(h, PCIC_ADDRWIN_ENABLE); - reg &= ~io_map_index[window].ioenable; - pcic_write(h, PCIC_ADDRWIN_ENABLE, reg); - - h->ioalloc &= ~(1 << window); -} - -static void -pcic_wait_ready(struct pcic_handle *h) -{ - int i; - - for (i = 0; i < 10000; i++) { - if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY) - return; - DELAY(500); -#ifdef PCICDEBUG - if (pcic_debug) { - if ((i>5000) && (i%100 == 99)) - printf("."); - } -#endif - } - -#ifdef DIAGNOSTIC - printf("pcic_wait_ready: ready never happened, status = %02x\n", - pcic_read(h, PCIC_IF_STATUS)); -#endif -} - -int -pcic_enable_socket(device_t dev, device_t child) -{ - struct pcic_handle *h = pcic_get_handle(dev, child); - int cardtype, reg, win; - - /* this bit is mostly stolen from pcic_attach_card */ - - /* power down the socket to reset it, clear the card reset pin */ - - pcic_write(h, PCIC_PWRCTL, 0); - - /* - * wait 300ms until power fails (Tpf). Then, wait 100ms since - * we are changing Vcc (Toff). - */ - DELAY((300 + 100) * 1000); - -#ifdef VADEM_POWER_HACK - bus_space_write_1(sc->iot, sc->ioh, PCIC_REG_INDEX, 0x0e); - bus_space_write_1(sc->iot, sc->ioh, PCIC_REG_INDEX, 0x37); - printf("prcr = %02x\n", pcic_read(h, 0x02)); - printf("cvsr = %02x\n", pcic_read(h, 0x2f)); - printf("DANGER WILL ROBINSON! Changing voltage select!\n"); - pcic_write(h, 0x2f, pcic_read(h, 0x2f) & ~0x03); - printf("cvsr = %02x\n", pcic_read(h, 0x2f)); -#endif - - /* power up the socket */ - - pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV - | PCIC_PWRCTL_PWR_ENABLE); - - /* - * wait 100ms until power raise (Tpr) and 20ms to become - * stable (Tsu(Vcc)). - * - * some machines require some more time to be settled - * (300ms is added here). - */ - DELAY((100 + 20 + 300) * 1000); - - pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV | PCIC_PWRCTL_OE - | PCIC_PWRCTL_PWR_ENABLE); - pcic_write(h, PCIC_INTR, 0); - - /* - * hold RESET at least 10us. - */ - DELAY(10); - - /* clear the reset flag */ - - pcic_write(h, PCIC_INTR, PCIC_INTR_RESET); - - /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */ - - DELAY(20000); - - /* wait for the chip to finish initializing */ - -#ifdef DIAGNOSTIC - reg = pcic_read(h, PCIC_IF_STATUS); - if (!(reg & PCIC_IF_STATUS_POWERACTIVE)) { - printf("pcic_chip_socket_enable: status %x", reg); - } -#endif - - pcic_wait_ready(h); - - /* zero out the address windows */ - pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); - - /* set the card type */ - CARD_GET_TYPE(h->dev, &cardtype); - - reg = pcic_read(h, PCIC_INTR); - reg &= ~(PCIC_INTR_CARDTYPE_MASK | PCIC_INTR_IRQ_MASK | PCIC_INTR_ENABLE); - reg |= ((cardtype == PCCARD_IFTYPE_IO) ? - PCIC_INTR_CARDTYPE_IO : - PCIC_INTR_CARDTYPE_MEM); - reg |= h->ih_irq; - pcic_write(h, PCIC_INTR, reg); - - DEVPRINTF((h->dev, "pcic_chip_socket_enable cardtype %s %02x\n", - ((cardtype == PCCARD_IFTYPE_IO) ? "io" : "mem"), reg)); - - /* reinstall all the memory and io mappings */ - - for (win = 0; win < PCIC_MEM_WINS; win++) - if (h->memalloc & (1 << win)) - pcic_chip_do_mem_map(h, win); - - for (win = 0; win < PCIC_IO_WINS; win++) - if (h->ioalloc & (1 << win)) - pcic_chip_do_io_map(h, win); - - return 0; -} - -int -pcic_disable_socket(device_t dev, device_t child) -{ - struct pcic_handle *h = pcic_get_handle(dev, child); - - /* power down the socket */ - - pcic_write(h, PCIC_PWRCTL, 0); - - /* - * wait 300ms until power fails (Tpf). - */ - DELAY(300 * 1000); - - return 0; -} - -static u_int8_t -st_pcic_read(struct pcic_handle *h, int idx) -{ - if (idx != -1) { - bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX, - h->sock + idx); - } - return bus_space_read_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA); -} - -static void -st_pcic_write(struct pcic_handle *h, int idx, u_int8_t data) -{ - if (idx != -1) { - bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX, - h->sock + idx); - } - - bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA, data); -} - -int -pcic_activate_resource(device_t dev, device_t child, int type, int rid, - struct resource *r) -{ - int err; - int sz; - int win; - bus_addr_t off; - struct pcic_handle *h = pcic_get_handle(dev, child); - - sz = rman_get_size(r); - switch (type) { - case SYS_RES_IOPORT: - win = rid; - err = pcic_chip_io_map(h, 0, 0, sz, &h->io[rid], &win); - if (err) { - pcic_chip_io_free(h, &h->io[rid]); - return err; - } - break; - case SYS_RES_MEMORY: - err = pcic_chip_mem_map(h, 0, 0, sz, &h->mem[rid], &off, &win); - if (err) { - pcic_chip_mem_free(h, &h->mem[rid]); - return err; - } - break; - default: - break; - } - err = bus_generic_activate_resource(device_get_parent(dev), child, - type, rid, r); - return (err); -} - -int -pcic_deactivate_resource(device_t dev, device_t child, int type, int rid, - struct resource *r) -{ - struct pcic_handle *h = pcic_get_handle(dev, child); - int err = 0; - - switch (type) { - case SYS_RES_IOPORT: - pcic_chip_io_unmap(h, rid); - break; - case SYS_RES_MEMORY: - pcic_chip_mem_unmap(h, rid); - default: - break; - } - err = bus_generic_deactivate_resource(device_get_parent(dev), child, - type, rid, r); - return (err); -} - -int -pcic_setup_intr(device_t dev, device_t child, struct resource *irqres, - int flags, driver_intr_t intr, void *arg, void **cookiep) -{ - struct pcic_handle *h = pcic_get_handle(dev, child); - int reg; - int irq; - int err; - - err = bus_generic_setup_intr(device_get_parent(dev), child, irqres, - flags, intr, arg, cookiep); - if (!err) - return (err); - - irq = rman_get_start(irqres); - reg = pcic_read(h, PCIC_INTR); - reg &= ~(PCIC_INTR_IRQ_MASK | PCIC_INTR_ENABLE); - reg |= irq; - pcic_write(h, PCIC_INTR, reg); - - h->ih_irq = irq; - - device_printf(dev, "card irq %d\n", irq); - - return 0; -} - -int -pcic_teardown_intr(device_t dev, device_t child, struct resource *irq, - void *cookiep) -{ - int reg; - struct pcic_handle *h = pcic_get_handle(dev, child); - - h->ih_irq = 0; - - reg = pcic_read(h, PCIC_INTR); - reg &= ~(PCIC_INTR_IRQ_MASK | PCIC_INTR_ENABLE); - pcic_write(h, PCIC_INTR, reg); - - return (bus_generic_teardown_intr(device_get_parent(dev), child, irq, - cookiep)); -} - -struct resource * -pcic_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags) -{ - int sz; - int err; - struct resource *r; - struct pcic_handle *h = pcic_get_handle(dev, child); - - /* Nearly default */ - if (type == SYS_RES_MEMORY && start == 0 && end == ~0 && count != 1) { - start = 0xd0000; /* XXX */ - end = 0xdffff; - } - - r = bus_generic_alloc_resource(dev, child, type, rid, start, end, - count, flags); - if (r == NULL) - return r; - sz = rman_get_size(r); - switch (type) { - case SYS_RES_IOPORT: - err = pcic_chip_io_alloc(h, rman_get_start(r), sz, 0, - &h->io[*rid]); - if (err) { - bus_generic_release_resource(dev, child, type, *rid, - r); - return 0; - } - break; - case SYS_RES_MEMORY: - err = pcic_chip_mem_alloc(h, r, sz, &h->mem[*rid]); - if (err) { - bus_generic_release_resource(dev, child, type, *rid, - r); - return 0; - } - break; - default: - break; - } - return r; -} - -int -pcic_release_resource(device_t dev, device_t child, int type, int rid, - struct resource *r) -{ - struct pcic_handle *h = pcic_get_handle(dev, child); - - switch (type) { - case SYS_RES_IOPORT: - pcic_chip_io_free(h, &h->io[rid]); - break; - case SYS_RES_MEMORY: - pcic_chip_mem_free(h, &h->mem[rid]); - default: - break; - } - return bus_generic_release_resource(dev, child, type, rid, r); -} - -int -pcic_suspend(device_t dev) -{ - /* - * Do nothing for now, maybe in time do what FreeBSD's current - * pccard code does and detach my children. That's the safest thing - * to do since we don't want to wake up and have different hardware - * in the slots. - */ - - return 0; -} - -int -pcic_resume(device_t dev) -{ - /* Need to port pcic_power from newer netbsd versions of this file */ - - return 0; -} - -int -pcic_set_res_flags(device_t dev, device_t child, int type, int rid, - u_int32_t flags) -{ - struct pcic_handle *h = pcic_get_handle(dev, child); - - if (type != SYS_RES_MEMORY) - return (EINVAL); - h->mem[rid].kind = PCCARD_MEM_ATTR; - pcic_chip_do_mem_map(h, rid); - - return 0; -} - -int -pcic_set_memory_offset(device_t dev, device_t child, int rid, u_int32_t offset, - u_int32_t *deltap) -{ - /* XXX BAD XXX */ - return EIO; -} - -static void -pcic_start_threads(void *arg) -{ - struct pcic_handle **walker; - walker = handles; - while (*walker) { - pcic_create_event_thread(*walker++); - } -} - -int -pcic_detach(device_t dev) -{ - device_t *kids; - int nkids; - int i; - int ret; - - pcic_deactivate(dev); - ret = bus_generic_detach(dev); - if (ret != 0) - return (ret); - /* - * Normally, one wouldn't delete the children. However, detach - * merely detaches the children w/o deleting them. So if - * we were to reattach, we add additional children and wind up - * with duplicates. So, we remove them here following the - * implicit "if you add it in attach, you should delete it in - * detach" rule that may or may not be documented. - */ - device_get_children(dev, &kids, &nkids); - for (i = 0; i < nkids; i++) { - if ((ret = device_delete_child(dev, kids[i])) != 0) - device_printf(dev, "delete of %s failed: %d\n", - device_get_nameunit(kids[i]), ret); - } - free(kids, M_TEMP); - return 0; -} - -SYSINIT(pcic, SI_SUB_KTHREAD_IDLE, SI_ORDER_ANY, pcic_start_threads, 0); -MODULE_VERSION(pcic, 1); diff --git a/sys/dev/pccard/pcic/i82365_isa.c b/sys/dev/pccard/pcic/i82365_isa.c deleted file mode 100644 index 22d8b083f0..0000000000 --- a/sys/dev/pccard/pcic/i82365_isa.c +++ /dev/null @@ -1,405 +0,0 @@ -/* $NetBSD: i82365_isasubr.c,v 1.3 1999/10/15 06:07:27 haya Exp $ */ -/* $NetBSD: i82365_isa.c,v 1.11 1998/06/09 07:25:00 thorpej Exp $ */ -/* $FreeBSD: src/sys/dev/pcic/i82365_isa.c,v 1.24 2002/05/30 17:37:46 takawata Exp $ */ -/* $DragonFly: src/sys/dev/pccard/pcic/Attic/i82365_isa.c,v 1.1 2004/02/10 07:55:47 joerg Exp $ */ - -/* - * Copyright (c) 1998 Bill Sommerfeld. All rights reserved. - * Copyright (c) 1997 Marc Horowitz. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Marc Horowitz. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include "power_if.h" -#include "card_if.h" - -/***************************************************************************** - * Configurable parameters. - *****************************************************************************/ - -/* - * Default I/O allocation range. If both are set to non-zero, these - * values will be used instead. Otherwise, the code attempts to probe - * the bus width. Systems with 10 address bits should use 0x300 and 0xff. - * Systems with 12 address bits (most) should use 0x400 and 0xbff. - */ - -#ifndef PCIC_ISA_ALLOC_IOBASE -#define PCIC_ISA_ALLOC_IOBASE 0 -#endif - -#ifndef PCIC_ISA_ALLOC_IOSIZE -#define PCIC_ISA_ALLOC_IOSIZE 0 -#endif - -int pcic_isa_alloc_iobase = PCIC_ISA_ALLOC_IOBASE; -int pcic_isa_alloc_iosize = PCIC_ISA_ALLOC_IOSIZE; - - -/* - * Default IRQ allocation bitmask. This defines the range of allowable - * IRQs for PCCARD slots. Useful if order of probing would screw up other - * devices, or if PCIC hardware/cards have trouble with certain interrupt - * lines. - * - * We disable IRQ 10 by default, since some common laptops (namely, the - * NEC Versa series) reserve IRQ 10 for the docking station SCSI interface. - */ - -#ifndef PCIC_ISA_INTR_ALLOC_MASK -#define PCIC_ISA_INTR_ALLOC_MASK 0xfbff -#endif - -int pcic_isa_intr_alloc_mask = PCIC_ISA_INTR_ALLOC_MASK; - -/***************************************************************************** - * End of configurable parameters. - *****************************************************************************/ - -#define PCICISADEBUG 1 - -#ifdef PCICISADEBUG -int pcicisa_debug = PCICISADEBUG; -#define DPRINTF(arg) if (pcicisa_debug) printf arg; -#define DEVPRINTF(arg) if (pcicisa_debug) device_printf arg; -#else -#define DPRINTF(arg) -#define DEVPRINTF(arg) -#endif - -static struct isa_pnp_id pcic_ids[] = { - {PCIC_PNP_ACTIONTEC, NULL}, /* AEI0218 */ - {PCIC_PNP_IBM3765, NULL}, /* IBM3765 */ - {PCIC_PNP_82365, NULL}, /* PNP0E00 */ - {PCIC_PNP_CL_PD6720, NULL}, /* PNP0E01 */ - {PCIC_PNP_VLSI_82C146, NULL}, /* PNP0E02 */ - {PCIC_PNP_82365_CARDBUS, NULL}, /* PNP0E03 */ - {PCIC_PNP_SCM_SWAPBOX, NULL}, /* SCM0469 */ - {0} -}; - -static void -pcic_isa_bus_width_probe (device_t dev) -{ - struct pcic_softc *sc = PCIC_SOFTC(dev); - bus_space_handle_t ioh_high; - int i, iobuswidth, tmp1, tmp2; - int rid; - u_long base; - u_int32_t length; - bus_space_tag_t iot; - bus_space_handle_t ioh; - struct resource *r; - - base = rman_get_start(sc->port_res); - length = rman_get_size(sc->port_res); - iot = sc->iot; - ioh = sc->ioh; - - /* - * figure out how wide the isa bus is. Do this by checking if the - * pcic controller is mirrored 0x400 above where we expect it to be. - */ - - iobuswidth = 12; - rid = 1; - r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, base + 0x400, - base + 0x400 + length, length, RF_ACTIVE); - if (!r) { - printf("Can't allocated mirror area for pcic bus width probe\n"); - return; - } - ioh_high = rman_get_bushandle(r); - for (i = 0; i < PCIC_NSLOTS; i++) { - if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) { - /* - * read the ident flags from the normal space and - * from the mirror, and compare them - */ - - bus_space_write_1(iot, ioh, PCIC_REG_INDEX, - sc->handle[i].sock + PCIC_IDENT); - tmp1 = bus_space_read_1(iot, ioh, PCIC_REG_DATA); - - bus_space_write_1(iot, ioh_high, PCIC_REG_INDEX, - sc->handle[i].sock + PCIC_IDENT); - tmp2 = bus_space_read_1(iot, ioh_high, PCIC_REG_DATA); - - if (tmp1 == tmp2) - iobuswidth = 10; - } - } - bus_release_resource(dev, SYS_RES_IOPORT, rid, r); - - /* - * XXX mycroft recommends I/O space range 0x400-0xfff . I should put - * this in a header somewhere - */ - - /* - * XXX some hardware doesn't seem to grok addresses in 0x400 range-- - * apparently missing a bit or more of address lines. (e.g. - * CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI - * TravelMate 5000--not clear which is at fault) - * - * Add a kludge to detect 10 bit wide buses and deal with them, - * and also a config file option to override the probe. - */ - - if (iobuswidth == 10) { - sc->iobase = 0x300; - sc->iosize = 0x0ff; - } else { -#if 0 - /* - * This is what we'd like to use, but... - */ - sc->iobase = 0x400; - sc->iosize = 0xbff; -#else - /* - * ...the above bus width probe doesn't always work. - * So, experimentation has shown the following range - * to not lose on systems that 0x300-0x3ff loses on - * (e.g. the NEC Versa 6030X). - */ - sc->iobase = 0x330; - sc->iosize = 0x0cf; -#endif - } - - DEVPRINTF((dev, "bus_space_alloc range 0x%04lx-0x%04lx (probed)\n", - (long) sc->iobase, (long) sc->iobase + sc->iosize)); - - if (pcic_isa_alloc_iobase && pcic_isa_alloc_iosize) { - sc->iobase = pcic_isa_alloc_iobase; - sc->iosize = pcic_isa_alloc_iosize; - - DEVPRINTF((dev, "bus_space_alloc range 0x%04lx-0x%04lx " - "(config override)\n", (long) sc->iobase, - (long) sc->iobase + sc->iosize)); - } -} - -#if 0 -static int -pcic_isa_check(device_t dev, u_int16_t addr) -{ - bus_space_tag_t iot; - bus_space_handle_t ioh; - int val, found; - int rid; - struct resource *res; - - rid = 0; - res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, addr, addr, - PCIC_IOSIZE, RF_ACTIVE); - if (!res) - return(ENXIO); - iot = rman_get_bustag(res); - ioh = rman_get_bushandle(res); - found = 0; - - /* - * this could be done with a loop, but it would violate the - * abstraction - */ - bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA + PCIC_IDENT); - val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); - if (pcic_ident_ok(val)) - found++; - - bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB + PCIC_IDENT); - val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); - if (pcic_ident_ok(val)) - found++; - - bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA + PCIC_IDENT); - val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); - if (pcic_ident_ok(val)) - found++; - - bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB + PCIC_IDENT); - val = bus_space_read_1(iot, ioh, PCIC_REG_DATA); - if (pcic_ident_ok(val)) - found++; - - bus_release_resource(dev, SYS_RES_IOPORT, rid, res); - - return (found); -} -#endif - -static int -pcic_isa_probe(device_t dev) -{ - int error; - struct resource *res; - int rid; - int i; - u_long mem; - - /* Check isapnp ids */ - error = ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids); - if (error == ENXIO) - return (ENXIO); - - /* If we had some other problem. */ - if (!(error == 0 || error == ENOENT)) - return (error); - - /* If we have the resources we need then we're good to go. */ - if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) - return (ENXIO); - rid = 0; - res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE); - if (res == NULL) { - /* - * No IRQ specified, find one. This can be due to the PnP - * data not specifying any IRQ - */ - for (i = 0; i < 16; i++) { - if (((1 << i) & PCIC_INTR_IRQ_VALIDMASK) == 0) - continue; - res = bus_alloc_resource(dev, SYS_RES_IRQ, - &rid, i, i, 1, RF_ACTIVE); - if (res != NULL) - break; - } - if (res == NULL) - return (ENXIO); - mem = rman_get_start(res); - bus_release_resource(dev, SYS_RES_IRQ, rid, res); - bus_set_resource(dev, SYS_RES_IRQ, 0, i, 1); - } else { - bus_release_resource(dev, SYS_RES_IRQ, rid, res); - } - /* XXX This might not be needed in future, get it directly from - * XXX parent */ - rid = 0; - res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, - 1 << 13, RF_ACTIVE); - if (res == NULL) { - /* - * We failed to get memory. Since this XXX comment above - * indicates that this is transient, we try to get a hunk - * of memory in the isa hole. Sure would be nice if there - * were some MI constants for this. - */ - res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - 0xa0000, 0xdffff, 1 << 13, RF_ACTIVE); - if (res != NULL) { - mem = rman_get_start(res); - bus_release_resource(dev, SYS_RES_MEMORY, rid, res); - bus_set_resource(dev, SYS_RES_MEMORY, 0, mem, 1 << 13); - } - } else { - bus_release_resource(dev, SYS_RES_MEMORY, rid, res); - } - if (res == NULL) { - device_printf(dev, "Cannot allocate mem\n"); - return ENOMEM; - } - return (0); -} - -static int -pcic_isa_attach(device_t dev) -{ - int err = 0; - - if ((err = pcic_attach(dev)) == 0) - pcic_isa_bus_width_probe (dev); - return err; -} - -static int -pcic_isa_detach(device_t dev) -{ - pcic_detach(dev); - return 0; -} - -static device_method_t pcic_isa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, pcic_isa_probe), - DEVMETHOD(device_attach, pcic_isa_attach), - DEVMETHOD(device_detach, pcic_isa_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, pcic_suspend), - DEVMETHOD(device_resume, pcic_resume), - - /* Bus Interface */ - DEVMETHOD(bus_driver_added, bus_generic_driver_added), - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_alloc_resource, pcic_alloc_resource), - DEVMETHOD(bus_release_resource, pcic_release_resource), - DEVMETHOD(bus_activate_resource, pcic_activate_resource), - DEVMETHOD(bus_deactivate_resource, pcic_deactivate_resource), - DEVMETHOD(bus_setup_intr, pcic_setup_intr), - DEVMETHOD(bus_teardown_intr, pcic_teardown_intr), - - /* pccard/cardbus interface */ - DEVMETHOD(card_set_res_flags, pcic_set_res_flags), - DEVMETHOD(card_set_memory_offset, pcic_set_memory_offset), - - /* Power Interface */ - DEVMETHOD(power_enable_socket, pcic_enable_socket), - DEVMETHOD(power_disable_socket, pcic_disable_socket), - { 0, 0 } -}; - -static driver_t pcic_driver = { - "pcic", - pcic_isa_methods, - sizeof(struct pcic_softc) -}; - -static devclass_t pcic_devclass; - -DRIVER_MODULE(pcic, isa, pcic_driver, pcic_devclass, 0, 0); -MODULE_DEPEND(pcic, pccard, 1, 1, 1); diff --git a/sys/dev/pccard/pcic/i82365reg.h b/sys/dev/pccard/pcic/i82365reg.h deleted file mode 100644 index cfcafc0250..0000000000 --- a/sys/dev/pccard/pcic/i82365reg.h +++ /dev/null @@ -1,366 +0,0 @@ -/* $NetBSD: i82365reg.h,v 1.3 1998/12/20 17:53:28 nathanw Exp $ */ -/* $FreeBSD: src/sys/dev/pcic/i82365reg.h,v 1.10 2001/06/16 06:10:53 imp Exp $ */ -/* $DragonFly: src/sys/dev/pccard/pcic/Attic/i82365reg.h,v 1.1 2004/02/10 07:55:47 joerg Exp $ */ - -/* - * Copyright (c) 1997 Marc Horowitz. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Marc Horowitz. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * All information is from the intel 82365sl PC Card Interface Controller - * (PCIC) data sheet, marked "preliminary". Order number 290423-002, January - * 1993. - */ - -#define PCIC_IOSIZE 2 - -#define PCIC_REG_INDEX 0 -#define PCIC_REG_DATA 1 - -/* - * I/o ports - */ -#define PCIC_INDEX0 0x3e0 - -/* - * The PCIC allows two chips to share the same address. In order not to run - * afoul of the netbsd device model, this driver will treat those chips as - * the same device. - */ - -#define PCIC_CHIP0_BASE 0x00 -#define PCIC_CHIP1_BASE 0x80 - -/* Each PCIC chip can drive two sockets */ - -#define PCIC_SOCKETA_INDEX 0x00 -#define PCIC_SOCKETB_INDEX 0x40 - -/* general setup registers */ - -#define PCIC_IDENT 0x00 /* RO */ -#define PCIC_IDENT_IFTYPE_MASK 0xC0 -#define PCIC_IDENT_IFTYPE_IO_ONLY 0x00 -#define PCIC_IDENT_IFTYPE_MEM_ONLY 0x40 -#define PCIC_IDENT_IFTYPE_MEM_AND_IO 0x80 -#define PCIC_IDENT_IFTYPE_RESERVED 0xC0 -#define PCIC_IDENT_ZERO 0x30 -#define PCIC_IDENT_REV_MASK 0x0F -#define PCIC_IDENT_REV_I82365SLR0 0x02 -#define PCIC_IDENT_REV_I82365SLR1 0x03 - -#define PCIC_IF_STATUS 0x01 /* RO */ -#define PCIC_IF_STATUS_GPI 0x80 /* General Purpose Input */ -#define PCIC_IF_STATUS_POWERACTIVE 0x40 -#define PCIC_IF_STATUS_READY 0x20 /* really READY/!BUSY */ -#define PCIC_IF_STATUS_MEM_WP 0x10 -#define PCIC_IF_STATUS_CARDDETECT_MASK 0x0C -#define PCIC_IF_STATUS_CARDDETECT_PRESENT 0x0C -#define PCIC_IF_STATUS_BATTERY_MASK 0x03 -#define PCIC_IF_STATUS_BATTERY_DEAD1 0x00 -#define PCIC_IF_STATUS_BATTERY_DEAD2 0x01 -#define PCIC_IF_STATUS_BATTERY_WARNING 0x02 -#define PCIC_IF_STATUS_BATTERY_GOOD 0x03 - -#define PCIC_PWRCTL 0x02 /* RW */ -#define PCIC_PWRCTL_OE 0x80 /* output enable */ -#define PCIC_PWRCTL_DISABLE_RESETDRV 0x40 -#define PCIC_PWRCTL_AUTOSWITCH_ENABLE 0x20 -#define PCIC_PWRCTL_PWR_ENABLE 0x10 -#define PCIC_PWRCTL_VPP2_MASK 0x0C -/* XXX these are a little unclear from the data sheet */ -#define PCIC_PWRCTL_VPP2_RESERVED 0x0C -#define PCIC_PWRCTL_VPP2_EN1 0x08 -#define PCIC_PWRCTL_VPP2_EN0 0x04 -#define PCIC_PWRCTL_VPP2_ENX 0x00 -#define PCIC_PWRCTL_VPP1_MASK 0x03 -/* XXX these are a little unclear from the data sheet */ -#define PCIC_PWRCTL_VPP1_RESERVED 0x03 -#define PCIC_PWRCTL_VPP1_EN1 0x02 -#define PCIC_PWRCTL_VPP1_EN0 0x01 -#define PCIC_PWRCTL_VPP1_ENX 0x00 - -#define PCIC_CSC 0x04 /* RW */ -#define PCIC_CSC_ZERO 0xE0 -#define PCIC_CSC_GPI 0x10 -#define PCIC_CSC_CD 0x08 /* Card Detect Change */ -#define PCIC_CSC_READY 0x04 -#define PCIC_CSC_BATTWARN 0x02 -#define PCIC_CSC_BATTDEAD 0x01 /* for memory cards */ -#define PCIC_CSC_RI 0x01 /* for i/o cards */ - -#define PCIC_ADDRWIN_ENABLE 0x06 /* RW */ -#define PCIC_ADDRWIN_ENABLE_IO1 0x80 -#define PCIC_ADDRWIN_ENABLE_IO0 0x40 -#define PCIC_ADDRWIN_ENABLE_MEMCS16 0x20 /* rtfds if you care */ -#define PCIC_ADDRWIN_ENABLE_MEM4 0x10 -#define PCIC_ADDRWIN_ENABLE_MEM3 0x08 -#define PCIC_ADDRWIN_ENABLE_MEM2 0x04 -#define PCIC_ADDRWIN_ENABLE_MEM1 0x02 -#define PCIC_ADDRWIN_ENABLE_MEM0 0x01 - -#define PCIC_CARD_DETECT 0x16 /* RW */ -#define PCIC_CARD_DETECT_RESERVED 0xC0 -#define PCIC_CARD_DETECT_SW_INTR 0x20 -#define PCIC_CARD_DETECT_RESUME_ENABLE 0x10 -#define PCIC_CARD_DETECT_GPI_TRANSCTL 0x08 -#define PCIC_CARD_DETECT_GPI_ENABLE 0x04 -#define PCIC_CARD_DETECT_CFGRST_ENABLE 0x02 -#define PCIC_CARD_DETECT_MEMDLY_INHIBIT 0x01 - -/* interrupt registers */ - -#define PCIC_INTR 0x03 /* RW */ -#define PCIC_INTR_RI_ENABLE 0x80 -#define PCIC_INTR_RESET 0x40 /* active low (zero) */ -#define PCIC_INTR_CARDTYPE_MASK 0x20 -#define PCIC_INTR_CARDTYPE_IO 0x20 -#define PCIC_INTR_CARDTYPE_MEM 0x00 -#define PCIC_INTR_ENABLE 0x10 -#define PCIC_INTR_IRQ_MASK 0x0F -#define PCIC_INTR_IRQ_SHIFT 0 -#define PCIC_INTR_IRQ_NONE 0x00 -#define PCIC_INTR_IRQ_RESERVED1 0x01 -#define PCIC_INTR_IRQ_RESERVED2 0x02 -#define PCIC_INTR_IRQ3 0x03 -#define PCIC_INTR_IRQ4 0x04 -#define PCIC_INTR_IRQ5 0x05 -#define PCIC_INTR_IRQ_RESERVED6 0x06 -#define PCIC_INTR_IRQ7 0x07 -#define PCIC_INTR_IRQ_RESERVED8 0x08 -#define PCIC_INTR_IRQ9 0x09 -#define PCIC_INTR_IRQ10 0x0A -#define PCIC_INTR_IRQ11 0x0B -#define PCIC_INTR_IRQ12 0x0C -#define PCIC_INTR_IRQ_RESERVED13 0x0D -#define PCIC_INTR_IRQ14 0x0E -#define PCIC_INTR_IRQ15 0x0F - -#define PCIC_INTR_IRQ_VALIDMASK 0xDEB8 /* 1101 1110 1011 1000 */ - -#define PCIC_CSC_INTR 0x05 /* RW */ -#define PCIC_CSC_INTR_IRQ_MASK 0xF0 -#define PCIC_CSC_INTR_IRQ_SHIFT 4 -#define PCIC_CSC_INTR_IRQ_NONE 0x00 -#define PCIC_CSC_INTR_IRQ_RESERVED1 0x10 -#define PCIC_CSC_INTR_IRQ_RESERVED2 0x20 -#define PCIC_CSC_INTR_IRQ3 0x30 -#define PCIC_CSC_INTR_IRQ4 0x40 -#define PCIC_CSC_INTR_IRQ5 0x50 -#define PCIC_CSC_INTR_IRQ_RESERVED6 0x60 -#define PCIC_CSC_INTR_IRQ7 0x70 -#define PCIC_CSC_INTR_IRQ_RESERVED8 0x80 -#define PCIC_CSC_INTR_IRQ9 0x90 -#define PCIC_CSC_INTR_IRQ10 0xA0 -#define PCIC_CSC_INTR_IRQ11 0xB0 -#define PCIC_CSC_INTR_IRQ12 0xC0 -#define PCIC_CSC_INTR_IRQ_RESERVED13 0xD0 -#define PCIC_CSC_INTR_IRQ14 0xE0 -#define PCIC_CSC_INTR_IRQ15 0xF0 -#define PCIC_CSC_INTR_CD_ENABLE 0x08 -#define PCIC_CSC_INTR_READY_ENABLE 0x04 -#define PCIC_CSC_INTR_BATTWARN_ENABLE 0x02 -#define PCIC_CSC_INTR_BATTDEAD_ENABLE 0x01 /* for memory cards */ -#define PCIC_CSC_INTR_RI_ENABLE 0x01 /* for I/O cards */ - -#define PCIC_CSC_INTR_IRQ_VALIDMASK 0xDEB8 /* 1101 1110 1011 1000 */ - -/* I/O registers */ - -#define PCIC_IO_WINS 2 - -#define PCIC_IOCTL 0x07 /* RW */ -#define PCIC_IOCTL_IO1_WAITSTATE 0x80 -#define PCIC_IOCTL_IO1_ZEROWAIT 0x40 -#define PCIC_IOCTL_IO1_IOCS16SRC_MASK 0x20 -#define PCIC_IOCTL_IO1_IOCS16SRC_CARD 0x20 -#define PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE 0x00 -#define PCIC_IOCTL_IO1_DATASIZE_MASK 0x10 -#define PCIC_IOCTL_IO1_DATASIZE_16BIT 0x10 -#define PCIC_IOCTL_IO1_DATASIZE_8BIT 0x00 -#define PCIC_IOCTL_IO0_WAITSTATE 0x08 -#define PCIC_IOCTL_IO0_ZEROWAIT 0x04 -#define PCIC_IOCTL_IO0_IOCS16SRC_MASK 0x02 -#define PCIC_IOCTL_IO0_IOCS16SRC_CARD 0x02 -#define PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE 0x00 -#define PCIC_IOCTL_IO0_DATASIZE_MASK 0x01 -#define PCIC_IOCTL_IO0_DATASIZE_16BIT 0x01 -#define PCIC_IOCTL_IO0_DATASIZE_8BIT 0x00 - -#define PCIC_IOADDR0_START_LSB 0x08 -#define PCIC_IOADDR0_START_MSB 0x09 -#define PCIC_IOADDR0_STOP_LSB 0x0A -#define PCIC_IOADDR0_STOP_MSB 0x0B -#define PCIC_IOADDR1_START_LSB 0x0C -#define PCIC_IOADDR1_START_MSB 0x0D -#define PCIC_IOADDR1_STOP_LSB 0x0E -#define PCIC_IOADDR1_STOP_MSB 0x0F - -/* memory registers */ - -/* - * memory window addresses refer to bits A23-A12 of the ISA system memory - * address. This is a shift of 12 bits. The LSB contains A19-A12, and the - * MSB contains A23-A20, plus some other bits. - */ - -#define PCIC_MEM_WINS 5 - -#define PCIC_MEM_SHIFT 12 -#define PCIC_MEM_PAGESIZE (1< - -#include - -struct proc; - -struct pcic_event { - STAILQ_ENTRY(pcic_event) pe_q; - int pe_type; -}; - -/* pe_type */ -#define PCIC_EVENT_INSERTION 0 -#define PCIC_EVENT_REMOVAL 1 - -struct proc; - -struct pcic_handle { - void *sc; - device_t dev; - bus_space_tag_t ph_bus_t; /* I/O or MEM? I don't mind */ - bus_space_handle_t ph_bus_h; - u_int8_t (*ph_read)(struct pcic_handle*, int); - void (*ph_write)(struct pcic_handle *, int, u_int8_t); - - int vendor; - int sock; - int flags; - int laststate; - int memalloc; - struct pccard_mem_handle mem[PCIC_MEM_WINS]; /* XXX BAD XXX */ - int ioalloc; - struct pccard_io_handle io[PCIC_IO_WINS]; /* XXX BAD XXX */ - int ih_irq; - - int shutdown; - struct thread *event_thread; - STAILQ_HEAD(, pcic_event) events; -}; - -#define PCIC_FLAG_SOCKETP 0x0001 -#define PCIC_FLAG_CARDP 0x0002 - -#define PCIC_LASTSTATE_PRESENT 0x0002 -#define PCIC_LASTSTATE_HALF 0x0001 -#define PCIC_LASTSTATE_EMPTY 0x0000 - -#define C0SA PCIC_CHIP0_BASE+PCIC_SOCKETA_INDEX -#define C0SB PCIC_CHIP0_BASE+PCIC_SOCKETB_INDEX -#define C1SA PCIC_CHIP1_BASE+PCIC_SOCKETA_INDEX -#define C1SB PCIC_CHIP1_BASE+PCIC_SOCKETB_INDEX - -/* - * This is sort of arbitrary. It merely needs to be "enough". It can be - * overridden in the conf file, anyway. - */ - -#define PCIC_MEM_PAGES 4 -#define PCIC_MEMSIZE PCIC_MEM_PAGES*PCIC_MEM_PAGESIZE - -#define PCIC_NSLOTS 4 - -struct pcic_softc { - device_t dev; - - bus_space_tag_t memt; - bus_space_handle_t memh; - bus_space_tag_t iot; - bus_space_handle_t ioh; - - void *intrhand; - struct resource *irq_res; - int irq_rid; - struct resource *mem_res; - int mem_rid; - struct resource *port_res; - int port_rid; - -#define PCIC_MAX_MEM_PAGES (8 * sizeof(int)) - - /* used by memory window mapping functions */ - bus_addr_t membase; - - /* - * used by io window mapping functions. These can actually overlap - * with another pcic, since the underlying extent mapper will deal - * with individual allocations. This is here to deal with the fact - * that different busses have different real widths (different pc - * hardware seems to use 10 or 12 bits for the I/O bus). - */ - bus_addr_t iobase; - bus_addr_t iosize; - - int irq; - void *ih; - - struct pcic_handle handle[PCIC_NSLOTS]; -}; - - -int pcic_ident_ok(int); -int pcic_vendor(struct pcic_handle *); -char *pcic_vendor_to_string(int); - -int pcic_attach(device_t dev); - -#define pcic_read(h, idx) (*(h)->ph_read)((h), (idx)) -#define pcic_write(h, idx, data) (*(h)->ph_write)((h), (idx), (data)) - -/* - * bus/device/etc routines - */ -int pcic_activate_resource(device_t dev, device_t child, int type, int rid, - struct resource *r); -struct resource *pcic_alloc_resource(device_t dev, device_t child, int type, - int *rid, u_long start, u_long end, u_long count, u_int flags); -void pcic_deactivate(device_t dev); -int pcic_deactivate_resource(device_t dev, device_t child, int type, int rid, - struct resource *r); -int pcic_detach(device_t dev); -int pcic_release_resource(device_t dev, device_t child, int type, int rid, - struct resource *r); -int pcic_setup_intr(device_t dev, device_t child, struct resource *irq, - int flags, driver_intr_t intr, void *arg, void **cookiep); -int pcic_teardown_intr(device_t dev, device_t child, struct resource *irq, - void *cookiep); -int pcic_suspend(device_t dev); -int pcic_resume(device_t dev); -int pcic_enable_socket(device_t dev, device_t child); -int pcic_disable_socket(device_t dev, device_t child); -int pcic_set_res_flags(device_t dev, device_t child, int type, int rid, - u_int32_t flags); -int pcic_set_memory_offset(device_t dev, device_t child, int rid, - u_int32_t offset, u_int32_t *deltap); - -#define PCIC_SOFTC(d) (struct pcic_softc *) device_get_softc(d) diff --git a/sys/dev/serial/rp2/rp.c b/sys/dev/serial/rp2/rp.c deleted file mode 100644 index 03a34b41d2..0000000000 --- a/sys/dev/serial/rp2/rp.c +++ /dev/null @@ -1,1973 +0,0 @@ -/* - * Copyright (c) Comtrol Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials prodided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/i386/isa/rp.c,v 1.33.2.2 2001/02/26 04:23:10 jlemon Exp $ - * $DragonFly: src/sys/dev/serial/rp2/Attic/rp.c,v 1.15 2004/12/08 20:36:39 joerg Exp $ - */ - -/* - * rp.c - for RocketPort FreeBSD - */ - -#include "opt_compat.h" -#include "opt_depricated.h" -#ifndef I_WANT_DEPRICATED_STUFF -#error "Add options I_WANT_DEPRICATED_STUFF to your kernel config and send a mail to kernel@" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#define ROCKET_C -#include "rpreg.h" -#include "rpvar.h" - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -static Byte_t RData[RDATASIZE] = -{ - 0x00, 0x09, 0xf6, 0x82, - 0x02, 0x09, 0x86, 0xfb, - 0x04, 0x09, 0x00, 0x0a, - 0x06, 0x09, 0x01, 0x0a, - 0x08, 0x09, 0x8a, 0x13, - 0x0a, 0x09, 0xc5, 0x11, - 0x0c, 0x09, 0x86, 0x85, - 0x0e, 0x09, 0x20, 0x0a, - 0x10, 0x09, 0x21, 0x0a, - 0x12, 0x09, 0x41, 0xff, - 0x14, 0x09, 0x82, 0x00, - 0x16, 0x09, 0x82, 0x7b, - 0x18, 0x09, 0x8a, 0x7d, - 0x1a, 0x09, 0x88, 0x81, - 0x1c, 0x09, 0x86, 0x7a, - 0x1e, 0x09, 0x84, 0x81, - 0x20, 0x09, 0x82, 0x7c, - 0x22, 0x09, 0x0a, 0x0a -}; - -static Byte_t RRegData[RREGDATASIZE]= -{ - 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */ - 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */ - 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */ - 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */ - 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */ - 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */ - 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */ - 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */ - 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */ - 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */ - 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */ - 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */ - 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */ -}; - -static CONTROLLER_T sController[CTL_SIZE] = -{ - {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}, - {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}, - {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}, - {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}} -}; - -#if 0 -/* IRQ number to MUDBAC register 2 mapping */ -Byte_t sIRQMap[16] = -{ - 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80 -}; -#endif - -static Byte_t sBitMapClrTbl[8] = -{ - 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f -}; - -static Byte_t sBitMapSetTbl[8] = -{ - 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 -}; - -static struct callout do_poll_ch; - -/*************************************************************************** -Function: sInitController -Purpose: Initialization of controller global registers and controller - structure. -Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize, - IRQNum,Frequency,PeriodicOnly) - CONTROLLER_T *CtlP; Ptr to controller structure - int CtlNum; Controller number - ByteIO_t MudbacIO; Mudbac base I/O address. - ByteIO_t *AiopIOList; List of I/O addresses for each AIOP. - This list must be in the order the AIOPs will be found on the - controller. Once an AIOP in the list is not found, it is - assumed that there are no more AIOPs on the controller. - int AiopIOListSize; Number of addresses in AiopIOList - int IRQNum; Interrupt Request number. Can be any of the following: - 0: Disable global interrupts - 3: IRQ 3 - 4: IRQ 4 - 5: IRQ 5 - 9: IRQ 9 - 10: IRQ 10 - 11: IRQ 11 - 12: IRQ 12 - 15: IRQ 15 - Byte_t Frequency: A flag identifying the frequency - of the periodic interrupt, can be any one of the following: - FREQ_DIS - periodic interrupt disabled - FREQ_137HZ - 137 Hertz - FREQ_69HZ - 69 Hertz - FREQ_34HZ - 34 Hertz - FREQ_17HZ - 17 Hertz - FREQ_9HZ - 9 Hertz - FREQ_4HZ - 4 Hertz - If IRQNum is set to 0 the Frequency parameter is - overidden, it is forced to a value of FREQ_DIS. - int PeriodicOnly: TRUE if all interrupts except the periodic - interrupt are to be blocked. - FALSE is both the periodic interrupt and - other channel interrupts are allowed. - If IRQNum is set to 0 the PeriodicOnly parameter is - overidden, it is forced to a value of FALSE. -Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller - initialization failed. - -Comments: - If periodic interrupts are to be disabled but AIOP interrupts - are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. - - If interrupts are to be completely disabled set IRQNum to 0. - - Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an - invalid combination. - - This function performs initialization of global interrupt modes, - but it does not actually enable global interrupts. To enable - and disable global interrupts use functions sEnGlobalInt() and - sDisGlobalInt(). Enabling of global interrupts is normally not - done until all other initializations are complete. - - Even if interrupts are globally enabled, they must also be - individually enabled for each channel that is to generate - interrupts. - -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. - - After this function all AIOPs on the controller are disabled, - they can be enabled with sEnAiop(). -*/ -int sInitController( CONTROLLER_T *CtlP, - int CtlNum, - ByteIO_t MudbacIO, - ByteIO_t *AiopIOList, - int AiopIOListSize, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly) -{ - int i; - ByteIO_t io; - - CtlP->CtlNum = CtlNum; - CtlP->BusType = isISA; - CtlP->CtlID = CTLID_0001; /* controller release 1 */ - - CtlP->MBaseIO = MudbacIO; - CtlP->MReg1IO = MudbacIO + 1; - CtlP->MReg2IO = MudbacIO + 2; - CtlP->MReg3IO = MudbacIO + 3; -#if 1 - CtlP->MReg2 = 0; /* interrupt disable */ - CtlP->MReg3 = 0; /* no periodic interrupts */ -#else - if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */ - { - CtlP->MReg2 = 0; /* interrupt disable */ - CtlP->MReg3 = 0; /* no periodic interrupts */ - } - else - { - CtlP->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */ - CtlP->MReg3 = Frequency; /* set frequency */ - if(PeriodicOnly) /* periodic interrupt only */ - { - CtlP->MReg3 |= PERIODIC_ONLY; - } - } -#endif - sOutB(CtlP->MReg2IO,CtlP->MReg2); - sOutB(CtlP->MReg3IO,CtlP->MReg3); - sControllerEOI(CtlP); /* clear EOI if warm init */ - - /* Init AIOPs */ - CtlP->NumAiop = 0; - for(i=0; i < AiopIOListSize; i++) - { - io = AiopIOList[i]; - CtlP->AiopIO[i] = (WordIO_t)io; - CtlP->AiopIntChanIO[i] = io + _INT_CHAN; - sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */ - sOutB(MudbacIO,(Byte_t)(io >> 6)); /* set up AIOP I/O in MUDBAC */ - sEnAiop(CtlP,i); /* enable the AIOP */ - - CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */ - if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ - { - sDisAiop(CtlP,i); /* disable AIOP */ - break; /* done looking for AIOPs */ - } - - CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */ - sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */ - sOutB(io + _INDX_DATA,CLOCK_PRESC); - CtlP->NumAiop++; /* bump count of AIOPs */ - sDisAiop(CtlP,i); /* disable AIOP */ - } - - if(CtlP->NumAiop == 0) - return(-1); - else - return(CtlP->NumAiop); -} - -int sPCIInitController( CONTROLLER_T *CtlP, - int CtlNum, - ByteIO_t *AiopIOList, - int AiopIOListSize, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly) -{ - int i; - ByteIO_t io; - - CtlP->CtlNum = CtlNum; - CtlP->BusType = isPCI; - CtlP->CtlID = CTLID_0001; /* controller release 1 */ - CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC); - - sPCIControllerEOI(CtlP); - - /* Init AIOPs */ - CtlP->NumAiop = 0; - for(i=0; i < AiopIOListSize; i++) - { - io = AiopIOList[i]; - CtlP->AiopIO[i] = (WordIO_t)io; - CtlP->AiopIntChanIO[i] = io + _INT_CHAN; - - CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */ - if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ - { - break; /* done looking for AIOPs */ - } - - CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */ - sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE); /* clock prescaler */ - sOutB(io + _INDX_DATA,CLOCK_PRESC); - CtlP->NumAiop++; /* bump count of AIOPs */ - } - - if(CtlP->NumAiop == 0) - return(-1); - else - return(CtlP->NumAiop); -} - -/*************************************************************************** -Function: sReadAiopID -Purpose: Read the AIOP idenfication number directly from an AIOP. -Call: sReadAiopID(io) - ByteIO_t io: AIOP base I/O address -Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X - is replace by an identifying number. - Flag AIOPID_NULL if no valid AIOP is found -Warnings: No context switches are allowed while executing this function. - -*/ -int sReadAiopID(ByteIO_t io) -{ - Byte_t AiopID; /* ID byte from AIOP */ - - sOutB(io + _CMD_REG,RESET_ALL); /* reset AIOP */ - sOutB(io + _CMD_REG,0x0); - AiopID = sInB(io + _CHN_STAT0) & 0x07; - if(AiopID == 0x06) - return(1); - else /* AIOP does not exist */ - return(-1); -} - -/*************************************************************************** -Function: sReadAiopNumChan -Purpose: Read the number of channels available in an AIOP directly from - an AIOP. -Call: sReadAiopNumChan(io) - WordIO_t io: AIOP base I/O address -Return: int: The number of channels available -Comments: The number of channels is determined by write/reads from identical - offsets within the SRAM address spaces for channels 0 and 4. - If the channel 4 space is mirrored to channel 0 it is a 4 channel - AIOP, otherwise it is an 8 channel. -Warnings: No context switches are allowed while executing this function. -*/ -int sReadAiopNumChan(WordIO_t io) -{ - Word_t x; - - sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */ - sOutW(io + _INDX_ADDR,0); /* read from SRAM, chan 0 */ - x = sInW(io + _INDX_DATA); - sOutW(io + _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */ - if(x != sInW(io + _INDX_DATA)) /* if different must be 8 chan */ - return(8); - else - return(4); -} - -/*************************************************************************** -Function: sInitChan -Purpose: Initialization of a channel and channel structure -Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) - CONTROLLER_T *CtlP; Ptr to controller structure - CHANNEL_T *ChP; Ptr to channel structure - int AiopNum; AIOP number within controller - int ChanNum; Channel number within AIOP -Return: int: TRUE if initialization succeeded, FALSE if it fails because channel - number exceeds number of channels available in AIOP. -Comments: This function must be called before a channel can be used. -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. -*/ -int sInitChan( CONTROLLER_T *CtlP, - CHANNEL_T *ChP, - int AiopNum, - int ChanNum) -{ - int i; - WordIO_t AiopIO; - WordIO_t ChIOOff; - Byte_t *ChR; - Word_t ChOff; - static Byte_t R[4]; - - if(ChanNum >= CtlP->AiopNumChan[AiopNum]) - return(FALSE); /* exceeds num chans in AIOP */ - - /* Channel, AIOP, and controller identifiers */ - ChP->CtlP = CtlP; - ChP->ChanID = CtlP->AiopID[AiopNum]; - ChP->AiopNum = AiopNum; - ChP->ChanNum = ChanNum; - - /* Global direct addresses */ - AiopIO = CtlP->AiopIO[AiopNum]; - ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG; - ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN; - ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK; - ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR; - ChP->IndexData = AiopIO + _INDX_DATA; - - /* Channel direct addresses */ - ChIOOff = AiopIO + ChP->ChanNum * 2; - ChP->TxRxData = ChIOOff + _TD0; - ChP->ChanStat = ChIOOff + _CHN_STAT0; - ChP->TxRxCount = ChIOOff + _FIFO_CNT0; - ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0; - - /* Initialize the channel from the RData array */ - for(i=0; i < RDATASIZE; i+=4) - { - R[0] = RData[i]; - R[1] = RData[i+1] + 0x10 * ChanNum; - R[2] = RData[i+2]; - R[3] = RData[i+3]; - sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0])); - } - - ChR = ChP->R; - for(i=0; i < RREGDATASIZE; i+=4) - { - ChR[i] = RRegData[i]; - ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum; - ChR[i+2] = RRegData[i+2]; - ChR[i+3] = RRegData[i+3]; - } - - /* Indexed registers */ - ChOff = (Word_t)ChanNum * 0x1000; - - ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD); - ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8); - ChP->BaudDiv[2] = (Byte_t)BRD9600; - ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8); - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]); - - ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL); - ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8); - ChP->TxControl[2] = 0; - ChP->TxControl[3] = 0; - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]); - - ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL); - ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8); - ChP->RxControl[2] = 0; - ChP->RxControl[3] = 0; - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]); - - ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS); - ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8); - ChP->TxEnables[2] = 0; - ChP->TxEnables[3] = 0; - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]); - - ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1); - ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8); - ChP->TxCompare[2] = 0; - ChP->TxCompare[3] = 0; - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]); - - ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1); - ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8); - ChP->TxReplace1[2] = 0; - ChP->TxReplace1[3] = 0; - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]); - - ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2); - ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8); - ChP->TxReplace2[2] = 0; - ChP->TxReplace2[3] = 0; - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]); - - ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; - ChP->TxFIFO = ChOff + _TX_FIFO; - - sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */ - sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Tx FIFO count */ - sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ - sOutW(ChP->IndexData,0); - ChP->RxFIFOPtrs = ChOff + _RXF_OUTP; - ChP->RxFIFO = ChOff + _RX_FIFO; - - sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */ - sOutB(ChP->Cmd,(Byte_t)ChanNum); /* remove reset Rx FIFO count */ - sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */ - sOutW(ChP->IndexData,0); - sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ - sOutW(ChP->IndexData,0); - ChP->TxPrioCnt = ChOff + _TXP_CNT; - sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt); - sOutB(ChP->IndexData,0); - ChP->TxPrioPtr = ChOff + _TXP_PNTR; - sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr); - sOutB(ChP->IndexData,0); - ChP->TxPrioBuf = ChOff + _TXP_BUF; - sEnRxProcessor(ChP); /* start the Rx processor */ - - return(TRUE); -} - -/*************************************************************************** -Function: sStopRxProcessor -Purpose: Stop the receive processor from processing a channel. -Call: sStopRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure - -Comments: The receive processor can be started again with sStartRxProcessor(). - This function causes the receive processor to skip over the - stopped channel. It does not stop it from processing other channels. - -Warnings: No context switches are allowed while executing this function. - - Do not leave the receive processor stopped for more than one - character time. - - After calling this function a delay of 4 uS is required to ensure - that the receive processor is no longer processing this channel. -*/ -void sStopRxProcessor(CHANNEL_T *ChP) -{ - Byte_t R[4]; - - R[0] = ChP->R[0]; - R[1] = ChP->R[1]; - R[2] = 0x0a; - R[3] = ChP->R[3]; - sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]); -} - -/*************************************************************************** -Function: sFlushRxFIFO -Purpose: Flush the Rx FIFO -Call: sFlushRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: void -Comments: To prevent data from being enqueued or dequeued in the Tx FIFO - while it is being flushed the receive processor is stopped - and the transmitter is disabled. After these operations a - 4 uS delay is done before clearing the pointers to allow - the receive processor to stop. These items are handled inside - this function. -Warnings: No context switches are allowed while executing this function. -*/ -void sFlushRxFIFO(CHANNEL_T *ChP) -{ - int i; - Byte_t Ch; /* channel number within AIOP */ - int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */ - - if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ - return; /* don't need to flush */ - - RxFIFOEnabled = FALSE; - if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */ - { - RxFIFOEnabled = TRUE; - sDisRxFIFO(ChP); /* disable it */ - for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/ - sInB(ChP->IntChan); /* depends on bus i/o timing */ - } - sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */ - Ch = (Byte_t)sGetChanNum(ChP); - sOutB(ChP->Cmd,Ch | RESRXFCNT); /* apply reset Rx FIFO count */ - sOutB(ChP->Cmd,Ch); /* remove reset Rx FIFO count */ - sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */ - sOutW(ChP->IndexData,0); - sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ - sOutW(ChP->IndexData,0); - if(RxFIFOEnabled) - sEnRxFIFO(ChP); /* enable Rx FIFO */ -} - -/*************************************************************************** -Function: sFlushTxFIFO -Purpose: Flush the Tx FIFO -Call: sFlushTxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: void -Comments: To prevent data from being enqueued or dequeued in the Tx FIFO - while it is being flushed the receive processor is stopped - and the transmitter is disabled. After these operations a - 4 uS delay is done before clearing the pointers to allow - the receive processor to stop. These items are handled inside - this function. -Warnings: No context switches are allowed while executing this function. -*/ -void sFlushTxFIFO(CHANNEL_T *ChP) -{ - int i; - Byte_t Ch; /* channel number within AIOP */ - int TxEnabled; /* TRUE if transmitter enabled */ - - if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ - return; /* don't need to flush */ - - TxEnabled = FALSE; - if(ChP->TxControl[3] & TX_ENABLE) - { - TxEnabled = TRUE; - sDisTransmit(ChP); /* disable transmitter */ - } - sStopRxProcessor(ChP); /* stop Rx processor */ - for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */ - sInB(ChP->IntChan); /* depends on bus i/o timing */ - Ch = (Byte_t)sGetChanNum(ChP); - sOutB(ChP->Cmd,Ch | RESTXFCNT); /* apply reset Tx FIFO count */ - sOutB(ChP->Cmd,Ch); /* remove reset Tx FIFO count */ - sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ - sOutW(ChP->IndexData,0); - if(TxEnabled) - sEnTransmit(ChP); /* enable transmitter */ - sStartRxProcessor(ChP); /* restart Rx processor */ -} - -/*************************************************************************** -Function: sWriteTxPrioByte -Purpose: Write a byte of priority transmit data to a channel -Call: sWriteTxPrioByte(ChP,Data) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Data; The transmit data byte - -Return: int: 1 if the bytes is successfully written, otherwise 0. - -Comments: The priority byte is transmitted before any data in the Tx FIFO. - -Warnings: No context switches are allowed while executing this function. -*/ -int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data) -{ - Byte_t DWBuf[4]; /* buffer for double word writes */ - Word_t *WordPtr; /* must be far because Win SS != DS */ - DWordIO_t IndexAddr; - - if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */ - { - IndexAddr = ChP->IndexAddr; - sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */ - if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */ - return(0); /* nothing sent */ - - WordPtr = (Word_t *)(&DWBuf[0]); - *WordPtr = ChP->TxPrioBuf; /* data byte address */ - - DWBuf[2] = Data; /* data byte value */ - sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */ - - *WordPtr = ChP->TxPrioCnt; /* Tx priority count address */ - - DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ - DWBuf[3] = 0; /* priority buffer pointer */ - sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */ - } - else /* write it to Tx FIFO */ - { - sWriteTxByte(sGetTxRxDataIO(ChP),Data); - } - return(1); /* 1 byte sent */ -} - -/*************************************************************************** -Function: sEnInterrupts -Purpose: Enable one or more interrupts for a channel -Call: sEnInterrupts(ChP,Flags) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Flags: Interrupt enable flags, can be any combination - of the following flags: - TXINT_EN: Interrupt on Tx FIFO empty - RXINT_EN: Interrupt on Rx FIFO at trigger level (see - sSetRxTrigger()) - SRCINT_EN: Interrupt on SRC (Special Rx Condition) - MCINT_EN: Interrupt on modem input change - CHANINT_EN: Allow channel interrupt signal to the AIOP's - Interrupt Channel Register. -Return: void -Comments: If an interrupt enable flag is set in Flags, that interrupt will be - enabled. If an interrupt enable flag is not set in Flags, that - interrupt will not be changed. Interrupts can be disabled with - function sDisInterrupts(). - - This function sets the appropriate bit for the channel in the AIOP's - Interrupt Mask Register if the CHANINT_EN flag is set. This allows - this channel's bit to be set in the AIOP's Interrupt Channel Register. - - Interrupts must also be globally enabled before channel interrupts - will be passed on to the host. This is done with function - sEnGlobalInt(). - - In some cases it may be desirable to disable interrupts globally but - enable channel interrupts. This would allow the global interrupt - status register to be used to determine which AIOPs need service. -*/ -void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags) -{ - Byte_t Mask; /* Interrupt Mask Register */ - - ChP->RxControl[2] |= - ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]); - - ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN); - - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]); - - if(Flags & CHANINT_EN) - { - Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum]; - sOutB(ChP->IntMask,Mask); - } -} - -/*************************************************************************** -Function: sDisInterrupts -Purpose: Disable one or more interrupts for a channel -Call: sDisInterrupts(ChP,Flags) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Flags: Interrupt flags, can be any combination - of the following flags: - TXINT_EN: Interrupt on Tx FIFO empty - RXINT_EN: Interrupt on Rx FIFO at trigger level (see - sSetRxTrigger()) - SRCINT_EN: Interrupt on SRC (Special Rx Condition) - MCINT_EN: Interrupt on modem input change - CHANINT_EN: Disable channel interrupt signal to the - AIOP's Interrupt Channel Register. -Return: void -Comments: If an interrupt flag is set in Flags, that interrupt will be - disabled. If an interrupt flag is not set in Flags, that - interrupt will not be changed. Interrupts can be enabled with - function sEnInterrupts(). - - This function clears the appropriate bit for the channel in the AIOP's - Interrupt Mask Register if the CHANINT_EN flag is set. This blocks - this channel's bit from being set in the AIOP's Interrupt Channel - Register. -*/ -void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags) -{ - Byte_t Mask; /* Interrupt Mask Register */ - - ChP->RxControl[2] &= - ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]); - ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN); - sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]); - - if(Flags & CHANINT_EN) - { - Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum]; - sOutB(ChP->IntMask,Mask); - } -} - -/********************************************************************* - Begin FreeBsd-specific driver code -**********************************************************************/ - -static int rpprobe (struct isa_device *); -static int rpattach (struct isa_device *); - -static const char* rp_pciprobe(pcici_t tag, pcidi_t type); -static void rp_pciattach(pcici_t tag, int unit); -static u_long rp_pcicount; - -static struct pci_device rp_pcidevice = { - "rp", - rp_pciprobe, - rp_pciattach, - &rp_pcicount, - NULL -}; - -COMPAT_PCI_DRIVER (rp_pci, rp_pcidevice); - -static timeout_t rpdtrwakeup; - -struct isa_driver rpdriver = { - rpprobe, rpattach, "rp" - }; - -static char driver_name[] = "rp"; - -static d_open_t rpopen; -static d_close_t rpclose; -static d_write_t rpwrite; -static d_ioctl_t rpioctl; - -#define CDEV_MAJOR 81 -static struct cdevsw rp_cdevsw = { - /* name */ driver_name, - /* maj */ CDEV_MAJOR, - /* flags */ D_TTY | D_KQFILTER, - /* port */ NULL, - /* clone */ NULL, - - /* open */ rpopen, - /* close */ rpclose, - /* read */ ttyread, - /* write */ rpwrite, - /* ioctl */ rpioctl, - /* poll */ ttypoll, - /* mmap */ nommap, - /* strategy */ nostrategy, - /* dump */ nodump, - /* psize */ nopsize, - /* kqfilter */ ttykqfilter -}; - -static int rp_controller_port = 0; -static int rp_num_ports_open = 0; -static int ndevs = 0; -static int minor_to_unit[128]; -#if 0 -static struct tty rp_tty[128]; -#endif - -static int rp_num_ports[4]; /* Number of ports on each controller */ - -#define _INLINE_ __inline -#define POLL_INTERVAL 1 - -#define CALLOUT_MASK 0x80 -#define CONTROL_MASK 0x60 -#define CONTROL_INIT_STATE 0x20 -#define CONTROL_LOCK_STATE 0x40 -#define DEV_UNIT(dev) (MINOR_TO_UNIT(minor(dev)) -#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) -#define MINOR_MAGIC(dev) ((minor(dev)) & ~MINOR_MAGIC_MASK) -#define IS_CALLOUT(dev) (minor(dev) & CALLOUT_MASK) -#define IS_CONTROL(dev) (minor(dev) & CONTROL_MASK) - -#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1) -#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff) -#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04) - -static struct rp_port *p_rp_addr[4]; -static struct rp_port *p_rp_table[MAX_RP_PORTS]; -#define rp_addr(unit) (p_rp_addr[unit]) -#define rp_table(port) (p_rp_table[port]) - -/* - * The top-level routines begin here - */ - -static int rpparam (struct tty *, struct termios *); -static void rpstart (struct tty *); -static void rpstop (struct tty *, int); -static void rphardclose (struct rp_port *); -static void rp_disc_optim (struct tty *tp, struct termios *t, - struct rp_port *rp); - -static _INLINE_ void rp_do_receive(struct rp_port *rp, struct tty *tp, - CHANNEL_t *cp, unsigned int ChanStatus) -{ - int spl; - unsigned int CharNStat; - int ToRecv, ch; - - ToRecv = sGetRxCnt(cp); - if(ToRecv == 0) - return; - -/* If status indicates there are errored characters in the - FIFO, then enter status mode (a word in FIFO holds - characters and status) -*/ - - if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { - if(!(ChanStatus & STATMODE)) { - ChanStatus |= STATMODE; - sEnRxStatusMode(cp); - } - } -/* - if we previously entered status mode then read down the - FIFO one word at a time, pulling apart the character and - the status. Update error counters depending on status. -*/ - if(ChanStatus & STATMODE) { - while(ToRecv) { - if(tp->t_state & TS_TBLOCK) { - break; - } - CharNStat = sInW(sGetTxRxDataIO(cp)); - ch = CharNStat & 0xff; - - if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) - ch |= TTY_FE; - else if (CharNStat & STMPARITYH) - ch |= TTY_PE; - else if (CharNStat & STMRCVROVRH) - rp->rp_overflows++; - - (*linesw[tp->t_line].l_rint)(ch, tp); - ToRecv--; - } -/* - After emtying FIFO in status mode, turn off status mode -*/ - - if(sGetRxCnt(cp) == 0) - sDisRxStatusMode(cp); - } - else { - while (ToRecv) { - if(tp->t_state & TS_TBLOCK) { - break; - } - ch = (u_char) sInB(sGetTxRxDataIO(cp)); - spl = spltty(); - (*linesw[tp->t_line].l_rint)(ch, tp); - splx(spl); - ToRecv--; - } - } -} - -static _INLINE_ void rp_handle_port(struct rp_port *rp) -{ - CHANNEL_t *cp; - struct tty *tp; - unsigned int IntMask, ChanStatus; - /* int oldcts; */ - - if(!rp) - return; - - cp = &rp->rp_channel; - tp = rp->rp_tty; - IntMask = sGetChanIntID(cp); - IntMask = IntMask & rp->rp_intmask; - ChanStatus = sGetChanStatus(cp); - if(IntMask & RXF_TRIG) - if(!(tp->t_state & TS_TBLOCK) && (tp->t_state & TS_CARR_ON) && (tp->t_state & TS_ISOPEN)) { - rp_do_receive(rp, tp, cp, ChanStatus); - } - if(IntMask & DELTA_CD) { - if(ChanStatus & CD_ACT) { - if(!(tp->t_state & TS_CARR_ON) ) { - (void)(*linesw[tp->t_line].l_modem)(tp, 1); - } - } else { - if((tp->t_state & TS_CARR_ON)) { - (void)(*linesw[tp->t_line].l_modem)(tp, 0); - if((*linesw[tp->t_line].l_modem)(tp, 0) == 0) { - rphardclose(rp); - } - } - } - } -/* oldcts = rp->rp_cts; - rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); - if(oldcts != rp->rp_cts) { - printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); - } -*/ -} - -static void rp_do_poll(void *not_used) -{ - CONTROLLER_t *ctl; - struct rp_port *rp; - struct tty *tp; - int unit, aiop, ch, line, count; - unsigned char CtlMask, AiopMask; - - for(unit = 0; unit <= ndevs; unit++) { - rp = rp_addr(unit); - ctl = rp->rp_ctlp; - if(ctl->BusType == isPCI) - CtlMask = sPCIGetControllerIntStatus(ctl); - else - CtlMask = sGetControllerIntStatus(ctl); - for(aiop=0; CtlMask; CtlMask >>=1, aiop++) { - if(CtlMask & 1) { - AiopMask = sGetAiopIntStatus(ctl, aiop); - for(ch = 0; AiopMask; AiopMask >>=1, ch++) { - if(AiopMask & 1) { - line = (unit << 5) | (aiop << 3) | ch; - rp = rp_table(line); - rp_handle_port(rp); - } - } - } - } - - for(line = 0, rp = rp_addr(unit); line < rp_num_ports[unit]; - line++, rp++) { - tp = rp->rp_tty; - if((tp->t_state & TS_BUSY) && (tp->t_state & TS_ISOPEN)) { - count = sGetTxCnt(&rp->rp_channel); - if(count == 0) - tp->t_state &= ~(TS_BUSY); - if(!(tp->t_state & TS_TTSTOP) && - (count <= rp->rp_restart)) { - (*linesw[tp->t_line].l_start)(tp); - } - } - } - } - if (rp_num_ports_open) - callout_reset(&do_poll_ch, POLL_INTERVAL, rp_do_poll, NULL); -} - -static const char* -rp_pciprobe(pcici_t tag, pcidi_t type) -{ - int vendor_id; - - vendor_id = type & 0xffff; - switch(vendor_id) - case 0x11fe: - return("rp"); - return(NULL); -} - -static -int -rpprobe(dev) -struct isa_device *dev; -{ - int controller, unit; - int aiop, num_aiops; - unsigned int aiopio[MAX_AIOPS_PER_BOARD]; - CONTROLLER_t *ctlp; - - unit = dev->id_unit; - if (dev->id_unit >= 4) { - printf("rpprobe: unit number %d invalid.\n", dev->id_unit); - return 1; - } - printf("probing for RocketPort(ISA) unit %d\n", unit); - if (rp_controller_port) - controller = rp_controller_port; - else { - controller = dev->id_iobase + 0x40; - } - - for (aiop=0; aiopid_iobase + (aiop * 0x400); - - ctlp = sCtlNumToCtlPtr(dev->id_unit); - num_aiops = sInitController(ctlp, dev->id_unit, - controller + ((unit-rp_pcicount)*0x400), - aiopio, MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0); - if (num_aiops <= 0) { - printf("board%d init failed\n", unit); - return 0; - } - - if (rp_controller_port) { - dev->id_msize = 64; - } else { - dev->id_msize = 68; - rp_controller_port = controller; - } - - dev->id_irq = 0; - - return 1; -} - -static void -rp_pciattach(pcici_t tag, int unit) -{ - int success, oldspl; - u_short iobase; - int num_ports, num_chan, num_aiops; - int aiop, chan, port; - int ChanStatus, line, i, count; - unsigned int aiopio[MAX_AIOPS_PER_BOARD]; - struct rp_port *rp; - struct tty *tty; - CONTROLLER_t *ctlp; - - success = pci_map_port(tag, 0x10, &iobase); - if(!success) - printf("ioaddr mapping failed for RocketPort(PCI)\n"); - - for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++) - aiopio[aiop] = iobase + (aiop * 0x40); - - ctlp = sCtlNumToCtlPtr(unit); - num_aiops = sPCIInitController(ctlp, unit, - aiopio, MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0); - - num_ports = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - sResetAiopByNum(ctlp, aiop); - num_ports += sGetAiopNumChan(ctlp, aiop); - } - printf("RocketPort%d = %d ports\n", unit, num_ports); - rp_num_ports[unit] = num_ports; - - rp = malloc(sizeof(struct rp_port) * num_ports, - M_TTYS, M_WAITOK | M_ZERO); - - count = unit * 32; /* board times max ports per card SG */ - for(i=count;i < (count + rp_num_ports[unit]);i++) - minor_to_unit[i] = unit; - - tty = malloc(sizeof(struct tty) * num_ports, M_TTYS, M_WAITOK | M_ZERO); - - oldspl = spltty(); - rp_addr(unit) = rp; - splx(oldspl); - - cdevsw_add(&rp_cdevsw, 0, 0); - - port = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - num_chan = sGetAiopNumChan(ctlp, aiop); - for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) { - rp->rp_tty = tty; - rp->rp_port = port; - rp->rp_ctlp = ctlp; - rp->rp_unit = unit; - rp->rp_chan = chan; - rp->rp_aiop = aiop; - - tty->t_line = 0; - /* tty->t_termios = deftermios; - */ - rp->dtr_wait = 3 * hz; - callout_init(&rp->dtr_ch); - rp->it_in.c_iflag = 0; - rp->it_in.c_oflag = 0; - rp->it_in.c_cflag = TTYDEF_CFLAG; - rp->it_in.c_lflag = 0; - termioschars(&rp->it_in); - /* termioschars(&tty->t_termios); - */ - rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; - rp->it_out = rp->it_in; - - rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | - DELTA_CD | DELTA_CTS | DELTA_DSR; - ChanStatus = sGetChanStatus(&rp->rp_channel); - if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { - printf("RocketPort sInitChan(%d, %d, %d) failed\n", - unit, aiop, chan); - return; - } - ChanStatus = sGetChanStatus(&rp->rp_channel); - rp->rp_cts = (ChanStatus & CTS_ACT) != 0; - line = (unit << 5) | (aiop << 3) | chan; - rp_table(line) = rp; - } - } -} - -static -int -rpattach(dev) -struct isa_device *dev; -{ - int iobase, unit, /*rpmajor,*/ oldspl; - int num_ports, num_chan, num_aiops; - int aiop, chan, port; - int ChanStatus, line, i, count; - unsigned int aiopio[MAX_AIOPS_PER_BOARD]; - struct rp_port *rp; - struct tty *tty; - CONTROLLER_t *ctlp; - - iobase = dev->id_iobase; - unit = dev->id_unit; - ndevs = unit; - - for(aiop=0; aiop < MAX_AIOPS_PER_BOARD; aiop++) - aiopio[aiop] = iobase + (aiop * 0x400); - - ctlp = sCtlNumToCtlPtr(unit); - num_aiops = sInitController(ctlp, unit, - rp_controller_port + ((unit-rp_pcicount) * 0x400), - aiopio, MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0); - - num_ports = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - sResetAiopByNum(ctlp, aiop); - sEnAiop(ctlp, aiop); - num_ports += sGetAiopNumChan(ctlp, aiop); - } - printf("RocketPort%d = %d ports\n", unit, num_ports); - rp_num_ports[unit] = num_ports; - - rp = malloc(sizeof(struct rp_port) * num_ports, - M_TTYS, M_WAITOK | M_ZERO); - - count = unit * 32; /* board # times max ports per card SG */ - for(i=count;i < (count + rp_num_ports[unit]);i++) - minor_to_unit[i] = unit; - - tty = malloc(sizeof(struct tty) * num_ports, M_TTYS, M_WAITOK | M_ZERO); - - oldspl = spltty(); - rp_addr(unit) = rp; - splx(oldspl); - - cdevsw_add(&rp_cdevsw, 0, 0); - - port = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - num_chan = sGetAiopNumChan(ctlp, aiop); - for(chan=0; chan < num_chan; chan++, port++, rp++, tty++) { - rp->rp_tty = tty; - rp->rp_port = port; - rp->rp_ctlp = ctlp; - rp->rp_unit = unit; - rp->rp_chan = chan; - rp->rp_aiop = aiop; - - tty->t_line = 0; - /* tty->t_termios = deftermios; - */ - rp->dtr_wait = 3 * hz; - rp->it_in.c_iflag = 0; - rp->it_in.c_oflag = 0; - rp->it_in.c_cflag = TTYDEF_CFLAG; - rp->it_in.c_lflag = 0; - termioschars(&rp->it_in); - /* termioschars(&tty->t_termios); - */ - rp->it_in.c_ispeed = rp->it_in.c_ospeed = TTYDEF_SPEED; - rp->it_out = rp->it_in; - - rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | - DELTA_CD | DELTA_CTS | DELTA_DSR; - ChanStatus = sGetChanStatus(&rp->rp_channel); - if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { - printf("RocketPort sInitChan(%d, %d, %d) failed\n", - unit, aiop, chan); - return(0); - } - ChanStatus = sGetChanStatus(&rp->rp_channel); - rp->rp_cts = (ChanStatus & CTS_ACT) != 0; - line = (unit << 5) | (aiop << 3) | chan; - rp_table(line) = rp; - } - } - - return(1); -} - -int -rpopen(dev, flag, mode, td) - dev_t dev; - int flag, mode; - struct thread *td; -{ - struct rp_port *rp; - int unit, port, mynor, umynor, flags; /* SG */ - struct tty *tp; - int oldspl, error; - unsigned int IntMask, ChanStatus; - - - umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ - port = (minor(dev) & 0x1f); /* SG */ - mynor = (port + umynor); /* SG */ - unit = minor_to_unit[mynor]; - if (rp_addr(unit) == NULL) - return (ENXIO); - if(IS_CONTROL(dev)) - return(0); - rp = rp_addr(unit) + port; -/* rp->rp_tty = &rp_tty[rp->rp_port]; -*/ - tp = rp->rp_tty; - dev->si_tty = tp; - - oldspl = spltty(); - -open_top: - while(rp->state & ~SET_DTR) { - error = tsleep(&rp->dtr_wait, PCATCH, "rpdtr", 0); - if(error != 0) - goto out; - } - - if(tp->t_state & TS_ISOPEN) { - if(IS_CALLOUT(dev)) { - if(!rp->active_out) { - error = EBUSY; - goto out; - } - } else { - if(rp->active_out) { - if(flag & O_NONBLOCK) { - error = EBUSY; - goto out; - } - error = tsleep(&rp->active_out, - PCATCH, "rpbi", 0); - if(error != 0) - goto out; - goto open_top; - } - } - if(tp->t_state & TS_XCLUDE && - suser(td)) { - splx(oldspl); - return(EBUSY); - } - } - else { - tp->t_dev = dev; - tp->t_param = rpparam; - tp->t_oproc = rpstart; - tp->t_stop = rpstop; - tp->t_line = 0; - tp->t_termios = IS_CALLOUT(dev) ? rp->it_out : rp->it_in; - flags = 0; - flags |= SET_RTS; - flags |= SET_DTR; - rp->rp_channel.TxControl[3] = - ((rp->rp_channel.TxControl[3] - & ~(SET_RTS | SET_DTR)) | flags); - sOutDW(rp->rp_channel.IndexAddr, - *(DWord_t *) &(rp->rp_channel.TxControl[0])); - sSetRxTrigger(&rp->rp_channel, TRIG_1); - sDisRxStatusMode(&rp->rp_channel); - sFlushRxFIFO(&rp->rp_channel); - sFlushTxFIFO(&rp->rp_channel); - - sEnInterrupts(&rp->rp_channel, - (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); - sSetRxTrigger(&rp->rp_channel, TRIG_1); - - sDisRxStatusMode(&rp->rp_channel); - sClrTxXOFF(&rp->rp_channel); - -/* sDisRTSFlowCtl(&rp->rp_channel); - sDisCTSFlowCtl(&rp->rp_channel); -*/ - sDisTxSoftFlowCtl(&rp->rp_channel); - - sStartRxProcessor(&rp->rp_channel); - - sEnRxFIFO(&rp->rp_channel); - sEnTransmit(&rp->rp_channel); - -/* sSetDTR(&rp->rp_channel); - sSetRTS(&rp->rp_channel); -*/ - - ++rp->wopeners; - error = rpparam(tp, &tp->t_termios); - --rp->wopeners; - if(error != 0) { - splx(oldspl); - return(error); - } - - rp_num_ports_open++; - - IntMask = sGetChanIntID(&rp->rp_channel); - IntMask = IntMask & rp->rp_intmask; - ChanStatus = sGetChanStatus(&rp->rp_channel); - if((IntMask & DELTA_CD) || IS_CALLOUT(dev)) { - if((ChanStatus & CD_ACT) || IS_CALLOUT(dev)) { - (void)(*linesw[tp->t_line].l_modem)(tp, 1); - } - } - - if (rp_num_ports_open == 1) - if ((do_poll_ch.c_flags & CALLOUT_DID_INIT) == 0) - callout_init(&do_poll_ch); - callout_reset(&do_poll_ch, POLL_INTERVAL, rp_do_poll, NULL); - } - - if(!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && - !(tp->t_state & TS_CARR_ON) && !(IS_CALLOUT(dev))) { - ++rp->wopeners; - error = tsleep(TSA_CARR_ON(tp), PCATCH, "rpdcd", 0); - --rp->wopeners; - if(error != 0) - goto out; - goto open_top; - } - error = (*linesw[tp->t_line].l_open)(dev, tp); - - rp_disc_optim(tp, &tp->t_termios, rp); - if(tp->t_state & TS_ISOPEN && IS_CALLOUT(dev)) - rp->active_out = TRUE; - -out: - splx(oldspl); - if(!(tp->t_state & TS_ISOPEN) && rp->wopeners == 0) { - rphardclose(rp); - } - return(error); -} - -int -rpclose(dev, flag, mode, td) - dev_t dev; - int flag, mode; - struct thread *td; -{ - int oldspl, unit, mynor, umynor, port; /* SG */ - struct rp_port *rp; - struct tty *tp; - CHANNEL_t *cp; - - umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ - port = (minor(dev) & 0x1f); /* SG */ - mynor = (port + umynor); /* SG */ - unit = minor_to_unit[mynor]; /* SG */ - - if(IS_CONTROL(dev)) - return(0); - rp = rp_addr(unit) + port; - cp = &rp->rp_channel; - tp = rp->rp_tty; - - oldspl = spltty(); - (*linesw[tp->t_line].l_close)(tp, flag); - rp_disc_optim(tp, &tp->t_termios, rp); - rpstop(tp, FREAD | FWRITE); - rphardclose(rp); - - tp->t_state &= ~TS_BUSY; - ttyclose(tp); - - splx(oldspl); - - return(0); -} - -static void -rphardclose(struct rp_port *rp) -{ - int mynor; - struct tty *tp; - CHANNEL_t *cp; - - cp = &rp->rp_channel; - tp = rp->rp_tty; - mynor = MINOR_MAGIC(tp->t_dev); - - sFlushRxFIFO(cp); - sFlushTxFIFO(cp); - sDisTransmit(cp); - sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); - sDisRTSFlowCtl(cp); - sDisCTSFlowCtl(cp); - sDisTxSoftFlowCtl(cp); - sClrTxXOFF(cp); - - if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !rp->active_out) { - sClrDTR(cp); - } - if(IS_CALLOUT(tp->t_dev)) { - sClrDTR(cp); - } - if(rp->dtr_wait != 0) { - callout_reset(&rp->dtr_ch, rp->dtr_wait, rpdtrwakeup, rp); - rp->state |= ~SET_DTR; - } - - rp->active_out = FALSE; - wakeup(&rp->active_out); - wakeup(TSA_CARR_ON(tp)); -} - -static -int -rpwrite(dev, uio, flag) - dev_t dev; - struct uio *uio; - int flag; -{ - struct rp_port *rp; - struct tty *tp; - int unit, mynor, port, umynor, error = 0; /* SG */ - - umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ - port = (minor(dev) & 0x1f); /* SG */ - mynor = (port + umynor); /* SG */ - unit = minor_to_unit[mynor]; /* SG */ - - if(IS_CONTROL(dev)) - return(ENODEV); - rp = rp_addr(unit) + port; - tp = rp->rp_tty; - while(rp->rp_disable_writes) { - rp->rp_waiting = 1; - error = ttysleep(tp, (caddr_t)rp, PCATCH, "rp_write", 0); - if (error) - return(error); - } - - error = (*linesw[tp->t_line].l_write)(tp, uio, flag); - return error; -} - -static void -rpdtrwakeup(void *chan) -{ - struct rp_port *rp; - - rp = (struct rp_port *)chan; - rp->state &= SET_DTR; - wakeup(&rp->dtr_wait); -} - -int -rpioctl(dev, cmd, data, flag, td) - dev_t dev; - u_long cmd; - caddr_t data; - int flag; - struct thread *td; -{ - struct rp_port *rp; - CHANNEL_t *cp; - struct tty *tp; - int unit, mynor, port, umynor; /* SG */ - int oldspl; - int error = 0; - int arg, flags, result, ChanStatus; - int oldcmd; - struct termios term, *t; - - umynor = (((minor(dev) >> 16) -1) * 32); /* SG */ - port = (minor(dev) & 0x1f); /* SG */ - mynor = (port + umynor); /* SG */ - unit = minor_to_unit[mynor]; - rp = rp_addr(unit) + port; - - if(IS_CONTROL(dev)) { - struct termios *ct; - - switch (IS_CONTROL(dev)) { - case CONTROL_INIT_STATE: - ct = IS_CALLOUT(dev) ? &rp->it_out : &rp->it_in; - break; - case CONTROL_LOCK_STATE: - ct = IS_CALLOUT(dev) ? &rp->lt_out : &rp->lt_in; - break; - default: - return(ENODEV); /* /dev/nodev */ - } - switch (cmd) { - case TIOCSETA: - error = suser(td); - if(error != 0) - return(error); - *ct = *(struct termios *)data; - return(0); - case TIOCGETA: - *(struct termios *)data = *ct; - return(0); - case TIOCGETD: - *(int *)data = TTYDISC; - return(0); - case TIOCGWINSZ: - bzero(data, sizeof(struct winsize)); - return(0); - default: - return(ENOTTY); - } - } - - tp = rp->rp_tty; - cp = &rp->rp_channel; - -#if defined(COMPAT_43) || defined(COMPAT_SUNOS) - term = tp->t_termios; - oldcmd = cmd; - error = ttsetcompat(tp, &cmd, data, &term); - if(error != 0) - return(error); - if(cmd != oldcmd) { - data = (caddr_t)&term; - } -#endif - if((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) { - int cc; - struct termios *dt = (struct termios *)data; - struct termios *lt = IS_CALLOUT(dev) - ? &rp->lt_out : &rp->lt_in; - - dt->c_iflag = (tp->t_iflag & lt->c_iflag) - | (dt->c_iflag & ~lt->c_iflag); - dt->c_oflag = (tp->t_oflag & lt->c_oflag) - | (dt->c_oflag & ~lt->c_oflag); - dt->c_cflag = (tp->t_cflag & lt->c_cflag) - | (dt->c_cflag & ~lt->c_cflag); - dt->c_lflag = (tp->t_lflag & lt->c_lflag) - | (dt->c_lflag & ~lt->c_lflag); - for(cc = 0; cc < NCCS; ++cc) - if(lt->c_cc[cc] != 0) - dt->c_cc[cc] = tp->t_cc[cc]; - if(lt->c_ispeed != 0) - dt->c_ispeed = tp->t_ispeed; - if(lt->c_ospeed != 0) - dt->c_ospeed = tp->t_ospeed; - } - - t = &tp->t_termios; - - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td); - if(error != ENOIOCTL) { - return(error); - } - oldspl = spltty(); - - flags = rp->rp_channel.TxControl[3]; - - error = ttioctl(tp, cmd, data, flag); - flags = rp->rp_channel.TxControl[3]; - rp_disc_optim(tp, &tp->t_termios, rp); - if(error != ENOIOCTL) { - splx(oldspl); - return(error); - } - switch(cmd) { - case TIOCSBRK: - sSendBreak(&rp->rp_channel); - break; - - case TIOCCBRK: - sClrBreak(&rp->rp_channel); - break; - - case TIOCSDTR: - sSetDTR(&rp->rp_channel); - sSetRTS(&rp->rp_channel); - break; - - case TIOCCDTR: - sClrDTR(&rp->rp_channel); - break; - - case TIOCMSET: - arg = *(int *) data; - flags = 0; - if(arg & TIOCM_RTS) - flags |= SET_RTS; - if(arg & TIOCM_DTR) - flags |= SET_DTR; - rp->rp_channel.TxControl[3] = - ((rp->rp_channel.TxControl[3] - & ~(SET_RTS | SET_DTR)) | flags); - sOutDW(rp->rp_channel.IndexAddr, - *(DWord_t *) &(rp->rp_channel.TxControl[0])); - break; - case TIOCMBIS: - arg = *(int *) data; - flags = 0; - if(arg & TIOCM_RTS) - flags |= SET_RTS; - if(arg & TIOCM_DTR) - flags |= SET_DTR; - rp->rp_channel.TxControl[3] |= flags; - sOutDW(rp->rp_channel.IndexAddr, - *(DWord_t *) &(rp->rp_channel.TxControl[0])); - break; - case TIOCMBIC: - arg = *(int *) data; - flags = 0; - if(arg & TIOCM_RTS) - flags |= SET_RTS; - if(arg & TIOCM_DTR) - flags |= SET_DTR; - rp->rp_channel.TxControl[3] &= ~flags; - sOutDW(rp->rp_channel.IndexAddr, - *(DWord_t *) &(rp->rp_channel.TxControl[0])); - break; - - - case TIOCMGET: - ChanStatus = sGetChanStatusLo(&rp->rp_channel); - flags = rp->rp_channel.TxControl[3]; - result = TIOCM_LE; /* always on while open for some reason */ - result |= (((flags & SET_DTR) ? TIOCM_DTR : 0) - | ((flags & SET_RTS) ? TIOCM_RTS : 0) - | ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) - | ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) - | ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0)); - - if(rp->rp_channel.RxControl[2] & RTSFC_EN) - { - result |= TIOCM_RTS; - } - - *(int *)data = result; - break; - case TIOCMSDTRWAIT: - error = suser(td); - if(error != 0) { - splx(oldspl); - return(error); - } - rp->dtr_wait = *(int *)data * hz/100; - break; - case TIOCMGDTRWAIT: - *(int *)data = rp->dtr_wait * 100/hz; - break; - default: - splx(oldspl); - return ENOTTY; - } - splx(oldspl); - return(0); -} - -static struct speedtab baud_table[] = { - {B0, 0}, {B50, BRD50}, {B75, BRD75}, - {B110, BRD110}, {B134, BRD134}, {B150, BRD150}, - {B200, BRD200}, {B300, BRD300}, {B600, BRD600}, - {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400}, - {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200}, - {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400}, - {B57600, BRD57600}, {B76800, BRD76800}, - {B115200, BRD115200}, {B230400, BRD230400}, - { -1, -1 } -}; - -static int -rpparam(tp, t) - struct tty *tp; - struct termios *t; -{ - struct rp_port *rp; - CHANNEL_t *cp; - int unit, mynor, port, umynor; /* SG */ - int oldspl, cflag, iflag, oflag, lflag; - int ospeed; - - - umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ - port = (minor(tp->t_dev) & 0x1f); /* SG */ - mynor = (port + umynor); /* SG */ - - unit = minor_to_unit[mynor]; - rp = rp_addr(unit) + port; - cp = &rp->rp_channel; - oldspl = spltty(); - - cflag = t->c_cflag; - iflag = t->c_iflag; - oflag = t->c_oflag; - lflag = t->c_lflag; - - ospeed = ttspeedtab(t->c_ispeed, baud_table); - if(ospeed < 0 || t->c_ispeed != t->c_ospeed) - return(EINVAL); - - tp->t_ispeed = t->c_ispeed; - tp->t_ospeed = t->c_ospeed; - tp->t_cflag = cflag; - tp->t_iflag = iflag; - tp->t_oflag = oflag; - tp->t_lflag = lflag; - - if(t->c_ospeed == 0) { - sClrDTR(cp); - return(0); - } - rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1; - - /* Set baud rate ----- we only pay attention to ispeed */ - sSetDTR(cp); - sSetRTS(cp); - sSetBaud(cp, ospeed); - - if(cflag & CSTOPB) { - sSetStop2(cp); - } else { - sSetStop1(cp); - } - - if(cflag & PARENB) { - sEnParity(cp); - if(cflag & PARODD) { - sSetOddParity(cp); - } else { - sSetEvenParity(cp); - } - } - else { - sDisParity(cp); - } - if((cflag & CSIZE) == CS8) { - sSetData8(cp); - rp->rp_imask = 0xFF; - } else { - sSetData7(cp); - rp->rp_imask = 0x7F; - } - - if(iflag & ISTRIP) { - rp->rp_imask &= 0x7F; - } - - if(cflag & CLOCAL) { - rp->rp_intmask &= ~DELTA_CD; - } else { - rp->rp_intmask |= DELTA_CD; - } - - /* Put flow control stuff here */ - - if(cflag & CCTS_OFLOW) { - sEnCTSFlowCtl(cp); - } else { - sDisCTSFlowCtl(cp); - } - - if(cflag & CRTS_IFLOW) { - rp->rp_rts_iflow = 1; - } else { - rp->rp_rts_iflow = 0; - } - - if(cflag & CRTS_IFLOW) { - sEnRTSFlowCtl(cp); - } else { - sDisRTSFlowCtl(cp); - } - rp_disc_optim(tp, t, rp); - - if((cflag & CLOCAL) || (sGetChanStatusLo(cp) & CD_ACT)) { - tp->t_state |= TS_CARR_ON; - wakeup(TSA_CARR_ON(tp)); - } - -/* tp->t_state |= TS_CAN_BYPASS_L_RINT; - flags = rp->rp_channel.TxControl[3]; - if(flags & SET_DTR) - else - if(flags & SET_RTS) - else -*/ - splx(oldspl); - - return(0); -} - -static void -rp_disc_optim(tp, t, rp) -struct tty *tp; -struct termios *t; -struct rp_port *rp; -{ - if(!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) - &&(!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) - &&(!(t->c_iflag & PARMRK) - ||(t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) - && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) - && linesw[tp->t_line].l_rint == ttyinput) - tp->t_state |= TS_CAN_BYPASS_L_RINT; - else - tp->t_state &= ~TS_CAN_BYPASS_L_RINT; -} - -static void -rpstart(tp) - struct tty *tp; -{ - struct rp_port *rp; - CHANNEL_t *cp; - struct clist *qp; - int unit, mynor, port, umynor; /* SG */ - char ch, flags; - int spl, xmit_fifo_room; - int count; - - - umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ - port = (minor(tp->t_dev) & 0x1f); /* SG */ - mynor = (port + umynor); /* SG */ - unit = minor_to_unit[mynor]; - rp = rp_addr(unit) + port; - cp = &rp->rp_channel; - flags = rp->rp_channel.TxControl[3]; - spl = spltty(); - - if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - splx(spl); - return; - } - if(rp->rp_xmit_stopped) { - sEnTransmit(cp); - rp->rp_xmit_stopped = 0; - } - count = sGetTxCnt(cp); - - if(tp->t_outq.c_cc == 0) { - if((tp->t_state & TS_BUSY) && (count == 0)) { - tp->t_state &= ~TS_BUSY; - } - ttwwakeup(tp); - splx(spl); - return; - } - xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); - qp = &tp->t_outq; - count = 0; - if(xmit_fifo_room > 0 && qp->c_cc > 0) { - tp->t_state |= TS_BUSY; - } - while(xmit_fifo_room > 0 && qp->c_cc > 0) { - ch = getc(qp); - sOutB(sGetTxRxDataIO(cp), ch); - xmit_fifo_room--; - count++; - } - rp->rp_restart = (qp->c_cc > 0) ? rp->rp_fifo_lw : 0; - - ttwwakeup(tp); - splx(spl); -} - -static -void -rpstop(tp, flag) - struct tty *tp; - int flag; -{ - struct rp_port *rp; - CHANNEL_t *cp; - int unit, mynor, port, umynor; /* SG */ - int spl; - - umynor = (((minor(tp->t_dev) >> 16) -1) * 32); /* SG */ - port = (minor(tp->t_dev) & 0x1f); /* SG */ - mynor = (port + umynor); /* SG */ - unit = minor_to_unit[mynor]; - rp = rp_addr(unit) + port; - cp = &rp->rp_channel; - - spl = spltty(); - - if(tp->t_state & TS_BUSY) { - if((tp->t_state&TS_TTSTOP) == 0) { - sFlushTxFIFO(cp); - } else { - if(rp->rp_xmit_stopped == 0) { - sDisTransmit(cp); - rp->rp_xmit_stopped = 1; - } - } - } - splx(spl); - rpstart(tp); -} diff --git a/sys/dev/serial/rp2/rpreg.h b/sys/dev/serial/rp2/rpreg.h deleted file mode 100644 index 239bf51c70..0000000000 --- a/sys/dev/serial/rp2/rpreg.h +++ /dev/null @@ -1,1046 +0,0 @@ -/* - * Copyright (c) Comtrol Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials prodided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/i386/isa/rpreg.h,v 1.2.6.1 2000/08/03 01:01:20 peter Exp $ - * $DragonFly: src/sys/dev/serial/rp2/Attic/rpreg.h,v 1.2 2003/06/17 04:28:37 dillon Exp $ - */ - -/* - * Begin OS-specific defines - rpreg.h - for RocketPort FreeBSD - */ - -typedef unsigned char Byte_t; -typedef unsigned int ByteIO_t; - -typedef unsigned int Word_t; -typedef unsigned int WordIO_t; - -typedef unsigned long DWord_t; -typedef unsigned int DWordIO_t; - -#define sOutB(a, b) outb(a, b) -#define sOutW(a, b) outw(a, b) -#define sOutDW(a, b) outl(a, b) -#define sInB(a) (inb(a)) -#define sInW(a) (inw(a)) -#define sOutStrW(port, addr, count) outsw(port, addr, count) -#define sInStrW(port, addr, count) insw(port, addr, count) - -/* - * End of OS-specific defines - */ - -#define ROCKET_H - -#define CTL_SIZE 4 -#define AIOP_CTL_SIZE 4 -#define CHAN_AIOP_SIZE 8 -#define MAX_PORTS_PER_AIOP 8 -#define MAX_AIOPS_PER_BOARD 4 -#define MAX_PORTS_PER_BOARD 32 - -/* Bus Type ID */ -#define isISA 0 -#define isPCI 1 -#define isMC 2 - -/* Controller ID numbers */ -#define CTLID_NULL -1 /* no controller exists */ -#define CTLID_0001 0x0001 /* controller release 1 */ - -/* PCI IDs */ -#define RP_VENDOR_ID 0x11FE -#define RP_DEVICE_ID_8OCTA 0x0001 -#define RP_DEVICE_ID_8INTF 0x0002 -#define RP_DEVICE_ID_16INTF 0x0003 -#define RP_DEVICE_ID_32INTF 0x0004 - -/* AIOP ID numbers, identifies AIOP type implementing channel */ -#define AIOPID_NULL -1 /* no AIOP or channel exists */ -#define AIOPID_0001 0x0001 /* AIOP release 1 */ - -#define NULLDEV -1 /* identifies non-existant device */ -#define NULLCTL -1 /* identifies non-existant controller */ -#define NULLCTLPTR (CONTROLLER_T *)0 /* identifies non-existant controller */ -#define NULLAIOP -1 /* identifies non-existant AIOP */ -#define NULLCHAN -1 /* identifies non-existant channel */ - -/************************************************************************ - Global Register Offsets - Direct Access - Fixed values -************************************************************************/ - -#define _CMD_REG 0x38 /* Command Register 8 Write */ -#define _INT_CHAN 0x39 /* Interrupt Channel Register 8 Read */ -#define _INT_MASK 0x3A /* Interrupt Mask Register 8 Read / Write */ -#define _UNUSED 0x3B /* Unused 8 */ -#define _INDX_ADDR 0x3C /* Index Register Address 16 Write */ -#define _INDX_DATA 0x3E /* Index Register Data 8/16 Read / Write */ - -/************************************************************************ - Channel Register Offsets for 1st channel in AIOP - Direct Access -************************************************************************/ -#define _TD0 0x00 /* Transmit Data 16 Write */ -#define _RD0 0x00 /* Receive Data 16 Read */ -#define _CHN_STAT0 0x20 /* Channel Status 8/16 Read / Write */ -#define _FIFO_CNT0 0x10 /* Transmit/Receive FIFO Count 16 Read */ -#define _INT_ID0 0x30 /* Interrupt Identification 8 Read */ - -/************************************************************************ - Tx Control Register Offsets - Indexed - External - Fixed -************************************************************************/ -#define _TX_ENBLS 0x980 /* Tx Processor Enables Register 8 Read / Write */ -#define _TXCMP1 0x988 /* Transmit Compare Value #1 8 Read / Write */ -#define _TXCMP2 0x989 /* Transmit Compare Value #2 8 Read / Write */ -#define _TXREP1B1 0x98A /* Tx Replace Value #1 - Byte 1 8 Read / Write */ -#define _TXREP1B2 0x98B /* Tx Replace Value #1 - Byte 2 8 Read / Write */ -#define _TXREP2 0x98C /* Transmit Replace Value #2 8 Read / Write */ - -/************************************************************************ - Receive FIFO -************************************************************************/ -#define RXFIFO_DATA 0x5f -#define RXFIFO_OUT 0x5c -#define RXFIFO_EN 0x08 -#define RXFIFO_DIS 0xa7 - -/************************************************************************ -Memory Controller Register Offsets - Indexed - External - Fixed -************************************************************************/ -#define _RX_FIFO 0x000 /* Rx FIFO */ -#define _TX_FIFO 0x800 /* Tx FIFO */ -#define _RXF_OUTP 0x990 /* Rx FIFO OUT pointer 16 Read / Write */ -#define _RXF_INP 0x992 /* Rx FIFO IN pointer 16 Read / Write */ -#define _TXF_OUTP 0x994 /* Tx FIFO OUT pointer 8 Read / Write */ -#define _TXF_INP 0x995 /* Tx FIFO IN pointer 8 Read / Write */ -#define _TXP_CNT 0x996 /* Tx Priority Count 8 Read / Write */ -#define _TXP_PNTR 0x997 /* Tx Priority Pointer 8 Read / Write */ - -#define PRI_PEND 0x80 /* Priority data pending (bit7, Tx pri cnt) */ -#define TXFIFO_SIZE 255 /* size of Tx FIFO */ -#define RXFIFO_SIZE 1023 /* size of Rx FIFO */ - -/************************************************************************ -Tx Priority Buffer - Indexed - External - Fixed -************************************************************************/ -#define _TXP_BUF 0x9C0 /* Tx Priority Buffer 32 Bytes Read / Write */ -#define TXP_SIZE 0x20 /* 32 bytes */ - -/************************************************************************ -Channel Register Offsets - Indexed - Internal - Fixed -************************************************************************/ - -#define _TX_CTRL 0xFF0 /* Transmit Control 16 Write */ -#define _RX_CTRL 0xFF2 /* Receive Control 8 Write */ -#define _BAUD 0xFF4 /* Baud Rate 16 Write */ -#define _CLK_PRE 0xFF6 /* Clock Prescaler 8 Write */ - -#define CLOCK_PRESC 0x19 /* mod 9 (divide by 10) prescale */ - -#define BRD50 4607 -#define BRD75 3071 -#define BRD110 2094 -#define BRD134 1712 -#define BRD150 1535 -#define BRD200 1151 -#define BRD300 767 -#define BRD600 383 -#define BRD1200 191 -#define BRD1800 127 -#define BRD2000 114 -#define BRD2400 95 -#define BRD3600 64 -#define BRD4800 47 -#define BRD7200 31 -#define BRD9600 23 -#define BRD14400 15 -#define BRD19200 11 -#define BRD38400 5 -#define BRD57600 3 -#define BRD76800 2 -#define BRD115200 1 -#define BRD230400 0 - -#define STMBREAK 0x08 /* BREAK */ -#define STMFRAME 0x04 /* framing error */ -#define STMRCVROVR 0x02 /* receiver over run error */ -#define STMPARITY 0x01 /* parity error */ -#define STMERROR (STMBREAK | STMFRAME | STMPARITY) -#define STMBREAKH 0x800 /* BREAK */ -#define STMFRAMEH 0x400 /* framing error */ -#define STMRCVROVRH 0x200 /* receiver over run error */ -#define STMPARITYH 0x100 /* parity error */ -#define STMERRORH (STMBREAKH | STMFRAMEH | STMPARITYH) - -#define CTS_ACT 0x20 /* CTS input asserted */ -#define DSR_ACT 0x10 /* DSR input asserted */ -#define CD_ACT 0x08 /* CD input asserted */ -#define TXFIFOMT 0x04 /* Tx FIFO is empty */ -#define TXSHRMT 0x02 /* Tx shift register is empty */ -#define RDA 0x01 /* Rx data available */ -#define DRAINED (TXFIFOMT | TXSHRMT) /* indicates Tx is drained */ - -#define STATMODE 0x8000 /* status mode enable bit */ -#define RXFOVERFL 0x2000 /* receive FIFO overflow */ -#define RX2MATCH 0x1000 /* receive compare byte 2 match */ -#define RX1MATCH 0x0800 /* receive compare byte 1 match */ -#define RXBREAK 0x0400 /* received BREAK */ -#define RXFRAME 0x0200 /* received framing error */ -#define RXPARITY 0x0100 /* received parity error */ -#define STATERROR (RXBREAK | RXFRAME | RXPARITY) - -#define CTSFC_EN 0x80 /* CTS flow control enable bit */ -#define RTSTOG_EN 0x40 /* RTS toggle enable bit */ -#define TXINT_EN 0x10 /* transmit interrupt enable */ -#define STOP2 0x08 /* enable 2 stop bits (0 = 1 stop) */ -#define PARITY_EN 0x04 /* enable parity (0 = no parity) */ -#define EVEN_PAR 0x02 /* even parity (0 = odd parity) */ -#define DATA8BIT 0x01 /* 8 bit data (0 = 7 bit data) */ - -#define SETBREAK 0x10 /* send break condition (must clear) */ -#define LOCALLOOP 0x08 /* local loopback set for test */ -#define SET_DTR 0x04 /* assert DTR */ -#define SET_RTS 0x02 /* assert RTS */ -#define TX_ENABLE 0x01 /* enable transmitter */ - -#define RTSFC_EN 0x40 /* RTS flow control enable */ -#define RXPROC_EN 0x20 /* receive processor enable */ -#define TRIG_NO 0x00 /* Rx FIFO trigger level 0 (no trigger) */ -#define TRIG_1 0x08 /* trigger level 1 char */ -#define TRIG_1_2 0x10 /* trigger level 1/2 */ -#define TRIG_7_8 0x18 /* trigger level 7/8 */ -#define TRIG_MASK 0x18 /* trigger level mask */ -#define SRCINT_EN 0x04 /* special Rx condition interrupt enable */ -#define RXINT_EN 0x02 /* Rx interrupt enable */ -#define MCINT_EN 0x01 /* modem change interrupt enable */ - -#define RXF_TRIG 0x20 /* Rx FIFO trigger level interrupt */ -#define TXFIFO_MT 0x10 /* Tx FIFO empty interrupt */ -#define SRC_INT 0x08 /* special receive condition interrupt */ -#define DELTA_CD 0x04 /* CD change interrupt */ -#define DELTA_CTS 0x02 /* CTS change interrupt */ -#define DELTA_DSR 0x01 /* DSR change interrupt */ - -#define REP1W2_EN 0x10 /* replace byte 1 with 2 bytes enable */ -#define IGN2_EN 0x08 /* ignore byte 2 enable */ -#define IGN1_EN 0x04 /* ignore byte 1 enable */ -#define COMP2_EN 0x02 /* compare byte 2 enable */ -#define COMP1_EN 0x01 /* compare byte 1 enable */ - -#define RESET_ALL 0x80 /* reset AIOP (all channels) */ -#define TXOVERIDE 0x40 /* Transmit software off override */ -#define RESETUART 0x20 /* reset channel's UART */ -#define RESTXFCNT 0x10 /* reset channel's Tx FIFO count register */ -#define RESRXFCNT 0x08 /* reset channel's Rx FIFO count register */ - -#define INTSTAT0 0x01 /* AIOP 0 interrupt status */ -#define INTSTAT1 0x02 /* AIOP 1 interrupt status */ -#define INTSTAT2 0x04 /* AIOP 2 interrupt status */ -#define INTSTAT3 0x08 /* AIOP 3 interrupt status */ - -#define INTR_EN 0x08 /* allow interrupts to host */ -#define INT_STROB 0x04 /* strobe and clear interrupt line (EOI) */ - -/************************************************************************** - MUDBAC remapped for PCI -**************************************************************************/ - -#define _CFG_INT_PCI 0x40 -#define _PCI_INT_FUNC 0x3A - -#define PCI_STROB 0x2000 -#define INTR_EN_PCI 0x0010 - -#define CHAN3_EN 0x08 /* enable AIOP 3 */ -#define CHAN2_EN 0x04 /* enable AIOP 2 */ -#define CHAN1_EN 0x02 /* enable AIOP 1 */ -#define CHAN0_EN 0x01 /* enable AIOP 0 */ -#define FREQ_DIS 0x00 -#define FREQ_274HZ 0x60 -#define FREQ_137HZ 0x50 -#define FREQ_69HZ 0x40 -#define FREQ_34HZ 0x30 -#define FREQ_17HZ 0x20 -#define FREQ_9HZ 0x10 -#define PERIODIC_ONLY 0x80 /* only PERIODIC interrupt */ - -#define CHANINT_EN 0x0100 /* flags to enable/disable channel ints */ - -#define RDATASIZE 72 -#define RREGDATASIZE 52 - -/* Controller level information structure */ -typedef struct -{ - int CtlID; - int CtlNum; - int BusType; - WordIO_t PCIIO; - ByteIO_t MBaseIO; - ByteIO_t MReg1IO; - ByteIO_t MReg2IO; - ByteIO_t MReg3IO; - Byte_t MReg2; - Byte_t MReg3; - int NumAiop; - WordIO_t AiopIO[AIOP_CTL_SIZE]; - ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE]; - int AiopID[AIOP_CTL_SIZE]; - int AiopNumChan[AIOP_CTL_SIZE]; -} CONTROLLER_T; - -typedef CONTROLLER_T CONTROLLER_t; - -/* Channel level information structure */ -typedef struct -{ - CONTROLLER_T *CtlP; - int AiopNum; - int ChanID; - int ChanNum; - - ByteIO_t Cmd; - ByteIO_t IntChan; - ByteIO_t IntMask; - DWordIO_t IndexAddr; - WordIO_t IndexData; - - WordIO_t TxRxData; - WordIO_t ChanStat; - WordIO_t TxRxCount; - ByteIO_t IntID; - - Word_t TxFIFO; - Word_t TxFIFOPtrs; - Word_t RxFIFO; - Word_t RxFIFOPtrs; - Word_t TxPrioCnt; - Word_t TxPrioPtr; - Word_t TxPrioBuf; - - Byte_t R[RREGDATASIZE]; - - Byte_t BaudDiv[4]; - Byte_t TxControl[4]; - Byte_t RxControl[4]; - Byte_t TxEnables[4]; - Byte_t TxCompare[4]; - Byte_t TxReplace1[4]; - Byte_t TxReplace2[4]; -} CHANNEL_T; - -typedef CHANNEL_T CHANNEL_t; -typedef CHANNEL_T * CHANPTR_T; - -/*************************************************************************** -Function: sClrBreak -Purpose: Stop sending a transmit BREAK signal -Call: sClrBreak(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrBreak(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SETBREAK; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sClrDTR -Purpose: Clr the DTR output -Call: sClrDTR(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrDTR(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SET_DTR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sClrRTS -Purpose: Clr the RTS output -Call: sClrRTS(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrRTS(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sClrTxXOFF -Purpose: Clear any existing transmit software flow control off condition -Call: sClrTxXOFF(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrTxXOFF(ChP) \ -{ \ - sOutB((ChP)->Cmd,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \ - sOutB((ChP)->Cmd,(Byte_t)(ChP)->ChanNum); \ -} - -/*************************************************************************** -Function: sCtlNumToCtlPtr -Purpose: Convert a controller number to controller structure pointer -Call: sCtlNumToCtlPtr(CtlNum) - int CtlNum; Controller number -Return: CONTROLLER_T *: Ptr to controller structure -*/ -#define sCtlNumToCtlPtr(CTLNUM) &sController[CTLNUM] - -/*************************************************************************** -Function: sControllerEOI -Purpose: Strobe the MUDBAC's End Of Interrupt bit. -Call: sControllerEOI(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -*/ -#define sControllerEOI(CTLP) sOutB((CTLP)->MReg2IO,(CTLP)->MReg2 | INT_STROB) - - -/*************************************************************************** -Function: sPCIControllerEOI -Purpose: Strobe the MUDBAC's End Of Interrupt bit. -Call: sPCIControllerEOI(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -*/ -#define sPCIControllerEOI(CTLP) sOutW((CTLP)->PCIIO, PCI_STROB) - -/*************************************************************************** -Function: sDisAiop -Purpose: Disable I/O access to an AIOP -Call: sDisAiop(CltP) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; Number of AIOP on controller -*/ -#define sDisAiop(CTLP,AIOPNUM) \ -{ \ - (CTLP)->MReg3 &= sBitMapClrTbl[AIOPNUM]; \ - sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \ -} - -/*************************************************************************** -Function: sDisCTSFlowCtl -Purpose: Disable output flow control using CTS -Call: sDisCTSFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisCTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~CTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: DisParity -Purpose: Disable parity -Call: sDisParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). -*/ -#define sDisParity(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~PARITY_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sDisRxFIFO -Purpose: Disable Rx FIFO -Call: sDisRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisRxFIFO(ChP) \ -{ \ - (ChP)->R[0x32] = 0x0a; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x30]); \ -} - -/*************************************************************************** -Function: sDisRxStatusMode -Purpose: Disable the Rx status mode -Call: sDisRxStatusMode(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This takes the channel out of the receive status mode. All - subsequent reads of receive data using sReadRxWord() will return - two data bytes. -*/ -#define sDisRxStatusMode(ChP) sOutW((ChP)->ChanStat,0) - -/*************************************************************************** -Function: sDisTransmit -Purpose: Disable transmit -Call: sDisTransmit(ChP) - CHANNEL_T *ChP; Ptr to channel structure - This disables movement of Tx data from the Tx FIFO into the 1 byte - Tx buffer. Therefore there could be up to a 2 byte latency - between the time sDisTransmit() is called and the transmit buffer - and transmit shift register going completely empty. -*/ -#define sDisTransmit(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~TX_ENABLE; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sDisTxSoftFlowCtl -Purpose: Disable Tx Software Flow Control -Call: sDisTxSoftFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisTxSoftFlowCtl(ChP) \ -{ \ - (ChP)->R[0x06] = 0x8a; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x04]); \ -} - -/*************************************************************************** -Function: sEnAiop -Purpose: Enable I/O access to an AIOP -Call: sEnAiop(CltP) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; Number of AIOP on controller -*/ -#define sEnAiop(CTLP,AIOPNUM) \ -{ \ - (CTLP)->MReg3 |= sBitMapSetTbl[AIOPNUM]; \ - sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \ -} - -/*************************************************************************** -Function: sEnCTSFlowCtl -Purpose: Enable output flow control using CTS -Call: sEnCTSFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnCTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] |= CTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: EnParity -Purpose: Enable parity -Call: sEnParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: Before enabling parity odd or even parity should be chosen using - functions sSetOddParity() or sSetEvenParity(). -*/ -#define sEnParity(ChP) \ -{ \ - (ChP)->TxControl[2] |= PARITY_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sEnRTSFlowCtl -Return: void -*/ -#define sEnRTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~RTSTOG_EN; \ - (ChP)->TxControl[3] &= ~SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ - (ChP)->RxControl[2] |= RTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ -} - -/*************************************************************************** -Function: sDisRTSFlowCtl -Return: void -*/ -#define sDisRTSFlowCtl(ChP) \ -{ \ - (ChP)->RxControl[2] &= ~RTSFC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ -} - -/*************************************************************************** -Function: sEnRxFIFO -Purpose: Enable Rx FIFO -Call: sEnRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnRxFIFO(ChP) \ -{ \ - (ChP)->R[0x32] = 0x08; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0x30]); \ -} - -/*************************************************************************** -Function: sEnRxProcessor -Purpose: Enable the receive processor -Call: sEnRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function is used to start the receive processor. When - the channel is in the reset state the receive processor is not - running. This is done to prevent the receive processor from - executing invalid microcode instructions prior to the - downloading of the microcode. - -Warnings: This function must be called after valid microcode has been - downloaded to the AIOP, and it must not be called before the - microcode has been downloaded. -*/ -#define sEnRxProcessor(ChP) \ -{ \ - (ChP)->RxControl[2] |= RXPROC_EN; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ -} - -/*************************************************************************** -Function: sEnRxStatusMode -Purpose: Enable the Rx status mode -Call: sEnRxStatusMode(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This places the channel in the receive status mode. All subsequent - reads of receive data using sReadRxWord() will return a data byte - in the low word and a status byte in the high word. - -*/ -#define sEnRxStatusMode(ChP) sOutW((ChP)->ChanStat,STATMODE) - -/*************************************************************************** -Function: sEnTransmit -Purpose: Enable transmit -Call: sEnTransmit(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnTransmit(ChP) \ -{ \ - (ChP)->TxControl[3] |= TX_ENABLE; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sGetAiopIntStatus -Purpose: Get the AIOP interrupt status -Call: sGetAiopIntStatus(CtlP,AiopNum) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; AIOP number -Return: Byte_t: The AIOP interrupt status. Bits 0 through 7 - represent channels 0 through 7 respectively. If a - bit is set that channel is interrupting. -*/ -#define sGetAiopIntStatus(CTLP,AIOPNUM) sInB((CTLP)->AiopIntChanIO[AIOPNUM]) - -/*************************************************************************** -Function: sGetAiopNumChan -Purpose: Get the number of channels supported by an AIOP -Call: sGetAiopNumChan(CtlP,AiopNum) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; AIOP number -Return: int: The number of channels supported by the AIOP -*/ -#define sGetAiopNumChan(CTLP,AIOPNUM) (CTLP)->AiopNumChan[AIOPNUM] - -/*************************************************************************** -Function: sGetChanIntID -Purpose: Get a channel's interrupt identification byte -Call: sGetChanIntID(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The channel interrupt ID. Can be any - combination of the following flags: - RXF_TRIG: Rx FIFO trigger level interrupt - TXFIFO_MT: Tx FIFO empty interrupt - SRC_INT: Special receive condition interrupt - DELTA_CD: CD change interrupt - DELTA_CTS: CTS change interrupt - DELTA_DSR: DSR change interrupt -*/ -#define sGetChanIntID(ChP) (sInB((ChP)->IntID) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR)) - -/*************************************************************************** -Function: sGetChanNum -Purpose: Get the number of a channel within an AIOP -Call: sGetChanNum(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: int: Channel number within AIOP, or NULLCHAN if channel does - not exist. -*/ -#define sGetChanNum(ChP) (ChP)->ChanNum - -/*************************************************************************** -Function: sGetChanStatus -Purpose: Get the channel status -Call: sGetChanStatus(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Word_t: The channel status. Can be any combination of - the following flags: - LOW BYTE FLAGS - CTS_ACT: CTS input asserted - DSR_ACT: DSR input asserted - CD_ACT: CD input asserted - TXFIFOMT: Tx FIFO is empty - TXSHRMT: Tx shift register is empty - RDA: Rx data available - - HIGH BYTE FLAGS - STATMODE: status mode enable bit - RXFOVERFL: receive FIFO overflow - RX2MATCH: receive compare byte 2 match - RX1MATCH: receive compare byte 1 match - RXBREAK: received BREAK - RXFRAME: received framing error - RXPARITY: received parity error -Warnings: This function will clear the high byte flags in the Channel - Status Register. -*/ -#define sGetChanStatus(ChP) sInW((ChP)->ChanStat) - -/*************************************************************************** -Function: sGetChanStatusLo -Purpose: Get the low byte only of the channel status -Call: sGetChanStatusLo(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The channel status low byte. Can be any combination - of the following flags: - CTS_ACT: CTS input asserted - DSR_ACT: DSR input asserted - CD_ACT: CD input asserted - TXFIFOMT: Tx FIFO is empty - TXSHRMT: Tx shift register is empty - RDA: Rx data available -*/ -#define sGetChanStatusLo(ChP) sInB((ByteIO_t)(ChP)->ChanStat) - -/*************************************************************************** -Function: sGetControllerIntStatus -Purpose: Get the controller interrupt status -Call: sGetControllerIntStatus(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -Return: Byte_t: The controller interrupt status in the lower 4 - bits. Bits 0 through 3 represent AIOP's 0 - through 3 respectively. If a bit is set that - AIOP is interrupting. Bits 4 through 7 will - always be cleared. -*/ -#define sGetControllerIntStatus(CTLP) (sInB((CTLP)->MReg1IO) & 0x0f) - -/*************************************************************************** -Function: sPCIGetControllerIntStatus -Purpose: Get the controller interrupt status -Call: sPCIGetControllerIntStatus(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -Return: Byte_t: The controller interrupt status in the lower 4 - bits. Bits 0 through 3 represent AIOP's 0 - through 3 respectively. If a bit is set that - AIOP is interrupting. Bits 4 through 7 will - always be cleared. -*/ -#define sPCIGetControllerIntStatus(CTLP) ((sInW((CTLP)->PCIIO) >> 8) & 0x1f) - -/*************************************************************************** -Function: sGetRxCnt -Purpose: Get the number of data bytes in the Rx FIFO -Call: sGetRxCnt(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: int: The number of data bytes in the Rx FIFO. -Comments: Byte read of count register is required to obtain Rx count. - -*/ -#define sGetRxCnt(ChP) sInW((ChP)->TxRxCount) - -/*************************************************************************** -Function: sGetTxCnt -Purpose: Get the number of data bytes in the Tx FIFO -Call: sGetTxCnt(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The number of data bytes in the Tx FIFO. -Comments: Byte read of count register is required to obtain Tx count. - -*/ -#define sGetTxCnt(ChP) sInB((ByteIO_t)(ChP)->TxRxCount) - -/***************************************************************************** -Function: sGetTxRxDataIO -Purpose: Get the I/O address of a channel's TxRx Data register -Call: sGetTxRxDataIO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: WordIO_t: I/O address of a channel's TxRx Data register -*/ -#define sGetTxRxDataIO(ChP) (ChP)->TxRxData - -/*************************************************************************** -Function: sInitChanDefaults -Purpose: Initialize a channel structure to its default state. -Call: sInitChanDefaults(ChP) - CHANNEL_T *ChP; Ptr to the channel structure -Comments: This function must be called once for every channel structure - that exists before any other SSCI calls can be made. - -*/ -#define sInitChanDefaults(ChP) \ -{ \ - (ChP)->CtlP = NULLCTLPTR; \ - (ChP)->AiopNum = NULLAIOP; \ - (ChP)->ChanID = AIOPID_NULL; \ - (ChP)->ChanNum = NULLCHAN; \ -} - -/*************************************************************************** -Function: sResetAiopByNum -Purpose: Reset the AIOP by number -Call: sResetAiopByNum(CTLP,AIOPNUM) - CONTROLLER_T CTLP; Ptr to controller structure - AIOPNUM; AIOP index -*/ -#define sResetAiopByNum(CTLP,AIOPNUM) \ -{ \ - sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,RESET_ALL); \ - sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,0x0); \ -} - -/*************************************************************************** -Function: sSendBreak -Purpose: Send a transmit BREAK signal -Call: sSendBreak(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSendBreak(ChP) \ -{ \ - (ChP)->TxControl[3] |= SETBREAK; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sSetBaud -Purpose: Set baud rate -Call: sSetBaud(ChP,Divisor) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Divisor; 16 bit baud rate divisor for channel -*/ -#define sSetBaud(ChP,DIVISOR) \ -{ \ - (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \ - (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->BaudDiv[0]); \ -} - -/*************************************************************************** -Function: sSetData7 -Purpose: Set data bits to 7 -Call: sSetData7(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetData7(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~DATA8BIT; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sSetData8 -Purpose: Set data bits to 8 -Call: sSetData8(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetData8(ChP) \ -{ \ - (ChP)->TxControl[2] |= DATA8BIT; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sSetDTR -Purpose: Set the DTR output -Call: sSetDTR(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetDTR(ChP) \ -{ \ - (ChP)->TxControl[3] |= SET_DTR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sSetEvenParity -Purpose: Set even parity -Call: sSetEvenParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: This function has no effect unless parity is enabled with function - sEnParity(). -*/ -#define sSetEvenParity(ChP) \ -{ \ - (ChP)->TxControl[2] |= EVEN_PAR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sSetOddParity -Purpose: Set odd parity -Call: sSetOddParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: This function has no effect unless parity is enabled with function - sEnParity(). -*/ -#define sSetOddParity(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~EVEN_PAR; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sSetRTS -Purpose: Set the RTS output -Call: sSetRTS(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetRTS(ChP) \ -{ \ - (ChP)->TxControl[3] |= SET_RTS; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sSetRxTrigger -Purpose: Set the Rx FIFO trigger level -Call: sSetRxProcessor(ChP,Level) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Level; Number of characters in Rx FIFO at which the - interrupt will be generated. Can be any of the following flags: - - TRIG_NO: no trigger - TRIG_1: 1 character in FIFO - TRIG_1_2: FIFO 1/2 full - TRIG_7_8: FIFO 7/8 full -Comments: An interrupt will be generated when the trigger level is reached - only if function sEnInterrupt() has been called with flag - RXINT_EN set. The RXF_TRIG flag in the Interrupt Idenfification - register will be set whenever the trigger level is reached - regardless of the setting of RXINT_EN. - -*/ -#define sSetRxTrigger(ChP,LEVEL) \ -{ \ - (ChP)->RxControl[2] &= ~TRIG_MASK; \ - (ChP)->RxControl[2] |= LEVEL; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->RxControl[0]); \ -} - -/*************************************************************************** -Function: sSetStop1 -Purpose: Set stop bits to 1 -Call: sSetStop1(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetStop1(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~STOP2; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sSetStop2 -Purpose: Set stop bits to 2 -Call: sSetStop2(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetStop2(ChP) \ -{ \ - (ChP)->TxControl[2] |= STOP2; \ - sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->TxControl[0]); \ -} - -/*************************************************************************** -Function: sStartRxProcessor -Purpose: Start a channel's receive processor -Call: sStartRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function is used to start a Rx processor after it was - stopped with sStopRxProcessor() or sStopSWInFlowCtl(). It - will restart both the Rx processor and software input flow control. - -*/ -#define sStartRxProcessor(ChP) sOutDW((ChP)->IndexAddr,*(DWord_t *)&(ChP)->R[0]) - -/*************************************************************************** -Function: sWriteTxByte -Purpose: Write a transmit data byte to a channel. - ByteIO_t io: Channel transmit register I/O address. This can - be obtained with sGetTxRxDataIO(). - Byte_t Data; The transmit data byte. -Warnings: This function writes the data byte without checking to see if - sMaxTxSize is exceeded in the Tx FIFO. -*/ -#define sWriteTxByte(IO,DATA) sOutB(IO,DATA) - -int sInitController( CONTROLLER_T *CtlP, - int CtlNum, - ByteIO_t MudbacIO, - ByteIO_t *AiopIOList, - int AiopIOListSize, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly); - -int sPCIInitController( CONTROLLER_T *CtlP, - int CtlNum, - ByteIO_t *AiopIOList, - int AiopIOListSize, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly); - -int sReadAiopID(ByteIO_t io); -int sReadAiopNumChan(WordIO_t io); -int sInitChan( CONTROLLER_T *CtlP, - CHANNEL_T *ChP, - int AiopNum, - int ChanNum); -Byte_t sGetRxErrStatus(CHANNEL_T *ChP); -void sStopRxProcessor(CHANNEL_T *ChP); -void sStopSWInFlowCtl(CHANNEL_T *ChP); -void sFlushRxFIFO(CHANNEL_T *ChP); -void sFlushTxFIFO(CHANNEL_T *ChP); -int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data); -void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags); -void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags); - -#ifndef ROCKET_C -extern Byte_t R[RDATASIZE]; -extern CONTROLLER_T sController[CTL_SIZE]; -extern Byte_t sIRQMap[16]; -extern Byte_t sBitMapClrTbl[8]; -extern Byte_t sBitMapSetTbl[8]; -#endif diff --git a/sys/dev/serial/rp2/rpvar.h b/sys/dev/serial/rp2/rpvar.h deleted file mode 100644 index 6c252ccd40..0000000000 --- a/sys/dev/serial/rp2/rpvar.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) Comtrol Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials prodided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/i386/isa/rpvar.h,v 1.1.6.1 2000/08/03 01:01:20 peter Exp $ - * $DragonFly: src/sys/dev/serial/rp2/Attic/rpvar.h,v 1.3 2004/09/19 01:55:07 dillon Exp $ - */ - -/* - * rpvar.h --- RocketPort data structure includes for FreeBSD - */ - -#define RP_UNIT(x) dv_unit(x) -#define RP_PORT(x) (minor(x) & 0x3f) -#define MAX_RP_PORTS 128 - - -struct rp_port { - struct tty * rp_tty; /* cross reference */ - -/* Initial state */ - struct termios it_in; - struct termios it_out; - -/* Lock state */ - struct termios lt_in; - struct termios lt_out; - -/* Nonzero if callout device is open */ - unsigned char active_out; - unsigned char state; /* state of dtr */ - -/* Time to hold DTR down on close */ - struct callout dtr_ch; - int dtr_wait; - int wopeners; /* processes waiting for DCD */ - - int rp_port; - int rp_flags; - int rp_unit:2; - int rp_aiop:2; - int rp_chan:3; - int rp_intmask; - int rp_imask; /* Input mask */ - int rp_fifo_lw; - int rp_restart; - int rp_overflows; - int rp_rts_iflow:1; - int rp_disable_writes:1; - int rp_cts:1; - int rp_waiting:1; - int rp_xmit_stopped:1; - CONTROLLER_t * rp_ctlp; - CHANNEL_t rp_channel; -}; - -struct termios deftermios = { - TTYDEF_IFLAG, - TTYDEF_OFLAG, - TTYDEF_CFLAG, - TTYDEF_LFLAG, - { CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT, - _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT, - CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE }, - TTYDEF_SPEED, - TTYDEF_SPEED -}; diff --git a/sys/dev/sound/isa/i386/dev_table.h b/sys/dev/sound/isa/i386/dev_table.h index f355163777..28fc5adcff 100644 --- a/sys/dev/sound/isa/i386/dev_table.h +++ b/sys/dev/sound/isa/i386/dev_table.h @@ -25,6 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * $DragonFly: src/sys/dev/sound/isa/i386/Attic/dev_table.h,v 1.2 2005/01/31 23:44:35 joerg Exp $ */ #ifndef _DEV_TABLE_H_ @@ -356,10 +357,6 @@ struct driver_info sound_drivers[] = { {"SB16", 0, SNDCARD_SB16, "SoundBlaster16", sb16_dsp_init, sb16_dsp_detect}, #endif -#ifdef CONFIG_AWE32 - {"AWE32", 0, SNDCARD_AWE32, "AWE32 Synth", - attach_awe, probe_awe}, -#endif #ifdef CONFIG_MIDI {"SB16MIDI", 0, SNDCARD_SB16MIDI, "SB16 MIDI", attach_sb16midi, probe_sb16midi}, diff --git a/sys/dev/sound/isa/i386/sound_calls.h b/sys/dev/sound/isa/i386/sound_calls.h index 7f96317da4..7ef2595c73 100644 --- a/sys/dev/sound/isa/i386/sound_calls.h +++ b/sys/dev/sound/isa/i386/sound_calls.h @@ -1,3 +1,5 @@ +/* $DragonFly: src/sys/dev/sound/isa/i386/Attic/sound_calls.h,v 1.2 2005/01/31 23:44:35 joerg Exp $ */ + /* * DMA buffer calls */ @@ -130,10 +132,6 @@ void opl3_init(int ioaddr, sound_os_info *osp); void attach_sb_card(struct address_info *hw_config); int probe_sb(struct address_info *hw_config); -/* From awe_wave.c */ -void attach_awe(struct address_info *hw_config); -int probe_awe(struct address_info *hw_config); - /* From adlib_card.c */ void attach_adlib_card(struct address_info *hw_config); int probe_adlib(struct address_info *hw_config); diff --git a/sys/dev/sound/isa/i386/soundcard.c b/sys/dev/sound/isa/i386/soundcard.c index 7b12c5c581..086f1208cb 100644 --- a/sys/dev/sound/isa/i386/soundcard.c +++ b/sys/dev/sound/isa/i386/soundcard.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/isa/sound/soundcard.c,v 1.87 1999/12/20 18:05:01 eivind Exp $ - * $DragonFly: src/sys/dev/sound/isa/i386/Attic/soundcard.c,v 1.7 2004/05/19 22:52:50 dillon Exp $ + * $DragonFly: src/sys/dev/sound/isa/i386/Attic/soundcard.c,v 1.8 2005/01/31 23:44:35 joerg Exp $ * */ #include "use_snd.h" @@ -129,7 +129,6 @@ struct isa_driver trixsbdriver = {sndprobe, sndattach, "trixsb"}; struct isa_driver sbdriver = {sndprobe, sndattach, "sb"}; struct isa_driver sbxvidriver = {sndprobe, sndattach, "sbxvi"}; struct isa_driver sbmididriver = {sndprobe, sndattach, "sbmidi"}; -struct isa_driver awedriver = {sndprobe, sndattach, "awe"}; struct isa_driver pasdriver = {sndprobe, sndattach, "pas"}; struct isa_driver mpudriver = {sndprobe, sndattach, "mpu"}; struct isa_driver gusdriver = {sndprobe, sndattach, "gus"}; @@ -316,8 +315,6 @@ driver_to_voxunit(struct isa_driver * driver) return (SNDCARD_SB16); else if (driver == &sbmididriver) return (SNDCARD_SB16MIDI); - else if(driver == &awedriver) - return(SNDCARD_AWE32); else if (driver == &uartdriver) return (SNDCARD_UART6850); else if (driver == &gusdriver) diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 5af0c49195..5c2ac527fe 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -3,7 +3,7 @@ # as much of the source tree as it can. # # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $ -# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.45 2005/01/10 19:37:23 joerg Exp $ +# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.46 2005/01/31 23:44:35 joerg Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -268,14 +268,8 @@ options CYRIX_CACHE_REALLY_WORKS # # A math emulator is mandatory if you wish to run on hardware which -# does not have a floating-point processor. Pick either the original, -# bogus (but freely-distributable) math emulator, or a much more -# fully-featured but GPL-licensed emulator taken from Linux. -# +# does not have a floating-point processor. options MATH_EMULATE #Support for x87 emulation -# Don't enable both of these in a real config. -#options GPL_MATH_EMULATE #Support for x87 emulation via - #new math emulator ##################################################################### # COMPATIBILITY OPTIONS @@ -1537,7 +1531,6 @@ options NATM #native ATM #device sb0 at isa? port 0x220 irq 5 drq 1 #device sbxvi0 at isa? drq 5 #device sbmidi0 at isa? port 0x330 -#device awe0 at isa? port 0x620 #device gus0 at isa? port 0x220 irq 12 drq 1 ##device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 #device mss0 at isa? port 0x530 irq 10 drq 1 @@ -2084,15 +2077,10 @@ options BKTR_NEW_MSP34XX_DRIVER # PCCARD/PCMCIA # # pccard: pccard slots -# pcic: isa/pccard bridge (OLDCARD) -# cardbus/cbb: cardbus bridge (NEWCARD) +# cardbus/cbb: cardbus bridge device pccard device cardbus device cbb -#device pcic - -# You may need to reset all pccards after resuming -options PCIC_RESUME_RESET # reset after resume # # Laptop/Notebook options: diff --git a/sys/i386/gnu/fpemul/Changelog b/sys/i386/gnu/fpemul/Changelog deleted file mode 100644 index b678e15d8b..0000000000 --- a/sys/i386/gnu/fpemul/Changelog +++ /dev/null @@ -1,39 +0,0 @@ -$FreeBSD: src/sys/gnu/i386/fpemul/Changelog,v 1.1.20.1 2000/08/03 00:53:55 peter Exp $ -$DragonFly: src/sys/i386/gnu/fpemul/Attic/Changelog,v 1.2 2003/06/17 04:28:34 dillon Exp $ - -This file contains the changes made to W. Metzenthem's 387 FPU -emulator to make it work under NetBSD. - -a, Changes to make it compile: - - 1 - Changed the #include's to get the appropriate .h files. - 2 - Renamed .S to .s, to satisfy the kernel Makefile. - 3 - Changed the C++ style // comments to /* */ - 4 - Changed the FPU_ORIG_EIP macro. A letter from bde included - in the package suggested using tf_isp for using instead - of the linux __orig_eip. This later turned out to interfere - with the user stack, so i created a separate variable, stored - in the i387_union. - 5 - Changed the get_fs_.. put_fs_.. fns to fubyte,fuword,subyte, - suword. - 6 - Removed the verify_area fns. I don't really know what they do, - i suppose they verify access to memory. The sufu routines - should do this. - -b, Changes to make it work: - - 1 - Made math_emulate() to return 0 when successful, so trap() won't - try to generate a signal. - 2 - Changed the size of the save87 struct in /sys/arch/i387/include/ - npx.h to accomodate the i387_union. - -d, Other changes: - - 1 - Removed obsolate and/or linux specific stuff. - 2 - Changed the RE_ENTRANT_CHECK_[ON|OFF] macro to - REENTRANT_CHECK([ON|OFF]) so indent can grok it. - 3 - Re-indented to Berkeley style. - 4 - Limited max no of lookaheads. LOOKAHEAD_LIMIT in fpu_entry.c - - - Szabolcs Szigeti (pink@fsz.bme.hu) diff --git a/sys/i386/gnu/fpemul/README b/sys/i386/gnu/fpemul/README deleted file mode 100644 index 6233ca6bc5..0000000000 --- a/sys/i386/gnu/fpemul/README +++ /dev/null @@ -1,279 +0,0 @@ -/* - * wm-FPU-emu an FPU emulator for 80386 and 80486SX microprocessors. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD: src/sys/gnu/i386/fpemul/README,v 1.2.20.1 2000/08/03 00:53:55 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/README,v 1.2 2003/06/17 04:28:34 dillon Exp $ - */ - -wm-FPU-emu is an FPU emulator for Linux. It is derived from wm-emu387 -which is my 80387 emulator for djgpp (gcc under msdos); wm-emu387 was -in turn based upon emu387 which was written by DJ Delorie for djgpp. -The interface to the Linux kernel is based upon the original Linux -math emulator by Linus Torvalds. - -My target FPU for wm-FPU-emu is that described in the Intel486 -Programmer's Reference Manual (1992 edition). Numerous facets of the -functioning of the FPU are not well covered in the Reference Manual; -in the absence of clear details I have made guesses about the most -reasonable behaviour. Recently, this situation has improved because -I now have some access to the results produced by a real 80486 FPU. - -wm-FPU-emu does not implement all of the behaviour of the 80486 FPU. -See "Limitations" later in this file for a partial list of some -differences. I believe that the missing features are never used by -normal C or FORTRAN programs. - - -Please report bugs, etc to me at: - apm233m@vaxc.cc.monash.edu.au - - ---Bill Metzenthen - May 1993 - - ------------------------ Internals of wm-FPU-emu ----------------------- - -Numeric algorithms: -(1) Add, subtract, and multiply. Nothing remarkable in these. -(2) Divide has been tuned to get reasonable performance. The algorithm - is not the obvious one which most people seem to use, but is designed - to take advantage of the characteristics of the 80386. I expect that - it has been invented many times before I discovered it, but I have not - seen it. It is based upon one of those ideas which one carries around - for years without ever bothering to check it out. -(3) The sqrt function has been tuned to get good performance. It is based - upon Newton's classic method. Performance was improved by capitalizing - upon the properties of Newton's method, and the code is once again - structured taking account of the 80386 characteristics. -(4) The trig, log, and exp functions are based in each case upon quasi- - "optimal" polynomial approximations. My definition of "optimal" was - based upon getting good accuracy with reasonable speed. - -The code of the emulator is complicated slightly by the need to -account for a limited form of re-entrancy. Normally, the emulator will -emulate each FPU instruction to completion without interruption. -However, it may happen that when the emulator is accessing the user -memory space, swapping may be needed. In this case the emulator may be -temporarily suspended while disk i/o takes place. During this time -another process may use the emulator, thereby changing some static -variables (eg FPU_st0_ptr, etc). The code which accesses user memory -is confined to five files: - fpu_entry.c - reg_ld_str.c - load_store.c - get_address.c - errors.c - ------------------------ Limitations of wm-FPU-emu ----------------------- - -There are a number of differences between the current wm-FPU-emu -(version beta 1.4) and the 80486 FPU (apart from bugs). Some of the -more important differences are listed below: - -All internal computations are performed at 64 bit or higher precision -and rounded etc as required by the PC bits of the FPU control word. -Under the crt0 version for Linux current at March 1993, the FPU PC -bits specify 53 bits precision. - -The precision flag (PE of the FPU status word) and the Roundup flag -(C1 of the status word) are now partially implemented. Does anyone -write code which uses these features? - -The functions which load/store the FPU state are partially implemented, -but the implementation should be sufficient for handling FPU errors etc -in 32 bit protected mode. - -The implementation of the exception mechanism is flawed for unmasked -interrupts. - -Detection of certain conditions, such as denormal operands, is not yet -complete. - ------------------------ Performance of wm-FPU-emu ----------------------- - -Speed. ------ - -The speed of floating point computation with the emulator will depend -upon instruction mix. Relative performance is best for the instructions -which require most computation. The simple instructions are adversely -affected by the fpu instruction trap overhead. - - -Timing: Some simple timing tests have been made on the emulator functions. -The times include load/store instructions. All times are in microseconds -measured on a 33MHz 386 with 64k cache. The Turbo C tests were under -ms-dos, the next two columns are for emulators running with the djgpp -ms-dos extender. The final column is for wm-FPU-emu in Linux 0.97, -using libm4.0 (hard). - -function Turbo C djgpp 1.06 WM-emu387 wm-FPU-emu - - + 60.5 154.8 76.5 139.4 - - 61.1-65.5 157.3-160.8 76.2-79.5 142.9-144.7 - * 71.0 190.8 79.6 146.6 - / 61.2-75.0 261.4-266.9 75.3-91.6 142.2-158.1 - - sin() 310.8 4692.0 319.0 398.5 - cos() 284.4 4855.2 308.0 388.7 - tan() 495.0 8807.1 394.9 504.7 - atan() 328.9 4866.4 601.1 419.5-491.9 - - sqrt() 128.7 crashed 145.2 227.0 - log() 413.1-419.1 5103.4-5354.21 254.7-282.2 409.4-437.1 - exp() 479.1 6619.2 469.1 850.8 - - -The performance under Linux is improved by the use of look-ahead code. -The following results show the improvement which is obtained under -Linux due to the look-ahead code. Also given are the times for the -original Linux emulator with the 4.1 'soft' lib. - - [ Linus' note: I changed look-ahead to be the default under linux, as - there was no reason not to use it after I had edited it to be - disabled during tracing ] - - wm-FPU-emu w original w - look-ahead 'soft' lib - + 106.4 190.2 - - 108.6-111.6 192.4-216.2 - * 113.4 193.1 - / 108.8-124.4 700.1-706.2 - - sin() 390.5 2642.0 - cos() 381.5 2767.4 - tan() 496.5 3153.3 - atan() 367.2-435.5 2439.4-3396.8 - - sqrt() 195.1 4732.5 - log() 358.0-387.5 3359.2-3390.3 - exp() 619.3 4046.4 - - -These figures are now somewhat out-of-date. The emulator has become -progressively slower for most functions as more of the 80486 features -have been implemented. - - ------------------------ Accuracy of wm-FPU-emu ----------------------- - - -Accuracy: The following table gives the accuracy of the sqrt(), trig -and log functions. Each function was tested at about 400 points. Ideal -results would be 64 bits. The reduced accuracy of cos() and tan() for -arguments greater than pi/4 can be thought of as being due to the -precision of the argument x; e.g. an argument of pi/2-(1e-10) which is -accurate to 64 bits can result in a relative accuracy in cos() of about -64 + log2(cos(x)) = 31 bits. Results for the Turbo C emulator are given -in the last column. - - -Function Tested x range Worst result (bits) Turbo C - -sqrt(x) 1 .. 2 64.1 63.2 -atan(x) 1e-10 .. 200 62.6 62.8 -cos(x) 0 .. pi/2-(1e-10) 63.2 (x <= pi/4) 62.4 - 35.2 (x = pi/2-(1e-10)) 31.9 -sin(x) 1e-10 .. pi/2 63.0 62.8 -tan(x) 1e-10 .. pi/2-(1e-10) 62.4 (x <= pi/4) 62.1 - 35.2 (x = pi/2-(1e-10)) 31.9 -exp(x) 0 .. 1 63.1 62.9 -log(x) 1+1e-6 .. 2 62.4 62.1 - - -As of version 1.3 of the emulator, the accuracy of the basic -arithmetic has been improved (by a small fraction of a bit). Care has -been taken to ensure full accuracy of the rounding of the basic -arithmetic functions (+,-,*,/,and fsqrt), and they all now produce -results which are exact to the 64th bit (unless there are any bugs -left). To ensure this, it was necessary to effectively get information -of up to about 128 bits precision. The emulator now passes the -"paranoia" tests (compiled with gcc 2.3.3) for 'float' variables (24 -bit precision numbers) when precision control is set to 24, 53 or 64 -bits, and for 'double' variables (53 bit precision numbers) when -precision control is set to 53 bits (a properly performing FPU cannot -pass the 'paranoia' tests for 'double' variables when precision -control is set to 64 bits). - -------------------------- Contributors ------------------------------- - -A number of people have contributed to the development of the -emulator, often by just reporting bugs, sometimes with a suggested -fix, and a few kind people have provided me with access in one way or -another to an 80486 machine. Contributors include (to those people who -I have forgotten, please excuse me): - -Linus Torvalds -Tommy.Thorn@daimi.aau.dk -Andrew.Tridgell@anu.edu.au -Nick Holloway alfie@dcs.warwick.ac.uk -Hermano Moura moura@dcs.gla.ac.uk -Jon Jagger J.Jagger@scp.ac.uk -Lennart Benschop -Brian Gallew geek+@CMU.EDU -Thomas Staniszewski ts3v+@andrew.cmu.edu -Martin Howell mph@plasma.apana.org.au -M Saggaf alsaggaf@athena.mit.edu -Peter Barker PETER@socpsy.sci.fau.edu -tom@vlsivie.tuwien.ac.at -Dan Russel russed@rpi.edu -Daniel Carosone danielce@ee.mu.oz.au -cae@jpmorgan.com -Hamish Coleman t933093@minyos.xx.rmit.oz.au - -...and numerous others who responded to my request for help with -a real 80486. - diff --git a/sys/i386/gnu/fpemul/control_w.h b/sys/i386/gnu/fpemul/control_w.h deleted file mode 100644 index 85c3bb6064..0000000000 --- a/sys/i386/gnu/fpemul/control_w.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * control_w.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/control_w.h,v 1.7 1999/08/28 00:42:48 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/control_w.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - -#ifndef _CONTROLW_H_ -#define _CONTROLW_H_ - -#ifdef LOCORE -#define _Const_(x) $/**/x -#else -#define _Const_(x) x -#endif - -#define CW_RC _Const_(0x0C00) /* rounding control */ -#define CW_PC _Const_(0x0300) /* precision control */ - -#define CW_Precision Const_(0x0020) /* loss of precision mask */ -#define CW_Underflow Const_(0x0010) /* underflow mask */ -#define CW_Overflow Const_(0x0008) /* overflow mask */ -#define CW_ZeroDiv Const_(0x0004) /* divide by zero mask */ -#define CW_Denormal Const_(0x0002) /* denormalized operand mask */ -#define CW_Invalid Const_(0x0001) /* invalid operation mask */ - -#define CW_Exceptions _Const_(0x003f) /* all masks */ - -#define RC_RND _Const_(0x0000) -#define RC_DOWN _Const_(0x0400) -#define RC_UP _Const_(0x0800) -#define RC_CHOP _Const_(0x0C00) - -/* p 15-5: Precision control bits affect only the following: - ADD, SUB(R), MUL, DIV(R), and SQRT */ -#define PR_24_BITS _Const_(0x000) -#define PR_53_BITS _Const_(0x200) -#define PR_64_BITS _Const_(0x300) -/* FULL_PRECISION simulates all exceptions masked */ -#define FULL_PRECISION (PR_64_BITS | RC_RND | 0x3f) - -#endif /* _CONTROLW_H_ */ diff --git a/sys/i386/gnu/fpemul/div_small.s b/sys/i386/gnu/fpemul/div_small.s deleted file mode 100644 index a1eff2bbaf..0000000000 --- a/sys/i386/gnu/fpemul/div_small.s +++ /dev/null @@ -1,98 +0,0 @@ - .file "div_small.S" -/* - * div_small.S - * - * Divide a 64 bit integer by a 32 bit integer & return remainder. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/div_small.s,v 1.8 1999/08/28 00:42:48 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/div_small.s,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | unsigned long div_small(unsigned long long *x, unsigned long y) | - +---------------------------------------------------------------------------*/ - -#include "fpu_asm.h" - -.text -ENTRY(div_small) - pushl %ebp - movl %esp,%ebp - - pushl %esi - - movl PARAM1,%esi /* pointer to num */ - movl PARAM2,%ecx /* The denominator */ - - movl 4(%esi),%eax /* Get the current num msw */ - xorl %edx,%edx - divl %ecx - - movl %eax,4(%esi) - - movl (%esi),%eax /* Get the num lsw */ - divl %ecx - - movl %eax,(%esi) - - movl %edx,%eax /* Return the remainder in eax */ - - popl %esi - - leave - ret - diff --git a/sys/i386/gnu/fpemul/errors.c b/sys/i386/gnu/fpemul/errors.c deleted file mode 100644 index 1c23787d9d..0000000000 --- a/sys/i386/gnu/fpemul/errors.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * errors.c - * - * The error handling functions for wm-FPU-emu - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/errors.c,v 1.10 1999/08/28 00:42:49 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/errors.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - - - - - -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" -#include "control_w.h" -#include "reg_constant.h" -#include "version.h" - -/* */ -#undef PRINT_MESSAGES -/* */ - - -void -Un_impl(void) -{ - unsigned char byte1, FPU_modrm; - - REENTRANT_CHECK(OFF); - byte1 = fubyte((unsigned char *) FPU_ORIG_EIP); - FPU_modrm = fubyte(1 + (unsigned char *) FPU_ORIG_EIP); - - printf("Unimplemented FPU Opcode at eip=%#08x : %02x ", - FPU_ORIG_EIP, byte1); - - if (FPU_modrm >= 0300) - printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); - else - printf("/%d\n", (FPU_modrm >> 3) & 7); - REENTRANT_CHECK(ON); - - EXCEPTION(EX_Invalid); - -} - - - - -void -emu_printall() -{ - int i; - static char *tag_desc[] = {"Valid", "Zero", "ERROR", "ERROR", - "DeNorm", "Inf", "NaN", "Empty"}; - unsigned char byte1, FPU_modrm; - - REENTRANT_CHECK(OFF); - byte1 = fubyte((unsigned char *) FPU_ORIG_EIP); - FPU_modrm = fubyte(1 + (unsigned char *) FPU_ORIG_EIP); - -#ifdef DEBUGGING - if (status_word & SW_Backward) - printf("SW: backward compatibility\n"); - if (status_word & SW_C3) - printf("SW: condition bit 3\n"); - if (status_word & SW_C2) - printf("SW: condition bit 2\n"); - if (status_word & SW_C1) - printf("SW: condition bit 1\n"); - if (status_word & SW_C0) - printf("SW: condition bit 0\n"); - if (status_word & SW_Summary) - printf("SW: exception summary\n"); - if (status_word & SW_Stack_Fault) - printf("SW: stack fault\n"); - if (status_word & SW_Precision) - printf("SW: loss of precision\n"); - if (status_word & SW_Underflow) - printf("SW: underflow\n"); - if (status_word & SW_Overflow) - printf("SW: overflow\n"); - if (status_word & SW_Zero_Div) - printf("SW: divide by zero\n"); - if (status_word & SW_Denorm_Op) - printf("SW: denormalized operand\n"); - if (status_word & SW_Invalid) - printf("SW: invalid operation\n"); -#endif /* DEBUGGING */ - - status_word = status_word & ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - - printf("At %#08x: %02x ", FPU_ORIG_EIP, byte1); - if (FPU_modrm >= 0300) - printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); - else - printf("/%d, mod=%d rm=%d\n", - (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7); - - printf(" SW: b=%d st=%d es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", - status_word & 0x8000 ? 1 : 0, /* busy */ - (int)((status_word & 0x3800) >> 11), /* stack top pointer */ - status_word & 0x80 ? 1 : 0, /* Error summary status */ - status_word & 0x40 ? 1 : 0, /* Stack flag */ - status_word & SW_C3 ? 1 : 0, status_word & SW_C2 ? 1 : 0, /* cc */ - status_word & SW_C1 ? 1 : 0, status_word & SW_C0 ? 1 : 0, /* cc */ - status_word & SW_Precision ? 1 : 0, status_word & SW_Underflow ? 1 : 0, - status_word & SW_Overflow ? 1 : 0, status_word & SW_Zero_Div ? 1 : 0, - status_word & SW_Denorm_Op ? 1 : 0, status_word & SW_Invalid ? 1 : 0); - - printf(" CW: ic=%d rc=%d%d pc=%d%d iem=%d ef=%d%d%d%d%d%d\n", - control_word & 0x1000 ? 1 : 0, - (int)((control_word & 0x800) >> 11), - (int)((control_word & 0x400) >> 10), - (int)((control_word & 0x200) >> 9), - (int)((control_word & 0x100) >> 8), - control_word & 0x80 ? 1 : 0, - control_word & SW_Precision ? 1 : 0, control_word & SW_Underflow ? 1 : 0, - control_word & SW_Overflow ? 1 : 0, control_word & SW_Zero_Div ? 1 : 0, - control_word & SW_Denorm_Op ? 1 : 0, control_word & SW_Invalid ? 1 : 0); - - for (i = 0; i < 8; i++) { - FPU_REG *r = &st(i); - switch (r->tag) { - case TW_Empty: - continue; - break; - case TW_Zero: - printf("st(%d) %c .0000 0000 0000 0000 ", - i, r->sign ? '-' : '+'); - break; - case TW_Valid: - case TW_NaN: - case TW_Denormal: - case TW_Infinity: - printf("st(%d) %c .%04lx %04lx %04lx %04lx e%+-6ld ", - i, r->sign ? '-' : '+', r->sigh >> 16, - r->sigh & 0xFFFF, r->sigl >> 16, r->sigl & 0xFFFF, - r->exp - EXP_BIAS + 1); - break; - default: - printf("Whoops! Error in errors.c "); - break; - } - printf("%s\n", tag_desc[(int) (unsigned) r->tag]); - } - - printf("[data] %c .%04lx %04lx %04lx %04lx e%+-6ld ", - FPU_loaded_data.sign ? '-' : '+', FPU_loaded_data.sigh >> 16, - FPU_loaded_data.sigh & 0xFFFF, FPU_loaded_data.sigl >> 16, - FPU_loaded_data.sigl & 0xFFFF, FPU_loaded_data.exp - EXP_BIAS + 1); - printf("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]); - REENTRANT_CHECK(ON); - -} - -static struct { - int type; - char *name; -} exception_names[] = { - { - EX_StackOver, "stack overflow" - }, - { - EX_StackUnder, "stack underflow" - }, - { - EX_Precision, "loss of precision" - }, - { - EX_Underflow, "underflow" - }, - { - EX_Overflow, "overflow" - }, - { - EX_ZeroDiv, "divide by zero" - }, - { - EX_Denormal, "denormalized operand" - }, - { - EX_Invalid, "invalid operation" - }, - { - EX_INTERNAL, "INTERNAL BUG in " FPU_VERSION - }, - { - 0, NULL - } -}; -/* - EX_INTERNAL is always given with a code which indicates where the - error was detected. - - Internal error types: - 0x14 in e14.c - 0x1nn in a *.c file: - 0x101 in reg_add_sub.c - 0x102 in reg_mul.c - 0x103 in poly_sin.c - 0x104 in poly_tan.c - 0x105 in reg_mul.c - 0x106 in reg_mov.c - 0x107 in fpu_trig.c - 0x108 in reg_compare.c - 0x109 in reg_compare.c - 0x110 in reg_add_sub.c - 0x111 in interface.c - 0x112 in fpu_trig.c - 0x113 in reg_add_sub.c - 0x114 in reg_ld_str.c - 0x115 in fpu_trig.c - 0x116 in fpu_trig.c - 0x117 in fpu_trig.c - 0x118 in fpu_trig.c - 0x119 in fpu_trig.c - 0x120 in poly_atan.c - 0x121 in reg_compare.c - 0x122 in reg_compare.c - 0x123 in reg_compare.c - 0x2nn in an *.s file: - 0x201 in reg_u_add.S - 0x202 in reg_u_div.S - 0x203 in reg_u_div.S - 0x204 in reg_u_div.S - 0x205 in reg_u_mul.S - 0x206 in reg_u_sub.S - 0x207 in wm_sqrt.S - 0x208 in reg_div.S - 0x209 in reg_u_sub.S - 0x210 in reg_u_sub.S - 0x211 in reg_u_sub.S - 0x212 in reg_u_sub.S - 0x213 in wm_sqrt.S - 0x214 in wm_sqrt.S - 0x215 in wm_sqrt.S - 0x216 in reg_round.S - 0x217 in reg_round.S - 0x218 in reg_round.S - */ - -void -exception(int n) -{ - int i, int_type; - - int_type = 0; /* Needed only to stop compiler warnings */ - if (n & EX_INTERNAL) { - int_type = n - EX_INTERNAL; - n = EX_INTERNAL; - /* Set lots of exception bits! */ - status_word |= (SW_Exc_Mask | SW_Summary | FPU_BUSY); - } else { - /* Extract only the bits which we use to set the status word */ - n &= (SW_Exc_Mask); - /* Set the corresponding exception bit */ - status_word |= n; - if (status_word & ~control_word & CW_Exceptions) - status_word |= SW_Summary; - if (n & (SW_Stack_Fault | EX_Precision)) { - if (!(n & SW_C1)) - /* This bit distinguishes over- from underflow - * for a stack fault, and roundup from - * round-down for precision loss. */ - status_word &= ~SW_C1; - } - } - - REENTRANT_CHECK(OFF); - if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) { -#ifdef PRINT_MESSAGES - /* My message from the sponsor */ - printf(FPU_VERSION " " __DATE__ " (C) W. Metzenthen.\n"); -#endif /* PRINT_MESSAGES */ - - /* Get a name string for error reporting */ - for (i = 0; exception_names[i].type; i++) - if ((exception_names[i].type & n) == exception_names[i].type) - break; - - if (exception_names[i].type) { -#ifdef PRINT_MESSAGES - printf("FP Exception: %s!\n", exception_names[i].name); -#endif /* PRINT_MESSAGES */ - } else - printf("FP emulator: Unknown Exception: 0x%04x!\n", n); - - if (n == EX_INTERNAL) { - printf("FP emulator: Internal error type 0x%04x\n", int_type); - emu_printall(); - } -#ifdef PRINT_MESSAGES - else - emu_printall(); -#endif /* PRINT_MESSAGES */ - - /* The 80486 generates an interrupt on the next non-control - * FPU instruction. So we need some means of flagging it. We - * use the ES (Error Summary) bit for this, assuming that this - * is the way a real FPU does it (until I can check it out), - * if not, then some method such as the following kludge might - * be needed. */ -/* regs[0].tag |= TW_FPU_Interrupt; */ - } - REENTRANT_CHECK(ON); - -#ifdef __DEBUG__ - math_abort(SIGFPE); -#endif /* __DEBUG__ */ - -} - - -/* Real operation attempted on two operands, one a NaN */ -void -real_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest) -{ - FPU_REG *x; - int signalling; - - x = a; - if (a->tag == TW_NaN) { - if (b->tag == TW_NaN) { - signalling = !(a->sigh & b->sigh & 0x40000000); - /* find the "larger" */ - if (*(long long *) &(a->sigl) < *(long long *) &(b->sigl)) - x = b; - } else { - /* return the quiet version of the NaN in a */ - signalling = !(a->sigh & 0x40000000); - } - } else -#ifdef PARANOID - if (b->tag == TW_NaN) -#endif /* PARANOID */ - { - signalling = !(b->sigh & 0x40000000); - x = b; - } -#ifdef PARANOID - else { - signalling = 0; - EXCEPTION(EX_INTERNAL | 0x113); - x = &CONST_QNaN; - } -#endif /* PARANOID */ - - if (!signalling) { - if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ - x = &CONST_QNaN; - reg_move(x, dest); - return; - } - if (control_word & CW_Invalid) { - /* The masked response */ - if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ - x = &CONST_QNaN; - reg_move(x, dest); - /* ensure a Quiet NaN */ - dest->sigh |= 0x40000000; - } - EXCEPTION(EX_Invalid); - - return; -} -/* Invalid arith operation on Valid registers */ -void -arith_invalid(FPU_REG * dest) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, dest); - } - EXCEPTION(EX_Invalid); - - return; - -} - - -/* Divide a finite number by zero */ -void -divide_by_zero(int sign, FPU_REG * dest) -{ - - if (control_word & CW_ZeroDiv) { - /* The masked response */ - reg_move(&CONST_INF, dest); - dest->sign = (unsigned char) sign; - } - EXCEPTION(EX_ZeroDiv); - - return; - -} - - -/* This may be called often, so keep it lean */ -void -set_precision_flag_up(void) -{ - if (control_word & CW_Precision) - status_word |= (SW_Precision | SW_C1); /* The masked response */ - else - exception(EX_Precision | SW_C1); - -} - - -/* This may be called often, so keep it lean */ -void -set_precision_flag_down(void) -{ - if (control_word & CW_Precision) { /* The masked response */ - status_word &= ~SW_C1; - status_word |= SW_Precision; - } else - exception(EX_Precision); -} - - -int -denormal_operand(void) -{ - if (control_word & CW_Denormal) { /* The masked response */ - status_word |= SW_Denorm_Op; - return 0; - } else { - exception(EX_Denormal); - return 1; - } -} - - -void -arith_overflow(FPU_REG * dest) -{ - - if (control_word & CW_Overflow) { - char sign; - /* The masked response */ -/* **** The response here depends upon the rounding mode */ - sign = dest->sign; - reg_move(&CONST_INF, dest); - dest->sign = sign; - } else { - /* Subtract the magic number from the exponent */ - dest->exp -= (3 * (1 << 13)); - } - - /* By definition, precision is lost. It appears that the roundup bit - * (C1) is also set by convention. */ - EXCEPTION(EX_Overflow | EX_Precision | SW_C1); - - return; - -} - - -void -arith_underflow(FPU_REG * dest) -{ - - if (control_word & CW_Underflow) { - /* The masked response */ - if (dest->exp <= EXP_UNDER - 63) - reg_move(&CONST_Z, dest); - } else { - /* Add the magic number to the exponent */ - dest->exp += (3 * (1 << 13)); - } - - EXCEPTION(EX_Underflow); - - return; -} - - -void -stack_overflow(void) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - top--; - reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0)); - } - EXCEPTION(EX_StackOver); - - return; - -} - - -void -stack_underflow(void) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, FPU_st0_ptr); - } - EXCEPTION(EX_StackUnder); - - return; - -} - - -void -stack_underflow_i(int i) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, &(st(i))); - } - EXCEPTION(EX_StackUnder); - - return; - -} - - -void -stack_underflow_pop(int i) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, &(st(i))); - pop(); - } - EXCEPTION(EX_StackUnder); - - return; - -} diff --git a/sys/i386/gnu/fpemul/exception.h b/sys/i386/gnu/fpemul/exception.h deleted file mode 100644 index dde835cd97..0000000000 --- a/sys/i386/gnu/fpemul/exception.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * exception.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/exception.h,v 1.9 1999/08/28 00:42:49 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/exception.h,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - * - */ - -#ifndef _EXCEPTION_H_ -#define _EXCEPTION_H_ - - -#ifdef LOCORE -#define Const_(x) $/**/x -#else -#define Const_(x) x -#endif - -#ifndef SW_C1 -#include "fpu_emu.h" -#endif /* SW_C1 */ - -#define FPU_BUSY Const_(0x8000) /* FPU busy bit (8087 compatibility) */ -#define EX_ErrorSummary Const_(0x0080) /* Error summary status */ -/* Special exceptions: */ -#define EX_INTERNAL Const_(0x8000) /* Internal error in wm-FPU-emu */ -#define EX_StackOver Const_(0x0041|SW_C1) /* stack overflow */ -#define EX_StackUnder Const_(0x0041) /* stack underflow */ -/* Exception flags: */ -#define EX_Precision Const_(0x0020) /* loss of precision */ -#define EX_Underflow Const_(0x0010) /* underflow */ -#define EX_Overflow Const_(0x0008) /* overflow */ -#define EX_ZeroDiv Const_(0x0004) /* divide by zero */ -#define EX_Denormal Const_(0x0002) /* denormalized operand */ -#define EX_Invalid Const_(0x0001) /* invalid operation */ - - -#ifndef LOCORE - -#ifdef DEBUG -#define EXCEPTION(x) \ - do { \ - printf("exception in %s at line %d\n", __FILE__, __LINE__); \ - exception(x); \ - } while (0) -#else -#define EXCEPTION(x) exception(x) -#endif - -#endif /* LOCORE */ - -#endif /* _EXCEPTION_H_ */ diff --git a/sys/i386/gnu/fpemul/fpu_arith.c b/sys/i386/gnu/fpemul/fpu_arith.c deleted file mode 100644 index 1c6178eb85..0000000000 --- a/sys/i386/gnu/fpemul/fpu_arith.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * fpu_arith.c - * - * Code to implement the FPU register/register arithmetic instructions - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_arith.c,v 1.9 1999/08/28 00:42:49 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_arith.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - - - -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" - - -void -fadd__() -{ - /* fadd st,st(i) */ - reg_add(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fmul__() -{ - /* fmul st,st(i) */ - reg_mul(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - - -void -fsub__() -{ - /* fsub st,st(i) */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fsubr_() -{ - /* fsubr st,st(i) */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word); -} - - -void -fdiv__() -{ - /* fdiv st,st(i) */ - reg_div(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fdivr_() -{ - /* fdivr st,st(i) */ - reg_div(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word); -} - - - -void -fadd_i() -{ - /* fadd st(i),st */ - reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fmul_i() -{ - /* fmul st(i),st */ - reg_mul(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - -void -fsubri() -{ - /* fsubr st(i),st */ - /* This is the sense of the 80486 manual reg_sub(&st(FPU_rm), - * FPU_st0_ptr, &st(FPU_rm), control_word); */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fsub_i() -{ - /* fsub st(i),st */ - /* This is the sense of the 80486 manual reg_sub(FPU_st0_ptr, - * &st(FPU_rm), &st(FPU_rm), control_word); */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - -void -fdivri() -{ - /* fdivr st(i),st */ - reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fdiv_i() -{ - /* fdiv st(i),st */ - reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - - -void -faddp_() -{ - /* faddp st(i),st */ - reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fmulp_() -{ - /* fmulp st(i),st */ - reg_mul(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} - - - -void -fsubrp() -{ - /* fsubrp st(i),st */ - /* This is the sense of the 80486 manual reg_sub(&st(FPU_rm), - * FPU_st0_ptr, &st(FPU_rm), control_word); */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fsubp_() -{ - /* fsubp st(i),st */ - /* This is the sense of the 80486 manual reg_sub(FPU_st0_ptr, - * &st(FPU_rm), &st(FPU_rm), control_word); */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} - - -void -fdivrp() -{ - /* fdivrp st(i),st */ - reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fdivp_() -{ - /* fdivp st(i),st */ - reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} diff --git a/sys/i386/gnu/fpemul/fpu_asm.h b/sys/i386/gnu/fpemul/fpu_asm.h deleted file mode 100644 index 608d73340b..0000000000 --- a/sys/i386/gnu/fpemul/fpu_asm.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * fpu_asm.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_asm.h,v 1.8 1999/08/28 00:42:50 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_asm.h,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#ifndef _FPU_ASM_H_ -#define _FPU_ASM_H_ - -#include -#include "fpu_emu.h" - -#define EXCEPTION exception - - -#define PARAM1 8(%ebp) -#define PARAM2 12(%ebp) -#define PARAM3 16(%ebp) -#define PARAM4 20(%ebp) - -#define SIGL_OFFSET 8 -#define SIGN(x) (x) -#define TAG(x) 1(x) -#define EXP(x) 4(x) -#define SIG(x) SIGL_OFFSET/**/(x) -#define SIGL(x) SIGL_OFFSET/**/(x) -#define SIGH(x) 12(x) - -#endif /* _FPU_ASM_H_ */ diff --git a/sys/i386/gnu/fpemul/fpu_aux.c b/sys/i386/gnu/fpemul/fpu_aux.c deleted file mode 100644 index 86f9cec2b1..0000000000 --- a/sys/i386/gnu/fpemul/fpu_aux.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * fpu_aux.c - * - * Code to implement some of the FPU auxiliary instructions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_aux.c,v 1.11 1999/10/12 02:23:14 msmith Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_aux.c,v 1.4 2005/01/06 08:33:11 asmodai Exp $ - * - */ - - -#include -#ifdef DEBUG -#include /* for printf() in EXCEPTION() */ -#endif -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" - - -static void -fclex(void) -{ - status_word &= ~(SW_Backward | SW_Summary | SW_Stack_Fault | SW_Precision | - SW_Underflow | SW_Overflow | SW_Zero_Div | SW_Denorm_Op | - SW_Invalid); - FPU_entry_eip = ip_offset; /* We want no net effect */ -} -/* Needs to be externally visible */ -void -finit() -{ - int r; - control_word = 0x037f; - status_word = 0; - top = 0; /* We don't keep top in the status word - * internally. */ - for (r = 0; r < 8; r++) { - regs[r].tag = TW_Empty; - } - FPU_entry_eip = ip_offset = 0; -} - -static FUNC finit_table[] = { - Un_impl, Un_impl, fclex, finit, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -finit_() -{ - (finit_table[FPU_rm]) (); -} - - -static void -fstsw_ax(void) -{ - - status_word &= ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - - *(short *) &FPU_EAX = status_word; - -} - -static FUNC fstsw_table[] = { - fstsw_ax, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -fstsw_() -{ - (fstsw_table[FPU_rm]) (); -} - - - -static void -fnop(void) -{ -} - -static FUNC fp_nop_table[] = { - fnop, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -fp_nop() -{ - (fp_nop_table[FPU_rm]) (); -} - - -void -fld_i_() -{ - FPU_REG *st_new_ptr; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - /* fld st(i) */ - if (NOT_EMPTY(FPU_rm)) { - reg_move(&st(FPU_rm), st_new_ptr); - push(); - } else { - if (control_word & EX_Invalid) { - /* The masked response */ - push(); - stack_underflow(); - } else - EXCEPTION(EX_StackUnder); - } - -} - - -void -fxch_i() -{ - /* fxch st(i) */ - FPU_REG t; - FPU_REG *sti_ptr = &st(FPU_rm); - - if (FPU_st0_tag == TW_Empty) { - if (sti_ptr->tag == TW_Empty) { - stack_underflow(); - stack_underflow_i(FPU_rm); - return; - } - reg_move(sti_ptr, FPU_st0_ptr); - stack_underflow_i(FPU_rm); - return; - } - if (sti_ptr->tag == TW_Empty) { - reg_move(FPU_st0_ptr, sti_ptr); - stack_underflow(); - return; - } - reg_move(FPU_st0_ptr, &t); - reg_move(sti_ptr, FPU_st0_ptr); - reg_move(&t, sti_ptr); -} - - -void -ffree_() -{ - /* ffree st(i) */ - st(FPU_rm).tag = TW_Empty; -} - - -void -ffreep() -{ - /* ffree st(i) + pop - unofficial code */ - st(FPU_rm).tag = TW_Empty; - pop(); -} - - -void -fst_i_() -{ - /* fst st(i) */ - reg_move(FPU_st0_ptr, &st(FPU_rm)); -} - - -void -fstp_i() -{ - /* fstp st(i) */ - reg_move(FPU_st0_ptr, &st(FPU_rm)); - pop(); -} diff --git a/sys/i386/gnu/fpemul/fpu_emu.h b/sys/i386/gnu/fpemul/fpu_emu.h deleted file mode 100644 index 8c92f81b17..0000000000 --- a/sys/i386/gnu/fpemul/fpu_emu.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * fpu_emu.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_emu.h,v 1.7 1999/08/28 00:42:50 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_emu.h,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -#ifndef _FPU_EMU_H_ -#define _FPU_EMU_H_ - -/* - * Define DENORM_OPERAND to make the emulator detect denormals - * and use the denormal flag of the status word. Note: this only - * affects the flag and corresponding interrupt, the emulator - * will always generate denormals and operate upon them as required. - */ -#define DENORM_OPERAND - -/* - * Define PECULIAR_486 to get a closer approximation to 80486 behaviour, - * rather than behaviour which appears to be cleaner. - * This is a matter of opinion: for all I know, the 80486 may simply - * be complying with the IEEE spec. Maybe one day I'll get to see the - * spec... - */ -#define PECULIAR_486 - -#ifdef LOCORE -#include "fpu_asm.h" -#define Const(x) $/**/x -#else -#define Const(x) x -#endif - -#define EXP_BIAS Const(0) -#define EXP_OVER Const(0x4000) /* smallest invalid large exponent */ -#define EXP_UNDER Const(-0x3fff) /* largest invalid small exponent */ - -#define SIGN_POS Const(0) -#define SIGN_NEG Const(1) - -/* Keep the order TW_Valid, TW_Zero, TW_Denormal */ -#define TW_Valid Const(0)/* valid */ -#define TW_Zero Const(1)/* zero */ -/* The following fold to 2 (Special) in the Tag Word */ -#define TW_Denormal Const(4)/* De-normal */ -#define TW_Infinity Const(5)/* + or - infinity */ -#define TW_NaN Const(6)/* Not a Number */ - -#define TW_Empty Const(7)/* empty */ - - /* #define TW_FPU_Interrupt Const(0x80) *//* Signals an interrupt */ - - -#ifndef LOCORE - -#include -#include "math_emu.h" - -#ifdef PARANOID -extern char emulating; -#define REENTRANT_CHECK(state) emulating = (state) -#define ON 1 -#define OFF 0 -#else -#define REENTRANT_CHECK(state) -#endif /* PARANOID */ - -typedef void (*FUNC) (void); -typedef struct fpu_reg FPU_REG; - -#define st(x) ( regs[((top+x) &7 )] ) - -#define STACK_OVERFLOW (st_new_ptr = &st(-1), st_new_ptr->tag != TW_Empty) -#define NOT_EMPTY(i) (st(i).tag != TW_Empty) -#define NOT_EMPTY_0 (FPU_st0_tag ^ TW_Empty) - -extern unsigned char FPU_rm; - -extern char FPU_st0_tag; -extern FPU_REG *FPU_st0_ptr; - -extern void *FPU_data_address; - -extern FPU_REG FPU_loaded_data; - -#define pop() { FPU_st0_ptr->tag = TW_Empty; top++; } - -/* push() does not affect the tags */ -#define push() { top--; FPU_st0_ptr = st_new_ptr; } - - -#define reg_move(x, y) { \ - *(short *)&((y)->sign) = *(short *)&((x)->sign); \ - *(long *)&((y)->exp) = *(long *)&((x)->exp); \ - *(long long *)&((y)->sigl) = *(long long *)&((x)->sigl); } - - -/*----- Prototypes for functions written in assembler -----*/ -/* extern void reg_move(FPU_REG *a, FPU_REG *b); */ - -extern void mul64(long long *a, long long *b, long long *result); -extern void poly_div2(long long *x); -extern void poly_div4(long long *x); -extern void poly_div16(long long *x); -extern void -polynomial(unsigned accum[], unsigned x[], - unsigned short terms[][4], int n); - extern void normalize(FPU_REG * x); - extern void normalize_nuo(FPU_REG * x); - extern void reg_div(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_sub(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_mul(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_div(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_add(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void wm_sqrt(FPU_REG * n, unsigned int control_w); - extern unsigned shrx(void *l, unsigned x); - extern unsigned shrxs(void *v, unsigned x); - extern unsigned long div_small(unsigned long long *x, unsigned long y); - extern void round_reg(FPU_REG * arg, unsigned int extent, - unsigned int control_w); - -#ifndef MAKING_PROTO -#include "fpu_proto.h" -#endif - -#endif /* LOCORE */ - -#endif /* _FPU_EMU_H_ */ diff --git a/sys/i386/gnu/fpemul/fpu_entry.c b/sys/i386/gnu/fpemul/fpu_entry.c deleted file mode 100644 index 3ce64f3170..0000000000 --- a/sys/i386/gnu/fpemul/fpu_entry.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * fpu_entry.c - * - * The entry function for wm-FPU-emu - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_entry.c,v 1.23 1999/10/12 02:23:14 msmith Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_entry.c,v 1.5 2004/12/08 20:36:39 joerg Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------+ - | math_emulate() is the sole entry point for wm-FPU-emu | - +---------------------------------------------------------------------------*/ - -#include "opt_depricated.h" -#ifndef I_WANT_DEPRICATED_STUFF -#error "Add options I_WANT_DEPRICATED_STUFF to your kernel config and send a mail to kernel@" -#endif - -#include -#include -#include -#include - -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" - - -#define __BAD__ Un_impl /* Not implemented */ - -#define FPU_LOOKAHEAD 1 /* For performance boost */ - -#if FPU_LOOKAHEAD != 0 /* I think thet we have to limit the */ -#define LOOKAHEAD_LIMIT 7 /* Max number of lookahead instructions*/ -#endif /* Or else a prog consisting of a million */ - /* fnops will spend all its time in kernel*/ - -#ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by - * default. */ - -/* WARNING: These codes are not documented by Intel in their 80486 manual - and may not work on FPU clones or later Intel FPUs. */ - -/* Changes to support the un-doc codes provided by Linus Torvalds. */ - -#define _d9_d8_ fstp_i /* unofficial code (19) */ -#define _dc_d0_ fcom_st /* unofficial code (14) */ -#define _dc_d8_ fcompst /* unofficial code (1c) */ -#define _dd_c8_ fxch_i /* unofficial code (0d) */ -#define _de_d0_ fcompst /* unofficial code (16) */ -#define _df_c0_ ffreep /* unofficial code (07) ffree + pop */ -#define _df_c8_ fxch_i /* unofficial code (0f) */ -#define _df_d0_ fstp_i /* unofficial code (17) */ -#define _df_d8_ fstp_i /* unofficial code (1f) */ - -static FUNC st_instr_table[64] = { - fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_, - fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_, - fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_, - fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_, - fsub__, fp_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, - fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, - fdiv__, trig_a, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, - fdivr_, trig_b, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, -}; -#else /* Support only documented FPU op-codes */ - -static FUNC st_instr_table[64] = { - fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__, - fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__, - fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__, - fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__, - fsub__, fp_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, - fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, - fdiv__, trig_a, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, - fdivr_, trig_b, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, -}; -#endif /* NO_UNDOC_CODE */ - - -#define _NONE_ 0 /* Take no special action */ -#define _REG0_ 1 /* Need to check for not empty st(0) */ -#define _REGI_ 2 /* Need to check for not empty st(0) and - * st(rm) */ -#define _REGi_ 0 /* Uses st(rm) */ -#define _PUSH_ 3 /* Need to check for space to push onto stack */ -#define _null_ 4 /* Function illegal or not implemented */ -#define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */ -#define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) - * then pop */ -#define _REGIc 0 /* Compare st(0) and st(rm) */ -#define _REGIn 0 /* Uses st(0) and st(rm), but handle checks - * later */ - -#ifndef NO_UNDOC_CODE - -/* Un-documented FPU op-codes supported by default. (see above) */ - -static unsigned char type_table[64] = { - _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_, - _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_, - _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, - _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, - _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, - _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ -}; -#else /* Support only documented FPU op-codes */ - -static unsigned char type_table[64] = { - _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_, - _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_, - _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_, - _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, - _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ -}; -#endif /* NO_UNDOC_CODE */ - -/* Be careful when using any of these global variables... - they might change if swapping is triggered */ -unsigned char FPU_rm; -char FPU_st0_tag; -FPU_REG *FPU_st0_ptr; - -#ifdef PARANOID -char emulating = 0; -#endif /* PARANOID */ - -#define bswapw(x) __asm__("xchgb %%al,%%ah":"=a" (x):"0" ((short)x)) -#define math_abort(signo) \ - FPU_EIP = FPU_ORIG_EIP;REENTRANT_CHECK(OFF);return(signo); - -static int -math_emulate(struct trapframe * tframe) -{ - - unsigned char FPU_modrm; - unsigned short code; -#ifdef LOOKAHEAD_LIMIT - int lookahead_limit = LOOKAHEAD_LIMIT; -#endif -#ifdef PARANOID - if (emulating) { - printf("ERROR: wm-FPU-emu is not RE-ENTRANT!\n"); - } - REENTRANT_CHECK(ON); -#endif /* PARANOID */ - - KKASSERT(curproc); - if ((((struct pcb *) curproc->p_addr)->pcb_flags & FP_SOFTFP) == 0) { - finit(); - control_word = __INITIAL_NPXCW__; - ((struct pcb *) curproc->p_addr)->pcb_flags |= FP_SOFTFP; - } - FPU_info = tframe; - FPU_ORIG_EIP = FPU_EIP; /* --pink-- */ - - if (FPU_CS != 0x001f) { - printf("math_emulate: %x : %x\n", FPU_CS, FPU_EIP); - panic("FPU emulation in kernel"); - } -#ifdef notyet - /* We cannot handle emulation in v86-mode */ - if (FPU_EFLAGS & 0x00020000) { - FPU_ORIG_EIP = FPU_EIP; - math_abort(FPU_info, SIGILL); - } -#endif - - FPU_lookahead = FPU_LOOKAHEAD; - if (curproc->p_flag & P_TRACED) - FPU_lookahead = 0; - -do_another_FPU_instruction: - - REENTRANT_CHECK(OFF); - code = fuword((u_int *) FPU_EIP); - REENTRANT_CHECK(ON); - if ((code & 0xff) == 0x9b) { /* fwait */ - if (status_word & SW_Summary) - goto do_the_FPU_interrupt; - else { - FPU_EIP++; - goto FPU_instruction_done; - } - } - if (status_word & SW_Summary) { - /* Ignore the error for now if the current instruction is a - * no-wait control instruction */ - /* The 80486 manual contradicts itself on this topic, so I use - * the following list of such instructions until I can check - * on a real 80486: fninit, fnstenv, fnsave, fnstsw, fnstenv, - * fnclex. */ - if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, - * fnstsw */ - (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, - * fnstenv, fnstsw */ - ((code & 0xc000) != 0xc000))))) { - /* This is a guess about what a real FPU might do to - * this bit: */ -/* status_word &= ~SW_Summary; ****/ - - /* We need to simulate the action of the kernel to FPU - * interrupts here. Currently, the "real FPU" part of - * the kernel (0.99.10) clears the exception flags, - * sets the registers to empty, and passes information - * back to the interrupted process via the cs selector - * and operand selector, so we do the same. */ - do_the_FPU_interrupt: - cs_selector &= 0xffff0000; - cs_selector |= (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift); - operand_selector = tag_word(); - status_word = 0; - top = 0; - { - int r; - for (r = 0; r < 8; r++) { - regs[r].tag = TW_Empty; - } - } - REENTRANT_CHECK(OFF); - math_abort(SIGFPE); - } - } - FPU_entry_eip = FPU_ORIG_EIP = FPU_EIP; - - if ((code & 0xff) == 0x66) { /* size prefix */ - FPU_EIP++; - REENTRANT_CHECK(OFF); - code = fuword((u_int *) FPU_EIP); - REENTRANT_CHECK(ON); - } - FPU_EIP += 2; - - FPU_modrm = code >> 8; - FPU_rm = FPU_modrm & 7; - - if (FPU_modrm < 0300) { - /* All of these instructions use the mod/rm byte to get a data - * address */ - get_address(FPU_modrm); - if (!(code & 1)) { - unsigned short status1 = status_word; - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - - /* Stack underflow has priority */ - if (NOT_EMPTY_0) { - switch ((code >> 1) & 3) { - case 0: - reg_load_single(); - break; - case 1: - reg_load_int32(); - break; - case 2: - reg_load_double(); - break; - case 3: - reg_load_int16(); - break; - } - - /* No more access to user memory, it is safe - * to use static data now */ - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - - /* NaN operands have the next priority. */ - /* We have to delay looking at st(0) until - * after loading the data, because that data - * might contain an SNaN */ - if ((FPU_st0_tag == TW_NaN) || - (FPU_loaded_data.tag == TW_NaN)) { - /* Restore the status word; we might - * have loaded a denormal. */ - status_word = status1; - if ((FPU_modrm & 0x30) == 0x10) { - /* fcom or fcomp */ - EXCEPTION(EX_Invalid); - setcc(SW_C3 | SW_C2 | SW_C0); - if (FPU_modrm & 0x08) - pop(); /* fcomp, so we pop. */ - } else - real_2op_NaN(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr); - goto reg_mem_instr_done; - } - switch ((FPU_modrm >> 3) & 7) { - case 0: /* fadd */ - reg_add(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 1: /* fmul */ - reg_mul(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 2: /* fcom */ - compare_st_data(); - break; - case 3: /* fcomp */ - compare_st_data(); - pop(); - break; - case 4: /* fsub */ - reg_sub(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 5: /* fsubr */ - reg_sub(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr, control_word); - break; - case 6: /* fdiv */ - reg_div(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 7: /* fdivr */ - if (FPU_st0_tag == TW_Zero) - status_word = status1; /* Undo any denorm tag, - * zero-divide has - * priority. */ - reg_div(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr, control_word); - break; - } - } else { - if ((FPU_modrm & 0x30) == 0x10) { - /* The instruction is fcom or fcomp */ - EXCEPTION(EX_StackUnder); - setcc(SW_C3 | SW_C2 | SW_C0); - if (FPU_modrm & 0x08) - pop(); /* fcomp, Empty or not, - * we pop. */ - } else - stack_underflow(); - } - } else { - load_store_instr(((FPU_modrm & 0x38) | (code & 6)) >> 1); - } - -reg_mem_instr_done: - - data_operand_offset = (intptr_t) (void *) FPU_data_address; - } else { - /* None of these instructions access user memory */ - unsigned char instr_index = (FPU_modrm & 0x38) | (code & 7); - - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - switch (type_table[(int) instr_index]) { - case _NONE_: /* also _REGIc: _REGIn */ - break; - case _REG0_: - if (!NOT_EMPTY_0) { - stack_underflow(); - goto FPU_instruction_done; - } - break; - case _REGIi: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow_i(FPU_rm); - goto FPU_instruction_done; - } - break; - case _REGIp: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow_i(FPU_rm); - pop(); - goto FPU_instruction_done; - } - break; - case _REGI_: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow(); - goto FPU_instruction_done; - } - break; - case _PUSH_: /* Only used by the fld st(i) instruction */ - break; - case _null_: - Un_impl(); - goto FPU_instruction_done; - default: - EXCEPTION(EX_INTERNAL | 0x111); - goto FPU_instruction_done; - } - (*st_instr_table[(int) instr_index]) (); - } - -FPU_instruction_done: - - ip_offset = FPU_entry_eip; - bswapw(code); - *(1 + (unsigned short *) &cs_selector) = code & 0x7ff; - -#ifdef DEBUG - REENTRANT_CHECK(OFF); - emu_printall(); - REENTRANT_CHECK(ON); -#endif /* DEBUG */ -#ifdef LOOKAHEAD_LIMIT -if (--lookahead_limit) -#endif - if (FPU_lookahead) { - unsigned char next; - - /* (This test should generate no machine code) */ - while (1) { - REENTRANT_CHECK(OFF); - next = fubyte((u_char *) FPU_EIP); - REENTRANT_CHECK(ON); - if (((next & 0xf8) == 0xd8) || (next == 0x9b)) { /* fwait */ - goto do_another_FPU_instruction; - } else - if (next == 0x66) { /* size prefix */ - REENTRANT_CHECK(OFF); - next = fubyte((u_char *) (FPU_EIP + 1)); - REENTRANT_CHECK(ON); - if ((next & 0xf8) == 0xd8) { - FPU_EIP++; - goto do_another_FPU_instruction; - } - } - break; - } - } - REENTRANT_CHECK(OFF); - return (0); /* --pink-- */ -} - -static int -gnufpu_modevent(module_t mod, int type, void *unused) -{ - switch (type) { - case MOD_LOAD: - if (pmath_emulate) { - printf("Another Math emulator already present\n"); - return EACCES; - } - pmath_emulate = math_emulate; - if (bootverbose) - printf("GPL Math emulator present\n"); - break; - case MOD_UNLOAD: - if (pmath_emulate != math_emulate) { - printf("Cannot unload another math emulator\n"); - return EACCES; - } - pmath_emulate = 0; - if (bootverbose) - printf("GPL Math emulator unloaded\n"); - break; - default: - break; - } - return 0; - -} -static moduledata_t gnufpumod = { - "gnufpu", - gnufpu_modevent, - 0 -}; -DECLARE_MODULE(gnufpu, gnufpumod, SI_SUB_DRIVERS, SI_ORDER_ANY); diff --git a/sys/i386/gnu/fpemul/fpu_etc.c b/sys/i386/gnu/fpemul/fpu_etc.c deleted file mode 100644 index 739ba2e457..0000000000 --- a/sys/i386/gnu/fpemul/fpu_etc.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * fpu_etc.c - * - * Implement a few FPU instructions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_etc.c,v 1.8 1999/08/28 00:42:51 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_etc.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include -#ifdef DEBUG -#include /* for printf() in EXCEPTION() */ -#endif -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" - - -static void -fchs(void) -{ - if (NOT_EMPTY_0) { - FPU_st0_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - status_word &= ~SW_C1; - } else - stack_underflow(); -} - -static void -fabs(void) -{ - if (FPU_st0_tag ^ TW_Empty) { - FPU_st0_ptr->sign = SIGN_POS; - status_word &= ~SW_C1; - } else - stack_underflow(); -} - - -static void -ftst_(void) -{ - switch (FPU_st0_tag) { - case TW_Zero: - setcc(SW_C3); - break; - case TW_Valid: - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - break; - case TW_NaN: - setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ - EXCEPTION(EX_Invalid); - break; - case TW_Infinity: - if (FPU_st0_ptr->sign == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - EXCEPTION(EX_Invalid); - break; - case TW_Empty: - setcc(SW_C0 | SW_C2 | SW_C3); - EXCEPTION(EX_StackUnder); - break; - default: - setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ - EXCEPTION(EX_INTERNAL | 0x14); - break; - } -} - -static void -fxam(void) -{ - int c = 0; - switch (FPU_st0_tag) { - case TW_Empty: - c = SW_C3 | SW_C0; - break; - case TW_Zero: - c = SW_C3; - break; - case TW_Valid: - /* This will need to be changed if TW_Denormal is ever used. */ - if (FPU_st0_ptr->exp <= EXP_UNDER) - c = SW_C2 | SW_C3; /* Denormal */ - else - c = SW_C3; - break; - case TW_NaN: - c = SW_C0; - break; - case TW_Infinity: - c = SW_C2 | SW_C0; - break; - } - if (FPU_st0_ptr->sign == SIGN_NEG) - c |= SW_C1; - setcc(c); -} - -static FUNC fp_etc_table[] = { - fchs, fabs, Un_impl, Un_impl, ftst_, fxam, Un_impl, Un_impl -}; - -void -fp_etc() -{ - (fp_etc_table[FPU_rm]) (); -} diff --git a/sys/i386/gnu/fpemul/fpu_proto.h b/sys/i386/gnu/fpemul/fpu_proto.h deleted file mode 100644 index 494a4c14cb..0000000000 --- a/sys/i386/gnu/fpemul/fpu_proto.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_proto.h,v 1.8 1999/08/28 00:42:51 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_proto.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - - -/* errors.c */ -extern void Un_impl(void); -extern void emu_printall(void); -extern void exception(int n); -extern void real_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest); -extern void arith_invalid(FPU_REG * dest); -extern void divide_by_zero(int sign, FPU_REG * dest); -extern void set_precision_flag_up(void); -extern void set_precision_flag_down(void); -extern int denormal_operand(void); -extern void arith_overflow(FPU_REG * dest); -extern void arith_underflow(FPU_REG * dest); -extern void stack_overflow(void); -extern void stack_underflow(void); -extern void stack_underflow_i(int i); -extern void stack_underflow_pop(int i); -/* fpu_arith.c */ -extern void fadd__(void); -extern void fmul__(void); -extern void fsub__(void); -extern void fsubr_(void); -extern void fdiv__(void); -extern void fdivr_(void); -extern void fadd_i(void); -extern void fmul_i(void); -extern void fsubri(void); -extern void fsub_i(void); -extern void fdivri(void); -extern void fdiv_i(void); -extern void faddp_(void); -extern void fmulp_(void); -extern void fsubrp(void); -extern void fsubp_(void); -extern void fdivrp(void); -extern void fdivp_(void); -/* fpu_aux.c */ -extern void finit(void); -extern void finit_(void); -extern void fstsw_(void); -extern void fp_nop(void); -extern void fld_i_(void); -extern void fxch_i(void); -extern void ffree_(void); -extern void ffreep(void); -extern void fst_i_(void); -extern void fstp_i(void); -/* fpu_entry.c */ -#if 0 -extern int math_emulate(struct trapframe * info); -#endif -/* fpu_etc.c */ -extern void fp_etc(void); -/* fpu_trig.c */ -extern void trig_a(void); -extern void trig_b(void); -/* get_address.c */ -extern void get_address(unsigned char FPU_modrm); -/* load_store.c */ -extern void load_store_instr(char type); -/* poly_2xm1.c */ -extern int poly_2xm1(FPU_REG * arg, FPU_REG * result); -/* poly_atan.c */ -extern void poly_atan(FPU_REG * arg); -/* poly_l2.c */ -extern void poly_l2(FPU_REG * arg, FPU_REG * result); -extern int poly_l2p1(FPU_REG * arg, FPU_REG * result); -/* poly_sin.c */ -extern void poly_sine(FPU_REG * arg, FPU_REG * result); -/* poly_tan.c */ -extern void poly_tan(FPU_REG * arg, FPU_REG * y_reg); -/* reg_add_sub.c */ -extern void reg_add(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w); -extern void reg_sub(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w); -/* reg_compare.c */ -extern int compare(FPU_REG * b); -extern int compare_st_data(void); -extern void fcom_st(void); -extern void fcompst(void); -extern void fcompp(void); -extern void fucom_(void); -extern void fucomp(void); -extern void fucompp(void); -/* reg_constant.c */ -extern void fconst(void); -/* reg_ld_str.c */ -extern void reg_load_extended(void); -extern void reg_load_double(void); -extern void reg_load_single(void); -extern void reg_load_int64(void); -extern void reg_load_int32(void); -extern void reg_load_int16(void); -extern void reg_load_bcd(void); -extern int reg_store_extended(void); -extern int reg_store_double(void); -extern int reg_store_single(void); -extern int reg_store_int64(void); -extern int reg_store_int32(void); -extern int reg_store_int16(void); -extern int reg_store_bcd(void); -extern int round_to_int(FPU_REG * r); -extern char *fldenv(void); -extern void frstor(void); -extern unsigned short tag_word(void); -extern char *fstenv(void); -extern void fsave(void); -/* reg_mul.c */ -extern void reg_mul(FPU_REG * a, FPU_REG * b, FPU_REG * dest, unsigned int control_w); diff --git a/sys/i386/gnu/fpemul/fpu_system.h b/sys/i386/gnu/fpemul/fpu_system.h deleted file mode 100644 index e3712bd531..0000000000 --- a/sys/i386/gnu/fpemul/fpu_system.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * fpu_system.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_system.h,v 1.7.2.1 2001/08/15 01:23:49 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_system.h,v 1.3 2004/04/30 00:59:48 dillon Exp $ - * - */ - - -#ifndef _FPU_SYSTEM_H -#define _FPU_SYSTEM_H - -/* system dependent definitions */ - -/* -#include -#include -*/ - -#define I387 (*(union i387_union *)(&curthread->td_savefpu->sv_87)) -#define FPU_info (I387.soft.frame) - -#define FPU_CS (*(unsigned short *) &(FPU_info->tf_cs)) -#define FPU_DS (*(unsigned short *) &(FPU_info->tf_ds)) -#define FPU_EAX (FPU_info->tf_eax) -#define FPU_EFLAGS (FPU_info->tf_eflags) -#define FPU_EIP (FPU_info->tf_eip) -/*#define FPU_ORIG_EIP (FPU_info->___orig_eip) */ -/*#define FPU_ORIG_EIP (FPU_info->tf_isp)*/ -#define FPU_ORIG_EIP (I387.soft.orig_eip) - -#define FPU_lookahead (I387.soft.lookahead) -#define FPU_entry_eip (I387.soft.entry_eip) - -#define status_word (I387.soft.swd) -#define control_word (I387.soft.cwd) -#define regs (I387.soft.regs) -#define top (I387.soft.top) - -#define ip_offset (I387.soft.fip) -#define cs_selector (I387.soft.fcs) -#define data_operand_offset (I387.soft.foo) -#define operand_selector (I387.soft.fos) - -#endif diff --git a/sys/i386/gnu/fpemul/fpu_trig.c b/sys/i386/gnu/fpemul/fpu_trig.c deleted file mode 100644 index 4916bc1243..0000000000 --- a/sys/i386/gnu/fpemul/fpu_trig.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* - * fpu_trig.c - * - * Implementation of the FPU "transcendental" functions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_trig.c,v 1.10 1999/08/28 00:42:52 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/fpu_trig.c,v 1.4 2005/01/06 08:33:11 asmodai Exp $ - * - */ - - -#include -#ifdef DEBUG -#include /* for printf() in EXCEPTION() */ -#endif -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" -#include "reg_constant.h" -#include "control_w.h" - -static void convert_l2reg(long *arg, FPU_REG * dest); - -static int -trig_arg(FPU_REG * X) -{ - FPU_REG tmp, quot; - int rv; - long long q; - int old_cw = control_word; - - control_word &= ~CW_RC; - control_word |= RC_CHOP; - - reg_move(X, "); - reg_div(", &CONST_PI2, ", FULL_PRECISION); - - reg_move(", &tmp); - round_to_int(&tmp); - if (tmp.sigh & 0x80000000) - return -1; /* |Arg| is >= 2^63 */ - tmp.exp = EXP_BIAS + 63; - q = *(long long *) &(tmp.sigl); - normalize(&tmp); - - reg_sub(", &tmp, X, FULL_PRECISION); - rv = q & 7; - - control_word = old_cw; - return rv;; -} - - -/* Convert a long to register */ -static void -convert_l2reg(long *arg, FPU_REG * dest) -{ - long num = *arg; - - if (num == 0) { - reg_move(&CONST_Z, dest); - return; - } - if (num > 0) - dest->sign = SIGN_POS; - else { - num = -num; - dest->sign = SIGN_NEG; - } - - dest->sigh = num; - dest->sigl = 0; - dest->exp = EXP_BIAS + 31; - dest->tag = TW_Valid; - normalize(dest); -} - - -static void -single_arg_error(void) -{ - switch (FPU_st0_tag) { - case TW_NaN: - if (!(FPU_st0_ptr->sigh & 0x40000000)) { /* Signaling ? */ - EXCEPTION(EX_Invalid); - /* Convert to a QNaN */ - FPU_st0_ptr->sigh |= 0x40000000; - } - break; /* return with a NaN in st(0) */ - case TW_Empty: - stack_underflow(); /* Puts a QNaN in st(0) */ - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x0112); -#endif /* PARANOID */ - } -} - - -/*---------------------------------------------------------------------------*/ - -static void -f2xm1(void) -{ - switch (FPU_st0_tag) { - case TW_Valid: - { - FPU_REG rv, tmp; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - /* poly_2xm1(x) requires 0 < x < 1. */ - if (poly_2xm1(FPU_st0_ptr, &rv)) - return; /* error */ - reg_mul(&rv, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - } else { -/* **** Should change poly_2xm1() to at least handle numbers near 0 */ - /* poly_2xm1(x) doesn't handle negative - * numbers. */ - /* So we compute (poly_2xm1(x+1)-1)/2, for -1 - * < x < 0 */ - reg_add(FPU_st0_ptr, &CONST_1, &tmp, FULL_PRECISION); - poly_2xm1(&tmp, &rv); - reg_mul(&rv, &tmp, &tmp, FULL_PRECISION); - reg_sub(&tmp, &CONST_1, FPU_st0_ptr, FULL_PRECISION); - FPU_st0_ptr->exp--; - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - } - return; - } - case TW_Zero: - return; - case TW_Infinity: - if (FPU_st0_ptr->sign == SIGN_NEG) { - /* -infinity gives -1 (p16-10) */ - reg_move(&CONST_1, FPU_st0_ptr); - FPU_st0_ptr->sign = SIGN_NEG; - } - return; - default: - single_arg_error(); - } -} - -static void -fptan(void) -{ - FPU_REG *st_new_ptr; - int q; - char arg_sign = FPU_st0_ptr->sign; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - switch (FPU_st0_tag) { - case TW_Valid: - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - FPU_st0_ptr->sign = SIGN_POS; - if ((q = trig_arg(FPU_st0_ptr)) != -1) { - if (q & 1) - reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - - poly_tan(FPU_st0_ptr, FPU_st0_ptr); - - FPU_st0_ptr->sign = (q & 1) ^ arg_sign; - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - - push(); - reg_move(&CONST_1, FPU_st0_ptr); - setcc(0); - } else { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } - break; - case TW_Infinity: - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - case TW_Zero: - push(); - reg_move(&CONST_1, FPU_st0_ptr); - setcc(0); - break; - default: - single_arg_error(); - break; - } -} - - -static void -fxtract(void) -{ - FPU_REG *st_new_ptr; - FPU_REG *st1_ptr = FPU_st0_ptr; /* anticipate */ - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - if (!(FPU_st0_tag ^ TW_Valid)) { - long e; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - push(); - reg_move(st1_ptr, FPU_st0_ptr); - FPU_st0_ptr->exp = EXP_BIAS; - e = st1_ptr->exp - EXP_BIAS; - convert_l2reg(&e, st1_ptr); - return; - } else - if (FPU_st0_tag == TW_Zero) { - char sign = FPU_st0_ptr->sign; - divide_by_zero(SIGN_NEG, FPU_st0_ptr); - push(); - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } else - if (FPU_st0_tag == TW_Infinity) { - char sign = FPU_st0_ptr->sign; - FPU_st0_ptr->sign = SIGN_POS; - push(); - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } else - if (FPU_st0_tag == TW_NaN) { - if (!(FPU_st0_ptr->sigh & 0x40000000)) { /* Signaling ? */ - EXCEPTION(EX_Invalid); - /* Convert to a QNaN */ - FPU_st0_ptr->sigh |= 0x40000000; - } - push(); - reg_move(st1_ptr, FPU_st0_ptr); - return; - } else - if (FPU_st0_tag == TW_Empty) { - /* Is this the correct - * behaviour? */ - if (control_word & EX_Invalid) { - stack_underflow(); - push(); - stack_underflow(); - } else - EXCEPTION(EX_StackUnder); - } -#ifdef PARANOID - else - EXCEPTION(EX_INTERNAL | 0x119); -#endif /* PARANOID */ -} - - -static void -fdecstp(void) -{ - top--; /* FPU_st0_ptr will be fixed in math_emulate() - * before the next instr */ -} - -static void -fincstp(void) -{ - top++; /* FPU_st0_ptr will be fixed in math_emulate() - * before the next instr */ -} - - -static void -fsqrt_(void) -{ - if (!(FPU_st0_tag ^ TW_Valid)) { - int expon; - - if (FPU_st0_ptr->sign == SIGN_NEG) { - arith_invalid(FPU_st0_ptr); /* sqrt(negative) is - * invalid */ - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - expon = FPU_st0_ptr->exp - EXP_BIAS; - FPU_st0_ptr->exp = EXP_BIAS + (expon & 1); /* make st(0) in [1.0 - * .. 4.0) */ - - wm_sqrt(FPU_st0_ptr, control_word); /* Do the computation */ - - FPU_st0_ptr->exp += expon >> 1; - FPU_st0_ptr->sign = SIGN_POS; - } else - if (FPU_st0_tag == TW_Zero) - return; - else - if (FPU_st0_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_NEG) - arith_invalid(FPU_st0_ptr); /* sqrt(-Infinity) is - * invalid */ - return; - } else { - single_arg_error(); - return; - } - -} - - -static void -frndint_(void) -{ - if (!(FPU_st0_tag ^ TW_Valid)) { - if (FPU_st0_ptr->exp > EXP_BIAS + 63) - return; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - round_to_int(FPU_st0_ptr); /* Fortunately, this can't - * overflow to 2^64 */ - FPU_st0_ptr->exp = EXP_BIAS + 63; - normalize(FPU_st0_ptr); - return; - } else - if ((FPU_st0_tag == TW_Zero) || (FPU_st0_tag == TW_Infinity)) - return; - else - single_arg_error(); -} - - -static void -fsin(void) -{ - char arg_sign = FPU_st0_ptr->sign; - - if (FPU_st0_tag == TW_Valid) { - int q; - FPU_st0_ptr->sign = SIGN_POS; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if ((q = trig_arg(FPU_st0_ptr)) != -1) { - FPU_REG rv; - - if (q & 1) - reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - - poly_sine(FPU_st0_ptr, &rv); - - setcc(0); - if (q & 2) - rv.sign ^= SIGN_POS ^ SIGN_NEG; - rv.sign ^= arg_sign; - reg_move(&rv, FPU_st0_ptr); - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - - set_precision_flag_up(); /* We do not really know - * if up or down */ - - return; - } else { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } - } else - if (FPU_st0_tag == TW_Zero) { - setcc(0); - return; - } else - if (FPU_st0_tag == TW_Infinity) { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } else - single_arg_error(); -} - - -static int -f_cos(FPU_REG * arg) -{ - char arg_sign = arg->sign; - - if (arg->tag == TW_Valid) { - int q; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return 1; -#endif /* DENORM_OPERAND */ - - arg->sign = SIGN_POS; - if ((q = trig_arg(arg)) != -1) { - FPU_REG rv; - - if (!(q & 1)) - reg_sub(&CONST_1, arg, arg, FULL_PRECISION); - - poly_sine(arg, &rv); - - setcc(0); - if ((q + 1) & 2) - rv.sign ^= SIGN_POS ^ SIGN_NEG; - reg_move(&rv, arg); - - set_precision_flag_up(); /* We do not really know - * if up or down */ - - return 0; - } else { - /* Operand is out of range */ - setcc(SW_C2); - arg->sign = arg_sign; /* restore st(0) */ - return 1; - } - } else - if (arg->tag == TW_Zero) { - reg_move(&CONST_1, arg); - setcc(0); - return 0; - } else - if (FPU_st0_tag == TW_Infinity) { - /* Operand is out of range */ - setcc(SW_C2); - arg->sign = arg_sign; /* restore st(0) */ - return 1; - } else { - single_arg_error(); /* requires arg == - * &st(0) */ - return 1; - } -} - - -static void -fcos(void) -{ - f_cos(FPU_st0_ptr); -} - - -static void -fsincos(void) -{ - FPU_REG *st_new_ptr; - FPU_REG arg; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - reg_move(FPU_st0_ptr, &arg); - if (!f_cos(&arg)) { - fsin(); - push(); - reg_move(&arg, FPU_st0_ptr); - } -} - - -/*---------------------------------------------------------------------------*/ -/* The following all require two arguments: st(0) and st(1) */ - -/* remainder of st(0) / st(1) */ -/* Assumes that st(0) and st(1) are both TW_Valid */ -static void -fprem_kernel(int round) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - FPU_REG tmp; - int old_cw = control_word; - int expdif = FPU_st0_ptr->exp - (st1_ptr)->exp; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - control_word &= ~CW_RC; - control_word |= round; - - if (expdif < 64) { - /* This should be the most common case */ - long long q; - int c = 0; - - reg_div(FPU_st0_ptr, st1_ptr, &tmp, FULL_PRECISION); - - round_to_int(&tmp); /* Fortunately, this can't - * overflow to 2^64 */ - tmp.exp = EXP_BIAS + 63; - q = *(long long *) &(tmp.sigl); - normalize(&tmp); - - reg_mul(st1_ptr, &tmp, &tmp, FULL_PRECISION); - reg_sub(FPU_st0_ptr, &tmp, FPU_st0_ptr, FULL_PRECISION); - - if (q & 4) - c |= SW_C3; - if (q & 2) - c |= SW_C1; - if (q & 1) - c |= SW_C0; - - setcc(c); - } else { - /* There is a large exponent difference ( >= 64 ) */ - int N_exp; - - reg_div(FPU_st0_ptr, st1_ptr, &tmp, FULL_PRECISION); - /* N is 'a number between 32 and 63' (p26-113) */ - N_exp = (tmp.exp & 31) + 32; - tmp.exp = EXP_BIAS + N_exp; - - round_to_int(&tmp); /* Fortunately, this can't - * overflow to 2^64 */ - tmp.exp = EXP_BIAS + 63; - normalize(&tmp); - - tmp.exp = EXP_BIAS + expdif - N_exp; - - reg_mul(st1_ptr, &tmp, &tmp, FULL_PRECISION); - reg_sub(FPU_st0_ptr, &tmp, FPU_st0_ptr, FULL_PRECISION); - - setcc(SW_C2); - } - control_word = old_cw; - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - return; - } else - if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) { - stack_underflow(); - return; - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - setcc(0); - return; - } else - if (st1_tag == TW_Zero) { - arith_invalid(FPU_st0_ptr); - return; - } - /* fprem(?,0) always invalid */ - else - if (st1_tag == TW_Infinity) { - setcc(0); - return; - } - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - arith_invalid(FPU_st0_ptr); /* fprem(Valid,Zero) is - * invalid */ - return; - } else - if (st1_tag != TW_NaN) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (st1_tag == TW_Infinity) { - /* fprem(Valid, - * Infinity) - * is o.k. */ - setcc(0); - return; - } - } - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag != TW_NaN) { - arith_invalid(FPU_st0_ptr); /* fprem(Infinity,?) is - * invalid */ - return; - } - } - /* One of the registers must contain a NaN is we got here. */ - -#ifdef PARANOID - if ((FPU_st0_tag != TW_NaN) && (st1_tag != TW_NaN)) - EXCEPTION(EX_INTERNAL | 0x118); -#endif /* PARANOID */ - - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - -} - - -/* ST(1) <- ST(1) * log ST; pop ST */ -static void -fyl2x(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - if (FPU_st0_ptr->sign == SIGN_POS) { - int saved_control, saved_status; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic, so we need - * to save these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - poly_l2(FPU_st0_ptr, FPU_st0_ptr); - - /* Enough of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - /* Let the multiply set the flags */ - reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION); - - pop(); - FPU_st0_ptr = &st(0); - } else { - /* negative */ - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* st(0) cannot be - * negative */ - return; - } - } else - if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_tag <= TW_Zero) && (st1_tag <= TW_Zero)) { - /* one of the args is zero, the other - * valid, or both zero */ - if (FPU_st0_tag == TW_Zero) { - pop(); - FPU_st0_ptr = &st(0); - if (FPU_st0_ptr->tag == TW_Zero) - arith_invalid(FPU_st0_ptr); /* Both args zero is - * invalid */ -#ifdef PECULIAR_486 - /* This case is not - * specifically covered in the - * manual, but divide-by-zero - * would seem to be the best - * response. However, a real - * 80486 does it this way... */ - else - if (FPU_st0_ptr->tag == TW_Infinity) { - reg_move(&CONST_INF, FPU_st0_ptr); - return; - } -#endif /* PECULIAR_486 */ - else - divide_by_zero(st1_ptr->sign ^ SIGN_NEG ^ SIGN_POS, FPU_st0_ptr); - return; - } else { - /* st(1) contains zero, st(0) - * valid <> 0 */ - /* Zero is the valid answer */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - if (FPU_st0_ptr->sign == SIGN_NEG) { - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* log(negative) */ - return; - } - if (FPU_st0_ptr->exp < EXP_BIAS) - sign ^= SIGN_NEG ^ SIGN_POS; - pop(); - FPU_st0_ptr = &st(0); - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - } - /* One or both arg must be an infinity */ - else - if (FPU_st0_tag == TW_Infinity) { - if ((FPU_st0_ptr->sign == SIGN_NEG) || (st1_tag == TW_Zero)) { - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* log(-infinity) or - * 0*log(infinity) */ - return; - } else { - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - pop(); - FPU_st0_ptr = &st(0); - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - } - /* st(1) must be infinity here */ - else - if ((FPU_st0_tag == TW_Valid) && (FPU_st0_ptr->sign == SIGN_POS)) { - if (FPU_st0_ptr->exp >= EXP_BIAS) { - if ((FPU_st0_ptr->exp == EXP_BIAS) && - (FPU_st0_ptr->sigh == 0x80000000) && - (FPU_st0_ptr->sigl == 0)) { - /* st(0 - * ) - * hold - * s - * 1.0 */ - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* infinity*log(1) */ - return; - } - /* st(0) is - * positive - * and > 1.0 */ - pop(); - } else { - /* st(0) is - * positive - * and < 1.0 */ - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - st1_ptr->sign ^= SIGN_NEG; - pop(); - } - return; - } else { - /* st(0) must be zero - * or negative */ - if (FPU_st0_ptr->tag == TW_Zero) { - pop(); - FPU_st0_ptr = st1_ptr; - st1_ptr->sign ^= SIGN_NEG ^ SIGN_POS; - /* This should - * be invalid, - * but a real - * 80486 is - * happy with - * it. */ -#ifndef PECULIAR_486 - divide_by_zero(st1_ptr->sign, FPU_st0_ptr); -#endif /* PECULIAR_486 */ - } else { - pop(); - FPU_st0_ptr = st1_ptr; - arith_invalid(FPU_st0_ptr); /* log(negative) */ - } - return; - } -} - - -static void -fpatan(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - int saved_control, saved_status; - FPU_REG sum; - int quadrant = st1_ptr->sign | ((FPU_st0_ptr->sign) << 1); - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic so we need to save - * these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - st1_ptr->sign = FPU_st0_ptr->sign = SIGN_POS; - if (compare(st1_ptr) == COMP_A_lt_B) { - quadrant |= 4; - reg_div(FPU_st0_ptr, st1_ptr, &sum, FULL_PRECISION); - } else - reg_div(st1_ptr, FPU_st0_ptr, &sum, FULL_PRECISION); - - poly_atan(&sum); - - if (quadrant & 4) { - reg_sub(&CONST_PI2, &sum, &sum, FULL_PRECISION); - } - if (quadrant & 2) { - reg_sub(&CONST_PI, &sum, &sum, FULL_PRECISION); - } - if (quadrant & 1) - sum.sign ^= SIGN_POS ^ SIGN_NEG; - - /* All of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - reg_move(&sum, st1_ptr); - } else - if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_tag == TW_Infinity) || (st1_tag == TW_Infinity)) { - char sign = st1_ptr->sign; - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_PI4, st1_ptr); - } else - reg_add(&CONST_PI4, &CONST_PI2, st1_ptr, FULL_PRECISION); - } else { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_Z, st1_ptr); - pop(); - return; - } else - reg_move(&CONST_PI, st1_ptr); - } - } else { - /* st(1) is infinity, st(0) - * not infinity */ -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - reg_move(&CONST_PI2, st1_ptr); - } - st1_ptr->sign = sign; - } else - if (st1_tag == TW_Zero) { - /* st(0) must be valid or zero */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_Z, st1_ptr); - pop(); - return; - } else - reg_move(&CONST_PI, st1_ptr); - st1_ptr->sign = sign; - } else - if (FPU_st0_tag == TW_Zero) { - /* st(1) must be - * TW_Valid here */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - reg_move(&CONST_PI2, st1_ptr); - st1_ptr->sign = sign; - } -#ifdef PARANOID - else - EXCEPTION(EX_INTERNAL | 0x220); -#endif /* PARANOID */ - - pop(); - set_precision_flag_up();/* We do not really know if up or down */ -} - - -static void -fprem(void) -{ - fprem_kernel(RC_CHOP); -} - - -static void -fprem1(void) -{ - fprem_kernel(RC_RND); -} - - -static void -fyl2xp1(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - int saved_control, saved_status; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic so we need to save - * these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - if (poly_l2p1(FPU_st0_ptr, FPU_st0_ptr)) { - arith_invalid(st1_ptr); /* poly_l2p1() returned - * invalid */ - pop(); - return; - } - /* Enough of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - /* Let the multiply set the flags */ - reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION); - - pop(); - } else - if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag <= TW_Zero) { - -#ifdef DENORM_OPERAND - if ((st1_tag == TW_Valid) && (st1_ptr->exp <= EXP_UNDER) && - (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - st1_ptr->sign ^= FPU_st0_ptr->sign; - reg_move(FPU_st0_ptr, st1_ptr); - } else - if (st1_tag == TW_Infinity) { - arith_invalid(st1_ptr); /* Infinity*log(1) */ - pop(); - return; - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x116); - return; - } -#endif /* PARANOID */ - pop(); - return; - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - if (FPU_st0_ptr->sign == SIGN_NEG) { - if (FPU_st0_ptr->exp >= EXP_BIAS) { - /* st(0) holds - * <= -1.0 */ - arith_invalid(st1_ptr); /* infinity*log(1) */ - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - pop(); - return; - } - if (st1_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_NEG) { - if ((FPU_st0_ptr->exp >= EXP_BIAS) && - !((FPU_st0_ptr->sigh == 0x80000000) && - (FPU_st0_ptr->sigl == 0))) { - /* st(0) holds - * < -1.0 */ - arith_invalid(st1_ptr); - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - pop(); - return; - } - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } - } else - if (FPU_st0_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_ptr->sign == SIGN_NEG) || - (st1_tag == TW_Zero)) { - arith_invalid(st1_ptr); /* log(infinity) */ - pop(); - return; - } - /* st(1) must be valid - * here. */ - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* The Manual says - * that log(Infinity) - * is invalid, but a - * real 80486 sensibly - * says that it is - * o.k. */ - { - char sign = st1_ptr->sign; - reg_move(&CONST_INF, st1_ptr); - st1_ptr->sign = sign; - } - pop(); - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x117); - } -#endif /* PARANOID */ -} - - -static void -emu_fscale(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - int old_cw = control_word; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - long scale; - FPU_REG tmp; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (st1_ptr->exp > EXP_BIAS + 30) { - /* 2^31 is far too large, would require 2^(2^30) or - * 2^(-2^30) */ - char sign; - - if (st1_ptr->sign == SIGN_POS) { - EXCEPTION(EX_Overflow); - sign = FPU_st0_ptr->sign; - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - } else { - EXCEPTION(EX_Underflow); - sign = FPU_st0_ptr->sign; - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - } - return; - } - control_word &= ~CW_RC; - control_word |= RC_CHOP; - reg_move(st1_ptr, &tmp); - round_to_int(&tmp); /* This can never overflow here */ - control_word = old_cw; - scale = st1_ptr->sign ? -tmp.sigl : tmp.sigl; - scale += FPU_st0_ptr->exp; - FPU_st0_ptr->exp = scale; - - /* Use round_reg() to properly detect under/overflow etc */ - round_reg(FPU_st0_ptr, 0, control_word); - - return; - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } - if (st1_tag == TW_Infinity) { - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (sign == SIGN_POS) { - reg_move(&CONST_INF, FPU_st0_ptr); - } else - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } else - if (st1_tag == TW_Zero) { - return; - } else - if (st1_tag == TW_Infinity) { - if (st1_ptr->sign == SIGN_NEG) - return; - else { - arith_invalid(FPU_st0_ptr); /* Zero scaled by - * +Infinity */ - return; - } - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } - if (((st1_tag == TW_Infinity) && (st1_ptr->sign == SIGN_POS)) - || (st1_tag == TW_Zero)) - return; - else - if (st1_tag == TW_Infinity) { - arith_invalid(FPU_st0_ptr); /* Infinity scaled by - * -Infinity */ - return; - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_NaN) { - if (st1_tag != TW_Empty) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } -#ifdef PARANOID - if (!((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty))) { - EXCEPTION(EX_INTERNAL | 0x115); - return; - } -#endif - - /* At least one of st(0), st(1) must be empty */ - stack_underflow(); - -} - - -/*---------------------------------------------------------------------------*/ - -static FUNC trig_table_a[] = { - f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp -}; - -void -trig_a(void) -{ - (trig_table_a[FPU_rm]) (); -} - - -static FUNC trig_table_b[] = -{ - fprem, fyl2xp1, fsqrt_, fsincos, frndint_, emu_fscale, fsin, fcos -}; - -void -trig_b(void) -{ - (trig_table_b[FPU_rm]) (); -} diff --git a/sys/i386/gnu/fpemul/get_address.c b/sys/i386/gnu/fpemul/get_address.c deleted file mode 100644 index 465dc448a0..0000000000 --- a/sys/i386/gnu/fpemul/get_address.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * get_address.c - * - * Get the effective address from an FPU instruction. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/get_address.c,v 1.10 1999/10/12 02:23:14 msmith Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/get_address.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" - -static int reg_offset[] = { -tEAX, tECX, tEDX, tEBX, tESP, tEBP, tESI, tEDI}; -#define REG_(x) (*(((int*)FPU_info) + reg_offset[(x)])) - -void *FPU_data_address; - - -/* Decode the SIB byte. This function assumes mod != 0 */ -static void * -sib(int mod) -{ - unsigned char ss, index, base; - long offset; - - REENTRANT_CHECK(OFF); - base = fubyte((char *) FPU_EIP); /* The SIB byte */ - REENTRANT_CHECK(ON); - FPU_EIP++; - ss = base >> 6; - index = (base >> 3) & 7; - base &= 7; - - if ((mod == 0) && (base == 5)) - offset = 0; /* No base register */ - else - offset = REG_(base); - - if (index == 4) { - /* No index register */ - /* A non-zero ss is illegal */ - if (ss) - EXCEPTION(EX_Invalid); - } else { - offset += (REG_(index)) << ss; - } - - if (mod == 1) { - /* 8 bit signed displacement */ - REENTRANT_CHECK(OFF); - offset += (signed char) fubyte((char *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP++; - } else - if (mod == 2 || base == 5) { /* The second condition also - * has mod==0 */ - /* 32 bit displacment */ - REENTRANT_CHECK(OFF); - offset += (signed) fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - } - return (void *) (intptr_t) offset; -} - - -/* - MOD R/M byte: MOD == 3 has a special use for the FPU - SIB byte used iff R/M = 100b - - 7 6 5 4 3 2 1 0 - ..... ......... ......... - MOD OPCODE(2) R/M - - - SIB byte - - 7 6 5 4 3 2 1 0 - ..... ......... ......... - SS INDEX BASE - -*/ - -void -get_address(unsigned char FPU_modrm) -{ - unsigned char mod; - long *cpu_reg_ptr; - int offset = 0; /* Initialized just to stop compiler warnings. */ - - mod = (FPU_modrm >> 6) & 3; - - if (FPU_rm == 4 && mod != 3) { - FPU_data_address = sib(mod); - return; - } - cpu_reg_ptr = (long *) ®_(FPU_rm); - switch (mod) { - case 0: - if (FPU_rm == 5) { - /* Special case: disp32 */ - REENTRANT_CHECK(OFF); - offset = fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - FPU_data_address = (void *) offset; - return; - } else { - /* Just return the contents of the cpu register */ - FPU_data_address = (void *) (intptr_t) *cpu_reg_ptr; - return; - } - case 1: - /* 8 bit signed displacement */ - REENTRANT_CHECK(OFF); - offset = (signed char) fubyte((char *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP++; - break; - case 2: - /* 32 bit displacement */ - REENTRANT_CHECK(OFF); - offset = (signed) fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - break; - case 3: - /* Not legal for the FPU */ - EXCEPTION(EX_Invalid); - } - - FPU_data_address = (void *) (intptr_t) (offset + *cpu_reg_ptr); -} diff --git a/sys/i386/gnu/fpemul/load_store.c b/sys/i386/gnu/fpemul/load_store.c deleted file mode 100644 index e2d089513f..0000000000 --- a/sys/i386/gnu/fpemul/load_store.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * load_store.c - * - * This file contains most of the code to interpret the FPU instructions - * which load and store from user memory. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/load_store.c,v 1.13 1999/08/28 00:42:52 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/load_store.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "status_w.h" - - -#define _NONE_ 0 /* FPU_st0_ptr etc not needed */ -#define _REG0_ 1 /* Will be storing st(0) */ -#define _PUSH_ 3 /* Need to check for space to push onto stack */ -#define _null_ 4 /* Function illegal or not implemented */ - -#define pop_0() { pop_ptr->tag = TW_Empty; top++; } - - -static unsigned char type_table[32] = { - _PUSH_, _PUSH_, _PUSH_, _PUSH_, - _null_, _null_, _null_, _null_, - _REG0_, _REG0_, _REG0_, _REG0_, - _REG0_, _REG0_, _REG0_, _REG0_, - _NONE_, _null_, _NONE_, _PUSH_, - _NONE_, _PUSH_, _null_, _PUSH_, - _NONE_, _null_, _NONE_, _REG0_, - _NONE_, _REG0_, _NONE_, _REG0_ -}; - -void -load_store_instr(char type) -{ - FPU_REG *pop_ptr; /* We need a version of FPU_st0_ptr which - * won't change. */ - - pop_ptr = NULL; /* Initialized just to stop compiler warnings. */ - - - switch (type_table[(int) (unsigned) type]) { - case _NONE_: - break; - case _REG0_: - pop_ptr = &st(0); /* Some of these instructions pop - * after storing */ - - FPU_st0_ptr = pop_ptr; /* Set the global variables. */ - FPU_st0_tag = FPU_st0_ptr->tag; - break; - case _PUSH_: - { - pop_ptr = &st(-1); - if (pop_ptr->tag != TW_Empty) { - stack_overflow(); - return; - } - top--; - } - break; - case _null_: - Un_impl(); - return; -#ifdef PARANOID - default: - return EXCEPTION(EX_INTERNAL); -#endif /* PARANOID */ - } - - switch (type) { - case 000: /* fld m32real */ - reg_load_single(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 001: /* fild m32int */ - reg_load_int32(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 002: /* fld m64real */ - reg_load_double(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 003: /* fild m16int */ - reg_load_int16(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 010: /* fst m32real */ - reg_store_single(); - break; - case 011: /* fist m32int */ - reg_store_int32(); - break; - case 012: /* fst m64real */ - reg_store_double(); - break; - case 013: /* fist m16int */ - reg_store_int16(); - break; - case 014: /* fstp m32real */ - if (reg_store_single()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 015: /* fistp m32int */ - if (reg_store_int32()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 016: /* fstp m64real */ - if (reg_store_double()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 017: /* fistp m16int */ - if (reg_store_int16()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 020: /* fldenv m14/28byte */ - fldenv(); - break; - case 022: /* frstor m94/108byte */ - frstor(); - break; - case 023: /* fbld m80dec */ - reg_load_bcd(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 024: /* fldcw */ - REENTRANT_CHECK(OFF); - control_word = fusword((unsigned short *) FPU_data_address); - REENTRANT_CHECK(ON); -#ifdef NO_UNDERFLOW_TRAP - if (!(control_word & EX_Underflow)) { - control_word |= EX_Underflow; - } -#endif - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 025: /* fld m80real */ - reg_load_extended(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 027: /* fild m64int */ - reg_load_int64(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 030: /* fstenv m14/28byte */ - fstenv(); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 032: /* fsave */ - fsave(); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 033: /* fbstp m80dec */ - if (reg_store_bcd()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 034: /* fstcw m16int */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, FPU_data_address, 2);*/ - susword( (short *) FPU_data_address,control_word); - REENTRANT_CHECK(ON); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t ) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 035: /* fstp m80real */ - if (reg_store_extended()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 036: /* fstsw m2byte */ - status_word &= ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, FPU_data_address, 2);*/ - susword( (short *) FPU_data_address,status_word); - REENTRANT_CHECK(ON); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 037: /* fistp m64int */ - if (reg_store_int64()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - } -} diff --git a/sys/i386/gnu/fpemul/math_emu.h b/sys/i386/gnu/fpemul/math_emu.h deleted file mode 100644 index a975bae152..0000000000 --- a/sys/i386/gnu/fpemul/math_emu.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * $FreeBSD: src/sys/gnu/i386/fpemul/math_emu.h,v 1.5 1999/08/28 00:42:52 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/math_emu.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - -#ifndef _MATH_EMU_H -#define _MATH_EMU_H - -struct fpu_reg { - char sign; - char tag; - long exp; - u_long sigl; - u_long sigh; -}; - -union i387_union { - struct i387_hard_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long st_space[20]; /* 8*10 bytes for each FP-reg = 80 - * bytes */ - } hard; - struct i387_soft_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long top; - struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128 - * bytes */ - unsigned char lookahead; - struct trapframe *frame; - unsigned long entry_eip; - int orig_eip; - } soft; -}; -#endif diff --git a/sys/i386/gnu/fpemul/poly_2xm1.c b/sys/i386/gnu/fpemul/poly_2xm1.c deleted file mode 100644 index ebffe238fb..0000000000 --- a/sys/i386/gnu/fpemul/poly_2xm1.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * poly_2xm1.c - * - * Function to compute 2^x-1 by a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_2xm1.c,v 1.8 1999/08/28 00:42:53 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/poly_2xm1.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "reg_constant.h" - - - -#define HIPOWER 13 -static unsigned short lterms[HIPOWER][4] = -{ - {0x79b5, 0xd1cf, 0x17f7, 0xb172}, - {0x1b56, 0x058b, 0x7bff, 0x3d7f}, - {0x8bb0, 0x8250, 0x846b, 0x0e35}, - {0xbc65, 0xf747, 0x556d, 0x0276}, - {0x17cb, 0x9e39, 0x61ff, 0x0057}, - {0xe018, 0x9776, 0x1848, 0x000a}, - {0x66f2, 0xff30, 0xffe5, 0x0000}, - {0x682f, 0xffb6, 0x162b, 0x0000}, - {0xb7ca, 0x2956, 0x01b5, 0x0000}, - {0xcd3e, 0x4817, 0x001e, 0x0000}, - {0xb7e2, 0xecbe, 0x0001, 0x0000}, - {0x0ed5, 0x1a27, 0x0000, 0x0000}, - {0x101d, 0x0222, 0x0000, 0x0000}, -}; - - -/*--- poly_2xm1() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -int -poly_2xm1(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - long long Xll; - FPU_REG accum; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, result); - return 0; - } - if (exponent >= 0) { /* Can't hack a number >= 1.0 */ - arith_invalid(result); /* Number too large */ - return 1; - } - if (arg->sign != SIGN_POS) { /* Can't hack a number < 0.0 */ - arith_invalid(result); /* Number negative */ - return 1; - } - if (exponent < -64) { - reg_move(&CONST_LN2, result); - return 0; - } - *(unsigned *) &Xll = arg->sigl; - *(((unsigned *) &Xll) + 1) = arg->sigh; - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&Xll, -1 - exponent) >= (unsigned)0x80000000) - Xll++; /* round up */ - } - *(short *) &(accum.sign) = 0; /* will be a valid positive nr with - * expon = 0 */ - accum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((unsigned *) &accum.sigl, (unsigned *) &Xll, lterms, HIPOWER - 1); - - /* Convert to 64 bit signed-compatible */ - accum.exp += EXP_BIAS - 1; - - reg_move(&accum, result); - - normalize(result); - - return 0; - -} diff --git a/sys/i386/gnu/fpemul/poly_atan.c b/sys/i386/gnu/fpemul/poly_atan.c deleted file mode 100644 index 07ec25945a..0000000000 --- a/sys/i386/gnu/fpemul/poly_atan.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * p_atan.c - * - * Compute the tan of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_atan.c,v 1.10 1999/08/28 00:42:53 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/poly_atan.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "reg_constant.h" -#include "control_w.h" - - -#define HIPOWERon 6 /* odd poly, negative terms */ -static unsigned oddnegterms[HIPOWERon][2] = -{ - {0x00000000, 0x00000000}, /* for + 1.0 */ - {0x763b6f3d, 0x1adc4428}, - {0x20f0630b, 0x0502909d}, - {0x4e825578, 0x0198ce38}, - {0x22b7cb87, 0x008da6e3}, - {0x9b30ca03, 0x00239c79} -}; -#define HIPOWERop 6 /* odd poly, positive terms */ -static unsigned oddplterms[HIPOWERop][2] = -{ - {0xa6f67cb8, 0x94d910bd}, - {0xa02ffab4, 0x0a43cb45}, - {0x04265e6b, 0x02bf5655}, - {0x0a728914, 0x00f280f7}, - {0x6d640e01, 0x004d6556}, - {0xf1dd2dbf, 0x000a530a} -}; - - -static unsigned denomterm[2] = -{0xfc4bd208, 0xea2e6612}; - - -static void poly_add_1(FPU_REG * src); - -/*--- poly_atan() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_atan(FPU_REG * arg) -{ - char recursions = 0; - short exponent; - FPU_REG odd_poly, even_poly, pos_poly, neg_poly; - FPU_REG argSq; - long long arg_signif, argSqSq; - - -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - arith_invalid(arg); - return; - } /* Need a positive number */ -#endif /* PARANOID */ - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, arg); - return; - } - if (exponent >= -2) { - /* argument is in the range [0.25 .. 1.0] */ - if (exponent >= 0) { -#ifdef PARANOID - if ((exponent == 0) && - (arg->sigl == 0) && (arg->sigh == 0x80000000)) -#endif /* PARANOID */ - { - reg_move(&CONST_PI4, arg); - return; - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic - * error */ -#endif /* PARANOID */ - } - /* If the argument is greater than sqrt(2)-1 (=0.414213562...) */ - /* convert the argument by an identity for atan */ - if ((exponent >= -1) || (arg->sigh > 0xd413ccd0)) { - FPU_REG numerator, denom; - - recursions++; - - arg_signif = *(long long *) &(arg->sigl); - if (exponent < -1) { - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - } - *(long long *) &(numerator.sigl) = -arg_signif; - numerator.exp = EXP_BIAS - 1; - normalize(&numerator); /* 1 - arg */ - - arg_signif = *(long long *) &(arg->sigl); - if (shrx(&arg_signif, -exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - *(long long *) &(denom.sigl) = arg_signif; - denom.sigh |= 0x80000000; /* 1 + arg */ - - arg->exp = numerator.exp; - reg_u_div(&numerator, &denom, arg, FULL_PRECISION); - - exponent = arg->exp - EXP_BIAS; - } - } - *(long long *) &arg_signif = *(long long *) &(arg->sigl); - -#ifdef PARANOID - /* This must always be true */ - if (exponent >= -1) { - EXCEPTION(EX_INTERNAL | 0x120); /* There must be a logic error */ - } -#endif /* PARANOID */ - - /* shift the argument right by the required places */ - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - - /* Now have arg_signif with binary point at the left .1xxxxxxxx */ - mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl)); - mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, - (unsigned short (*)[4]) oddplterms, HIPOWERop - 1); - mul64((long long *) (&argSq.sigl), (long long *) (&pos_poly.sigl), - (long long *) (&pos_poly.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, - (unsigned short (*)[4]) oddnegterms, HIPOWERon - 1); - - /* Subtract the mantissas */ - *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl)); - - reg_move(&pos_poly, &odd_poly); - poly_add_1(&odd_poly); - - /* The complete odd polynomial */ - reg_u_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(even_poly.sign) = 0; - - mul64((long long *) (&argSq.sigl), - (long long *) (&denomterm), (long long *) (&even_poly.sigl)); - - poly_add_1(&even_poly); - - reg_div(&odd_poly, &even_poly, arg, FULL_PRECISION); - - if (recursions) - reg_sub(&CONST_PI4, arg, arg, FULL_PRECISION); -} - - -/* The argument to this function must be polynomial() compatible, - i.e. have an exponent (not checked) of EXP_BIAS-1 but need not - be normalized. - This function adds 1.0 to the (assumed positive) argument. */ -static void -poly_add_1(FPU_REG * src) -{ -/* Rounding in a consistent direction produces better results - for the use of this function in poly_atan. Simple truncation - is used here instead of round-to-nearest. */ - -#ifdef OBSOLETE - char round = (src->sigl & 3) == 3; -#endif /* OBSOLETE */ - - shrx(&src->sigl, 1); - -#ifdef OBSOLETE - if (round) - (*(long long *) &src->sigl)++; /* Round to even */ -#endif /* OBSOLETE */ - - src->sigh |= 0x80000000; - - src->exp = EXP_BIAS; - -} diff --git a/sys/i386/gnu/fpemul/poly_div.s b/sys/i386/gnu/fpemul/poly_div.s deleted file mode 100644 index 7d8f69f477..0000000000 --- a/sys/i386/gnu/fpemul/poly_div.s +++ /dev/null @@ -1,139 +0,0 @@ - .file "poly_div.S" -/* - * poly_div.S - * - * A set of functions to divide 64 bit integers by fixed numbers. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_div.s,v 1.8 1999/08/28 00:42:53 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/poly_div.s,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "fpu_asm.h" - -.text - -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div2) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - shrl $1,4(%ecx) - rcrl $1,(%ecx) - - testw $1,%ax - je poly_div2_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div2_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div4) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - movl 4(%ecx),%edx - shll $30,%edx - - shrl $2,4(%ecx) - shrl $2,(%ecx) - - orl %edx,(%ecx) - - testw $2,%ax - je poly_div4_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div4_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div16) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - movl 4(%ecx),%edx - shll $28,%edx - - shrl $4,4(%ecx) - shrl $4,(%ecx) - - orl %edx,(%ecx) - - testw $8,%ax - je poly_div16_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div16_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ diff --git a/sys/i386/gnu/fpemul/poly_l2.c b/sys/i386/gnu/fpemul/poly_l2.c deleted file mode 100644 index 25ee2d51a1..0000000000 --- a/sys/i386/gnu/fpemul/poly_l2.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * poly_l2.c - * - * Compute the base 2 log of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_l2.c,v 1.10 1999/08/28 00:42:53 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/poly_l2.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -#include "reg_constant.h" -#include "control_w.h" - - - -#define HIPOWER 9 -static unsigned short lterms[HIPOWER][4] = -{ - /* Ideal computation with these coeffs gives about 64.6 bit rel - * accuracy. */ - {0xe177, 0xb82f, 0x7652, 0x7154}, - {0xee0f, 0xe80f, 0x2770, 0x7b1c}, - {0x0fc0, 0xbe87, 0xb143, 0x49dd}, - {0x78b9, 0xdadd, 0xec54, 0x34c2}, - {0x003a, 0x5de9, 0x628b, 0x2909}, - {0x5588, 0xed16, 0x4abf, 0x2193}, - {0xb461, 0x85f7, 0x347a, 0x1c6a}, - {0x0975, 0x87b3, 0xd5bf, 0x1876}, - {0xe85c, 0xcec9, 0x84e7, 0x187d} -}; - - - - -/*--- poly_l2() -------------------------------------------------------------+ - | Base 2 logarithm by a polynomial approximation. | - +---------------------------------------------------------------------------*/ -void -poly_l2(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - char zero; /* flag for an Xx == 0 */ - unsigned short bits, shift; - long long Xsq; - FPU_REG accum, denom, num, Xx; - - - exponent = arg->exp - EXP_BIAS; - - accum.tag = TW_Valid; /* set the tags to Valid */ - - if (arg->sigh > (unsigned) 0xb504f334) { - /* This is good enough for the computation of the polynomial - * sum, but actually results in a loss of precision for the - * computation of Xx. This will matter only if exponent - * becomes zero. */ - exponent++; - accum.sign = 1; /* sign to negative */ - num.exp = EXP_BIAS; /* needed to prevent errors in div - * routine */ - reg_u_div(&CONST_1, arg, &num, FULL_PRECISION); - } else { - accum.sign = 0; /* set the sign to positive */ - num.sigl = arg->sigl; /* copy the mantissa */ - num.sigh = arg->sigh; - } - - - /* shift num left, lose the ms bit */ - num.sigh <<= 1; - if (num.sigl & 0x80000000) - num.sigh |= 1; - num.sigl <<= 1; - - denom.sigl = num.sigl; - denom.sigh = num.sigh; - poly_div4((long long *) &(denom.sigl)); - denom.sigh += 0x80000000; /* set the msb */ - Xx.exp = EXP_BIAS; /* needed to prevent errors in div routine */ - reg_u_div(&num, &denom, &Xx, FULL_PRECISION); - - zero = !(Xx.sigh | Xx.sigl); - - mul64((long long *) &Xx.sigl, (long long *) &Xx.sigl, &Xsq); - poly_div16(&Xsq); - - accum.exp = -1; /* exponent of accum */ - - /* Do the basic fixed point polynomial evaluation */ - polynomial((unsigned *) &accum.sigl, (unsigned *) &Xsq, lterms, HIPOWER - 1); - - if (!exponent) { - /* If the exponent is zero, then we would lose precision by - * sticking to fixed point computation here */ - /* We need to re-compute Xx because of loss of precision. */ - FPU_REG lXx; - char sign; - - sign = accum.sign; - accum.sign = 0; - - /* make accum compatible and normalize */ - accum.exp = EXP_BIAS + accum.exp; - normalize(&accum); - - if (zero) { - reg_move(&CONST_Z, result); - } else { - /* we need to re-compute lXx to better accuracy */ - num.tag = TW_Valid; /* set the tags to Vaild */ - num.sign = 0; /* set the sign to positive */ - num.exp = EXP_BIAS - 1; - if (sign) { - /* The argument is of the form 1-x */ - /* Use 1-1/(1-x) = x/(1-x) */ - *((long long *) &num.sigl) = -*((long long *) &(arg->sigl)); - normalize(&num); - reg_div(&num, arg, &num, FULL_PRECISION); - } else { - normalize(&num); - } - - denom.tag = TW_Valid; /* set the tags to Valid */ - denom.sign = SIGN_POS; /* set the sign to positive */ - denom.exp = EXP_BIAS; - - reg_div(&num, &denom, &lXx, FULL_PRECISION); - - reg_u_mul(&lXx, &accum, &accum, FULL_PRECISION); - - reg_u_add(&lXx, &accum, result, FULL_PRECISION); - - normalize(result); - } - - result->sign = sign; - return; - } - mul64((long long *) &accum.sigl, - (long long *) &Xx.sigl, (long long *) &accum.sigl); - - *((long long *) (&accum.sigl)) += *((long long *) (&Xx.sigl)); - - if (Xx.sigh > accum.sigh) { - /* There was an overflow */ - - poly_div2((long long *) &accum.sigl); - accum.sigh |= 0x80000000; - accum.exp++; - } - /* When we add the exponent to the accum result later, we will require - * that their signs are the same. Here we ensure that this is so. */ - if (exponent && ((exponent < 0) ^ (accum.sign))) { - /* signs are different */ - - accum.sign = !accum.sign; - - /* An exceptional case is when accum is zero */ - if (accum.sigl | accum.sigh) { - /* find 1-accum */ - /* Shift to get exponent == 0 */ - if (accum.exp < 0) { - poly_div2((long long *) &accum.sigl); - accum.exp++; - } - /* Just negate, but throw away the sign */ - *((long long *) &(accum.sigl)) = -*((long long *) &(accum.sigl)); - if (exponent < 0) - exponent++; - else - exponent--; - } - } - shift = exponent >= 0 ? exponent : -exponent; - bits = 0; - if (shift) { - if (accum.exp) { - accum.exp++; - poly_div2((long long *) &accum.sigl); - } - while (shift) { - poly_div2((long long *) &accum.sigl); - if (shift & 1) - accum.sigh |= 0x80000000; - shift >>= 1; - bits++; - } - } - /* Convert to 64 bit signed-compatible */ - accum.exp += bits + EXP_BIAS - 1; - - reg_move(&accum, result); - normalize(result); - - return; -} - - -/*--- poly_l2p1() -----------------------------------------------------------+ - | Base 2 logarithm by a polynomial approximation. | - | log2(x+1) | - +---------------------------------------------------------------------------*/ -int -poly_l2p1(FPU_REG * arg, FPU_REG * result) -{ - char sign = 0; - long long Xsq; - FPU_REG arg_pl1, denom, accum, local_arg, poly_arg; - - - sign = arg->sign; - - reg_add(arg, &CONST_1, &arg_pl1, FULL_PRECISION); - - if ((arg_pl1.sign) | (arg_pl1.tag)) { /* We need a valid positive - * number! */ - return 1; - } - reg_add(&CONST_1, &arg_pl1, &denom, FULL_PRECISION); - reg_div(arg, &denom, &local_arg, FULL_PRECISION); - local_arg.sign = 0; /* Make the sign positive */ - - /* Now we need to check that |local_arg| is less than 3-2*sqrt(2) = - * 0.17157.. = .0xafb0ccc0 * 2^-2 */ - - if (local_arg.exp >= EXP_BIAS - 3) { - if ((local_arg.exp > EXP_BIAS - 3) || - (local_arg.sigh > (unsigned) 0xafb0ccc0)) { - /* The argument is large */ - poly_l2(&arg_pl1, result); - return 0; - } - } - /* Make a copy of local_arg */ - reg_move(&local_arg, &poly_arg); - - /* Get poly_arg bits aligned as required */ - shrx((unsigned *) &(poly_arg.sigl), -(poly_arg.exp - EXP_BIAS + 3)); - - mul64((long long *) &(poly_arg.sigl), (long long *) &(poly_arg.sigl), &Xsq); - poly_div16(&Xsq); - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &accum.sigl, (unsigned *) &Xsq, lterms, HIPOWER - 1); - - accum.tag = TW_Valid; /* set the tags to Valid */ - accum.sign = SIGN_POS; /* and make accum positive */ - - /* make accum compatible and normalize */ - accum.exp = EXP_BIAS - 1; - normalize(&accum); - - reg_u_mul(&local_arg, &accum, &accum, FULL_PRECISION); - - reg_u_add(&local_arg, &accum, result, FULL_PRECISION); - - /* Multiply the result by 2 */ - result->exp++; - - result->sign = sign; - - return 0; -} diff --git a/sys/i386/gnu/fpemul/poly_mul64.s b/sys/i386/gnu/fpemul/poly_mul64.s deleted file mode 100644 index 9b2d676012..0000000000 --- a/sys/i386/gnu/fpemul/poly_mul64.s +++ /dev/null @@ -1,123 +0,0 @@ -/* - * poly_mul64.S - * - * Multiply two 64 bit integers. - * - * Call from C as: - * void mul64(long long *a, long long *b, long long *result) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_mul64.s,v 1.8 1999/08/28 00:42:54 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/poly_mul64.s,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -#include "fpu_asm.h" - -.text -ENTRY(mul64) - pushl %ebp - movl %esp,%ebp - subl $16,%esp - pushl %esi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%ecx - movl PARAM3,%ebx - - xor %eax,%eax - movl %eax,-4(%ebp) - movl %eax,-8(%ebp) - - movl (%esi),%eax - mull (%ecx) - movl %eax,-16(%ebp) /* Not used */ - movl %edx,-12(%ebp) - - movl (%esi),%eax - mull 4(%ecx) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl 4(%esi),%eax - mull (%ecx) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl 4(%esi),%eax - mull 4(%ecx) - addl %eax,-8(%ebp) - adcl %edx,-4(%ebp) - - testb $128,-9(%ebp) - je L_no_round - - addl $1,-8(%ebp) - adcl $0,-4(%ebp) - -L_no_round: - movl -8(%ebp),%esi - movl %esi,(%ebx) - movl -4(%ebp),%esi - movl %esi,4(%ebx) - - popl %ebx - popl %esi - leave - ret diff --git a/sys/i386/gnu/fpemul/poly_sin.c b/sys/i386/gnu/fpemul/poly_sin.c deleted file mode 100644 index b0310dbc7a..0000000000 --- a/sys/i386/gnu/fpemul/poly_sin.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * poly_sin.c - * - * Computation of an approximation of the sin function by a polynomial - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_sin.c,v 1.10 1999/08/28 00:42:54 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/poly_sin.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#ifdef DEBUG -#include -#include /* for printf() in EXCEPTION() */ -#endif - -#include "exception.h" -#include "reg_constant.h" -#include "control_w.h" - - -#define HIPOWER 5 -static unsigned short lterms[HIPOWER][4] = -{ - {0x846a, 0x42d1, 0xb544, 0x921f}, - {0xe110, 0x75aa, 0xbc67, 0x1466}, - {0x503d, 0xa43f, 0x83c1, 0x000a}, - {0x8f9d, 0x7a19, 0x00f4, 0x0000}, - {0xda03, 0x06aa, 0x0000, 0x0000}, -}; - -static unsigned short negterms[HIPOWER][4] = -{ - {0x95ed, 0x2df2, 0xe731, 0xa55d}, - {0xd159, 0xe62b, 0xd2cc, 0x0132}, - {0x6342, 0xe9fb, 0x3c60, 0x0000}, - {0x6256, 0xdf5a, 0x0002, 0x0000}, - {0xf279, 0x000b, 0x0000, 0x0000}, -}; - - -/*--- poly_sine() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_sine(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - FPU_REG Xx, Xx2, Xx4, accum, negaccum; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, result); - return; - } -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - EXCEPTION(EX_Invalid); - reg_move(&CONST_QNaN, result); - return; - } - if (exponent >= 0) { /* Can't hack a number > 1.0 */ - if ((exponent == 0) && (arg->sigl == 0) && (arg->sigh == 0x80000000)) { - reg_move(&CONST_1, result); - return; - } - EXCEPTION(EX_Invalid); - reg_move(&CONST_QNaN, result); - return; - } -#endif /* PARANOID */ - - Xx.sigl = arg->sigl; - Xx.sigh = arg->sigh; - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&(Xx.sigl), -1 - exponent) >= (unsigned)0x80000000) - (*((long long *) (&(Xx.sigl))))++; /* round up */ - } - mul64((long long *) &(Xx.sigl), (long long *) &(Xx.sigl), - (long long *) &(Xx2.sigl)); - mul64((long long *) &(Xx2.sigl), (long long *) &(Xx2.sigl), - (long long *) &(Xx4.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(accum.sign) = 0; - accum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &(accum.sigl), (u_int *)&(Xx4.sigl), lterms, HIPOWER - 1); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(negaccum.sign) = 0; - negaccum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &(negaccum.sigl), (u_int *)&(Xx4.sigl), negterms, HIPOWER - 1); - mul64((long long *) &(Xx2.sigl), (long long *) &(negaccum.sigl), - (long long *) &(negaccum.sigl)); - - /* Subtract the mantissas */ - *((long long *) (&(accum.sigl))) -= *((long long *) (&(negaccum.sigl))); - - /* Convert to 64 bit signed-compatible */ - accum.exp = EXP_BIAS - 1 + accum.exp; - - *(short *) &(result->sign) = *(short *) &(accum.sign); - result->exp = accum.exp; - result->sigl = accum.sigl; - result->sigh = accum.sigh; - - normalize(result); - - reg_mul(result, arg, result, FULL_PRECISION); - reg_u_add(result, arg, result, FULL_PRECISION); - - /* A small overflow may be possible... but an illegal result. */ - if (result->exp >= EXP_BIAS) { - if ((result->exp > EXP_BIAS) /* Larger or equal 2.0 */ - ||(result->sigl > 1) /* Larger than 1.0+msb */ - ||(result->sigh != 0x80000000) /* Much > 1.0 */ - ) { -#ifdef DEBUGGING - RE_ENTRANT_CHECK_OFF - printk("\nEXP=%d, MS=%08x, LS=%08x\n", result->exp, - result->sigh, result->sigl); - RE_ENTRANT_CHECK_ON -#endif /* DEBUGGING */ - EXCEPTION(EX_INTERNAL | 0x103); - } -#ifdef DEBUGGING - RE_ENTRANT_CHECK_OFF - printk("\n***CORRECTING ILLEGAL RESULT*** in poly_sin() computation\n"); - printk("EXP=%d, MS=%08x, LS=%08x\n", result->exp, - result->sigh, result->sigl); - RE_ENTRANT_CHECK_ON -#endif /* DEBUGGING */ - - result->sigl = 0; /* Truncate the result to 1.00 */ - } -} diff --git a/sys/i386/gnu/fpemul/poly_tan.c b/sys/i386/gnu/fpemul/poly_tan.c deleted file mode 100644 index 7f8fca060a..0000000000 --- a/sys/i386/gnu/fpemul/poly_tan.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * poly_tan.c - * - * Compute the tan of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_tan.c,v 1.10 1999/08/28 00:42:54 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/poly_tan.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "reg_constant.h" -#include "control_w.h" - - -#define HIPOWERop 3 /* odd poly, positive terms */ -static unsigned short oddplterms[HIPOWERop][4] = -{ - {0x846a, 0x42d1, 0xb544, 0x921f}, - {0x6fb2, 0x0215, 0x95c0, 0x099c}, - {0xfce6, 0x0cc8, 0x1c9a, 0x0000} -}; -#define HIPOWERon 2 /* odd poly, negative terms */ -static unsigned short oddnegterms[HIPOWERon][4] = -{ - {0x6906, 0xe205, 0x25c8, 0x8838}, - {0x1dd7, 0x3fe3, 0x944e, 0x002c} -}; -#define HIPOWERep 2 /* even poly, positive terms */ -static unsigned short evenplterms[HIPOWERep][4] = -{ - {0xdb8f, 0x3761, 0x1432, 0x2acf}, - {0x16eb, 0x13c1, 0x3099, 0x0003} -}; -#define HIPOWERen 2 /* even poly, negative terms */ -static unsigned short evennegterms[HIPOWERen][4] = -{ - {0x3a7c, 0xe4c5, 0x7f87, 0x2945}, - {0x572b, 0x664c, 0xc543, 0x018c} -}; - - -/*--- poly_tan() ------------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_tan(FPU_REG * arg, FPU_REG * y_reg) -{ - char invert = 0; - short exponent; - FPU_REG odd_poly, even_poly, pos_poly, neg_poly; - FPU_REG argSq; - long long arg_signif, argSqSq; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, y_reg); - return; - } - if (exponent >= -1) { - /* argument is in the range [0.5 .. 1.0] */ - if (exponent >= 0) { -#ifdef PARANOID - if ((exponent == 0) && - (arg->sigl == 0) && (arg->sigh == 0x80000000)) -#endif /* PARANOID */ - { - arith_overflow(y_reg); - return; - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic - * error */ - return; -#endif /* PARANOID */ - } - /* The argument is in the range [0.5 .. 1.0) */ - /* Convert the argument to a number in the range (0.0 .. 0.5] */ - *((long long *) (&arg->sigl)) = -*((long long *) (&arg->sigl)); - normalize(arg); /* Needed later */ - exponent = arg->exp - EXP_BIAS; - invert = 1; - } -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - arith_invalid(y_reg); - return; - } /* Need a positive number */ -#endif /* PARANOID */ - - *(long long *) &arg_signif = *(long long *) &(arg->sigl); - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - } - mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl)); - mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, oddplterms, HIPOWERop - 1); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, oddnegterms, HIPOWERon - 1); - mul64((long long *) (&argSq.sigl), (long long *) (&neg_poly.sigl), - (long long *) (&neg_poly.sigl)); - - /* Subtract the mantissas */ - *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl)); - - /* Convert to 64 bit signed-compatible */ - pos_poly.exp -= 1; - - reg_move(&pos_poly, &odd_poly); - normalize(&odd_poly); - - reg_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION); - reg_u_add(&odd_poly, arg, &odd_poly, FULL_PRECISION); /* This is just the odd - * polynomial */ - - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, evenplterms, HIPOWERep - 1); - mul64((long long *) (&argSq.sigl), - (long long *) (&pos_poly.sigl), (long long *) (&pos_poly.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, evennegterms, HIPOWERen - 1); - - /* Subtract the mantissas */ - *((long long *) (&neg_poly.sigl)) -= *((long long *) (&pos_poly.sigl)); - /* and multiply by argSq */ - - /* Convert argSq to a valid reg number */ - *(short *) &(argSq.sign) = 0; - argSq.exp = EXP_BIAS - 1; - normalize(&argSq); - - /* Convert to 64 bit signed-compatible */ - neg_poly.exp -= 1; - - reg_move(&neg_poly, &even_poly); - normalize(&even_poly); - - reg_mul(&even_poly, &argSq, &even_poly, FULL_PRECISION); - reg_add(&even_poly, &argSq, &even_poly, FULL_PRECISION); - reg_sub(&CONST_1, &even_poly, &even_poly, FULL_PRECISION); /* This is just the even - * polynomial */ - - /* Now ready to copy the results */ - if (invert) { - reg_div(&even_poly, &odd_poly, y_reg, FULL_PRECISION); - } else { - reg_div(&odd_poly, &even_poly, y_reg, FULL_PRECISION); - } - -} diff --git a/sys/i386/gnu/fpemul/polynomial.s b/sys/i386/gnu/fpemul/polynomial.s deleted file mode 100644 index 51b226cbba..0000000000 --- a/sys/i386/gnu/fpemul/polynomial.s +++ /dev/null @@ -1,191 +0,0 @@ -/* - * polynomial.S - * - * Fixed point arithmetic polynomial evaluation. - * - * Call from C as: - * void polynomial(unsigned accum[], unsigned x[], unsigned terms[][2], - * int n) - * - * Computes: - * terms[0] + (terms[1] + (terms[2] + ... + (terms[n-1]*x)*x)*x)*x) ... )*x - * The result is returned in accum. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/polynomial.s,v 1.8 1999/08/28 00:42:55 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/polynomial.s,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - .file "fpolynom.s" - -#include "fpu_asm.h" - - -/* #define EXTRA_PRECISE*/ - -#define TERM_SIZE $8 - - -.text -ENTRY(polynomial) - pushl %ebp - movl %esp,%ebp - subl $32,%esp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* accum */ - movl PARAM2,%edi /* x */ - movl PARAM3,%ebx /* terms */ - movl PARAM4,%ecx /* n */ - - movl TERM_SIZE,%eax - mull %ecx - movl %eax,%ecx - - movl 4(%ebx,%ecx,1),%edx /* terms[n] */ - movl %edx,-20(%ebp) - movl (%ebx,%ecx,1),%edx /* terms[n] */ - movl %edx,-24(%ebp) - xor %eax,%eax - movl %eax,-28(%ebp) - - subl TERM_SIZE,%ecx - js L_accum_done - -L_accum_loop: - xor %eax,%eax - movl %eax,-4(%ebp) - movl %eax,-8(%ebp) - -#ifdef EXTRA_PRECISE - movl -28(%ebp),%eax - mull 4(%edi) /* x ms long */ - movl %edx,-12(%ebp) -#endif EXTRA_PRECISE - - movl -24(%ebp),%eax - mull (%edi) /* x ls long */ -/* movl %eax,-16(%ebp) */ /* Not needed */ - addl %edx,-12(%ebp) - adcl $0,-8(%ebp) - - movl -24(%ebp),%eax - mull 4(%edi) /* x ms long */ - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl -20(%ebp),%eax - mull (%edi) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl -20(%ebp),%eax - mull 4(%edi) - addl %eax,-8(%ebp) - adcl %edx,-4(%ebp) - -/* Now add the next term */ - movl (%ebx,%ecx,1),%eax - addl %eax,-8(%ebp) - movl 4(%ebx,%ecx,1),%eax - adcl %eax,-4(%ebp) - -/* And put into the second register */ - movl -4(%ebp),%eax - movl %eax,-20(%ebp) - movl -8(%ebp),%eax - movl %eax,-24(%ebp) - -#ifdef EXTRA_PRECISE - movl -12(%ebp),%eax - movl %eax,-28(%ebp) -#else - testb $128,-25(%ebp) - je L_no_poly_round - - addl $1,-24(%ebp) - adcl $0,-20(%ebp) -L_no_poly_round: -#endif EXTRA_PRECISE - - subl TERM_SIZE,%ecx - jns L_accum_loop - -L_accum_done: -#ifdef EXTRA_PRECISE -/* And round the result */ - testb $128,-25(%ebp) - je L_poly_done - - addl $1,-24(%ebp) - adcl $0,-20(%ebp) -#endif EXTRA_PRECISE - -L_poly_done: - movl -24(%ebp),%eax - movl %eax,(%esi) - movl -20(%ebp),%eax - movl %eax,4(%esi) - - popl %ebx - popl %edi - popl %esi - leave - ret diff --git a/sys/i386/gnu/fpemul/reg_add_sub.c b/sys/i386/gnu/fpemul/reg_add_sub.c deleted file mode 100644 index 1538fb0f34..0000000000 --- a/sys/i386/gnu/fpemul/reg_add_sub.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * reg_add_sub.c - * - * Functions to add or subtract two registers and put the result in a third. - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_add_sub.c,v 1.8 1999/08/28 00:42:55 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_add_sub.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | For each function, the destination may be any FPU_REG, including one of | - | the source FPU_REGs. | - +---------------------------------------------------------------------------*/ - -#include "reg_constant.h" -#include "control_w.h" - - -void -reg_add(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w) -{ - int diff; - - if (!(a->tag | b->tag)) { - /* Both registers are valid */ - if (!(a->sign ^ b->sign)) { - /* signs are the same */ - reg_u_add(a, b, dest, control_w); - dest->sign = a->sign; - return; - } - /* The signs are different, so do a subtraction */ - diff = a->exp - b->exp; - if (!diff) { - diff = a->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (!diff) { - diff = a->sigl > b->sigl; - if (!diff) - diff = -(a->sigl < b->sigl); - } - } - if (diff > 0) { - reg_u_sub(a, b, dest, control_w); - dest->sign = a->sign; - } else - if (diff == 0) { - reg_move(&CONST_Z, dest); - /* sign depends upon rounding mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } else { - reg_u_sub(b, a, dest, control_w); - dest->sign = b->sign; - } - return; - } else { - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (a->tag == TW_Zero) { - if (b->tag == TW_Zero) { - char different_signs = a->sign ^ b->sign; - /* Both are zero, result will be zero. */ - reg_move(a, dest); - if (different_signs) { - /* Signs are different. */ - /* Sign of answer depends upon - * rounding mode. */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } - } else { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - } - return; - } else - if (b->tag == TW_Zero) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag != TW_Infinity) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } - if (a->sign == b->sign) { - /* They are both + or - * - infinity */ - reg_move(a, dest); - return; - } - arith_invalid(dest); /* Infinity-Infinity is - * undefined. */ - return; - } else - if (b->tag == TW_Infinity) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - return; - } - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x101); -#endif -} - - -/* Subtract b from a. (a-b) -> dest */ -void -reg_sub(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w) -{ - int diff; - - if (!(a->tag | b->tag)) { - /* Both registers are valid */ - diff = a->exp - b->exp; - if (!diff) { - diff = a->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (!diff) { - diff = a->sigl > b->sigl; - if (!diff) - diff = -(a->sigl < b->sigl); - } - } - switch (a->sign * 2 + b->sign) { - case 0: /* P - P */ - case 3: /* N - N */ - if (diff > 0) { - reg_u_sub(a, b, dest, control_w); - dest->sign = a->sign; - } else - if (diff == 0) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(&CONST_Z, dest); - /* sign depends upon rounding mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } else { - reg_u_sub(b, a, dest, control_w); - dest->sign = a->sign ^ SIGN_POS ^ SIGN_NEG; - } - return; - case 1: /* P - N */ - reg_u_add(a, b, dest, control_w); - dest->sign = SIGN_POS; - return; - case 2: /* N - P */ - reg_u_add(a, b, dest, control_w); - dest->sign = SIGN_NEG; - return; - } - } else { - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (b->tag == TW_Zero) { - if (a->tag == TW_Zero) { - char same_signs = !(a->sign ^ b->sign); - /* Both are zero, result will be zero. */ - reg_move(a, dest); /* Answer for different - * signs. */ - if (same_signs) { - /* Sign depends upon rounding - * mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } - } else { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - } - return; - } else - if (a->tag == TW_Zero) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign ^= SIGN_POS ^ SIGN_NEG; - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag != TW_Infinity) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } - /* Both args are Infinity */ - if (a->sign == b->sign) { - arith_invalid(dest); /* Infinity-Infinity is - * undefined. */ - return; - } - reg_move(a, dest); - return; - } else - if (b->tag == TW_Infinity) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign ^= SIGN_POS ^ SIGN_NEG; - return; - } - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x110); -#endif -} diff --git a/sys/i386/gnu/fpemul/reg_compare.c b/sys/i386/gnu/fpemul/reg_compare.c deleted file mode 100644 index c79814f169..0000000000 --- a/sys/i386/gnu/fpemul/reg_compare.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * reg_compare.c - * - * Compare two floating point registers - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_compare.c,v 1.11 1999/08/28 00:42:55 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_compare.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | compare() is the core FPU_REG comparison function | - +---------------------------------------------------------------------------*/ -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "control_w.h" -#include "status_w.h" - - -int -compare(FPU_REG * b) -{ - int diff; - - if (FPU_st0_ptr->tag | b->tag) { - if (FPU_st0_ptr->tag == TW_Zero) { - if (b->tag == TW_Zero) - return COMP_A_eq_B; - if (b->tag == TW_Valid) { -#ifdef DENORM_OPERAND - if ((b->exp <= EXP_UNDER) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - } - } else - if (b->tag == TW_Zero) { - if (FPU_st0_ptr->tag == TW_Valid) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - } - } - if (FPU_st0_ptr->tag == TW_Infinity) { - if ((b->tag == TW_Valid) || (b->tag == TW_Zero)) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) - && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - } else - if (b->tag == TW_Infinity) { - /* The 80486 book says that infinities - * can be equal! */ - return (FPU_st0_ptr->sign == b->sign) ? COMP_A_eq_B : - ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); - } - /* Fall through to the NaN code */ - } else - if (b->tag == TW_Infinity) { - if ((FPU_st0_ptr->tag == TW_Valid) || (FPU_st0_ptr->tag == TW_Zero)) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->tag == TW_Valid) - && (FPU_st0_ptr->exp <= EXP_UNDER) - && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - } - /* Fall through to the NaN code */ - } - /* The only possibility now should be that one of the - * arguments is a NaN */ - if ((FPU_st0_ptr->tag == TW_NaN) || (b->tag == TW_NaN)) { - if (((FPU_st0_ptr->tag == TW_NaN) && !(FPU_st0_ptr->sigh & 0x40000000)) - || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000))) - /* At least one arg is a signaling NaN */ - return COMP_No_Comp | COMP_SNaN | COMP_NaN; - else - /* Neither is a signaling NaN */ - return COMP_No_Comp | COMP_NaN; - } - EXCEPTION(EX_Invalid); - } -#ifdef PARANOID - if (!(FPU_st0_ptr->sigh & 0x80000000)) - EXCEPTION(EX_Invalid); - if (!(b->sigh & 0x80000000)) - EXCEPTION(EX_Invalid); -#endif /* PARANOID */ - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (b->exp <= EXP_UNDER)) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign != b->sign) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - - diff = FPU_st0_ptr->exp - b->exp; - if (diff == 0) { - diff = FPU_st0_ptr->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (diff == 0) { - diff = FPU_st0_ptr->sigl > b->sigl; - if (diff == 0) - diff = -(FPU_st0_ptr->sigl < b->sigl); - } - } - if (diff > 0) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - if (diff < 0) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - return COMP_A_eq_B; - -} - - -/* This function requires that st(0) is not empty */ -int -compare_st_data(void) -{ - int f = 0, c; - - c = compare(&FPU_loaded_data); - - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - EXCEPTION(EX_Invalid); - f = SW_C3 | SW_C2 | SW_C0; - } else { - /* One of the operands is a de-normal */ - return 0; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x121); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} - - -static int -compare_st_st(int nr) -{ - int f = 0, c; - - if (!NOT_EMPTY_0 || !NOT_EMPTY(nr)) { - setcc(SW_C3 | SW_C2 | SW_C0); - /* Stack fault */ - EXCEPTION(EX_StackUnder); - return control_word & CW_Invalid; - } - c = compare(&st(nr)); - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - setcc(SW_C3 | SW_C2 | SW_C0); - EXCEPTION(EX_Invalid); - return control_word & CW_Invalid; - } else { - /* One of the operands is a de-normal */ - return control_word & CW_Denormal; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x122); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} - - -static int -compare_u_st_st(int nr) -{ - int f = 0, c; - - if (!NOT_EMPTY_0 || !NOT_EMPTY(nr)) { - setcc(SW_C3 | SW_C2 | SW_C0); - /* Stack fault */ - EXCEPTION(EX_StackUnder); - return control_word & CW_Invalid; - } - c = compare(&st(nr)); - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - setcc(SW_C3 | SW_C2 | SW_C0); - if (c & COMP_SNaN) { /* This is the only difference - * between un-ordered and - * ordinary comparisons */ - EXCEPTION(EX_Invalid); - return control_word & CW_Invalid; - } - return 1; - } else { - /* One of the operands is a de-normal */ - return control_word & CW_Denormal; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x123); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} -/*---------------------------------------------------------------------------*/ - -void -fcom_st() -{ - /* fcom st(i) */ - compare_st_st(FPU_rm); -} - - -void -fcompst() -{ - /* fcomp st(i) */ - if (compare_st_st(FPU_rm)) - pop(); -} - - -void -fcompp() -{ - /* fcompp */ - if (FPU_rm != 1) { - Un_impl(); - return; - } - if (compare_st_st(1)) { - pop(); - FPU_st0_ptr = &st(0); - pop(); - } -} - - -void -fucom_() -{ - /* fucom st(i) */ - compare_u_st_st(FPU_rm); - -} - - -void -fucomp() -{ - /* fucomp st(i) */ - if (compare_u_st_st(FPU_rm)) - pop(); -} - - -void -fucompp() -{ - /* fucompp */ - if (FPU_rm == 1) { - if (compare_u_st_st(1)) { - pop(); - FPU_st0_ptr = &st(0); - pop(); - } - } else - Un_impl(); -} diff --git a/sys/i386/gnu/fpemul/reg_constant.c b/sys/i386/gnu/fpemul/reg_constant.c deleted file mode 100644 index e88cac5b5b..0000000000 --- a/sys/i386/gnu/fpemul/reg_constant.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * reg_constant.c - * - * All of the constant FPU_REGs - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_constant.c,v 1.6.8.1 2000/08/03 00:53:55 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_constant.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - */ - - - -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "status_w.h" - - -FPU_REG CONST_1 = {SIGN_POS, TW_Valid, EXP_BIAS, -0x00000000, 0x80000000}; -static FPU_REG CONST_L2T = {SIGN_POS, TW_Valid, EXP_BIAS + 1, -0xcd1b8afe, 0xd49a784b}; -static FPU_REG CONST_L2E = {SIGN_POS, TW_Valid, EXP_BIAS, -0x5c17f0bc, 0xb8aa3b29}; -FPU_REG CONST_PI = {SIGN_POS, TW_Valid, EXP_BIAS + 1, -0x2168c235, 0xc90fdaa2}; -FPU_REG CONST_PI2 = {SIGN_POS, TW_Valid, EXP_BIAS, -0x2168c235, 0xc90fdaa2}; -FPU_REG CONST_PI4 = {SIGN_POS, TW_Valid, EXP_BIAS - 1, -0x2168c235, 0xc90fdaa2}; -static FPU_REG CONST_LG2 = {SIGN_POS, TW_Valid, EXP_BIAS - 2, -0xfbcff799, 0x9a209a84}; -FPU_REG CONST_LN2 = {SIGN_POS, TW_Valid, EXP_BIAS - 1, -0xd1cf79ac, 0xb17217f7}; -/* Only the sign (and tag) is used in internal zeroes */ -FPU_REG CONST_Z = {SIGN_POS, TW_Zero, 0, 0x0, 0x0}; -/* Only the sign and significand (and tag) are used in internal NaNs */ -/* The 80486 never generates one of these -FPU_REG CONST_SNAN = { SIGN_POS, TW_NaN, EXP_OVER, 0x00000001, 0x80000000 }; - */ -/* This is the real indefinite QNaN */ -FPU_REG CONST_QNaN = {SIGN_NEG, TW_NaN, EXP_OVER, 0x00000000, 0xC0000000}; -/* Only the sign (and tag) is used in internal infinities */ -FPU_REG CONST_INF = {SIGN_POS, TW_Infinity, EXP_OVER, 0x00000000, 0x80000000}; - - - -static void -fld_const(FPU_REG * c) -{ - FPU_REG *st_new_ptr; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - push(); - reg_move(c, FPU_st0_ptr); - status_word &= ~SW_C1; -} - - -static void -fld1(void) -{ - fld_const(&CONST_1); -} - -static void -fldl2t(void) -{ - fld_const(&CONST_L2T); -} - -static void -fldl2e(void) -{ - fld_const(&CONST_L2E); -} - -static void -fldpi(void) -{ - fld_const(&CONST_PI); -} - -static void -fldlg2(void) -{ - fld_const(&CONST_LG2); -} - -static void -fldln2(void) -{ - fld_const(&CONST_LN2); -} - -static void -fldz(void) -{ - fld_const(&CONST_Z); -} - -static FUNC constants_table[] = { - fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, Un_impl -}; - -void -fconst(void) -{ - (constants_table[FPU_rm]) (); -} diff --git a/sys/i386/gnu/fpemul/reg_constant.h b/sys/i386/gnu/fpemul/reg_constant.h deleted file mode 100644 index 1482196612..0000000000 --- a/sys/i386/gnu/fpemul/reg_constant.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * reg_constant.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_constant.h,v 1.7 1999/08/28 00:42:55 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_constant.h,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#ifndef _REG_CONSTANT_H_ -#define _REG_CONSTANT_H_ - -#include "fpu_emu.h" - -extern FPU_REG CONST_1; -extern FPU_REG CONST_2; -extern FPU_REG CONST_HALF; -extern FPU_REG CONST_L2T; -extern FPU_REG CONST_L2E; -extern FPU_REG CONST_PI; -extern FPU_REG CONST_PI2; -extern FPU_REG CONST_PI4; -extern FPU_REG CONST_LG2; -extern FPU_REG CONST_LN2; -extern FPU_REG CONST_Z; -extern FPU_REG CONST_PINF; -extern FPU_REG CONST_INF; -extern FPU_REG CONST_MINF; -extern FPU_REG CONST_QNaN; - -#endif /* _REG_CONSTANT_H_ */ diff --git a/sys/i386/gnu/fpemul/reg_div.s b/sys/i386/gnu/fpemul/reg_div.s deleted file mode 100644 index 7f74105d94..0000000000 --- a/sys/i386/gnu/fpemul/reg_div.s +++ /dev/null @@ -1,291 +0,0 @@ - .file "reg_div.S" -/* - * reg_div.S - * - * Divide one FPU_REG by another and put the result in a destination FPU_REG. - * - * Call from C as: - * void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest, - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_div.s,v 1.9.2.1 2000/07/07 00:38:42 obrien Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_div.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "fpu_asm.h" - -.text -ENTRY(reg_div) - pushl %ebp - movl %esp,%ebp - - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%ebx - movl PARAM3,%edi - - movb TAG(%esi),%al - orb TAG(%ebx),%al - - jne L_div_special /* Not (both numbers TW_Valid) */ - -#ifdef DENORM_OPERAND -/* Check for denormals */ - cmpl EXP_UNDER,EXP(%esi) - jg xL_arg1_not_denormal - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xL_arg1_not_denormal: - cmpl EXP_UNDER,EXP(%ebx) - jg xL_arg2_not_denormal - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xL_arg2_not_denormal: -#endif DENORM_OPERAND - -/* Both arguments are TW_Valid */ - movb TW_Valid,TAG(%edi) - - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%ebx) - setne (%edi) /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */ - - movl EXP(%esi),%edx - movl EXP(%ebx),%eax - subl %eax,%edx - addl EXP_BIAS,%edx - movl %edx,EXP(%edi) - - jmp _divide_kernel - - -/*-----------------------------------------------------------------------*/ -L_div_special: - cmpb TW_NaN,TAG(%esi) /* A NaN with anything to give NaN */ - je L_arg1_NaN - - cmpb TW_NaN,TAG(%ebx) /* A NaN with anything to give NaN */ - jne L_no_NaN_arg - -/* Operations on NaNs */ -L_arg1_NaN: -L_arg2_NaN: - pushl %edi /* Destination */ - pushl %ebx - pushl %esi - call real_2op_NaN - jmp LDiv_exit - -/* Invalid operations */ -L_zero_zero: -L_inf_inf: - pushl %edi /* Destination */ - call arith_invalid /* 0/0 or Infinity/Infinity */ - jmp LDiv_exit - -L_no_NaN_arg: - cmpb TW_Infinity,TAG(%esi) - jne L_arg1_not_inf - - cmpb TW_Infinity,TAG(%ebx) - je L_inf_inf /* invalid operation */ - - cmpb TW_Valid,TAG(%ebx) - je L_inf_valid - -#ifdef PARANOID - /* arg2 must be zero or valid */ - cmpb TW_Zero,TAG(%ebx) - ja L_unknown_tags -#endif PARANOID - - /* Note that p16-9 says that infinity/0 returns infinity */ - jmp L_copy_arg1 /* Answer is Inf */ - -L_inf_valid: -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%ebx) - jg L_copy_arg1 /* Answer is Inf */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif DENORM_OPERAND - - jmp L_copy_arg1 /* Answer is Inf */ - -L_arg1_not_inf: - cmpb TW_Zero,TAG(%ebx) /* Priority to div-by-zero error */ - jne L_arg2_not_zero - - cmpb TW_Zero,TAG(%esi) - je L_zero_zero /* invalid operation */ - -#ifdef PARANOID - /* arg1 must be valid */ - cmpb TW_Valid,TAG(%esi) - ja L_unknown_tags -#endif PARANOID - -/* Division by zero error */ - pushl %edi /* destination */ - movb SIGN(%esi),%al - xorb SIGN(%ebx),%al - pushl %eax /* lower 8 bits have the sign */ - call divide_by_zero - jmp LDiv_exit - -L_arg2_not_zero: - cmpb TW_Infinity,TAG(%ebx) - jne L_arg2_not_inf - -#ifdef DENORM_OPERAND - cmpb TW_Valid,TAG(%esi) - jne L_return_zero - - cmpl EXP_UNDER,EXP(%esi) - jg L_return_zero /* Answer is zero */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif DENORM_OPERAND - - jmp L_return_zero /* Answer is zero */ - -L_arg2_not_inf: - -#ifdef PARANOID - cmpb TW_Zero,TAG(%esi) - jne L_unknown_tags -#endif PARANOID - - /* arg1 is zero, arg2 is not Infinity or a NaN */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%ebx) - jg L_copy_arg1 /* Answer is zero */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif DENORM_OPERAND - -L_copy_arg1: - movb TAG(%esi),%al - movb %al,TAG(%edi) - movl EXP(%esi),%eax - movl %eax,EXP(%edi) - movl SIGL(%esi),%eax - movl %eax,SIGL(%edi) - movl SIGH(%esi),%eax - movl %eax,SIGH(%edi) - - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%ebx) - jne LDiv_negative_result - - movb SIGN_POS,SIGN(%edi) - jmp LDiv_exit - -LDiv_set_result_sign: - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%edi) - jne LDiv_negative_result - - movb SIGN_POS,SIGN(%ebx) - jmp LDiv_exit - -LDiv_negative_result: - movb SIGN_NEG,SIGN(%edi) - -LDiv_exit: - leal -12(%ebp),%esp - - popl %ebx - popl %edi - popl %esi - leave - ret - - -L_return_zero: - movb TW_Zero,TAG(%edi) - jmp LDiv_set_result_sign - -#ifdef PARANOID -L_unknown_tags: - push EX_INTERNAL | 0x208 - call EXCEPTION - - /* Generate a NaN for unknown tags */ - movl _CONST_QNaN,%eax - movl %eax,(%edi) - movl _CONST_QNaN+4,%eax - movl %eax,SIGL(%edi) - movl _CONST_QNaN+8,%eax - movl %eax,SIGH(%edi) - jmp LDiv_exit -#endif PARANOID diff --git a/sys/i386/gnu/fpemul/reg_ld_str.c b/sys/i386/gnu/fpemul/reg_ld_str.c deleted file mode 100644 index df50d6b1c9..0000000000 --- a/sys/i386/gnu/fpemul/reg_ld_str.c +++ /dev/null @@ -1,1389 +0,0 @@ -/* - * reg_ld_str.c - * - * All of the functions which transfer data between user memory and FPU_REGs. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_ld_str.c,v 1.13 1999/08/28 00:42:56 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_ld_str.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "reg_constant.h" -#include "control_w.h" -#include "status_w.h" - - -#define EXTENDED_Emax 0x3fff /* largest valid exponent */ -#define EXTENDED_Ebias 0x3fff -#define EXTENDED_Emin (-0x3ffe) /* smallest valid exponent */ - -#define DOUBLE_Emax 1023 /* largest valid exponent */ -#define DOUBLE_Ebias 1023 -#define DOUBLE_Emin (-1022) /* smallest valid exponent */ - -#define SINGLE_Emax 127 /* largest valid exponent */ -#define SINGLE_Ebias 127 -#define SINGLE_Emin (-126) /* smallest valid exponent */ - -#define LOST_UP (EX_Precision | SW_C1) -#define LOST_DOWN EX_Precision - -FPU_REG FPU_loaded_data; - - -/* Get a long double from user memory */ -void -reg_load_extended(void) -{ - long double *s = (long double *) FPU_data_address; - unsigned long sigl, sigh, exp; - - REENTRANT_CHECK(OFF); - /* Use temporary variables here because FPU_loaded data is static and - * hence re-entrancy problems can arise */ - sigl = fuword((unsigned long *) s); - sigh = fuword(1 + (unsigned long *) s); - exp = fusword(4 + (unsigned short *) s); - REENTRANT_CHECK(ON); - - FPU_loaded_data.sigl = sigl; - FPU_loaded_data.sigh = sigh; - FPU_loaded_data.exp = exp; - - if (FPU_loaded_data.exp & 0x8000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - if ((FPU_loaded_data.exp &= 0x7fff) == 0) { - if (!(FPU_loaded_data.sigl | FPU_loaded_data.sigh)) { - FPU_loaded_data.tag = TW_Zero; - return; - } - /* The number is a de-normal or pseudodenormal. */ - /* The 80486 doesn't regard pseudodenormals as denormals here. */ - if (!(FPU_loaded_data.sigh & 0x80000000)) - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp++; - - /* The default behaviour will now take care of it. */ - } else - if (FPU_loaded_data.exp == 0x7fff) { - FPU_loaded_data.exp = EXTENDED_Emax; - if ((FPU_loaded_data.sigh == 0x80000000) - && (FPU_loaded_data.sigl == 0)) { - FPU_loaded_data.tag = TW_Infinity; - return; - } else - if (!(FPU_loaded_data.sigh & 0x80000000)) { - /* Unsupported NaN data type */ - EXCEPTION(EX_Invalid); - FPU_loaded_data.tag = TW_NaN; - return; - } - FPU_loaded_data.tag = TW_NaN; - return; - } - FPU_loaded_data.exp = (FPU_loaded_data.exp & 0x7fff) - EXTENDED_Ebias - + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - - if (!(sigh & 0x80000000)) { - /* Unsupported data type */ - EXCEPTION(EX_Invalid); - normalize_nuo(&FPU_loaded_data); - } -} - - -/* Get a double from user memory */ -void -reg_load_double(void) -{ - double *dfloat = (double *) FPU_data_address; - int exp; - unsigned m64, l64; - - REENTRANT_CHECK(OFF); - m64 = fuword(1 + (unsigned long *) dfloat); - l64 = fuword((unsigned long *) dfloat); - REENTRANT_CHECK(ON); - - if (m64 & 0x80000000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias; - m64 &= 0xfffff; - if (exp > DOUBLE_Emax) { - /* Infinity or NaN */ - if ((m64 == 0) && (l64 == 0)) { - /* +- infinity */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_Infinity; - return; - } else { - /* Must be a signaling or quiet NaN */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_NaN; - FPU_loaded_data.sigh = (m64 << 11) | 0x80000000; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - return; - } - } else - if (exp < DOUBLE_Emin) { - /* Zero or de-normal */ - if ((m64 == 0) && (l64 == 0)) { - /* Zero */ - int c = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = c; - return; - } else { - /* De-normal */ - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp = DOUBLE_Emin + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = m64 << 11; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - normalize_nuo(&FPU_loaded_data); - return; - } - } else { - FPU_loaded_data.exp = exp + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = (m64 << 11) | 0x80000000; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - - return; - } -} - - -/* Get a float from user memory */ -void -reg_load_single(void) -{ - float *single = (float *) FPU_data_address; - unsigned m32; - int exp; - - REENTRANT_CHECK(OFF); - m32 = fuword((unsigned long *) single); - REENTRANT_CHECK(ON); - - if (m32 & 0x80000000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - if (!(m32 & 0x7fffffff)) { - /* Zero */ - int c = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = c; - return; - } - exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias; - m32 = (m32 & 0x7fffff) << 8; - if (exp < SINGLE_Emin) { - /* De-normals */ - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp = SINGLE_Emin + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = m32; - FPU_loaded_data.sigl = 0; - normalize_nuo(&FPU_loaded_data); - return; - } else - if (exp > SINGLE_Emax) { - /* Infinity or NaN */ - if (m32 == 0) { - /* +- infinity */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_Infinity; - return; - } else { - /* Must be a signaling or quiet NaN */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_NaN; - FPU_loaded_data.sigh = m32 | 0x80000000; - FPU_loaded_data.sigl = 0; - return; - } - } else { - FPU_loaded_data.exp = exp + EXP_BIAS; - FPU_loaded_data.sigh = m32 | 0x80000000; - FPU_loaded_data.sigl = 0; - FPU_loaded_data.tag = TW_Valid; - } -} - - -/* Get a long long from user memory */ -void -reg_load_int64(void) -{ - long long *_s = (long long *) FPU_data_address; - int e; - long long s; - - REENTRANT_CHECK(OFF); - ((unsigned long *) &s)[0] = fuword((unsigned long *) _s); - ((unsigned long *) &s)[1] = fuword(1 + (unsigned long *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 63; - *((long long *) &FPU_loaded_data.sigl) = s; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a long from user memory */ -void -reg_load_int32(void) -{ - long *_s = (long *) FPU_data_address; - long s; - int e; - - REENTRANT_CHECK(OFF); - s = (long) fuword((unsigned long *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 31; - FPU_loaded_data.sigh = s; - FPU_loaded_data.sigl = 0; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a short from user memory */ -void -reg_load_int16(void) -{ - short *_s = (short *) FPU_data_address; - int s, e; - - REENTRANT_CHECK(OFF); - /* Cast as short to get the sign extended. */ - s = (short) fusword((unsigned short *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 15; - FPU_loaded_data.sigh = s << 16; - - FPU_loaded_data.sigl = 0; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a packed bcd array from user memory */ -void -reg_load_bcd(void) -{ - char *s = (char *) FPU_data_address; - int pos; - unsigned char bcd; - long long l = 0; - - for (pos = 8; pos >= 0; pos--) { - l *= 10; - REENTRANT_CHECK(OFF); - bcd = (unsigned char) fubyte((unsigned char *) s + pos); - REENTRANT_CHECK(ON); - l += bcd >> 4; - l *= 10; - l += bcd & 0x0f; - } - - /* Finish all access to user memory before putting stuff into the - * static FPU_loaded_data */ - REENTRANT_CHECK(OFF); - FPU_loaded_data.sign = - ((unsigned char) fubyte((unsigned char *) s + 9)) & 0x80 ? - SIGN_NEG : SIGN_POS; - REENTRANT_CHECK(ON); - - if (l == 0) { - char sign = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = sign; - } else { - *((long long *) &FPU_loaded_data.sigl) = l; - FPU_loaded_data.exp = EXP_BIAS + 63; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); - } -} -/*===========================================================================*/ - -/* Put a long double into user memory */ -int -reg_store_extended(void) -{ - long double *d = (long double *) FPU_data_address; - long e = FPU_st0_ptr->exp - EXP_BIAS + EXTENDED_Ebias; - unsigned short sign = FPU_st0_ptr->sign * 0x8000; - unsigned long ls, ms; - - - if (FPU_st0_tag == TW_Valid) { - if (e >= 0x7fff) { - EXCEPTION(EX_Overflow); /* Overflow */ - /* This is a special case: see sec 16.2.5.1 of the - * 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - ls = 0; - ms = 0x80000000; - e = 0x7fff; - } else - return 0; - } else - if (e <= 0) { - if (e > -63) { - /* Correctly format the de-normal */ - int precision_loss; - FPU_REG tmp; - - EXCEPTION(EX_Denormal); - reg_move(FPU_st0_ptr, &tmp); - tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */ - if ((precision_loss = round_to_int(&tmp))) { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see - * sec 16.2.5.1 of the 80486 - * book */ - if (!(control_word & EX_Underflow)) - return 0; - } - e = 0; - ls = tmp.sigl; - ms = tmp.sigh; - } else { - /* ****** ??? This should not be - * possible */ - EXCEPTION(EX_Underflow); /* Underflow */ - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (control_word & EX_Underflow) { - /* Underflow to zero */ - ls = 0; - ms = 0; - e = FPU_st0_ptr->sign == SIGN_POS ? 0x7fff : 0xffff; - } else - return 0; - } - } else { - ls = FPU_st0_ptr->sigl; - ms = FPU_st0_ptr->sigh; - } - } else - if (FPU_st0_tag == TW_Zero) { - ls = ms = 0; - e = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - ls = 0; - ms = 0x80000000; - e = 0x7fff; - } else - if (FPU_st0_tag == TW_NaN) { - ls = FPU_st0_ptr->sigl; - ms = FPU_st0_ptr->sigh; - e = 0x7fff; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - ls = 0; - ms = 0xc0000000; - e = 0xffff; - } else - return 0; - } else { - /* We don't use TW_Denormal - * yet ... perhaps never! */ - EXCEPTION(EX_Invalid); - /* Store a NaN */ - e = 0x7fff; - ls = 1; - ms = 0x80000000; - } - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 10); */ - suword((unsigned long *) d, ls); - suword(1 + (unsigned long *) d, ms); - susword(4 + (short *) d, (unsigned short) e | sign); - REENTRANT_CHECK(ON); - - return 1; - -} - - -/* Put a double into user memory */ -int -reg_store_double(void) -{ - double *dfloat = (double *) FPU_data_address; - unsigned long l[2]; - if (FPU_st0_tag == TW_Valid) { - int exp; - FPU_REG tmp; - - reg_move(FPU_st0_ptr, &tmp); - exp = tmp.exp - EXP_BIAS; - - if (exp < DOUBLE_Emin) { /* It may be a denormal */ - /* Make a de-normal */ - int precision_loss; - - if (exp <= -EXTENDED_Ebias) - EXCEPTION(EX_Denormal); - - tmp.exp += -DOUBLE_Emin + 52; /* largest exp to be 51 */ - - if ((precision_loss = round_to_int(&tmp))) { -#ifdef PECULIAR_486 - /* Did it round to a non-denormal ? */ - /* This behaviour might be regarded as - * peculiar, it appears that the 80486 rounds - * to the dest precision, then converts to - * decide underflow. */ - if ((tmp.sigh == 0x00100000) && (tmp.sigl == 0) && - (FPU_st0_ptr->sigl & 0x000007ff)) - EXCEPTION(precision_loss); - else -#endif /* PECULIAR_486 */ - { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (!(control_word & EX_Underflow)) - return 0; - } - } - l[0] = tmp.sigl; - l[1] = tmp.sigh; - } else { - if (tmp.sigl & 0x000007ff) { - unsigned long increment = 0; /* avoid gcc warnings */ - - switch (control_word & CW_RC) { - case RC_RND: - /* Rounding can get a little messy.. */ - increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */ - ((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */ - break; - case RC_DOWN: /* towards -infinity */ - increment = (tmp.sign == SIGN_POS) ? 0 : tmp.sigl & 0x7ff; - break; - case RC_UP: /* towards +infinity */ - increment = (tmp.sign == SIGN_POS) ? tmp.sigl & 0x7ff : 0; - break; - case RC_CHOP: - increment = 0; - break; - } - - /* Truncate the mantissa */ - tmp.sigl &= 0xfffff800; - - if (increment) { - set_precision_flag_up(); - - if (tmp.sigl >= 0xfffff800) { - /* the sigl part overflows */ - if (tmp.sigh == 0xffffffff) { - /* The sigh part - * overflows */ - tmp.sigh = 0x80000000; - exp++; - if (exp >= EXP_OVER) - goto overflow; - } else { - tmp.sigh++; - } - tmp.sigl = 0x00000000; - } else { - /* We only need to increment - * sigl */ - tmp.sigl += 0x00000800; - } - } else - set_precision_flag_down(); - } - l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21); - l[1] = ((tmp.sigh >> 11) & 0xfffff); - - if (exp > DOUBLE_Emax) { - overflow: - EXCEPTION(EX_Overflow); - /* This is a special case: see sec 16.2.5.1 of - * the 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - l[0] = 0x00000000; /* Set to */ - l[1] = 0x7ff00000; /* + INF */ - } else - return 0; - } else { - /* Add the exponent */ - l[1] |= (((exp + DOUBLE_Ebias) & 0x7ff) << 20); - } - } - } else - if (FPU_st0_tag == TW_Zero) { - /* Number is zero */ - l[0] = 0; - l[1] = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - l[0] = 0; - l[1] = 0x7ff00000; - } else - if (FPU_st0_tag == TW_NaN) { - /* See if we can get a valid NaN from - * the FPU_REG */ - l[0] = (FPU_st0_ptr->sigl >> 11) | (FPU_st0_ptr->sigh << 21); - l[1] = ((FPU_st0_ptr->sigh >> 11) & 0xfffff); - if (!(l[0] | l[1])) { - /* This case does not seem to - * be handled by the 80486 - * specs */ - EXCEPTION(EX_Invalid); - /* Make the quiet NaN "real - * indefinite" */ - goto put_indefinite; - } - l[1] |= 0x7ff00000; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - put_indefinite: - REENTRANT_CHECK(OFF); - /* verify_area(VERIFY_W - * RITE, (void *) - * dfloat, 8); */ - suword((unsigned long *) dfloat, 0); - suword(1 + (unsigned long *) dfloat, 0xfff80000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - else - if (FPU_st0_tag == TW_Denormal) { - /* Extended real -> - * double real will - * always underflow */ - l[0] = l[1] = 0; - EXCEPTION(EX_Underflow); - } -#endif - if (FPU_st0_ptr->sign) - l[1] |= 0x80000000; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) dfloat, 8);*/ - suword((u_long *) dfloat, l[0]); - suword((u_long *) dfloat + 1, l[1]); -/* - suword(l[0], (unsigned long *) dfloat); - suword(l[1], 1 + (unsigned long *) dfloat);*/ - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a float into user memory */ -int -reg_store_single(void) -{ - float *single = (float *) FPU_data_address; - long templ = 0; - - if (FPU_st0_tag == TW_Valid) { - int exp; - FPU_REG tmp; - - reg_move(FPU_st0_ptr, &tmp); - exp = tmp.exp - EXP_BIAS; - - if (exp < SINGLE_Emin) { - /* Make a de-normal */ - int precision_loss; - - if (exp <= -EXTENDED_Ebias) - EXCEPTION(EX_Denormal); - - tmp.exp += -SINGLE_Emin + 23; /* largest exp to be 22 */ - - if ((precision_loss = round_to_int(&tmp))) { -#ifdef PECULIAR_486 - /* Did it round to a non-denormal ? */ - /* This behaviour might be regarded as - * peculiar, it appears that the 80486 rounds - * to the dest precision, then converts to - * decide underflow. */ - if ((tmp.sigl == 0x00800000) && - ((FPU_st0_ptr->sigh & 0x000000ff) || FPU_st0_ptr->sigl)) - EXCEPTION(precision_loss); - else -#endif /* PECULIAR_486 */ - { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (!(control_word & EX_Underflow)) - return 0; - } - } - templ = tmp.sigl; - } else { - if (tmp.sigl | (tmp.sigh & 0x000000ff)) { - unsigned long increment = 0; /* avoid gcc warnings */ - unsigned long sigh = tmp.sigh; - unsigned long sigl = tmp.sigl; - - switch (control_word & CW_RC) { - case RC_RND: - increment = ((sigh & 0xff) > 0x80) /* more than half */ - ||(((sigh & 0xff) == 0x80) && sigl) /* more than half */ - ||((sigh & 0x180) == 0x180); /* round to even */ - break; - case RC_DOWN: /* towards -infinity */ - increment = (tmp.sign == SIGN_POS) - ? 0 : (sigl | (sigh & 0xff)); - break; - case RC_UP: /* towards +infinity */ - increment = (tmp.sign == SIGN_POS) - ? (sigl | (sigh & 0xff)) : 0; - break; - case RC_CHOP: - increment = 0; - break; - } - - /* Truncate part of the mantissa */ - tmp.sigl = 0; - - if (increment) { - set_precision_flag_up(); - - if (sigh >= 0xffffff00) { - /* The sigh part overflows */ - tmp.sigh = 0x80000000; - exp++; - if (exp >= EXP_OVER) - goto overflow; - } else { - tmp.sigh &= 0xffffff00; - tmp.sigh += 0x100; - } - } else { - set_precision_flag_down(); - tmp.sigh &= 0xffffff00; /* Finish the truncation */ - } - } - templ = (tmp.sigh >> 8) & 0x007fffff; - - if (exp > SINGLE_Emax) { - overflow: - EXCEPTION(EX_Overflow); - /* This is a special case: see sec 16.2.5.1 of - * the 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - templ = 0x7f800000; - } else - return 0; - } else - templ |= ((exp + SINGLE_Ebias) & 0xff) << 23; - } - } else - if (FPU_st0_tag == TW_Zero) { - templ = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - templ = 0x7f800000; - } else - if (FPU_st0_tag == TW_NaN) { - /* See if we can get a valid NaN from - * the FPU_REG */ - templ = FPU_st0_ptr->sigh >> 8; - if (!(templ & 0x3fffff)) { - /* This case does not seem to - * be handled by the 80486 - * specs */ - EXCEPTION(EX_Invalid); - /* Make the quiet NaN "real - * indefinite" */ - goto put_indefinite; - } - templ |= 0x7f800000; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - put_indefinite: - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) single, 4); */ - suword((unsigned long *) single, 0xffc00000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - else - if (FPU_st0_tag == TW_Denormal) { - /* Extended real -> - * real will always - * underflow */ - templ = 0; - EXCEPTION(EX_Underflow); - } -#endif -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x106); - return 0; - } -#endif - if (FPU_st0_ptr->sign) - templ |= 0x80000000; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) single, 4); */ - suword((unsigned long *) single, templ); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a long long into user memory */ -int -reg_store_int64(void) -{ - long long *d = (long long *) FPU_data_address; - FPU_REG t; - long long tll; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - goto put_indefinite; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - ((long *) &tll)[0] = t.sigl; - ((long *) &tll)[1] = t.sigh; - if ((t.sigh & 0x80000000) && - !((t.sigh == 0x80000000) && (t.sigl == 0) && (t.sign == SIGN_NEG))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - put_indefinite: - ((long *) &tll)[1] = 0x80000000; - ((long *) &tll)[0] = 0; - } else - return 0; - } else - if (t.sign) - tll = -tll; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) d, 8); */ - suword((unsigned long *) d, ((long *) &tll)[0]); - suword(1 + (unsigned long *) d, ((long *) &tll)[1]); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a long into user memory */ -int -reg_store_int32(void) -{ - long *d = (long *) FPU_data_address; - FPU_REG t; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 4);*/ - suword((unsigned long *) d, 0x80000000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - if (t.sigh || - ((t.sigl & 0x80000000) && - !((t.sigl == 0x80000000) && (t.sign == SIGN_NEG)))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - t.sigl = 0x80000000; - } else - return 0; - } else - if (t.sign) - t.sigl = -(long) t.sigl; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 4); */ - suword((unsigned long *) d, t.sigl); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a short into user memory */ -int -reg_store_int16(void) -{ - short *d = (short *) FPU_data_address; - FPU_REG t; - short ts; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 2);*/ - susword((unsigned short *) d, 0x8000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - if (t.sigh || - ((t.sigl & 0xffff8000) && - !((t.sigl == 0x8000) && (t.sign == SIGN_NEG)))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - ts = 0x8000; - } else - return 0; - } else - if (t.sign) - t.sigl = -t.sigl; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 2); */ - susword((short *) d, (short) t.sigl); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a packed bcd array into user memory */ -int -reg_store_bcd(void) -{ - char *d = (char *) FPU_data_address; - FPU_REG t; - long long ll; - unsigned char b; - int i; - unsigned char sign = (FPU_st0_ptr->sign == SIGN_NEG) ? 0x80 : 0; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - goto put_indefinite; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - ll = *(long long *) (&t.sigl); - - /* Check for overflow, by comparing with 999999999999999999 decimal. */ - if ((t.sigh > 0x0de0b6b3) || - ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - put_indefinite: - /* Produce "indefinite" */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 10);*/ - subyte((unsigned char *) d + 7, 0xff); - subyte((unsigned char *) d + 8, 0xff); - subyte((unsigned char *) d + 9, 0xff); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -/* verify_area(VERIFY_WRITE, d, 10);*/ - for (i = 0; i < 9; i++) { - b = div_small(&ll, 10); - b |= (div_small(&ll, 10)) << 4; - REENTRANT_CHECK(OFF); - subyte((unsigned char *) d + i, b); - REENTRANT_CHECK(ON); - } - REENTRANT_CHECK(OFF); - subyte((unsigned char *) d + 9, sign); - REENTRANT_CHECK(ON); - - return 1; -} -/*===========================================================================*/ - -/* r gets mangled such that sig is int, sign: - it is NOT normalized */ -/* The return value (in eax) is zero if the result is exact, - if bits are changed due to rounding, truncation, etc, then - a non-zero value is returned */ -/* Overflow is signalled by a non-zero return value (in eax). - In the case of overflow, the returned significand always has the - the largest possible value */ -/* The value returned in eax is never actually needed :-) */ -int -round_to_int(FPU_REG * r) -{ - char very_big; - unsigned eax; - - if (r->tag == TW_Zero) { - /* Make sure that zero is returned */ - *(long long *) &r->sigl = 0; - return 0; /* o.k. */ - } - if (r->exp > EXP_BIAS + 63) { - r->sigl = r->sigh = ~0; /* The largest representable number */ - return 1; /* overflow */ - } - eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp); - very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */ -#define half_or_more (eax & 0x80000000) -#define frac_part (eax) -#define more_than_half ((eax & 0x80000001) == 0x80000001) - switch (control_word & CW_RC) { - case RC_RND: - if (more_than_half /* nearest */ - || (half_or_more && (r->sigl & 1))) { /* odd -> even */ - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_DOWN: - if (frac_part && r->sign) { - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_UP: - if (frac_part && !r->sign) { - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_CHOP: - break; - } - - return eax ? LOST_DOWN : 0; - -} -/*===========================================================================*/ - -char * -fldenv(void) -{ - char *s = (char *) FPU_data_address; - unsigned short tag_word = 0; - unsigned char tag; - int i; - - REENTRANT_CHECK(OFF); - control_word = fusword((unsigned short *) s); - status_word = fusword((unsigned short *) (s + 4)); - tag_word = fusword((unsigned short *) (s + 8)); - ip_offset = fuword((unsigned long *) (s + 0x0c)); - cs_selector = fuword((unsigned long *) (s + 0x10)); - data_operand_offset = fuword((unsigned long *) (s + 0x14)); - operand_selector = fuword((unsigned long *) (s + 0x18)); - REENTRANT_CHECK(ON); - - top = (status_word >> SW_Top_Shift) & 7; - - for (i = 0; i < 8; i++) { - tag = tag_word & 3; - tag_word >>= 2; - - switch (tag) { - case 0: - regs[i].tag = TW_Valid; - break; - case 1: - regs[i].tag = TW_Zero; - break; - case 2: - regs[i].tag = TW_NaN; - break; - case 3: - regs[i].tag = TW_Empty; - break; - } - } - - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - - return s + 0x1c; -} - - -void -frstor(void) -{ - int i, stnr; - unsigned char tag; - unsigned short saved_status, saved_control; - char *s = (char *) fldenv(); - - saved_status = status_word; - saved_control = control_word; - control_word = 0x037f; /* Mask all interrupts while we load. */ - for (i = 0; i < 8; i++) { - /* load each register */ - FPU_data_address = (void *) (s + i * 10); - reg_load_extended(); - stnr = (i + top) & 7; - tag = regs[stnr].tag; /* derived from the loaded tag word */ - reg_move(&FPU_loaded_data, ®s[stnr]); - if (tag == TW_NaN) { - /* The current data is a special, i.e. NaN, - * unsupported, infinity, or denormal */ - unsigned char t = regs[stnr].tag; /* derived from the new - * data */ - if ( /* (t == TW_Valid) || *** */ (t == TW_Zero)) - regs[stnr].tag = TW_NaN; - } else - regs[stnr].tag = tag; - } - control_word = saved_control; - status_word = saved_status; - - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; -} - - -unsigned short -tag_word(void) -{ - unsigned short word = 0; - unsigned char tag; - int i; - - for (i = 7; i >= 0; i--) { - switch (tag = regs[i].tag) { -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - case TW_Denormal: -#endif - case TW_Valid: - if (regs[i].exp <= (EXP_BIAS - EXTENDED_Ebias)) - tag = 2; - break; - case TW_Infinity: - case TW_NaN: - tag = 2; - break; - case TW_Empty: - tag = 3; - break; - /* TW_Valid and TW_Zero already have the correct value */ - } - word <<= 2; - word |= tag; - } - return word; -} - - -char * -fstenv(void) -{ - char *d = (char *) FPU_data_address; - -/* verify_area(VERIFY_WRITE, d, 28);*/ - -#if 0 /****/ - *(unsigned short *) &cs_selector = fpu_cs; - *(unsigned short *) &operand_selector = fpu_os; -#endif /****/ - - REENTRANT_CHECK(OFF); - susword((unsigned short *) d, control_word); - susword((unsigned short *) (d + 4), (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift)); - susword((unsigned short *) (d + 8), tag_word()); - suword((unsigned long *) (d + 0x0c), ip_offset); - suword((unsigned long *) (d + 0x10), cs_selector); - suword((unsigned long *) (d + 0x14), data_operand_offset); - suword((unsigned long *) (d + 0x18), operand_selector); - REENTRANT_CHECK(ON); - - return d + 0x1c; -} - - -void -fsave(void) -{ - char *d; - FPU_REG tmp, *rp; - int i; - short e; - - d = fstenv(); -/* verify_area(VERIFY_WRITE, d, 80);*/ - for (i = 0; i < 8; i++) { - /* Store each register in the order: st(0), st(1), ... */ - rp = ®s[(top + i) & 7]; - - e = rp->exp - EXP_BIAS + EXTENDED_Ebias; - - if (rp->tag == TW_Valid) { - if (e >= 0x7fff) { - /* Overflow to infinity */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (e <= 0) { - if (e > -63) { - /* Make a de-normal */ - reg_move(rp, &tmp); - tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */ - round_to_int(&tmp); - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), tmp.sigl); - suword((unsigned long *) (d + i * 10 + 4), tmp.sigh); - REENTRANT_CHECK(ON); - } else { - /* Underflow to zero */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - } - e = 0; - } else { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - } - } else - if (rp->tag == TW_Zero) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - e = 0; - } else - if (rp->tag == TW_Infinity) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0x80000000); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (rp->tag == TW_NaN) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (rp->tag == TW_Empty) { - /* just copy the reg */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - } - e |= rp->sign == SIGN_POS ? 0 : 0x8000; - REENTRANT_CHECK(OFF); - susword((unsigned short *) (d + i * 10 + 8), e); - REENTRANT_CHECK(ON); - } - - finit(); - -} -/*===========================================================================*/ diff --git a/sys/i386/gnu/fpemul/reg_mul.c b/sys/i386/gnu/fpemul/reg_mul.c deleted file mode 100644 index c4d88fe6a2..0000000000 --- a/sys/i386/gnu/fpemul/reg_mul.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * reg_mul.c - * - * Multiply one FPU_REG by another, put the result in a destination FPU_REG. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_mul.c,v 1.8 1999/08/28 00:42:56 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_mul.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | The destination may be any FPU_REG, including one of the source FPU_REGs. | - +---------------------------------------------------------------------------*/ - -#include "reg_constant.h" - - -/* This routine must be called with non-empty source registers */ -void -reg_mul(FPU_REG * a, FPU_REG * b, FPU_REG * dest, unsigned int control_w) -{ - char sign = (a->sign ^ b->sign); - - if (!(a->tag | b->tag)) { - /* This should be the most common case */ - reg_u_mul(a, b, dest, control_w); - dest->sign = sign; - return; - } else - if ((a->tag <= TW_Zero) && (b->tag <= TW_Zero)) { -#ifdef DENORM_OPERAND - if (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) || - ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER))) { - if (denormal_operand()) - return; - } -#endif /* DENORM_OPERAND */ - /* Must have either both arguments == zero, or one - * valid and the other zero. The result is therefore - * zero. */ - reg_move(&CONST_Z, dest); -#ifdef PECULIAR_486 - /* The 80486 book says that the answer is +0, but a - * real 80486 appears to behave this way... */ - dest->sign = sign; -#endif /* PECULIAR_486 */ - return; - } -#if 0 /* TW_Denormal is not used yet... perhaps - * never will be. */ - else - if ((a->tag <= TW_Denormal) && (b->tag <= TW_Denormal)) { - /* One or both arguments are de-normalized */ - /* Internal de-normalized numbers are not - * supported yet */ - EXCEPTION(EX_INTERNAL | 0x105); - reg_move(&CONST_Z, dest); - } -#endif - else { - /* Must have infinities, NaNs, etc */ - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag == TW_Zero) { - arith_invalid(dest); - return; - } - /* Zero*Infinity is invalid */ - else { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - dest->sign = sign; - } - return; - } else - if (b->tag == TW_Infinity) { - if (a->tag == TW_Zero) { - arith_invalid(dest); - return; - } - /* Zero*Infinity is - * invalid */ - else { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign = sign; - } - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x102); - } -#endif /* PARANOID */ - } -} diff --git a/sys/i386/gnu/fpemul/reg_norm.s b/sys/i386/gnu/fpemul/reg_norm.s deleted file mode 100644 index 6ae87fc41f..0000000000 --- a/sys/i386/gnu/fpemul/reg_norm.s +++ /dev/null @@ -1,177 +0,0 @@ -/* - * reg_norm.s - * - * Normalize the value in a FPU_REG. - * - * Call from C as: - * void normalize(FPU_REG *n) - * - * void normalize_nuo(FPU_REG *n) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_norm.s,v 1.8 1999/08/28 00:42:57 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_norm.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -#include "fpu_asm.h" - - -.text - -ENTRY(normalize) - pushl %ebp - movl %esp,%ebp - pushl %ebx - - movl PARAM1,%ebx - - movl SIGH(%ebx),%edx - movl SIGL(%ebx),%eax - - orl %edx,%edx /* ms bits */ - js L_done /* Already normalized */ - jnz L_shift_1 /* Shift left 1 - 31 bits */ - - orl %eax,%eax - jz L_zero /* The contents are zero */ - -/* L_shift_32: */ - movl %eax,%edx - xorl %eax,%eax - subl $32,EXP(%ebx) /* This can cause an underflow */ - -/* We need to shift left by 1 - 31 bits */ -L_shift_1: - bsrl %edx,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%eax,%edx - shl %cl,%eax - subl %ecx,EXP(%ebx) /* This can cause an underflow */ - - movl %edx,SIGH(%ebx) - movl %eax,SIGL(%ebx) - -L_done: - cmpl EXP_OVER,EXP(%ebx) - jge L_overflow - - cmpl EXP_UNDER,EXP(%ebx) - jle L_underflow - -L_exit: - popl %ebx - leave - ret - - -L_zero: - movl EXP_UNDER,EXP(%ebx) - movb TW_Zero,TAG(%ebx) - jmp L_exit - -L_underflow: - push %ebx - call arith_underflow - pop %ebx - jmp L_exit - -L_overflow: - push %ebx - call arith_overflow - pop %ebx - jmp L_exit - - - -/* Normalise without reporting underflow or overflow */ -ENTRY(normalize_nuo) - pushl %ebp - movl %esp,%ebp - pushl %ebx - - movl PARAM1,%ebx - - movl SIGH(%ebx),%edx - movl SIGL(%ebx),%eax - - orl %edx,%edx /* ms bits */ - js L_exit /* Already normalized */ - jnz L_nuo_shift_1 /* Shift left 1 - 31 bits */ - - orl %eax,%eax - jz L_zero /* The contents are zero */ - -/* L_nuo_shift_32: */ - movl %eax,%edx - xorl %eax,%eax - subl $32,EXP(%ebx) /* This can cause an underflow */ - -/* We need to shift left by 1 - 31 bits */ -L_nuo_shift_1: - bsrl %edx,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%eax,%edx - shl %cl,%eax - subl %ecx,EXP(%ebx) /* This can cause an underflow */ - - movl %edx,SIGH(%ebx) - movl %eax,SIGL(%ebx) - jmp L_exit - - diff --git a/sys/i386/gnu/fpemul/reg_round.s b/sys/i386/gnu/fpemul/reg_round.s deleted file mode 100644 index 47502a2175..0000000000 --- a/sys/i386/gnu/fpemul/reg_round.s +++ /dev/null @@ -1,651 +0,0 @@ - .file "reg_round.S" -/* - * reg_round.S - * - * Rounding/truncation/etc for FPU basic arithmetic functions. - * - * This code has four possible entry points. - * The following must be entered by a jmp intruction: - * FPU_round, FPU_round_sqrt, and FPU_Arith_exit. - * - * The _round_reg entry point is intended to be used by C code. - * From C, call as: - * void round_reg(FPU_REG *arg, unsigned int extent, unsigned int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_round.s,v 1.9.2.1 2000/07/07 00:38:42 obrien Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_round.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -/*---------------------------------------------------------------------------+ - | Four entry points. | - | | - | Needed by both the FPU_round and FPU_round_sqrt entry points: | - | %eax:%ebx 64 bit significand | - | %edx 32 bit extension of the significand | - | %edi pointer to an FPU_REG for the result to be stored | - | stack calling function must have set up a C stack frame and | - | pushed %esi, %edi, and %ebx | - | | - | Needed just for the FPU_round_sqrt entry point: | - | %cx A control word in the same format as the FPU control word. | - | Otherwise, PARAM4 must give such a value. | - | | - | | - | The significand and its extension are assumed to be exact in the | - | following sense: | - | If the significand by itself is the exact result then the significand | - | extension (%edx) must contain 0, otherwise the significand extension | - | must be non-zero. | - | If the significand extension is non-zero then the significand is | - | smaller than the magnitude of the correct exact result by an amount | - | greater than zero and less than one ls bit of the significand. | - | The significand extension is only required to have three possible | - | non-zero values: | - | less than 0x80000000 <=> the significand is less than 1/2 an ls | - | bit smaller than the magnitude of the | - | true exact result. | - | exactly 0x80000000 <=> the significand is exactly 1/2 an ls bit | - | smaller than the magnitude of the true | - | exact result. | - | greater than 0x80000000 <=> the significand is more than 1/2 an ls | - | bit smaller than the magnitude of the | - | true exact result. | - | | - +---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------+ - | The code in this module has become quite complex, but it should handle | - | all of the FPU flags which are set at this stage of the basic arithmetic | - | computations. | - | There are a few rare cases where the results are not set identically to | - | a real FPU. These require a bit more thought because at this stage the | - | results of the code here appear to be more consistent... | - | This may be changed in a future version. | - +---------------------------------------------------------------------------*/ - - -#include "exception.h" -#include "control_w.h" - -#define LOST_DOWN $1 -#define LOST_UP $2 -#define DENORMAL $1 -#define UNMASKED_UNDERFLOW $2 - -.data - ALIGN_DATA -FPU_bits_lost: - .byte 0 -FPU_denormal: - .byte 0 - -.text -.globl FPU_round -.globl FPU_round_sqrt -.globl FPU_Arith_exit - -/* Entry point when called from C */ -ENTRY(round_reg) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%edi - movl SIGH(%edi),%eax - movl SIGL(%edi),%ebx - movl PARAM2,%edx - movl PARAM3,%ecx - jmp FPU_round_sqrt - -FPU_round: /* Normal entry point */ - movl PARAM4,%ecx - -FPU_round_sqrt: /* Entry point from wm_sqrt.S */ - -#ifdef PARANOID -/* Cannot use this here yet */ -/* orl %eax,%eax */ -/* jns L_entry_bugged */ -#endif PARANOID - - cmpl EXP_UNDER,EXP(%edi) - jle xMake_denorm /* The number is a de-normal*/ - - movb $0,FPU_denormal /* 0 -> not a de-normal*/ - -xDenorm_done: - movb $0,FPU_bits_lost /*No bits yet lost in rounding*/ - - movl %ecx,%esi - andl CW_PC,%ecx - cmpl PR_64_BITS,%ecx - je LRound_To_64 - - cmpl PR_53_BITS,%ecx - je LRound_To_53 - - cmpl PR_24_BITS,%ecx - je LRound_To_24 - -#ifdef PARANOID - jmp L_bugged /* There is no bug, just a bad control word */ -#endif PARANOID - - -/* Round etc to 24 bit precision */ -LRound_To_24: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_24 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_24 - - cmpl RC_UP,%ecx /* Towards +infinity */ - je LUp_24 - - cmpl RC_DOWN,%ecx /* Towards -infinity */ - je LDown_24 - -#ifdef PARANOID - jmp L_bugged -#endif PARANOID - -LUp_24: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_24 /* If negative then up==truncate */ - - jmp LCheck_24_round_up - -LDown_24: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_24 /* If positive then down==truncate */ - -LCheck_24_round_up: - movl %eax,%ecx - andl $0x000000ff,%ecx - orl %ebx,%ecx - orl %edx,%ecx - jnz LDo_24_round_up - jmp LRe_normalise - -LRound_nearest_24: - /* Do rounding of the 24th bit if needed (nearest or even) */ - movl %eax,%ecx - andl $0x000000ff,%ecx - cmpl $0x00000080,%ecx - jc LCheck_truncate_24 /*less than half, no increment needed*/ - - jne LGreater_Half_24 /* greater than half, increment needed*/ - - /* Possibly half, we need to check the ls bits */ - orl %ebx,%ebx - jnz LGreater_Half_24 /* greater than half, increment needed*/ - - orl %edx,%edx - jnz LGreater_Half_24 /* greater than half, increment needed*/ - - /* Exactly half, increment only if 24th bit is 1 (round to even)*/ - testl $0x00000100,%eax - jz LDo_truncate_24 - -LGreater_Half_24: /*Rounding: increment at the 24th bit*/ -LDo_24_round_up: - andl $0xffffff00,%eax /*Truncate to 24 bits*/ - xorl %ebx,%ebx - movb LOST_UP,FPU_bits_lost - addl $0x00000100,%eax - jmp LCheck_Round_Overflow - -LCheck_truncate_24: - movl %eax,%ecx - andl $0x000000ff,%ecx - orl %ebx,%ecx - orl %edx,%ecx - jz LRe_normalise /* No truncation needed*/ - -LDo_truncate_24: - andl $0xffffff00,%eax /* Truncate to 24 bits*/ - xorl %ebx,%ebx - movb LOST_DOWN,FPU_bits_lost - jmp LRe_normalise - - -/* Round etc to 53 bit precision */ -LRound_To_53: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_53 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_53 - - cmpl RC_UP,%ecx /* Towards +infinity*/ - je LUp_53 - - cmpl RC_DOWN,%ecx /* Towards -infinity*/ - je LDown_53 - -#ifdef PARANOID - jmp L_bugged -#endif PARANOID - -LUp_53: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_53 /* If negative then up==truncate*/ - - jmp LCheck_53_round_up - -LDown_53: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_53 /* If positive then down==truncate*/ - -LCheck_53_round_up: - movl %ebx,%ecx - andl $0x000007ff,%ecx - orl %edx,%ecx - jnz LDo_53_round_up - jmp LRe_normalise - -LRound_nearest_53: - /*Do rounding of the 53rd bit if needed (nearest or even)*/ - movl %ebx,%ecx - andl $0x000007ff,%ecx - cmpl $0x00000400,%ecx - jc LCheck_truncate_53 /* less than half, no increment needed*/ - - jnz LGreater_Half_53 /* greater than half, increment needed*/ - - /*Possibly half, we need to check the ls bits*/ - orl %edx,%edx - jnz LGreater_Half_53 /* greater than half, increment needed*/ - - /* Exactly half, increment only if 53rd bit is 1 (round to even)*/ - testl $0x00000800,%ebx - jz LTruncate_53 - -LGreater_Half_53: /*Rounding: increment at the 53rd bit*/ -LDo_53_round_up: - movb LOST_UP,FPU_bits_lost - andl $0xfffff800,%ebx /* Truncate to 53 bits*/ - addl $0x00000800,%ebx - adcl $0,%eax - jmp LCheck_Round_Overflow - -LCheck_truncate_53: - movl %ebx,%ecx - andl $0x000007ff,%ecx - orl %edx,%ecx - jz LRe_normalise - -LTruncate_53: - movb LOST_DOWN,FPU_bits_lost - andl $0xfffff800,%ebx /* Truncate to 53 bits*/ - jmp LRe_normalise - - -/* Round etc to 64 bit precision*/ -LRound_To_64: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_64 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_64 - - cmpl RC_UP,%ecx /* Towards +infinity*/ - je LUp_64 - - cmpl RC_DOWN,%ecx /* Towards -infinity*/ - je LDown_64 - -#ifdef PARANOID - jmp L_bugged -#endif PARANOID - -LUp_64: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_64 /* If negative then up==truncate*/ - - orl %edx,%edx - jnz LDo_64_round_up - jmp LRe_normalise - -LDown_64: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_64 /*If positive then down==truncate*/ - - orl %edx,%edx - jnz LDo_64_round_up - jmp LRe_normalise - -LRound_nearest_64: - cmpl $0x80000000,%edx - jc LCheck_truncate_64 - - jne LDo_64_round_up - - /* Now test for round-to-even */ - testb $1,%bl - jz LCheck_truncate_64 - -LDo_64_round_up: - movb LOST_UP,FPU_bits_lost - addl $1,%ebx - adcl $0,%eax - -LCheck_Round_Overflow: - jnc LRe_normalise /* Rounding done, no overflow */ - - /* Overflow, adjust the result (to 1.0) */ - rcrl $1,%eax - rcrl $1,%ebx - incl EXP(%edi) - jmp LRe_normalise - -LCheck_truncate_64: - orl %edx,%edx - jz LRe_normalise - -LTruncate_64: - movb LOST_DOWN,FPU_bits_lost - -LRe_normalise: - testb $0xff,FPU_denormal - jnz xNormalise_result - -xL_Normalised: - cmpb LOST_UP,FPU_bits_lost - je xL_precision_lost_up - - cmpb LOST_DOWN,FPU_bits_lost - je xL_precision_lost_down - -xL_no_precision_loss: - cmpl EXP_OVER,EXP(%edi) - jge L_overflow - - /* store the result */ - movb TW_Valid,TAG(%edi) - -xL_Store_significand: - movl %eax,SIGH(%edi) - movl %ebx,SIGL(%edi) - -FPU_Arith_exit: - popl %ebx - popl %edi - popl %esi - leave - ret - - -/* Set the FPU status flags to represent precision loss due to*/ -/* round-up.*/ -xL_precision_lost_up: - push %eax - call set_precision_flag_up - popl %eax - jmp xL_no_precision_loss - -/* Set the FPU status flags to represent precision loss due to*/ -/* truncation.*/ -xL_precision_lost_down: - push %eax - call set_precision_flag_down - popl %eax - jmp xL_no_precision_loss - - -/* The number is a denormal (which might get rounded up to a normal) -// Shift the number right the required number of bits, which will -// have to be undone later...*/ -xMake_denorm: - /* The action to be taken depends upon whether the underflow - // exception is masked*/ - testb CW_Underflow,%cl /* Underflow mask.*/ - jz xUnmasked_underflow /* Do not make a denormal.*/ - - movb DENORMAL,FPU_denormal - - pushl %ecx /* Save*/ - movl EXP(%edi),%ecx - subl EXP_UNDER+1,%ecx - negl %ecx - - cmpl $64,%ecx /* shrd only works for 0..31 bits */ - jnc xDenorm_shift_more_than_63 - - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc xDenorm_shift_more_than_32 - -/* We got here without jumps by assuming that the most common requirement -// is for a small de-normalising shift. -// Shift by [1..31] bits */ - addl %ecx,EXP(%edi) - orl %edx,%edx /* extension*/ - setne %ch - xorl %edx,%edx - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orb %ch,%dl - popl %ecx - jmp xDenorm_done - -/* Shift by [32..63] bits*/ -xDenorm_shift_more_than_32: - addl %ecx,EXP(%edi) - subb $32,%cl - orl %edx,%edx - setne %ch - orb %ch,%bl - xorl %edx,%edx - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orl %edx,%edx /*test these 32 bits*/ - setne %cl - orb %ch,%bl - orb %cl,%bl - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - popl %ecx - jmp xDenorm_done - -/* Shift by [64..) bits*/ -xDenorm_shift_more_than_63: - cmpl $64,%ecx - jne xDenorm_shift_more_than_64 - -/* Exactly 64 bit shift*/ - addl %ecx,EXP(%edi) - xorl %ecx,%ecx - orl %edx,%edx - setne %cl - orl %ebx,%ebx - setne %ch - orb %ch,%cl - orb %cl,%al - movl %eax,%edx - xorl %eax,%eax - xorl %ebx,%ebx - popl %ecx - jmp xDenorm_done - -xDenorm_shift_more_than_64: - movl EXP_UNDER+1,EXP(%edi) -/* This is easy, %eax must be non-zero, so..*/ - movl $1,%edx - xorl %eax,%eax - xorl %ebx,%ebx - popl %ecx - jmp xDenorm_done - - -xUnmasked_underflow: - /* Increase the exponent by the magic number*/ - addl $(3*(1<<13)),EXP(%edi) - movb UNMASKED_UNDERFLOW,FPU_denormal - jmp xDenorm_done - - -/* Undo the de-normalisation.*/ -xNormalise_result: - cmpb UNMASKED_UNDERFLOW,FPU_denormal - je xSignal_underflow - -/* The number must be a denormal if we got here.*/ -#ifdef PARANOID - /* But check it... just in case.*/ - cmpl EXP_UNDER+1,EXP(%edi) - jne L_norm_bugged -#endif PARANOID - - orl %eax,%eax /* ms bits*/ - jnz LNormalise_shift_up_to_31 /* Shift left 0 - 31 bits*/ - - orl %ebx,%ebx - jz L_underflow_to_zero /* The contents are zero*/ - -/* Shift left 32 - 63 bits*/ - movl %ebx,%eax - xorl %ebx,%ebx - subl $32,EXP(%edi) - -LNormalise_shift_up_to_31: - bsrl %eax,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%ebx,%eax - shl %cl,%ebx - subl %ecx,EXP(%edi) - -LNormalise_shift_done: - testb $0xff,FPU_bits_lost /* bits lost == underflow*/ - jz xL_Normalised - - /* There must be a masked underflow*/ - push %eax - pushl EX_Underflow - call exception - popl %eax - popl %eax - jmp xL_Normalised - - -/* The operations resulted in a number too small to represent. -// Masked response.*/ -L_underflow_to_zero: - push %eax - call set_precision_flag_down - popl %eax - - push %eax - pushl EX_Underflow - call exception - popl %eax - popl %eax - - movb TW_Zero,TAG(%edi) - jmp xL_Store_significand - - -/* The operations resulted in a number too large to represent.*/ -L_overflow: - push %edi - call arith_overflow - pop %edi - jmp FPU_Arith_exit - - -xSignal_underflow: - push %eax - pushl EX_Underflow - call EXCEPTION - popl %eax - popl %eax - jmp xL_Normalised - - -#ifdef PARANOID -/* If we ever get here then we have problems! */ -L_bugged: - pushl EX_INTERNAL|0x201 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit - -L_norm_bugged: - pushl EX_INTERNAL|0x216 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit - -L_entry_bugged: - pushl EX_INTERNAL|0x217 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit -#endif PARANOID diff --git a/sys/i386/gnu/fpemul/reg_u_add.s b/sys/i386/gnu/fpemul/reg_u_add.s deleted file mode 100644 index cf91d8695e..0000000000 --- a/sys/i386/gnu/fpemul/reg_u_add.s +++ /dev/null @@ -1,241 +0,0 @@ - .file "reg_u_add.S" -/* - * reg_u_add.S - * - * Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the - * result in a destination FPU_REG. - * - * Call from C as: - * void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, - * int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_add.s,v 1.9 1999/08/28 00:42:57 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_u_add.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -/* - | Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ). - | Takes two valid reg f.p. numbers (TW_Valid), which are - | treated as unsigned numbers, - | and returns their sum as a TW_Valid or TW_S f.p. number. - | The returned number is normalized. - | Basic checks are performed if PARANOID is defined. - */ - -#include "fpu_asm.h" - -.text -ENTRY(reg_u_add) - pushl %ebp - movl %esp,%ebp -/* subl $16,%esp*/ - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* source 1 */ - movl PARAM2,%edi /* source 2 */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%esi) - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - cmpl EXP_UNDER,EXP(%edi) - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif DENORM_OPERAND - -/* xorl %ecx,%ecx*/ - movl EXP(%esi),%ecx - subl EXP(%edi),%ecx /* exp1 - exp2 */ -/* jnc L_arg1_larger*/ - jge L_arg1_larger - - /* num1 is smaller */ - movl SIGL(%esi),%ebx - movl SIGH(%esi),%eax - - movl %edi,%esi - negw %cx - jmp L_accum_loaded - -L_arg1_larger: - /* num1 has larger or equal exponent */ - movl SIGL(%edi),%ebx - movl SIGH(%edi),%eax - -L_accum_loaded: - movl PARAM3,%edi /* destination */ - movb SIGN(%esi),%dl - movb %dl,SIGN(%edi) /* Copy the sign from the first arg */ - - - movl EXP(%esi),%edx - movl %edx,EXP(%edi) /* Copy exponent to destination */ - - xorl %edx,%edx /* clear the extension */ - -#ifdef PARANOID - testl $0x80000000,%eax - je L_bugged - - testl $0x80000000,SIGH(%esi) - je L_bugged -#endif PARANOID - -/* The number to be shifted is in %eax:%ebx:%edx*/ - cmpw $32,%cx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - jmp L_shift_done - -L_more_than_31: - cmpw $64,%cx - jnc L_more_than_63 - - subb $32,%cl - jz L_exactly_32 - - shrd %cl,%eax,%edx - shr %cl,%eax - orl %ebx,%ebx - jz L_more_31_no_low /* none of the lowest bits is set*/ - - orl $1,%edx /* record the fact in the extension*/ - -L_more_31_no_low: - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_exactly_32: - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_more_than_63: - cmpw $65,%cx - jnc L_more_than_64 - - movl %eax,%edx - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_64: - movl $1,%edx /* The shifted nr always at least one '1'*/ - -L_more_63_no_low: - xorl %ebx,%ebx - xorl %eax,%eax - -L_shift_done: - /* Now do the addition */ - addl SIGL(%esi),%ebx - adcl SIGH(%esi),%eax - jnc L_round_the_result - - /* Overflow, adjust the result */ - rcrl $1,%eax - rcrl $1,%ebx - rcrl $1,%edx - jnc L_no_bit_lost - - orl $1,%edx - -L_no_bit_lost: - incl EXP(%edi) - -L_round_the_result: - jmp FPU_round /* Round the result*/ - - - -#ifdef PARANOID -/* If we ever get here then we have problems! */ -L_bugged: - pushl EX_INTERNAL|0x201 - call EXCEPTION - pop %ebx - jmp L_exit -#endif PARANOID - - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret diff --git a/sys/i386/gnu/fpemul/reg_u_div.s b/sys/i386/gnu/fpemul/reg_u_div.s deleted file mode 100644 index 85b60fcedc..0000000000 --- a/sys/i386/gnu/fpemul/reg_u_div.s +++ /dev/null @@ -1,502 +0,0 @@ - .file "reg_u_div.S" -/* - * reg_u_div.S - * - * Core division routines - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_div.s,v 1.9 1999/08/28 00:42:58 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_u_div.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Kernel for the division routines. | - | | - | void reg_u_div(FPU_REG *a, FPU_REG *a, | - | FPU_REG *dest, unsigned int control_word) | - | | - | Does not compute the destination exponent, but does adjust it. | - +---------------------------------------------------------------------------*/ - -#include "fpu_asm.h" - - -/* #define dSIGL(x) (x) */ -/* #define dSIGH(x) 4(x) */ - - -.data -/* - Local storage: - Result: accum_3:accum_2:accum_1:accum_0 - Overflow flag: ovfl_flag - */ - ALIGN_DATA -accum_3: - .long 0 -accum_2: - .long 0 -accum_1: - .long 0 -accum_0: - .long 0 -result_1: - .long 0 -result_2: - .long 0 -ovfl_flag: - .byte 0 - - -.text - -.globl _divide_kernel - -ENTRY(reg_u_div) - pushl %ebp - movl %esp,%ebp - - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* pointer to num */ - movl PARAM2,%ebx /* pointer to denom */ - movl PARAM3,%edi /* pointer to answer */ - -#ifdef DENORM_OPERAND - movl EXP(%esi),%eax - cmpl EXP_UNDER,%eax - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - movl EXP(%ebx),%eax - cmpl EXP_UNDER,%eax - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif DENORM_OPERAND - -_divide_kernel: -#ifdef PARANOID -/* testl $0x80000000, SIGH(%esi) *//* Dividend */ -/* je L_bugged */ - testl $0x80000000, SIGH(%ebx) /* Divisor*/ - je L_bugged -#endif PARANOID - -/* Check if the divisor can be treated as having just 32 bits */ - cmpl $0,SIGL(%ebx) - jnz L_Full_Division /* Can't do a quick divide */ - -/* We should be able to zip through the division here */ - movl SIGH(%ebx),%ecx /* The divisor */ - movl SIGH(%esi),%edx /* Dividend */ - movl SIGL(%esi),%eax /* Dividend */ - - cmpl %ecx,%edx - setaeb ovfl_flag /* Keep a record */ - jb L_no_adjust - - subl %ecx,%edx /* Prevent the overflow */ - -L_no_adjust: - /* Divide the 64 bit number by the 32 bit denominator */ - divl %ecx - movl %eax,result_2 - - /* Work on the remainder of the first division */ - xorl %eax,%eax - divl %ecx - movl %eax,result_1 - - /* Work on the remainder of the 64 bit division */ - xorl %eax,%eax - divl %ecx - - testb $255,ovfl_flag /* was the num > denom ? */ - je L_no_overflow - - /* Do the shifting here */ - /* increase the exponent */ - incl EXP(%edi) - - /* shift the mantissa right one bit */ - stc /* To set the ms bit */ - rcrl result_2 - rcrl result_1 - rcrl %eax - -L_no_overflow: - jmp LRound_precision /* Do the rounding as required*/ - - -/*---------------------------------------------------------------------------+ - | Divide: Return arg1/arg2 to arg3. | - | | - | This routine does not use the exponents of arg1 and arg2, but does | - | adjust the exponent of arg3. | - | | - | The maximum returned value is (ignoring exponents) | - | .ffffffff ffffffff | - | ------------------ = 1.ffffffff fffffffe | - | .80000000 00000000 | - | and the minimum is | - | .80000000 00000000 | - | ------------------ = .80000000 00000001 (rounded) | - | .ffffffff ffffffff | - | | - +---------------------------------------------------------------------------*/ - - -L_Full_Division: - /* Save extended dividend in local register*/ - movl SIGL(%esi),%eax - movl %eax,accum_2 - movl SIGH(%esi),%eax - movl %eax,accum_3 - xorl %eax,%eax - movl %eax,accum_1 /* zero the extension */ - movl %eax,accum_0 /* zero the extension */ - - movl SIGL(%esi),%eax /* Get the current num */ - movl SIGH(%esi),%edx - -/*----------------------------------------------------------------------*/ -/* Initialization done */ -/* Do the first 32 bits */ - - movb $0,ovfl_flag - cmpl SIGH(%ebx),%edx /* Test for imminent overflow */ - jb LLess_than_1 - ja LGreater_than_1 - - cmpl SIGL(%ebx),%eax - jb LLess_than_1 - -LGreater_than_1: -/* The dividend is greater or equal, would cause overflow */ - setaeb ovfl_flag /* Keep a record */ - - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx /* Prevent the overflow */ - movl %eax,accum_2 - movl %edx,accum_3 - -LLess_than_1: -/* At this point, we have a dividend < divisor, with a record of - adjustment in ovfl_flag */ - - /* We will divide by a number which is too large */ - movl SIGH(%ebx),%ecx - addl $1,%ecx - jnc LFirst_div_not_1 - - /* here we need to divide by 100000000h, - i.e., no division at all.. */ - mov %edx,%eax - jmp LFirst_div_done - -LFirst_div_not_1: - divl %ecx /* Divide the numerator by the augmented - denom ms dw */ - -LFirst_div_done: - movl %eax,result_2 /* Put the result in the answer */ - - mull SIGH(%ebx) /* mul by the ms dw of the denom */ - - subl %eax,accum_2 /* Subtract from the num local reg */ - sbbl %edx,accum_3 - - movl result_2,%eax /* Get the result back */ - mull SIGL(%ebx) /* now mul the ls dw of the denom */ - - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - sbbl $0,accum_3 - je LDo_2nd_32_bits /* Must check for non-zero result here */ - -#ifdef PARANOID - jb L_bugged_1 -#endif PARANOID - - /* need to subtract another once of the denom */ - incl result_2 /* Correct the answer */ - - movl SIGL(%ebx),%eax - movl SIGH(%ebx),%edx - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - -#ifdef PARANOID - sbbl $0,accum_3 - jne L_bugged_1 /* Must check for non-zero result here */ -#endif PARANOID - -/*----------------------------------------------------------------------*/ -/* Half of the main problem is done, there is just a reduced numerator - to handle now */ -/* Work with the second 32 bits, accum_0 not used from now on */ -LDo_2nd_32_bits: - movl accum_2,%edx /* get the reduced num */ - movl accum_1,%eax - - /* need to check for possible subsequent overflow */ - cmpl SIGH(%ebx),%edx - jb LDo_2nd_div - ja LPrevent_2nd_overflow - - cmpl SIGL(%ebx),%eax - jb LDo_2nd_div - -LPrevent_2nd_overflow: -/* The numerator is greater or equal, would cause overflow */ - /* prevent overflow */ - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx - movl %edx,accum_2 - movl %eax,accum_1 - - incl result_2 /* Reflect the subtraction in the answer */ - -#ifdef PARANOID - je L_bugged_2 /* Can't bump the result to 1.0 */ -#endif PARANOID - -LDo_2nd_div: - cmpl $0,%ecx /* augmented denom msw*/ - jnz LSecond_div_not_1 - - /* %ecx == 0, we are dividing by 1.0 */ - mov %edx,%eax - jmp LSecond_div_done - -LSecond_div_not_1: - divl %ecx /* Divide the numerator by the denom ms dw */ - -LSecond_div_done: - movl %eax,result_1 /* Put the result in the answer */ - - mull SIGH(%ebx) /* mul by the ms dw of the denom */ - - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - -#ifdef PARANOID - jc L_bugged_2 -#endif PARANOID - - movl result_1,%eax /* Get the result back */ - mull SIGL(%ebx) /* now mul the ls dw of the denom */ - - subl %eax,accum_0 /* Subtract from the num local reg */ - sbbl %edx,accum_1 /* Subtract from the num local reg */ - sbbl $0,accum_2 - -#ifdef PARANOID - jc L_bugged_2 -#endif PARANOID - - jz LDo_3rd_32_bits - -#ifdef PARANOID - cmpl $1,accum_2 - jne L_bugged_2 -#endif PARANOID - - /* need to subtract another once of the denom */ - movl SIGL(%ebx),%eax - movl SIGH(%ebx),%edx - subl %eax,accum_0 /* Subtract from the num local reg */ - sbbl %edx,accum_1 - sbbl $0,accum_2 - -#ifdef PARANOID - jc L_bugged_2 - jne L_bugged_2 -#endif PARANOID - - addl $1,result_1 /* Correct the answer */ - adcl $0,result_2 - -#ifdef PARANOID - jc L_bugged_2 /* Must check for non-zero result here */ -#endif PARANOID - -/*----------------------------------------------------------------------*/ -/* The division is essentially finished here, we just need to perform - tidying operations. */ -/* deal with the 3rd 32 bits */ -LDo_3rd_32_bits: - movl accum_1,%edx /* get the reduced num */ - movl accum_0,%eax - - /* need to check for possible subsequent overflow */ - cmpl SIGH(%ebx),%edx /* denom*/ - jb LRound_prep - ja LPrevent_3rd_overflow - - cmpl SIGL(%ebx),%eax /* denom */ - jb LRound_prep - -LPrevent_3rd_overflow: - /* prevent overflow */ - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx - movl %edx,accum_1 - movl %eax,accum_0 - - addl $1,result_1 /* Reflect the subtraction in the answer */ - adcl $0,result_2 - jne LRound_prep - jnc LRound_prep - - /* This is a tricky spot, there is an overflow of the answer */ - movb $255,ovfl_flag /* Overflow -> 1.000 */ - -LRound_prep: -/* Prepare for rounding. -// To test for rounding, we just need to compare 2*accum with the -// denom. */ - movl accum_0,%ecx - movl accum_1,%edx - movl %ecx,%eax - orl %edx,%eax - jz LRound_ovfl /* The accumulator contains zero.*/ - - /* Multiply by 2 */ - clc - rcll $1,%ecx - rcll $1,%edx - jc LRound_large /* No need to compare, denom smaller */ - - subl SIGL(%ebx),%ecx - sbbl SIGH(%ebx),%edx - jnc LRound_not_small - - movl $0x70000000,%eax /* Denom was larger */ - jmp LRound_ovfl - -LRound_not_small: - jnz LRound_large - - movl $0x80000000,%eax /* Remainder was exactly 1/2 denom */ - jmp LRound_ovfl - -LRound_large: - movl $0xff000000,%eax /* Denom was smaller */ - -LRound_ovfl: -/* We are now ready to deal with rounding, but first we must get - the bits properly aligned */ - testb $255,ovfl_flag /* was the num > denom ? */ - je LRound_precision - - incl EXP(%edi) - - /* shift the mantissa right one bit */ - stc /* Will set the ms bit */ - rcrl result_2 - rcrl result_1 - rcrl %eax - -/* Round the result as required */ -LRound_precision: - decl EXP(%edi) /* binary point between 1st & 2nd bits */ - - movl %eax,%edx - movl result_1,%ebx - movl result_2,%eax - jmp FPU_round - - -#ifdef PARANOID -/* The logic is wrong if we got here */ -L_bugged: - pushl EX_INTERNAL|0x202 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_1: - pushl EX_INTERNAL|0x203 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_2: - pushl EX_INTERNAL|0x204 - call EXCEPTION - pop %ebx - jmp L_exit - -L_exit: - popl %ebx - popl %edi - popl %esi - - leave - ret -#endif PARANOID diff --git a/sys/i386/gnu/fpemul/reg_u_mul.s b/sys/i386/gnu/fpemul/reg_u_mul.s deleted file mode 100644 index 126ed4c9ff..0000000000 --- a/sys/i386/gnu/fpemul/reg_u_mul.s +++ /dev/null @@ -1,195 +0,0 @@ - .file "reg_u_mul.S" -/* - * reg_u_mul.S - * - * Core multiplication routine - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_mul.s,v 1.9 1999/08/28 00:42:58 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_u_mul.s,v 1.4 2003/08/07 21:17:21 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Basic multiplication routine. | - | Does not check the resulting exponent for overflow/underflow | - | | - | reg_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw); | - | | - | Internal working is at approx 128 bits. | - | Result is rounded to nearest 53 or 64 bits, using "nearest or even". | - +---------------------------------------------------------------------------*/ - -#include "fpu_asm.h" - - -.data - ALIGN_DATA -accum_0: - .long 0 -accum_1: - .long 0 - - -.text -ENTRY(reg_u_mul) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%edi - -#ifdef PARANOID - testl $0x80000000,SIGH(%esi) - jz L_bugged - testl $0x80000000,SIGH(%edi) - jz L_bugged -#endif PARANOID - -#ifdef DENORM_OPERAND - movl EXP(%esi),%eax - cmpl EXP_UNDER,%eax - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - movl EXP(%edi),%eax - cmpl EXP_UNDER,%eax - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif DENORM_OPERAND - - xorl %ecx,%ecx - xorl %ebx,%ebx - - movl SIGL(%esi),%eax - mull SIGL(%edi) - movl %eax,accum_0 - movl %edx,accum_1 - - movl SIGL(%esi),%eax - mull SIGH(%edi) - addl %eax,accum_1 - adcl %edx,%ebx -/* adcl $0,%ecx *//* overflow here is not possible */ - - movl SIGH(%esi),%eax - mull SIGL(%edi) - addl %eax,accum_1 - adcl %edx,%ebx - adcl $0,%ecx - - movl SIGH(%esi),%eax - mull SIGH(%edi) - addl %eax,%ebx - adcl %edx,%ecx - - movl EXP(%esi),%eax /* Compute the exponent */ - addl EXP(%edi),%eax - subl EXP_BIAS-1,%eax -/* Have now finished with the sources */ - movl PARAM3,%edi /* Point to the destination */ - movl %eax,EXP(%edi) - -/* Now make sure that the result is normalized */ - testl $0x80000000,%ecx - jnz LResult_Normalised - - /* Normalize by shifting left one bit */ - shll $1,accum_0 - rcll $1,accum_1 - rcll $1,%ebx - rcll $1,%ecx - decl EXP(%edi) - -LResult_Normalised: - movl accum_0,%eax - movl accum_1,%edx - orl %eax,%eax - jz L_extent_zero - - orl $1,%edx - -L_extent_zero: - movl %ecx,%eax - jmp FPU_round - - -#ifdef PARANOID -L_bugged: - pushl EX_INTERNAL|0x205 - call EXCEPTION - pop %ebx - jmp L_exit - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret -#endif PARANOID - diff --git a/sys/i386/gnu/fpemul/reg_u_sub.s b/sys/i386/gnu/fpemul/reg_u_sub.s deleted file mode 100644 index cec12eaca4..0000000000 --- a/sys/i386/gnu/fpemul/reg_u_sub.s +++ /dev/null @@ -1,358 +0,0 @@ - .file "reg_u_sub.S" -/* - * reg_u_sub.S - * - * Core floating point subtraction routine. - * - * Call from C as: - * void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, - * int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_sub.s,v 1.9 1999/08/28 00:42:58 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/reg_u_sub.s,v 1.4 2003/08/07 21:17:21 dillon Exp $ - * - */ - -/* - | Kernel subtraction routine reg_u_sub(reg *arg1, reg *arg2, reg *answ). - | Takes two valid reg f.p. numbers (TW_Valid), which are - | treated as unsigned numbers, - | and returns their difference as a TW_Valid or TW_Zero f.p. - | number. - | The first number (arg1) must be the larger. - | The returned number is normalized. - | Basic checks are performed if PARANOID is defined. - */ - -#include "fpu_asm.h" - -.text -ENTRY(reg_u_sub) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* source 1 */ - movl PARAM2,%edi /* source 2 */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%esi) - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - cmpl EXP_UNDER,EXP(%edi) - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif DENORM_OPERAND - -/* xorl %ecx,%ecx */ - movl EXP(%esi),%ecx - subl EXP(%edi),%ecx /* exp1 - exp2 */ - -#ifdef PARANOID - /* source 2 is always smaller than source 1 */ -/* jc L_bugged */ - js L_bugged_1 - - testl $0x80000000,SIGH(%edi) /* The args are assumed to be be normalized */ - je L_bugged_2 - - testl $0x80000000,SIGH(%esi) - je L_bugged_2 -#endif PARANOID - -/*--------------------------------------+ - | Form a register holding the | - | smaller number | - +--------------------------------------*/ - movl SIGH(%edi),%eax /* register ms word */ - movl SIGL(%edi),%ebx /* register ls word */ - - movl PARAM3,%edi /* destination */ - movl EXP(%esi),%edx - movl %edx,EXP(%edi) /* Copy exponent to destination */ - movb SIGN(%esi),%dl - movb %dl,SIGN(%edi) /* Copy the sign from the first arg */ - - xorl %edx,%edx /* register extension */ - -/*--------------------------------------+ - | Shift the temporary register | - | right the required number of | - | places. | - +--------------------------------------*/ -L_shift_r: - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - jmp L_shift_done - -L_more_than_31: - cmpl $64,%ecx - jnc L_more_than_63 - - subb $32,%cl - jz L_exactly_32 - - shrd %cl,%eax,%edx - shr %cl,%eax - orl %ebx,%ebx - jz L_more_31_no_low /* none of the lowest bits is set */ - - orl $1,%edx /* record the fact in the extension */ - -L_more_31_no_low: - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_exactly_32: - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_more_than_63: - cmpw $65,%cx - jnc L_more_than_64 - - /* Shift right by 64 bits */ - movl %eax,%edx - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_64: - jne L_more_than_65 - - /* Shift right by 65 bits */ - /* Carry is clear if we get here */ - movl %eax,%edx - rcrl %edx - jnc L_shift_65_nc - - orl $1,%edx - jmp L_more_63_no_low - -L_shift_65_nc: - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_65: - movl $1,%edx /* The shifted nr always at least one '1' */ - -L_more_63_no_low: - xorl %ebx,%ebx - xorl %eax,%eax - -L_shift_done: -L_subtr: -/*------------------------------+ - | Do the subtraction | - +------------------------------*/ - xorl %ecx,%ecx - subl %edx,%ecx - movl %ecx,%edx - movl SIGL(%esi),%ecx - sbbl %ebx,%ecx - movl %ecx,%ebx - movl SIGH(%esi),%ecx - sbbl %eax,%ecx - movl %ecx,%eax - -#ifdef PARANOID - /* We can never get a borrow */ - jc L_bugged -#endif PARANOID - -/*--------------------------------------+ - | Normalize the result | - +--------------------------------------*/ - testl $0x80000000,%eax - jnz L_round /* no shifting needed */ - - orl %eax,%eax - jnz L_shift_1 /* shift left 1 - 31 bits */ - - orl %ebx,%ebx - jnz L_shift_32 /* shift left 32 - 63 bits */ - -/* A rare case, the only one which is non-zero if we got here -// is: 1000000 .... 0000 -// -0111111 .... 1111 1 -// -------------------- -// 0000000 .... 0000 1 */ - - cmpl $0x80000000,%edx - jnz L_must_be_zero - - /* Shift left 64 bits */ - subl $64,EXP(%edi) - movl %edx,%eax - jmp L_store - -L_must_be_zero: -#ifdef PARANOID - orl %edx,%edx - jnz L_bugged_3 -#endif PARANOID - - /* The result is zero */ - movb TW_Zero,TAG(%edi) - movl $0,EXP(%edi) /* exponent */ - movl $0,SIGL(%edi) - movl $0,SIGH(%edi) - jmp L_exit /* Does not underflow */ - -L_shift_32: - movl %ebx,%eax - movl %edx,%ebx - movl $0,%edx - subl $32,EXP(%edi) /* Can get underflow here */ - -/* We need to shift left by 1 - 31 bits */ -L_shift_1: - bsrl %eax,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%ebx,%eax - shld %cl,%edx,%ebx - shl %cl,%edx - subl %ecx,EXP(%edi) /* Can get underflow here */ - -L_round: - jmp FPU_round /* Round the result */ - - -#ifdef PARANOID -L_bugged_1: - pushl EX_INTERNAL|0x206 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_2: - pushl EX_INTERNAL|0x209 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_3: - pushl EX_INTERNAL|0x210 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_4: - pushl EX_INTERNAL|0x211 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged: - pushl EX_INTERNAL|0x212 - call EXCEPTION - pop %ebx - jmp L_exit -#endif PARANOID - - -L_store: -/*------------------------------+ - | Store the result | - +------------------------------*/ - movl %eax,SIGH(%edi) - movl %ebx,SIGL(%edi) - - movb TW_Valid,TAG(%edi) /* Set the tags to TW_Valid */ - - cmpl EXP_UNDER,EXP(%edi) - jle L_underflow - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret - - -L_underflow: - push %edi - call arith_underflow - pop %ebx - jmp L_exit - diff --git a/sys/i386/gnu/fpemul/status_w.h b/sys/i386/gnu/fpemul/status_w.h deleted file mode 100644 index 70df8777b0..0000000000 --- a/sys/i386/gnu/fpemul/status_w.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * status_w.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/status_w.h,v 1.6 1999/08/28 00:42:59 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/status_w.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - - -#ifndef _STATUS_H_ -#define _STATUS_H_ - - -#ifdef LOCORE -#define Const__(x) $/**/x -#else -#define Const__(x) x -#endif - -#define SW_Backward Const__(0x8000) /* backward compatibility */ -#define SW_C3 Const__(0x4000) /* condition bit 3 */ -#define SW_Top Const__(0x3800) /* top of stack */ -#define SW_Top_Shift Const__(11) /* shift for top of stack bits */ -#define SW_C2 Const__(0x0400) /* condition bit 2 */ -#define SW_C1 Const__(0x0200) /* condition bit 1 */ -#define SW_C0 Const__(0x0100) /* condition bit 0 */ -#define SW_Summary Const__(0x0080) /* exception summary */ -#define SW_Stack_Fault Const__(0x0040) /* stack fault */ -#define SW_Precision Const__(0x0020) /* loss of precision */ -#define SW_Underflow Const__(0x0010) /* underflow */ -#define SW_Overflow Const__(0x0008) /* overflow */ -#define SW_Zero_Div Const__(0x0004) /* divide by zero */ -#define SW_Denorm_Op Const__(0x0002) /* denormalized operand */ -#define SW_Invalid Const__(0x0001) /* invalid operation */ - -#define SW_Exc_Mask Const__(0x27f) /* Status word exception bit mask */ - -#ifndef LOCORE - -#define COMP_A_gt_B 1 -#define COMP_A_eq_B 2 -#define COMP_A_lt_B 3 -#define COMP_No_Comp 4 -#define COMP_Denormal 0x20 -#define COMP_NaN 0x40 -#define COMP_SNaN 0x80 - -#define setcc(cc) ({ \ - status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \ - status_word |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); }) - -#endif /* LOCORE */ - -#endif /* _STATUS_H_ */ diff --git a/sys/i386/gnu/fpemul/version.h b/sys/i386/gnu/fpemul/version.h deleted file mode 100644 index 1117a19227..0000000000 --- a/sys/i386/gnu/fpemul/version.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * version.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/version.h,v 1.6 1999/08/28 00:42:59 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/version.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - -#define FPU_VERSION "wm-FPU-emu version BETA 1.4" diff --git a/sys/i386/gnu/fpemul/wm_shrx.s b/sys/i386/gnu/fpemul/wm_shrx.s deleted file mode 100644 index ffc62b10d1..0000000000 --- a/sys/i386/gnu/fpemul/wm_shrx.s +++ /dev/null @@ -1,259 +0,0 @@ - .file "wm_shrx.S" -/* - * wm_shrx.S - * - * 64 bit right shift functions - * - * Call from C as: - * unsigned shrx(void *arg1, unsigned arg2) - * and - * unsigned shrxs(void *arg1, unsigned arg2) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/wm_shrx.s,v 1.8 1999/08/28 00:42:59 peter Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/wm_shrx.s,v 1.4 2003/08/07 21:17:21 dillon Exp $ - * - */ - - -#include "fpu_asm.h" - -.text - -/*---------------------------------------------------------------------------+ - | unsigned shrx(void *arg1, unsigned arg2) | - | | - | Extended shift right function. | - | Fastest for small shifts. | - | Shifts the 64 bit quantity pointed to by the first arg (arg1) | - | right by the number of bits specified by the second arg (arg2). | - | Forms a 96 bit quantity from the 64 bit arg and eax: | - | [ 64 bit arg ][ eax ] | - | shift right ---------> | - | The eax register is initialized to 0 before the shifting. | - | Results returned in the 64 bit arg and eax. | - +---------------------------------------------------------------------------*/ - -ENTRY(shrx) - push %ebp - movl %esp,%ebp - pushl %esi - movl PARAM2,%ecx - movl PARAM1,%esi - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - pushl %ebx - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %eax,%eax /* extension */ - shrd %cl,%ebx,%eax - shrd %cl,%edx,%ebx - shr %cl,%edx - movl %ebx,(%esi) - movl %edx,4(%esi) - popl %ebx - popl %esi - leave - ret - -L_more_than_31: - cmpl $64,%ecx - jnc L_more_than_63 - - subb $32,%cl - movl (%esi),%eax /* lsl */ - movl 4(%esi),%edx /* msl */ - shrd %cl,%edx,%eax - shr %cl,%edx - movl %edx,(%esi) - movl $0,4(%esi) - popl %esi - leave - ret - -L_more_than_63: - cmpl $96,%ecx - jnc L_more_than_95 - - subb $64,%cl - movl 4(%esi),%eax /* msl */ - shr %cl,%eax - xorl %edx,%edx - movl %edx,(%esi) - movl %edx,4(%esi) - popl %esi - leave - ret - -L_more_than_95: - xorl %eax,%eax - movl %eax,(%esi) - movl %eax,4(%esi) - popl %esi - leave - ret - - -/*---------------------------------------------------------------------------+ - | unsigned shrxs(void *arg1, unsigned arg2) | - | | - | Extended shift right function (optimized for small floating point | - | integers). | - | Shifts the 64 bit quantity pointed to by the first arg (arg1) | - | right by the number of bits specified by the second arg (arg2). | - | Forms a 96 bit quantity from the 64 bit arg and eax: | - | [ 64 bit arg ][ eax ] | - | shift right ---------> | - | The eax register is initialized to 0 before the shifting. | - | The lower 8 bits of eax are lost and replaced by a flag which is | - | set (to 0x01) if any bit, apart from the first one, is set in the | - | part which has been shifted out of the arg. | - | Results returned in the 64 bit arg and eax. | - +---------------------------------------------------------------------------*/ - .globl shrxs -shrxs: - push %ebp - movl %esp,%ebp - pushl %esi - pushl %ebx - movl PARAM2,%ecx - movl PARAM1,%esi - cmpl $64,%ecx /* shrd only works for 0..31 bits */ - jnc Ls_more_than_63 - - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jc Ls_less_than_32 - -/* We got here without jumps by assuming that the most common requirement - is for small integers */ -/* Shift by [32..63] bits */ - subb $32,%cl - movl (%esi),%eax /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %ebx,%ebx - shrd %cl,%eax,%ebx - shrd %cl,%edx,%eax - shr %cl,%edx - orl %ebx,%ebx /* test these 32 bits */ - setne %bl - test $0x7fffffff,%eax /* and 31 bits here */ - setne %bh - orw %bx,%bx /* Any of the 63 bit set ? */ - setne %al - movl %edx,(%esi) - movl $0,4(%esi) - popl %ebx - popl %esi - leave - ret - -/* Shift by [0..31] bits */ -Ls_less_than_32: - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %eax,%eax /* extension */ - shrd %cl,%ebx,%eax - shrd %cl,%edx,%ebx - shr %cl,%edx - test $0x7fffffff,%eax /* only need to look at eax here */ - setne %al - movl %ebx,(%esi) - movl %edx,4(%esi) - popl %ebx - popl %esi - leave - ret - -/* Shift by [64..95] bits */ -Ls_more_than_63: - cmpl $96,%ecx - jnc Ls_more_than_95 - - subb $64,%cl - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%eax /* msl */ - xorl %edx,%edx /* extension */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orl %ebx,%edx - setne %bl - test $0x7fffffff,%eax /* only need to look at eax here */ - setne %bh - orw %bx,%bx - setne %al - xorl %edx,%edx - movl %edx,(%esi) /* set to zero */ - movl %edx,4(%esi) /* set to zero */ - popl %ebx - popl %esi - leave - ret - -Ls_more_than_95: -/* Shift by [96..inf) bits */ - xorl %eax,%eax - movl (%esi),%ebx - orl 4(%esi),%ebx - setne %al - xorl %ebx,%ebx - movl %ebx,(%esi) - movl %ebx,4(%esi) - popl %ebx - popl %esi - leave - ret diff --git a/sys/i386/gnu/fpemul/wm_sqrt.s b/sys/i386/gnu/fpemul/wm_sqrt.s deleted file mode 100644 index e721cd628a..0000000000 --- a/sys/i386/gnu/fpemul/wm_sqrt.s +++ /dev/null @@ -1,493 +0,0 @@ - .file "wm_sqrt.S" -/* - * wm_sqrt.S - * - * Fixed point arithmetic square root evaluation. - * - * Call from C as: - * void wm_sqrt(FPU_REG *n, unsigned int control_word) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/wm_sqrt.s,v 1.9.2.1 2000/07/07 00:38:42 obrien Exp $ - * $DragonFly: src/sys/i386/gnu/fpemul/Attic/wm_sqrt.s,v 1.3 2003/08/07 21:17:21 dillon Exp $ - * - */ - - -/*---------------------------------------------------------------------------+ - | wm_sqrt(FPU_REG *n, unsigned int control_word) | - | returns the square root of n in n. | - | | - | Use Newton's method to compute the square root of a number, which must | - | be in the range [1.0 .. 4.0), to 64 bits accuracy. | - | Does not check the sign or tag of the argument. | - | Sets the exponent, but not the sign or tag of the result. | - | | - | The guess is kept in %esi:%edi | - +---------------------------------------------------------------------------*/ - -#include "fpu_asm.h" - - -.data -/* - Local storage: - */ - ALIGN_DATA -accum_3: - .long 0 /* ms word */ -accum_2: - .long 0 -accum_1: - .long 0 -accum_0: - .long 0 - -/* The de-normalised argument: -// sq_2 sq_1 sq_0 -// b b b b b b b ... b b b b b b .... b b b b 0 0 0 ... 0 -// ^ binary point here */ -fsqrt_arg_2: - .long 0 /* ms word */ -fsqrt_arg_1: - .long 0 -fsqrt_arg_0: - .long 0 /* ls word, at most the ms bit is set */ - -.text - -ENTRY(wm_sqrt) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - - movl SIGH(%esi),%eax - movl SIGL(%esi),%ecx - xorl %edx,%edx - -/* We use a rough linear estimate for the first guess.. */ - - cmpl EXP_BIAS,EXP(%esi) - jnz sqrt_arg_ge_2 - - shrl $1,%eax /* arg is in the range [1.0 .. 2.0) */ - rcrl $1,%ecx - rcrl $1,%edx - -sqrt_arg_ge_2: -/* From here on, n is never accessed directly again until it is -// replaced by the answer. */ - - movl %eax,fsqrt_arg_2 /* ms word of n */ - movl %ecx,fsqrt_arg_1 - movl %edx,fsqrt_arg_0 - -/* Make a linear first estimate */ - shrl $1,%eax - addl $0x40000000,%eax - movl $0xaaaaaaaa,%ecx - mull %ecx - shll %edx /* max result was 7fff... */ - testl $0x80000000,%edx /* but min was 3fff... */ - jnz sqrt_prelim_no_adjust - - movl $0x80000000,%edx /* round up */ - -sqrt_prelim_no_adjust: - movl %edx,%esi /* Our first guess */ - -/* We have now computed (approx) (2 + x) / 3, which forms the basis - for a few iterations of Newton's method */ - - movl fsqrt_arg_2,%ecx /* ms word */ - -/* From our initial estimate, three iterations are enough to get us -// to 30 bits or so. This will then allow two iterations at better -// precision to complete the process. - -// Compute (g + n/g)/2 at each iteration (g is the guess). */ - shrl %ecx /* Doing this first will prevent a divide */ - /* overflow later. */ - - movl %ecx,%edx /* msw of the arg / 2 */ - divl %esi /* current estimate */ - shrl %esi /* divide by 2 */ - addl %eax,%esi /* the new estimate */ - - movl %ecx,%edx - divl %esi - shrl %esi - addl %eax,%esi - - movl %ecx,%edx - divl %esi - shrl %esi - addl %eax,%esi - -/* Now that an estimate accurate to about 30 bits has been obtained (in %esi), -// we improve it to 60 bits or so. - -// The strategy from now on is to compute new estimates from -// guess := guess + (n - guess^2) / (2 * guess) */ - -/* First, find the square of the guess */ - movl %esi,%eax - mull %esi -/* guess^2 now in %edx:%eax */ - - movl fsqrt_arg_1,%ecx - subl %ecx,%eax - movl fsqrt_arg_2,%ecx /* ms word of normalized n */ - sbbl %ecx,%edx - jnc sqrt_stage_2_positive -/* subtraction gives a negative result -// negate the result before division */ - notl %edx - notl %eax - addl $1,%eax - adcl $0,%edx - - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - jmp sqrt_stage_2_finish - -sqrt_stage_2_positive: - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - notl %ecx - notl %eax - addl $1,%eax - adcl $0,%ecx - -sqrt_stage_2_finish: - sarl $1,%ecx /* divide by 2 */ - rcrl $1,%eax - - /* Form the new estimate in %esi:%edi */ - movl %eax,%edi - addl %ecx,%esi - - jnz sqrt_stage_2_done /* result should be [1..2) */ - -#ifdef PARANOID -/* It should be possible to get here only if the arg is ffff....ffff*/ - cmp $0xffffffff,fsqrt_arg_1 - jnz sqrt_stage_2_error -#endif PARANOID - -/* The best rounded result.*/ - xorl %eax,%eax - decl %eax - movl %eax,%edi - movl %eax,%esi - movl $0x7fffffff,%eax - jmp sqrt_round_result - -#ifdef PARANOID -sqrt_stage_2_error: - pushl EX_INTERNAL|0x213 - call EXCEPTION -#endif PARANOID - -sqrt_stage_2_done: - -/* Now the square root has been computed to better than 60 bits */ - -/* Find the square of the guess*/ - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,accum_1 - - movl %esi,%eax - mull %esi - movl %edx,accum_3 - movl %eax,accum_2 - - movl %edi,%eax - mull %esi - addl %eax,accum_1 - adcl %edx,accum_2 - adcl $0,accum_3 - -/* movl %esi,%eax*/ -/* mull %edi*/ - addl %eax,accum_1 - adcl %edx,accum_2 - adcl $0,accum_3 - -/* guess^2 now in accum_3:accum_2:accum_1*/ - - movl fsqrt_arg_0,%eax /* get normalized n*/ - subl %eax,accum_1 - movl fsqrt_arg_1,%eax - sbbl %eax,accum_2 - movl fsqrt_arg_2,%eax /* ms word of normalized n*/ - sbbl %eax,accum_3 - jnc sqrt_stage_3_positive - -/* subtraction gives a negative result*/ -/* negate the result before division */ - notl accum_1 - notl accum_2 - notl accum_3 - addl $1,accum_1 - adcl $0,accum_2 - -#ifdef PARANOID - adcl $0,accum_3 /* This must be zero */ - jz sqrt_stage_3_no_error - -sqrt_stage_3_error: - pushl EX_INTERNAL|0x207 - call EXCEPTION - -sqrt_stage_3_no_error: -#endif PARANOID - - movl accum_2,%edx - movl accum_1,%eax - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - sarl $1,%ecx /* divide by 2*/ - rcrl $1,%eax - - /* prepare to round the result*/ - - addl %ecx,%edi - adcl $0,%esi - - jmp sqrt_stage_3_finished - -sqrt_stage_3_positive: - movl accum_2,%edx - movl accum_1,%eax - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - sarl $1,%ecx /* divide by 2*/ - rcrl $1,%eax - - /* prepare to round the result*/ - - notl %eax /* Negate the correction term*/ - notl %ecx - addl $1,%eax - adcl $0,%ecx /* carry here ==> correction == 0*/ - adcl $0xffffffff,%esi - - addl %ecx,%edi - adcl $0,%esi - -sqrt_stage_3_finished: - -/* The result in %esi:%edi:%esi should be good to about 90 bits here, -// and the rounding information here does not have sufficient accuracy -// in a few rare cases. */ - cmpl $0xffffffe0,%eax - ja sqrt_near_exact_x - - cmpl $0x00000020,%eax - jb sqrt_near_exact - - cmpl $0x7fffffe0,%eax - jb sqrt_round_result - - cmpl $0x80000020,%eax - jb sqrt_get_more_precision - -sqrt_round_result: -/* Set up for rounding operations*/ - movl %eax,%edx - movl %esi,%eax - movl %edi,%ebx - movl PARAM1,%edi - movl EXP_BIAS,EXP(%edi) /* Result is in [1.0 .. 2.0)*/ - movl PARAM2,%ecx - jmp FPU_round_sqrt - - -sqrt_near_exact_x: -/* First, the estimate must be rounded up.*/ - addl $1,%edi - adcl $0,%esi - -sqrt_near_exact: -/* This is an easy case because x^1/2 is monotonic. -// We need just find the square of our estimate, compare it -// with the argument, and deduce whether our estimate is -// above, below, or exact. We use the fact that the estimate -// is known to be accurate to about 90 bits. */ - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,%ebx /* 2nd ls word of square*/ - movl %eax,%ecx /* ls word of square*/ - - movl %edi,%eax - mull %esi - addl %eax,%ebx - addl %eax,%ebx - -#ifdef PARANOID - cmp $0xffffffb0,%ebx - jb sqrt_near_exact_ok - - cmp $0x00000050,%ebx - ja sqrt_near_exact_ok - - pushl EX_INTERNAL|0x214 - call EXCEPTION - -sqrt_near_exact_ok: -#endif PARANOID - - or %ebx,%ebx - js sqrt_near_exact_small - - jnz sqrt_near_exact_large - - or %ebx,%edx - jnz sqrt_near_exact_large - -/* Our estimate is exactly the right answer*/ - xorl %eax,%eax - jmp sqrt_round_result - -sqrt_near_exact_small: -/* Our estimate is too small*/ - movl $0x000000ff,%eax - jmp sqrt_round_result - -sqrt_near_exact_large: -/* Our estimate is too large, we need to decrement it*/ - subl $1,%edi - sbbl $0,%esi - movl $0xffffff00,%eax - jmp sqrt_round_result - - -sqrt_get_more_precision: -/* This case is almost the same as the above, except we start*/ -/* with an extra bit of precision in the estimate.*/ - stc /* The extra bit.*/ - rcll $1,%edi /* Shift the estimate left one bit*/ - rcll $1,%esi - - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,%ebx /* 2nd ls word of square*/ - movl %eax,%ecx /* ls word of square*/ - - movl %edi,%eax - mull %esi - addl %eax,%ebx - addl %eax,%ebx - -/* Put our estimate back to its original value*/ - stc /* The ms bit.*/ - rcrl $1,%esi /* Shift the estimate left one bit*/ - rcrl $1,%edi - -#ifdef PARANOID - cmp $0xffffff60,%ebx - jb sqrt_more_prec_ok - - cmp $0x000000a0,%ebx - ja sqrt_more_prec_ok - - pushl EX_INTERNAL|0x215 - call EXCEPTION - -sqrt_more_prec_ok: -#endif PARANOID - - or %ebx,%ebx - js sqrt_more_prec_small - - jnz sqrt_more_prec_large - - or %ebx,%ecx - jnz sqrt_more_prec_large - -/* Our estimate is exactly the right answer*/ - movl $0x80000000,%eax - jmp sqrt_round_result - -sqrt_more_prec_small: -/* Our estimate is too small*/ - movl $0x800000ff,%eax - jmp sqrt_round_result - -sqrt_more_prec_large: -/* Our estimate is too large*/ - movl $0x7fffff00,%eax - jmp sqrt_round_result diff --git a/sys/i386/gnu/isa/dgb.c b/sys/i386/gnu/isa/dgb.c index 59bef90b81..ae26bf5532 100644 --- a/sys/i386/gnu/isa/dgb.c +++ b/sys/i386/gnu/isa/dgb.c @@ -1,6 +1,6 @@ /*- * dgb.c $FreeBSD: src/sys/gnu/i386/isa/dgb.c,v 1.56.2.1 2001/02/26 04:23:09 jlemon Exp $ - * dgb.c $DragonFly: src/sys/i386/gnu/isa/Attic/dgb.c,v 1.14 2004/12/08 20:36:39 joerg Exp $ + * dgb.c $DragonFly: src/sys/i386/gnu/isa/Attic/dgb.c,v 1.15 2005/01/31 23:44:35 joerg Exp $ * * Digiboard driver. * @@ -31,8 +31,8 @@ #include "opt_compat.h" #include "opt_dgb.h" #include "opt_depricated.h" -#ifndef I_WANT_DEPRICATED_STUFF -#error "Add options I_WANT_DEPRICATED_STUFF to your kernel config and send a mail to kernel@" +#ifndef I_WANT_DEPRECATED_STUFF +#error "Add options I_WANT_DEPRECATED_STUFF to your kernel config and send a mail to kernel@" #endif #include "use_dgb.h" diff --git a/sys/i386/gnu/isa/sound/awe_compat.h b/sys/i386/gnu/isa/sound/awe_compat.h deleted file mode 100644 index eeac113936..0000000000 --- a/sys/i386/gnu/isa/sound/awe_compat.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * sound/awe_compat.h - * - * Compat defines for the AWE32/Sound Blaster 32 wave table synth. driver - * version 0.4.2c; Oct. 7, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $DragonFly: src/sys/i386/gnu/isa/sound/Attic/awe_compat.h,v 1.2 2004/02/12 23:33:26 joerg Exp $ - */ - -/*---------------------------------------------------------------- - * compatibility macros for AWE32 driver - *----------------------------------------------------------------*/ - -/* redefine following macros */ -#undef IOCTL_IN -#undef IOCTL_OUT -#undef OUTW -#undef COPY_FROM_USER -#undef COPY_TO_USER -#undef GET_BYTE_FROM_USER -#undef GET_SHORT_FROM_USER -#undef IOCTL_TO_USER - -#ifdef linux - -/*================================================================ - * Linux macros - *================================================================*/ - -/* use inline prefix */ -#define INLINE inline - -/*---------------------------------------------------------------- - * memory management for linux - *----------------------------------------------------------------*/ - -#ifdef AWE_OBSOLETE_VOXWARE -/* old type linux system */ - -/* i/o requests; nothing */ -#define awe_check_port() 0 /* always false */ -#define awe_request_region() /* nothing */ -#define awe_release_region() /* nothing */ - -static int _mem_start; /* memory pointer for permanent buffers */ - -#define my_malloc_init(memptr) _mem_start = (memptr) -#define my_malloc_memptr() _mem_start -#define my_free(ptr) /* do nothing */ -#define my_realloc(buf,oldsize,size) NULL /* no realloc */ - -static void *my_malloc(int size) -{ - char *ptr; - PERMANENT_MALLOC(ptr, char*, size, _mem_start); - return (void*)ptr; -} - -/* allocate buffer only once */ -#define INIT_TABLE(buffer,index,nums,type) {\ -buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\ -} - -#else - -#define AWE_DYNAMIC_BUFFER - -#define my_malloc_init(ptr) /* nothing */ -#define my_malloc_memptr() 0 -#define my_malloc(size) vmalloc(size) -#define my_free(ptr) if (ptr) {vfree(ptr);} - -static void *my_realloc(void *buf, int oldsize, int size) -{ - void *ptr; - if ((ptr = vmalloc(size)) == NULL) - return NULL; - memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) ); - vfree(buf); - return ptr; -} - -/* do not allocate buffer at beginning */ -#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;} - -/* old type macro */ -#define RET_ERROR(err) -err - -#endif - -/*---------------------------------------------------------------- - * i/o interfaces for linux - *----------------------------------------------------------------*/ - -#define OUTW(data,addr) outw(data, addr) - -#ifdef AWE_NEW_KERNEL_INTERFACE -#define COPY_FROM_USER(target,source,offs,count) \ - copy_from_user(target, (source)+(offs), count) -#define GET_BYTE_FROM_USER(target,addr,offs) \ - get_user(target, (unsigned char*)&((addr)[offs])) -#define GET_SHORT_FROM_USER(target,addr,offs) \ - get_user(target, (unsigned short*)&((addr)[offs])) -#ifdef AWE_OSS38 -#define IOCTL_TO_USER(target,offs,source,count) \ - memcpy(target, (source)+(offs), count) -#define IO_WRITE_CHECK(cmd) (_SIOC_DIR(cmd) & _IOC_WRITE) -#else -#define IOCTL_TO_USER(target,offs,source,count) \ - copy_to_user(target, (source)+(offs), count) -#define IO_WRITE_CHECK(cmd) (_IOC_DIR(cmd) & _IOC_WRITE) -#endif /* AWE_OSS38 */ -#define COPY_TO_USER IOCTL_TO_USER -#define IOCTL_IN(arg) (*(int*)(arg)) -#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val)) - -#else /* old type i/o */ -#define COPY_FROM_USER(target,source,offs,count) \ - memcpy_fromfs(target, (source)+(offs), (count)) -#define GET_BYTE_FROM_USER(target,addr,offs) \ - *((char *)&(target)) = get_fs_byte((addr)+(offs)) -#define GET_SHORT_FROM_USER(target,addr,offs) \ - *((short *)&(target)) = get_fs_word((addr)+(offs)) -#define IOCTL_TO_USER(target,offs,source,count) \ - memcpy_tofs(target, (source)+(offs), (count)) -#define COPY_TO_USER IOCTL_TO_USER -#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN) -#define IOCTL_IN(arg) get_fs_long((long *)(arg)) -#define IOCTL_OUT(arg,ret) snd_ioctl_return((int *)arg, ret) - -#endif /* AWE_NEW_KERNEL_INTERFACE */ - -#define BZERO(target,len) memset(target, 0, len) -#define MEMCPY(dst,src,len) memcpy(dst, src, len) - - -#elif defined(__DragonFly__) || defined(__FreeBSD__) - -/*================================================================ - * FreeBSD macros - *================================================================*/ - -/* inline is not checked yet.. maybe it'll work */ -#define INLINE /*inline*/ - -/*---------------------------------------------------------------- - * memory management for freebsd - *----------------------------------------------------------------*/ - -/* i/o requests; nothing */ -#define awe_check_port() 0 /* always false */ -#define awe_request_region() /* nothing */ -#define awe_release_region() /* nothing */ - -#define AWE_DYNAMIC_BUFFER - -#define my_malloc_init(ptr) /* nothing */ -#define my_malloc_memptr() 0 -#define my_malloc(size) malloc(size, M_TEMP, M_WAITOK) -#define my_free(ptr) if (ptr) {free(ptr, M_TEMP);} - -#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;} - -/* it should be realloc? */ -static void *my_realloc(void *buf, int oldsize, int size) -{ - void *ptr; - if ((ptr = my_malloc(size)) == NULL) - return NULL; - memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) ); - my_free(buf); - return ptr; -} - -/*---------------------------------------------------------------- - * i/o interfaces for freebsd - *----------------------------------------------------------------*/ - -/* according to linux rule; the arguments are swapped */ -#define OUTW(data,addr) outw(addr, data) - -#define COPY_FROM_USER(target,source,offs,count) \ - uiomove(((caddr_t)(target)),(count),((struct uio *)(source))) -#define COPY_TO_USER(target,source,offs,count) \ - uiomove(((caddr_t)(source)),(count),((struct uio *)(target))) -#define GET_BYTE_FROM_USER(target,addr,offs) \ - uiomove(((char*)&(target)), 1, ((struct uio *)(addr))) -#define GET_SHORT_FROM_USER(target,addr,offs) \ - uiomove(((char*)&(target)), 2, ((struct uio *)(addr))) -#define IOCTL_TO_USER(target,offs,source,count) \ - memcpy(&((target)[offs]), (source), (count)) -#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN) -#define IOCTL_IN(arg) (*(int*)(arg)) -#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val)) -#define BZERO(target,len) bzero((caddr_t)target, len) -#define MEMCPY(dst,src,len) bcopy((caddr_t)src, (caddr_t)dst, len) - -#ifndef AWE_OBSOLETE_VOXWARE -# define printk printf -# define RET_ERROR(err) -err -#endif - -#endif - diff --git a/sys/i386/gnu/isa/sound/awe_config.h b/sys/i386/gnu/isa/sound/awe_config.h deleted file mode 100644 index cf2b3f9388..0000000000 --- a/sys/i386/gnu/isa/sound/awe_config.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * sound/awe_config.h - * - * Configuration of AWE32 sound driver - * version 0.4.2; Sep. 15, 1997 - * - * Copyright (C) 1996 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $DragonFly: src/sys/i386/gnu/isa/sound/Attic/awe_config.h,v 1.2 2004/02/12 23:33:26 joerg Exp $ - */ - -#ifndef AWE_CONFIG_H_DEF -#define AWE_CONFIG_H_DEF - -/*---------------------------------------------------------------- - * system configuration - *----------------------------------------------------------------*/ - -/* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or pre-Voxware 3.5 - * versions of FreeBSD), define the following line. - */ -#undef AWE_OBSOLETE_VOXWARE - -/* if you're using OSS-Lite on Linux 2.1.6 or later, define the - * following line. - */ -#undef AWE_NEW_KERNEL_INTERFACE - -/* if you have lowlevel.h in the lowlevel directory (OSS-Lite), define - * the following line. - */ -#undef HAS_LOWLEVEL_H - -/* if your system doesn't support patch manager (OSS 3.7 or newer), - * define the following line. - */ -#undef AWE_NO_PATCHMGR - -/* if your system has an additional parameter (OSS 3.8b5 or newer), - * define this. - */ -#undef AWE_OSS38 - -/*---------------------------------------------------------------- - * AWE32 card configuration: - * uncomment the following lines only when auto detection doesn't - * work properly on your machine. - *----------------------------------------------------------------*/ - -/*#define AWE_DEFAULT_BASE_ADDR 0x620*/ /* base port address */ -/*#define AWE_DEFAULT_MEM_SIZE 512*/ /* kbytes */ - - -/*---------------------------------------------------------------- - * maximum size of soundfont list table: - * you usually don't need to touch this value. - *----------------------------------------------------------------*/ - -#define AWE_MAX_SF_LISTS 16 - - -/*---------------------------------------------------------------- - * chunk size of sample and voice tables: - * you usually don't need to touch these values. - *----------------------------------------------------------------*/ - -#define AWE_MAX_SAMPLES 400 -#define AWE_MAX_INFOS 800 - - -/*---------------------------------------------------------------- - * chorus & reverb effects send for FM chip: from 0 to 0xff - * larger numbers often cause weird sounds. - *----------------------------------------------------------------*/ - -#define DEF_FM_CHORUS_DEPTH 0x10 -#define DEF_FM_REVERB_DEPTH 0x10 - - -/*----------------------------------------------------------------* - * other compile conditions - *----------------------------------------------------------------*/ - -/* initialize FM passthrough even without extended RAM */ -#undef AWE_ALWAYS_INIT_FM - -/* debug on */ -#define AWE_DEBUG_ON - -/* GUS compatible mode */ -#define AWE_HAS_GUS_COMPATIBILITY - -/* accept all notes/sounds off controls */ -#define AWE_ACCEPT_ALL_SOUNDS_CONTROL - -/* add mixer control of emu8000 equalizer */ -#define CONFIG_AWE32_MIXER - -/* look up voices according to MIDI channel priority */ -#define AWE_LOOKUP_MIDI_PRIORITY - -/*----------------------------------------------------------------*/ - -/* reading configuration of sound driver */ - -#ifdef AWE_OBSOLETE_VOXWARE - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include -#else -# include "sound_config.h" -#endif - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32) -#define CONFIG_AWE32_SYNTH -#endif - -#else /* AWE_OBSOLETE_VOXWARE */ - -#ifdef HAS_LOWLEVEL_H -#include "lowlevel.h" -#endif - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include -# if defined(CONFIGURE_SOUNDCARD) && defined(CONFIG_AWE32) -# define CONFIG_AWE32_SYNTH -# endif -#else -# include "../sound_config.h" -#endif - - -#endif /* AWE_OBSOLETE_VOXWARE */ - - -#endif /* AWE_CONFIG_H_DEF */ diff --git a/sys/i386/gnu/isa/sound/awe_hw.h b/sys/i386/gnu/isa/sound/awe_hw.h deleted file mode 100644 index 7d0d88e77d..0000000000 --- a/sys/i386/gnu/isa/sound/awe_hw.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * sound/awe_hw.h - * - * Access routines and definitions for the low level driver for the - * AWE32/Sound Blaster 32 wave table synth. - * version 0.4.2; Sep. 15, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef AWE_HW_H_DEF -#define AWE_HW_H_DEF - -/* - * Emu-8000 control registers - * name(channel) reg, port - */ - -#define awe_cmd_idx(reg,ch) (((reg)<< 5) | (ch)) - -#define Data0 0x620 /* doubleword r/w */ -#define Data1 0xA20 /* doubleword r/w */ -#define Data2 0xA22 /* word r/w */ -#define Data3 0xE20 /* word r/w */ -#define Pointer 0xE22 /* register pointer r/w */ - -#define AWE_CPF(ch) awe_cmd_idx(0,ch), Data0 /* DW: current pitch and fractional address */ -#define AWE_PTRX(ch) awe_cmd_idx(1,ch), Data0 /* DW: pitch target and reverb send */ -#define AWE_CVCF(ch) awe_cmd_idx(2,ch), Data0 /* DW: current volume and filter cutoff */ -#define AWE_VTFT(ch) awe_cmd_idx(3,ch), Data0 /* DW: volume and filter cutoff targets */ -#define AWE_PSST(ch) awe_cmd_idx(6,ch), Data0 /* DW: pan send and loop start address */ -#define AWE_CSL(ch) awe_cmd_idx(7,ch), Data0 /* DW: chorus send and loop end address */ -#define AWE_CCCA(ch) awe_cmd_idx(0,ch), Data1 /* DW: Q, control bits, and current address */ -#define AWE_HWCF4 awe_cmd_idx(1,9), Data1 /* DW: config dw 4 */ -#define AWE_HWCF5 awe_cmd_idx(1,10), Data1 /* DW: config dw 5 */ -#define AWE_HWCF6 awe_cmd_idx(1,13), Data1 /* DW: config dw 6 */ -#define AWE_HWCF7 awe_cmd_idx(1,14), Data1 /* DW: config dw 7? (not documented) */ -#define AWE_SMALR awe_cmd_idx(1,20), Data1 /* DW: sound memory address for left read */ -#define AWE_SMARR awe_cmd_idx(1,21), Data1 /* DW: for right read */ -#define AWE_SMALW awe_cmd_idx(1,22), Data1 /* DW: sound memory address for left write */ -#define AWE_SMARW awe_cmd_idx(1,23), Data1 /* DW: for right write */ -#define AWE_SMLD awe_cmd_idx(1,26), Data1 /* W: sound memory left data */ -#define AWE_SMRD awe_cmd_idx(1,26), Data2 /* W: right data */ -#define AWE_WC awe_cmd_idx(1,27), Data2 /* W: sample counter */ -#define AWE_WC_Cmd awe_cmd_idx(1,27) -#define AWE_WC_Port Data2 -#define AWE_HWCF1 awe_cmd_idx(1,29), Data1 /* W: config w 1 */ -#define AWE_HWCF2 awe_cmd_idx(1,30), Data1 /* W: config w 2 */ -#define AWE_HWCF3 awe_cmd_idx(1,31), Data1 /* W: config w 3 */ -#define AWE_INIT1(ch) awe_cmd_idx(2,ch), Data1 /* W: init array 1 */ -#define AWE_INIT2(ch) awe_cmd_idx(2,ch), Data2 /* W: init array 2 */ -#define AWE_INIT3(ch) awe_cmd_idx(3,ch), Data1 /* W: init array 3 */ -#define AWE_INIT4(ch) awe_cmd_idx(3,ch), Data2 /* W: init array 4 */ -#define AWE_ENVVOL(ch) awe_cmd_idx(4,ch), Data1 /* W: volume envelope delay */ -#define AWE_DCYSUSV(ch) awe_cmd_idx(5,ch), Data1 /* W: volume envelope sustain and decay */ -#define AWE_ENVVAL(ch) awe_cmd_idx(6,ch), Data1 /* W: modulation envelope delay */ -#define AWE_DCYSUS(ch) awe_cmd_idx(7,ch), Data1 /* W: modulation envelope sustain and decay */ -#define AWE_ATKHLDV(ch) awe_cmd_idx(4,ch), Data2 /* W: volume envelope attack and hold */ -#define AWE_LFO1VAL(ch) awe_cmd_idx(5,ch), Data2 /* W: LFO#1 Delay */ -#define AWE_ATKHLD(ch) awe_cmd_idx(6,ch), Data2 /* W: modulation envelope attack and hold */ -#define AWE_LFO2VAL(ch) awe_cmd_idx(7,ch), Data2 /* W: LFO#2 Delay */ -#define AWE_IP(ch) awe_cmd_idx(0,ch), Data3 /* W: initial pitch */ -#define AWE_IFATN(ch) awe_cmd_idx(1,ch), Data3 /* W: initial filter cutoff and attenuation */ -#define AWE_PEFE(ch) awe_cmd_idx(2,ch), Data3 /* W: pitch and filter envelope heights */ -#define AWE_FMMOD(ch) awe_cmd_idx(3,ch), Data3 /* W: vibrato and filter modulation freq */ -#define AWE_TREMFRQ(ch) awe_cmd_idx(4,ch), Data3 /* W: LFO#1 tremolo amount and freq */ -#define AWE_FM2FRQ2(ch) awe_cmd_idx(5,ch), Data3 /* W: LFO#2 vibrato amount and freq */ - -/* used during detection (returns ROM version?; not documented in ADIP) */ -#define AWE_U1 0xE0, Data3 /* (R)(W) used in initialization */ -#define AWE_U2(ch) 0xC0+(ch), Data3 /* (W)(W) used in init envelope */ - - -#define AWE_MAX_VOICES 32 -#define AWE_NORMAL_VOICES 30 /*30&31 are reserved for DRAM refresh*/ - -#define AWE_MAX_CHANNELS 32 /* max midi channels (must >= voices) */ -#define AWE_MAX_LAYERS AWE_MAX_VOICES /* maximum number of multiple layers */ - -#define AWE_DRAM_OFFSET 0x200000 -#define AWE_MAX_DRAM_SIZE (28 * 1024) /* 28 MB is max onboard memory */ - -#define AWE_DEFAULT_ATTENUATION 32 /* 12dB below */ -#define AWE_DEFAULT_MOD_SENSE 18 - -#endif diff --git a/sys/i386/gnu/isa/sound/awe_version.h b/sys/i386/gnu/isa/sound/awe_version.h deleted file mode 100644 index 42013bbbf2..0000000000 --- a/sys/i386/gnu/isa/sound/awe_version.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * sound/awe_version.h - * - * Version defines for the AWE32/Sound Blaster 32 wave table synth driver. - * version 0.4.2c; Oct. 7, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* AWE32 driver version number */ - -#ifndef AWE_VERSION_H_DEF -#define AWE_VERSION_H_DEF - -#define AWE_VERSION_NUMBER 0x00040203 -#define AWEDRV_VERSION "0.4.2c" -#define AWE_MAJOR_VERSION(id) (((id) >> 16) & 0xff) -#define AWE_MINOR_VERSION(id) (((id) >> 8) & 0xff) -#define AWE_TINY_VERSION(id) ((id) & 0xff) - -#endif diff --git a/sys/i386/gnu/isa/sound/awe_voice.h b/sys/i386/gnu/isa/sound/awe_voice.h deleted file mode 100644 index aa13131314..0000000000 --- a/sys/i386/gnu/isa/sound/awe_voice.h +++ /dev/null @@ -1,490 +0,0 @@ -/* - * sound/awe_voice.h - * - * Voice information definitions for the low level driver for the - * AWE32/Sound Blaster 32 wave table synth. - * version 0.4.2c; Oct. 7, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef AWE_VOICE_H -#define AWE_VOICE_H - -#ifndef SAMPLE_TYPE_AWE32 -#define SAMPLE_TYPE_AWE32 0x20 -#endif - -#ifndef _PATCHKEY -#define _PATCHKEY(id) ((id<<8)|0xfd) -#endif - -/*---------------------------------------------------------------- - * patch information record - *----------------------------------------------------------------*/ - -/* patch interface header: 16 bytes */ -typedef struct awe_patch_info { - short key; /* use AWE_PATCH here */ -#define AWE_PATCH _PATCHKEY(0x07) - - short device_no; /* synthesizer number */ - unsigned short sf_id; /* file id (should be zero) */ - short optarg; /* optional argument */ - int len; /* data length (without this header) */ - - short type; /* patch operation type */ -#define AWE_LOAD_INFO 0 /* awe_voice_rec */ -#define AWE_LOAD_DATA 1 /* awe_sample_info */ -#define AWE_OPEN_PATCH 2 /* awe_open_parm */ -#define AWE_CLOSE_PATCH 3 /* none */ -#define AWE_UNLOAD_PATCH 4 /* none */ -#define AWE_REPLACE_DATA 5 /* awe_sample_info (optarg=#channels)*/ -#define AWE_MAP_PRESET 6 /* awe_voice_map */ -#define AWE_LOAD_CHORUS_FX 0x10 /* awe_chorus_fx_rec (optarg=mode) */ -#define AWE_LOAD_REVERB_FX 0x11 /* awe_reverb_fx_rec (optarg=mode) */ - - short reserved; /* word alignment data */ - - /* the actual patch data begins after this */ -#if defined(AWE_COMPAT_030) && AWE_COMPAT_030 - char data[0]; -#endif -} awe_patch_info; - -/*#define AWE_PATCH_INFO_SIZE 16*/ -#define AWE_PATCH_INFO_SIZE sizeof(awe_patch_info) - - -/*---------------------------------------------------------------- - * open patch - *----------------------------------------------------------------*/ - -#define AWE_PATCH_NAME_LEN 32 - -typedef struct _awe_open_parm { - unsigned short type; /* sample type */ -#define AWE_PAT_TYPE_MISC 0 -#define AWE_PAT_TYPE_GM 1 -#define AWE_PAT_TYPE_GS 2 -#define AWE_PAT_TYPE_MT32 3 -#define AWE_PAT_TYPE_XG 4 -#define AWE_PAT_TYPE_SFX 5 -#define AWE_PAT_TYPE_GUS 6 -#define AWE_PAT_TYPE_MAP 7 - -#define AWE_PAT_LOCKED 0x100 /* lock the samples */ - - short reserved; - char name[AWE_PATCH_NAME_LEN]; -} awe_open_parm; - -/*#define AWE_OPEN_PARM_SIZE 28*/ -#define AWE_OPEN_PARM_SIZE sizeof(awe_open_parm) - - -/*---------------------------------------------------------------- - * raw voice information record - *----------------------------------------------------------------*/ - -/* wave table envelope & effect parameters to control EMU8000 */ -typedef struct _awe_voice_parm { - unsigned short moddelay; /* modulation delay (0x8000) */ - unsigned short modatkhld; /* modulation attack & hold time (0x7f7f) */ - unsigned short moddcysus; /* modulation decay & sustain (0x7f7f) */ - unsigned short modrelease; /* modulation release time (0x807f) */ - short modkeyhold, modkeydecay; /* envelope change per key (not used) */ - unsigned short voldelay; /* volume delay (0x8000) */ - unsigned short volatkhld; /* volume attack & hold time (0x7f7f) */ - unsigned short voldcysus; /* volume decay & sustain (0x7f7f) */ - unsigned short volrelease; /* volume release time (0x807f) */ - short volkeyhold, volkeydecay; /* envelope change per key (not used) */ - unsigned short lfo1delay; /* LFO1 delay (0x8000) */ - unsigned short lfo2delay; /* LFO2 delay (0x8000) */ - unsigned short pefe; /* modulation pitch & cutoff (0x0000) */ - unsigned short fmmod; /* LFO1 pitch & cutoff (0x0000) */ - unsigned short tremfrq; /* LFO1 volume & freq (0x0000) */ - unsigned short fm2frq2; /* LFO2 pitch & freq (0x0000) */ - unsigned char cutoff; /* initial cutoff (0xff) */ - unsigned char filterQ; /* initial filter Q [0-15] (0x0) */ - unsigned char chorus; /* chorus send (0x00) */ - unsigned char reverb; /* reverb send (0x00) */ - unsigned short reserved[4]; /* not used */ -} awe_voice_parm; - -#define AWE_VOICE_PARM_SIZE 48 - - -/* wave table parameters: 92 bytes */ -typedef struct _awe_voice_info { - unsigned short sf_id; /* file id (should be zero) */ - unsigned short sample; /* sample id */ - int start, end; /* sample offset correction */ - int loopstart, loopend; /* loop offset correction */ - short rate_offset; /* sample rate pitch offset */ - unsigned short mode; /* sample mode */ -#define AWE_MODE_ROMSOUND 0x8000 -#define AWE_MODE_STEREO 1 -#define AWE_MODE_LOOPING 2 -#define AWE_MODE_NORELEASE 4 /* obsolete */ -#define AWE_MODE_INIT_PARM 8 - - short root; /* midi root key */ - short tune; /* pitch tuning (in cents) */ - char low, high; /* key note range */ - char vellow, velhigh; /* velocity range */ - char fixkey, fixvel; /* fixed key, velocity */ - char pan, fixpan; /* panning, fixed panning */ - short exclusiveClass; /* exclusive class (0 = none) */ - unsigned char amplitude; /* sample volume (127 max) */ - unsigned char attenuation; /* attenuation (0.375dB) */ - short scaleTuning; /* pitch scale tuning(%), normally 100 */ - awe_voice_parm parm; /* voice envelope parameters */ - short index; /* internal index (set by driver) */ -} awe_voice_info; - -/*#define AWE_VOICE_INFO_SIZE 92*/ -#define AWE_VOICE_INFO_SIZE sizeof(awe_voice_info) - -/*----------------------------------------------------------------*/ - -/* The info entry of awe_voice_rec is changed from 0 to 1 - * for some compilers refusing zero size array. - * Due to this change, sizeof(awe_voice_rec) becomes different - * from older versions. - * Use AWE_VOICE_REC_SIZE instead. - */ - -/* instrument info header: 4 bytes */ -typedef struct _awe_voice_rec_hdr { - unsigned char bank; /* midi bank number */ - unsigned char instr; /* midi preset number */ - char nvoices; /* number of voices */ - char write_mode; /* write mode; normally 0 */ -#define AWE_WR_APPEND 0 /* append anyway */ -#define AWE_WR_EXCLUSIVE 1 /* skip if already exists */ -#define AWE_WR_REPLACE 2 /* replace if already exists */ -} awe_voice_rec_hdr; - -/*#define AWE_VOICE_REC_SIZE 4*/ -#define AWE_VOICE_REC_SIZE sizeof(awe_voice_rec_hdr) - -/* the standard patch structure for one sample */ -typedef struct _awe_voice_rec_patch { - awe_patch_info patch; - awe_voice_rec_hdr hdr; - awe_voice_info info; -} awe_voice_rec_patch; - - -/* obsolete data type */ -#if defined(AWE_COMPAT_030) && AWE_COMPAT_030 -#define AWE_INFOARRAY_SIZE 0 -#else -#define AWE_INFOARRAY_SIZE 1 -#endif - -typedef struct _awe_voice_rec { - unsigned char bank; /* midi bank number */ - unsigned char instr; /* midi preset number */ - short nvoices; /* number of voices */ - /* voice information follows here */ - awe_voice_info info[AWE_INFOARRAY_SIZE]; -} awe_voice_rec; - - -/*---------------------------------------------------------------- - * sample wave information - *----------------------------------------------------------------*/ - -/* wave table sample header: 32 bytes */ -typedef struct awe_sample_info { - unsigned short sf_id; /* file id (should be zero) */ - unsigned short sample; /* sample id */ - int start, end; /* start & end offset */ - int loopstart, loopend; /* loop start & end offset */ - int size; /* size (0 = ROM) */ - short checksum_flag; /* use check sum = 1 */ - unsigned short mode_flags; /* mode flags */ -#define AWE_SAMPLE_8BITS 1 /* wave data is 8bits */ -#define AWE_SAMPLE_UNSIGNED 2 /* wave data is unsigned */ -#define AWE_SAMPLE_NO_BLANK 4 /* no blank loop is attached */ -#define AWE_SAMPLE_SINGLESHOT 8 /* single-shot w/o loop */ -#define AWE_SAMPLE_BIDIR_LOOP 16 /* bidirectional looping */ -#define AWE_SAMPLE_STEREO_LEFT 32 /* stereo left sound */ -#define AWE_SAMPLE_STEREO_RIGHT 64 /* stereo right sound */ -#define AWE_SAMPLE_REVERSE_LOOP 128 /* reverse looping */ - unsigned int checksum; /* check sum */ -#if defined(AWE_COMPAT_030) && AWE_COMPAT_030 - unsigned short data[0]; /* sample data follows here */ -#endif -} awe_sample_info; - -/*#define AWE_SAMPLE_INFO_SIZE 32*/ -#define AWE_SAMPLE_INFO_SIZE sizeof(awe_sample_info) - - -/*---------------------------------------------------------------- - * voice preset mapping - *----------------------------------------------------------------*/ - -typedef struct awe_voice_map { - int map_bank, map_instr, map_key; /* key = -1 means all keys */ - int src_bank, src_instr, src_key; -} awe_voice_map; - -#define AWE_VOICE_MAP_SIZE sizeof(awe_voice_map) - - -/*---------------------------------------------------------------- - * awe hardware controls - *----------------------------------------------------------------*/ - -#define _AWE_DEBUG_MODE 0x00 -#define _AWE_REVERB_MODE 0x01 -#define _AWE_CHORUS_MODE 0x02 -#define _AWE_REMOVE_LAST_SAMPLES 0x03 -#define _AWE_INITIALIZE_CHIP 0x04 -#define _AWE_SEND_EFFECT 0x05 -#define _AWE_TERMINATE_CHANNEL 0x06 -#define _AWE_TERMINATE_ALL 0x07 -#define _AWE_INITIAL_VOLUME 0x08 -#define _AWE_INITIAL_ATTEN _AWE_INITIAL_VOLUME -#define _AWE_RESET_CHANNEL 0x09 -#define _AWE_CHANNEL_MODE 0x0a -#define _AWE_DRUM_CHANNELS 0x0b -#define _AWE_MISC_MODE 0x0c -#define _AWE_RELEASE_ALL 0x0d -#define _AWE_NOTEOFF_ALL 0x0e -#define _AWE_CHN_PRESSURE 0x0f -/*#define _AWE_GET_CURRENT_MODE 0x10*/ -#define _AWE_EQUALIZER 0x11 -/*#define _AWE_GET_MISC_MODE 0x12*/ -/*#define _AWE_GET_FONTINFO 0x13*/ - -#define _AWE_MODE_FLAG 0x80 -#define _AWE_COOKED_FLAG 0x40 /* not supported */ -#define _AWE_MODE_VALUE_MASK 0x3F - -/*----------------------------------------------------------------*/ - -#define _AWE_SET_CMD(p,dev,voice,cmd,p1,p2) \ -{((char*)(p))[0] = SEQ_PRIVATE;\ - ((char*)(p))[1] = dev;\ - ((char*)(p))[2] = _AWE_MODE_FLAG|(cmd);\ - ((char*)(p))[3] = voice;\ - ((unsigned short*)(p))[2] = p1;\ - ((unsigned short*)(p))[3] = p2;} - -/* buffered access */ -#define _AWE_CMD(dev, voice, cmd, p1, p2) \ -{_SEQ_NEEDBUF(8);\ - _AWE_SET_CMD(_seqbuf + _seqbufptr, dev, voice, cmd, p1, p2);\ - _SEQ_ADVBUF(8);} - -/* direct access */ -#define _AWE_CMD_NOW(seqfd,dev,voice,cmd,p1,p2) \ -{struct seq_event_rec tmp;\ - _AWE_SET_CMD(&tmp, dev, voice, cmd, p1, p2);\ - ioctl(seqfd, SNDCTL_SEQ_OUTOFBAND, &tmp);} - -/*----------------------------------------------------------------*/ - -/* set debugging mode */ -#define AWE_DEBUG_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0) -/* set reverb mode; from 0 to 7 */ -#define AWE_REVERB_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0) -/* set chorus mode; from 0 to 7 */ -#define AWE_CHORUS_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0) - -/* reset channel */ -#define AWE_RESET_CHANNEL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 0, 0) -#define AWE_RESET_CONTROL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 1, 0) - -/* send an effect to all layers */ -#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value) -#define AWE_ADD_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x80),value) -#define AWE_UNSET_EFFECT(dev,voice,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x40),0) -/* send an effect to a layer */ -#define AWE_SEND_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)),value) -#define AWE_ADD_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x80),value) -#define AWE_UNSET_LAYER_EFFECT(dev,voice,layer,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x40),0) - -/* terminate sound on the channel/voice */ -#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0) -/* terminate all sounds */ -#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0) -/* release all sounds (w/o sustain effect) */ -#define AWE_RELEASE_ALL(dev) _AWE_CMD(dev, 0, _AWE_RELEASE_ALL, 0, 0) -/* note off all sounds (w sustain effect) */ -#define AWE_NOTEOFF_ALL(dev) _AWE_CMD(dev, 0, _AWE_NOTEOFF_ALL, 0, 0) - -/* set initial attenuation */ -#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0) -#define AWE_INITIAL_ATTEN AWE_INITIAL_VOLUME -/* relative attenuation */ -#define AWE_SET_ATTEN(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 1) - -/* set channel playing mode; mode=0/1/2 */ -#define AWE_SET_CHANNEL_MODE(dev,mode) _AWE_CMD(dev, 0, _AWE_CHANNEL_MODE, mode, 0) -#define AWE_PLAY_INDIRECT 0 /* indirect voice mode (default) */ -#define AWE_PLAY_MULTI 1 /* multi note voice mode */ -#define AWE_PLAY_DIRECT 2 /* direct single voice mode */ -#define AWE_PLAY_MULTI2 3 /* sequencer2 mode; used internally */ - -/* set drum channel mask; channels is 32bit long value */ -#define AWE_DRUM_CHANNELS(dev,channels) _AWE_CMD(dev, 0, _AWE_DRUM_CHANNELS, ((channels) & 0xffff), ((channels) >> 16)) - -/* set bass and treble control; values are from 0 to 11 */ -#define AWE_EQUALIZER(dev,bass,treble) _AWE_CMD(dev, 0, _AWE_EQUALIZER, bass, treble) - -/* remove last loaded samples */ -#define AWE_REMOVE_LAST_SAMPLES(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0) -/* initialize emu8000 chip */ -#define AWE_INITIALIZE_CHIP(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_INITIALIZE_CHIP, 0, 0) - -/* set miscellaneous modes; meta command */ -#define AWE_MISC_MODE(dev,mode,value) _AWE_CMD(dev, 0, _AWE_MISC_MODE, mode, value) -/* exclusive sound off; 1=off */ -#define AWE_EXCLUSIVE_SOUND(dev,mode) AWE_MISC_MODE(dev,AWE_MD_EXCLUSIVE_SOUND,mode) -/* default GUS bank number */ -#define AWE_SET_GUS_BANK(dev,bank) AWE_MISC_MODE(dev,AWE_MD_GUS_BANK,bank) -/* change panning position in realtime; 0=don't 1=do */ -#define AWE_REALTIME_PAN(dev,mode) AWE_MISC_MODE(dev,AWE_MD_REALTIME_PAN,mode) - -/* extended pressure controls; not portable with other sound drivers */ -#define AWE_KEY_PRESSURE(dev,ch,note,vel) SEQ_START_NOTE(dev,ch,(note)+128,vel) -#define AWE_CHN_PRESSURE(dev,ch,vel) _AWE_CMD(dev,ch,_AWE_CHN_PRESSURE,vel,0) - -/*----------------------------------------------------------------*/ - -/* reverb mode parameters */ -#define AWE_REVERB_ROOM1 0 -#define AWE_REVERB_ROOM2 1 -#define AWE_REVERB_ROOM3 2 -#define AWE_REVERB_HALL1 3 -#define AWE_REVERB_HALL2 4 -#define AWE_REVERB_PLATE 5 -#define AWE_REVERB_DELAY 6 -#define AWE_REVERB_PANNINGDELAY 7 -#define AWE_REVERB_PREDEFINED 8 -/* user can define reverb modes up to 32 */ -#define AWE_REVERB_NUMBERS 32 - -typedef struct awe_reverb_fx_rec { - unsigned short parms[28]; -} awe_reverb_fx_rec; - -/*----------------------------------------------------------------*/ - -/* chorus mode parameters */ -#define AWE_CHORUS_1 0 -#define AWE_CHORUS_2 1 -#define AWE_CHORUS_3 2 -#define AWE_CHORUS_4 3 -#define AWE_CHORUS_FEEDBACK 4 -#define AWE_CHORUS_FLANGER 5 -#define AWE_CHORUS_SHORTDELAY 6 -#define AWE_CHORUS_SHORTDELAY2 7 -#define AWE_CHORUS_PREDEFINED 8 -/* user can define chorus modes up to 32 */ -#define AWE_CHORUS_NUMBERS 32 - -typedef struct awe_chorus_fx_rec { - unsigned short feedback; /* feedback level (0xE600-0xE6FF) */ - unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */ - unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */ - unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */ - unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */ -} awe_chorus_fx_rec; - -/*----------------------------------------------------------------*/ - -/* misc mode types */ -enum { -/* 0*/ AWE_MD_EXCLUSIVE_OFF, /* obsolete */ -/* 1*/ AWE_MD_EXCLUSIVE_ON, /* obsolete */ -/* 2*/ AWE_MD_VERSION, /* read only */ -/* 3*/ AWE_MD_EXCLUSIVE_SOUND, /* ignored */ -/* 4*/ AWE_MD_REALTIME_PAN, /* 0/1: do realtime pan change (default=1) */ -/* 5*/ AWE_MD_GUS_BANK, /* bank number for GUS patches (default=0) */ -/* 6*/ AWE_MD_KEEP_EFFECT, /* 0/1: keep effect values, (default=0) */ -/* 7*/ AWE_MD_ZERO_ATTEN, /* attenuation of max volume (default=32) */ -/* 8*/ AWE_MD_CHN_PRIOR, /* 0/1: set MIDI channel priority mode (default=1) */ -/* 9*/ AWE_MD_MOD_SENSE, /* integer: modwheel sensitivity (def=18) */ -/*10*/ AWE_MD_DEF_PRESET, /* integer: default preset number (def=0) */ -/*11*/ AWE_MD_DEF_BANK, /* integer: default bank number (def=0) */ -/*12*/ AWE_MD_DEF_DRUM, /* integer: default drumset number (def=0) */ -/*13*/ AWE_MD_TOGGLE_DRUM_BANK, /* 0/1: toggle drum flag with bank# (def=0) */ - AWE_MD_END, -}; - -/*----------------------------------------------------------------*/ - -/* effect parameters */ -enum { - -/* modulation envelope parameters */ -/* 0*/ AWE_FX_ENV1_DELAY, /* WORD: ENVVAL */ -/* 1*/ AWE_FX_ENV1_ATTACK, /* BYTE: up ATKHLD */ -/* 2*/ AWE_FX_ENV1_HOLD, /* BYTE: lw ATKHLD */ -/* 3*/ AWE_FX_ENV1_DECAY, /* BYTE: lw DCYSUS */ -/* 4*/ AWE_FX_ENV1_RELEASE, /* BYTE: lw DCYSUS */ -/* 5*/ AWE_FX_ENV1_SUSTAIN, /* BYTE: up DCYSUS */ -/* 6*/ AWE_FX_ENV1_PITCH, /* BYTE: up PEFE */ -/* 7*/ AWE_FX_ENV1_CUTOFF, /* BYTE: lw PEFE */ - -/* volume envelope parameters */ -/* 8*/ AWE_FX_ENV2_DELAY, /* WORD: ENVVOL */ -/* 9*/ AWE_FX_ENV2_ATTACK, /* BYTE: up ATKHLDV */ -/*10*/ AWE_FX_ENV2_HOLD, /* BYTE: lw ATKHLDV */ -/*11*/ AWE_FX_ENV2_DECAY, /* BYTE: lw DCYSUSV */ -/*12*/ AWE_FX_ENV2_RELEASE, /* BYTE: lw DCYSUSV */ -/*13*/ AWE_FX_ENV2_SUSTAIN, /* BYTE: up DCYSUSV */ - -/* LFO1 (tremolo & vibrato) parameters */ -/*14*/ AWE_FX_LFO1_DELAY, /* WORD: LFO1VAL */ -/*15*/ AWE_FX_LFO1_FREQ, /* BYTE: lo TREMFRQ */ -/*16*/ AWE_FX_LFO1_VOLUME, /* BYTE: up TREMFRQ */ -/*17*/ AWE_FX_LFO1_PITCH, /* BYTE: up FMMOD */ -/*18*/ AWE_FX_LFO1_CUTOFF, /* BYTE: lo FMMOD */ - -/* LFO2 (vibrato) parameters */ -/*19*/ AWE_FX_LFO2_DELAY, /* WORD: LFO2VAL */ -/*20*/ AWE_FX_LFO2_FREQ, /* BYTE: lo FM2FRQ2 */ -/*21*/ AWE_FX_LFO2_PITCH, /* BYTE: up FM2FRQ2 */ - -/* Other overall effect parameters */ -/*22*/ AWE_FX_INIT_PITCH, /* SHORT: pitch offset */ -/*23*/ AWE_FX_CHORUS, /* BYTE: chorus effects send (0-255) */ -/*24*/ AWE_FX_REVERB, /* BYTE: reverb effects send (0-255) */ -/*25*/ AWE_FX_CUTOFF, /* BYTE: up IFATN */ -/*26*/ AWE_FX_FILTERQ, /* BYTE: up CCCA */ - -/* Sample / loop offset changes */ -/*27*/ AWE_FX_SAMPLE_START, /* SHORT: offset */ -/*28*/ AWE_FX_LOOP_START, /* SHORT: offset */ -/*29*/ AWE_FX_LOOP_END, /* SHORT: offset */ -/*30*/ AWE_FX_COARSE_SAMPLE_START, /* SHORT: upper word offset */ -/*31*/ AWE_FX_COARSE_LOOP_START, /* SHORT: upper word offset */ -/*32*/ AWE_FX_COARSE_LOOP_END, /* SHORT: upper word offset */ -/*33*/ AWE_FX_ATTEN, /* BYTE: lo IFATN */ - - AWE_FX_END, -}; - -#endif /* AWE_VOICE_H */ diff --git a/sys/i386/gnu/isa/sound/awe_wave.c b/sys/i386/gnu/isa/sound/awe_wave.c deleted file mode 100644 index 05703f6901..0000000000 --- a/sys/i386/gnu/isa/sound/awe_wave.c +++ /dev/null @@ -1,4581 +0,0 @@ -/* - * sound/awe_wave.c - * - * The low level driver for the AWE32/Sound Blaster 32 wave table synth. - * version 0.4.2c; Oct. 7, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $DragonFly: src/sys/i386/gnu/isa/sound/Attic/awe_wave.c,v 1.4 2004/12/08 20:36:39 joerg Exp $ - */ - -#include "opt_depricated.h" -#ifndef I_WANT_DEPRICATED_STUFF -#error "Add options I_WANT_DEPRICATED_STUFF to your kernel config and send a mail to kernel@" -#endif - -#include - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include "awe_config.h" -#else -# include "awe_config.h" -#endif - -/*----------------------------------------------------------------*/ - -#ifdef CONFIG_AWE32_SYNTH - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include "awe_hw.h" -# include "awe_version.h" -# include "awe_voice.h" -#else -# include "awe_hw.h" -# include "awe_version.h" -# include "awe_voice.h" -#endif - -#ifdef AWE_HAS_GUS_COMPATIBILITY -/* include finetune table */ - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# ifdef AWE_OBSOLETE_VOXWARE -# define SEQUENCER_C -# endif -# include -#else -# ifdef AWE_OBSOLETE_VOXWARE -# include "tuning.h" -# else -# include "../tuning.h" -# endif -#endif - -#ifdef linux -# include -#elif defined(__DragonFly__) || defined(__FreeBSD__) -# include -#endif - -#endif /* AWE_HAS_GUS_COMPATIBILITY */ - - -/*---------------------------------------------------------------- - * debug message - *----------------------------------------------------------------*/ - -static int debug_mode = 0; -#ifdef AWE_DEBUG_ON -#define AWE_DEBUG(LVL,XXX) {if (debug_mode > LVL) { XXX; }} -#define ERRMSG(XXX) {if (debug_mode) { XXX; }} -#define FATALERR(XXX) XXX -#else -#define AWE_DEBUG(LVL,XXX) /**/ -#define ERRMSG(XXX) XXX -#define FATALERR(XXX) XXX -#endif - -/*---------------------------------------------------------------- - * bank and voice record - *----------------------------------------------------------------*/ - -/* soundfont record */ -typedef struct _sf_list { - unsigned short sf_id; - unsigned short type; - int num_info; /* current info table index */ - int num_sample; /* current sample table index */ - int mem_ptr; /* current word byte pointer */ - int infos; - int samples; - /*char name[AWE_PATCH_NAME_LEN];*/ -} sf_list; - -/* bank record */ -typedef struct _awe_voice_list { - int next; /* linked list with same sf_id */ - unsigned char bank, instr; /* preset number information */ - char type, disabled; /* type=normal/mapped, disabled=boolean */ - awe_voice_info v; /* voice information */ - int next_instr; /* preset table list */ - int next_bank; /* preset table list */ -} awe_voice_list; - -/* voice list type */ -#define V_ST_NORMAL 0 -#define V_ST_MAPPED 1 - -typedef struct _awe_sample_list { - int next; /* linked list with same sf_id */ - awe_sample_info v; /* sample information */ -} awe_sample_list; - -/* sample and information table */ -static int current_sf_id = 0; -static int locked_sf_id = 0; -static int max_sfs; -static sf_list *sflists = NULL; - -#define awe_free_mem_ptr() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].mem_ptr) -#define awe_free_info() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].num_info) -#define awe_free_sample() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].num_sample) - -static int max_samples; -static awe_sample_list *samples = NULL; - -static int max_infos; -static awe_voice_list *infos = NULL; - - -#define AWE_MAX_PRESETS 256 -#define AWE_DEFAULT_PRESET 0 -#define AWE_DEFAULT_BANK 0 -#define AWE_DEFAULT_DRUM 0 -#define AWE_DRUM_BANK 128 - -#define MAX_LAYERS AWE_MAX_VOICES - -/* preset table index */ -static int preset_table[AWE_MAX_PRESETS]; - -/*---------------------------------------------------------------- - * voice table - *----------------------------------------------------------------*/ - -/* effects table */ -typedef struct FX_Rec { /* channel effects */ - unsigned char flags[AWE_FX_END]; - short val[AWE_FX_END]; -} FX_Rec; - - -/* channel parameters */ -typedef struct _awe_chan_info { - int channel; /* channel number */ - int bank; /* current tone bank */ - int instr; /* current program */ - int bender; /* midi pitchbend (-8192 - 8192) */ - int bender_range; /* midi bender range (x100) */ - int panning; /* panning (0-127) */ - int main_vol; /* channel volume (0-127) */ - int expression_vol; /* midi expression (0-127) */ - int chan_press; /* channel pressure */ - int vrec; /* instrument list */ - int def_vrec; /* default instrument list */ - int sustained; /* sustain status in MIDI */ - FX_Rec fx; /* effects */ - FX_Rec fx_layer[MAX_LAYERS]; /* layer effects */ -} awe_chan_info; - -/* voice parameters */ -typedef struct _voice_info { - int state; -#define AWE_ST_OFF (1<<0) /* no sound */ -#define AWE_ST_ON (1<<1) /* playing */ -#define AWE_ST_STANDBY (1<<2) /* stand by for playing */ -#define AWE_ST_SUSTAINED (1<<3) /* sustained */ -#define AWE_ST_MARK (1<<4) /* marked for allocation */ -#define AWE_ST_DRAM (1<<5) /* DRAM read/write */ -#define AWE_ST_FM (1<<6) /* reserved for FM */ -#define AWE_ST_RELEASED (1<<7) /* released */ - - int ch; /* midi channel */ - int key; /* internal key for search */ - int layer; /* layer number (for channel mode only) */ - int time; /* allocated time */ - awe_chan_info *cinfo; /* channel info */ - - int note; /* midi key (0-127) */ - int velocity; /* midi velocity (0-127) */ - int sostenuto; /* sostenuto on/off */ - awe_voice_info *sample; /* assigned voice */ - - /* EMU8000 parameters */ - int apitch; /* pitch parameter */ - int avol; /* volume parameter */ - int apan; /* panning parameter */ -} voice_info; - -/* voice information */ -static voice_info *voices; - -#define IS_NO_SOUND(v) (voices[v].state & (AWE_ST_OFF|AWE_ST_RELEASED|AWE_ST_STANDBY|AWE_ST_SUSTAINED)) -#define IS_NO_EFFECT(v) (voices[v].state != AWE_ST_ON) -#define IS_PLAYING(v) (voices[v].state & (AWE_ST_ON|AWE_ST_SUSTAINED|AWE_ST_RELEASED)) -#define IS_EMPTY(v) (voices[v].state & (AWE_ST_OFF|AWE_ST_MARK|AWE_ST_DRAM|AWE_ST_FM)) - - -/* MIDI channel effects information (for hw control) */ -static awe_chan_info *channels; - - -/*---------------------------------------------------------------- - * global variables - *----------------------------------------------------------------*/ - -#ifndef AWE_DEFAULT_BASE_ADDR -#define AWE_DEFAULT_BASE_ADDR 0 /* autodetect */ -#endif - -#ifndef AWE_DEFAULT_MEM_SIZE -#define AWE_DEFAULT_MEM_SIZE 0 /* autodetect */ -#endif - -/* awe32 base address (overwritten at initialization) */ -static int awe_base = AWE_DEFAULT_BASE_ADDR; -/* memory byte size */ -static int awe_mem_size = AWE_DEFAULT_MEM_SIZE; -/* DRAM start offset */ -static int awe_mem_start = AWE_DRAM_OFFSET; - -/* maximum channels for playing */ -static int awe_max_voices = AWE_MAX_VOICES; - -static int patch_opened = 0; /* sample already loaded? */ - -static int reverb_mode = 4; /* reverb mode */ -static int chorus_mode = 2; /* chorus mode */ -static short init_atten = AWE_DEFAULT_ATTENUATION; /* 12dB below */ - -static int awe_present = FALSE; /* awe device present? */ -static int awe_busy = FALSE; /* awe device opened? */ - -#define DEFAULT_DRUM_FLAGS ((1 << 9) | (1 << 25)) -#define IS_DRUM_CHANNEL(c) (drum_flags & (1 << (c))) -#define DRUM_CHANNEL_ON(c) (drum_flags |= (1 << (c))) -#define DRUM_CHANNEL_OFF(c) (drum_flags &= ~(1 << (c))) -static unsigned int drum_flags = DEFAULT_DRUM_FLAGS; /* channel flags */ - -static int playing_mode = AWE_PLAY_INDIRECT; -#define SINGLE_LAYER_MODE() (playing_mode == AWE_PLAY_INDIRECT || playing_mode == AWE_PLAY_DIRECT) -#define MULTI_LAYER_MODE() (playing_mode == AWE_PLAY_MULTI || playing_mode == AWE_PLAY_MULTI2) - -static int current_alloc_time = 0; /* voice allocation index for channel mode */ - -static struct MiscModeDef { - int value; - int init_each_time; -} misc_modes_default[AWE_MD_END] = { - {0,0}, {0,0}, /* <-- not used */ - {AWE_VERSION_NUMBER, FALSE}, - {TRUE, TRUE}, /* exclusive */ - {TRUE, TRUE}, /* realpan */ - {AWE_DEFAULT_BANK, TRUE}, /* gusbank */ - {FALSE, TRUE}, /* keep effect */ - {AWE_DEFAULT_ATTENUATION, FALSE}, /* zero_atten */ - {FALSE, TRUE}, /* chn_prior */ - {AWE_DEFAULT_MOD_SENSE, TRUE}, /* modwheel sense */ - {AWE_DEFAULT_PRESET, TRUE}, /* def_preset */ - {AWE_DEFAULT_BANK, TRUE}, /* def_bank */ - {AWE_DEFAULT_DRUM, TRUE}, /* def_drum */ - {FALSE, TRUE}, /* toggle_drum_bank */ -}; - -static int misc_modes[AWE_MD_END]; - -static int awe_bass_level = 5; -static int awe_treble_level = 9; - - -static struct synth_info awe_info = { - "AWE32 Synth", /* name */ - 0, /* device */ - SYNTH_TYPE_SAMPLE, /* synth_type */ - SAMPLE_TYPE_AWE32, /* synth_subtype */ - 0, /* perc_mode (obsolete) */ - AWE_MAX_VOICES, /* nr_voices */ - 0, /* nr_drums (obsolete) */ - AWE_MAX_INFOS /* instr_bank_size */ -}; - - -static struct voice_alloc_info *voice_alloc; /* set at initialization */ - - -/*---------------------------------------------------------------- - * function prototypes - *----------------------------------------------------------------*/ - -#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE) -static int awe_check_port(void); -static void awe_request_region(void); -static void awe_release_region(void); -#endif - -static void awe_reset_samples(void); -/* emu8000 chip i/o access */ -static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data); -static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data); -static unsigned short awe_peek(unsigned short cmd, unsigned short port); -static unsigned int awe_peek_dw(unsigned short cmd, unsigned short port); -static void awe_wait(unsigned short delay); - -/* initialize emu8000 chip */ -static void awe_initialize(void); - -/* set voice parameters */ -static void awe_init_misc_modes(int init_all); -static void awe_init_voice_info(awe_voice_info *vp); -static void awe_init_voice_parm(awe_voice_parm *pp); -#ifdef AWE_HAS_GUS_COMPATIBILITY -static int freq_to_note(int freq); -static int calc_rate_offset(int Hz); -/*static int calc_parm_delay(int msec);*/ -static int calc_parm_hold(int msec); -static int calc_parm_attack(int msec); -static int calc_parm_decay(int msec); -static int calc_parm_search(int msec, short *table); -#endif - -/* turn on/off note */ -static void awe_note_on(int voice); -static void awe_note_off(int voice); -static void awe_terminate(int voice); -static void awe_exclusive_off(int voice); -static void awe_note_off_all(int do_sustain); - -/* calculate voice parameters */ -typedef void (*fx_affect_func)(int voice, int forced); -static void awe_set_pitch(int voice, int forced); -static void awe_set_voice_pitch(int voice, int forced); -static void awe_set_volume(int voice, int forced); -static void awe_set_voice_vol(int voice, int forced); -static void awe_set_pan(int voice, int forced); -static void awe_fx_fmmod(int voice, int forced); -static void awe_fx_tremfrq(int voice, int forced); -static void awe_fx_fm2frq2(int voice, int forced); -static void awe_fx_filterQ(int voice, int forced); -static void awe_calc_pitch(int voice); -#ifdef AWE_HAS_GUS_COMPATIBILITY -static void awe_calc_pitch_from_freq(int voice, int freq); -#endif -static void awe_calc_volume(int voice); -static void awe_voice_init(int voice, int init_all); -static void awe_channel_init(int ch, int init_all); -static void awe_fx_init(int ch); - -/* sequencer interface */ -static int awe_open(int dev, int mode); -static void awe_close(int dev); -static int awe_ioctl(int dev, unsigned int cmd, caddr_t arg); -static int awe_kill_note(int dev, int voice, int note, int velocity); -static int awe_start_note(int dev, int v, int note_num, int volume); -static int awe_set_instr(int dev, int voice, int instr_no); -static int awe_set_instr_2(int dev, int voice, int instr_no); -static void awe_reset(int dev); -static void awe_hw_control(int dev, unsigned char *event); -static int awe_load_patch(int dev, int format, const char *addr, - int offs, int count, int pmgr_flag); -static void awe_aftertouch(int dev, int voice, int pressure); -static void awe_controller(int dev, int voice, int ctrl_num, int value); -static void awe_panning(int dev, int voice, int value); -static void awe_volume_method(int dev, int mode); -#ifndef AWE_NO_PATCHMGR -static int awe_patchmgr(int dev, struct patmgr_info *rec); -#endif -static void awe_bender(int dev, int voice, int value); -static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc); -static void awe_setup_voice(int dev, int voice, int chn); - -/* hardware controls */ -#ifdef AWE_HAS_GUS_COMPATIBILITY -static void awe_hw_gus_control(int dev, int cmd, unsigned char *event); -#endif -static void awe_hw_awe_control(int dev, int cmd, unsigned char *event); -static void awe_voice_change(int voice, fx_affect_func func); -static void awe_sostenuto_on(int voice, int forced); -static void awe_sustain_off(int voice, int forced); -static void awe_terminate_and_init(int voice, int forced); - -/* voice search */ -static int awe_search_instr(int bank, int preset); -static int awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist); -static void awe_alloc_multi_voices(int ch, int note, int velocity, int key); -static void awe_alloc_one_voice(int voice, int note, int velocity); -static int awe_clear_voice(void); - -/* load / remove patches */ -static int awe_open_patch(awe_patch_info *patch, const char *addr, int count); -static int awe_close_patch(awe_patch_info *patch, const char *addr, int count); -static int awe_unload_patch(awe_patch_info *patch, const char *addr, int count); -static int awe_load_info(awe_patch_info *patch, const char *addr, int count); -static int awe_load_data(awe_patch_info *patch, const char *addr, int count); -static int awe_replace_data(awe_patch_info *patch, const char *addr, int count); -static int awe_load_map(awe_patch_info *patch, const char *addr, int count); -#ifdef AWE_HAS_GUS_COMPATIBILITY -static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag); -#endif -static int check_patch_opened(int type, char *name); -static int awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels); -static void add_sf_info(int rec); -static void add_sf_sample(int rec); -static void purge_old_list(int rec, int next); -static void add_info_list(int rec); -static void awe_remove_samples(int sf_id); -static void rebuild_preset_list(void); -static short awe_set_sample(awe_voice_info *vp); - -/* lowlevel functions */ -static void awe_init_audio(void); -static void awe_init_dma(void); -static void awe_init_array(void); -static void awe_send_array(unsigned short *data); -static void awe_tweak_voice(int voice); -static void awe_tweak(void); -static void awe_init_fm(void); -static int awe_open_dram_for_write(int offset, int channels); -static void awe_open_dram_for_check(void); -static void awe_close_dram(void); -static void awe_write_dram(unsigned short c); -static int awe_detect_base(int addr); -static int awe_detect(void); -static int awe_check_dram(void); -static int awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count); -static void awe_set_chorus_mode(int mode); -static int awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count); -static void awe_set_reverb_mode(int mode); -static void awe_equalizer(int bass, int treble); -#ifdef CONFIG_AWE32_MIXER -static int awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg); -#endif - -/* define macros for compatibility */ -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include "awe_compat.h" -#else -# include "awe_compat.h" -#endif - -/*---------------------------------------------------------------- - * synth operation table - *----------------------------------------------------------------*/ - -static struct synth_operations awe_operations = -{ -#ifdef AWE_OSS38 - "EMU8K", -#endif - &awe_info, - 0, - SYNTH_TYPE_SAMPLE, - SAMPLE_TYPE_AWE32, - awe_open, - awe_close, - awe_ioctl, - awe_kill_note, - awe_start_note, - awe_set_instr_2, - awe_reset, - awe_hw_control, - awe_load_patch, - awe_aftertouch, - awe_controller, - awe_panning, - awe_volume_method, -#ifndef AWE_NO_PATCHMGR - awe_patchmgr, -#endif - awe_bender, - awe_alloc, - awe_setup_voice -}; - -#ifdef CONFIG_AWE32_MIXER -static struct mixer_operations awe_mixer_operations = { -#if !defined(__DragonFly__) && !defined(__FreeBSD__) - "AWE32", -#endif - "AWE32 Equalizer", - awe_mixer_ioctl, -}; -#endif - - -/*================================================================ - * attach / unload interface - *================================================================*/ - -#ifdef AWE_OBSOLETE_VOXWARE -#define ATTACH_DECL static -#else -#define ATTACH_DECL /**/ -#endif - -#if (defined(__DragonFly__) || defined(__FreeBSD__)) && !defined(AWE_OBSOLETE_VOXWARE) -# define ATTACH_RET -void attach_awe(struct address_info *hw_config) -#else -# define ATTACH_RET ret -ATTACH_DECL -int attach_awe(void) -#endif -{ - int ret = 0; - - /* check presence of AWE32 card */ - if (! awe_detect()) { - printk("AWE32: not detected\n"); - return ATTACH_RET; - } - - /* check AWE32 ports are available */ - if (awe_check_port()) { - printk("AWE32: I/O area already used.\n"); - return ATTACH_RET; - } - - /* set buffers to NULL */ - voices = NULL; - channels = NULL; - sflists = NULL; - samples = NULL; - infos = NULL; - - /* voice & channel info */ - voices = (voice_info*)my_malloc(AWE_MAX_VOICES * sizeof(voice_info)); - channels = (awe_chan_info*)my_malloc(AWE_MAX_CHANNELS * sizeof(awe_chan_info)); - - if (voices == NULL || channels == NULL) { - my_free(voices); - my_free(channels); - printk("AWE32: can't allocate sample tables\n"); - return ATTACH_RET; - } - - /* allocate sample tables */ - INIT_TABLE(sflists, max_sfs, AWE_MAX_SF_LISTS, sf_list); - INIT_TABLE(samples, max_samples, AWE_MAX_SAMPLES, awe_sample_list); - INIT_TABLE(infos, max_infos, AWE_MAX_INFOS, awe_voice_list); - - if (num_synths >= MAX_SYNTH_DEV) - printk("AWE32 Error: too many synthesizers\n"); - else { - voice_alloc = &awe_operations.alloc; - voice_alloc->max_voice = awe_max_voices; - synth_devs[num_synths++] = &awe_operations; - } - -#ifdef CONFIG_AWE32_MIXER - if (num_mixers < MAX_MIXER_DEV) { - mixer_devs[num_mixers++] = &awe_mixer_operations; - } -#endif - - /* reserve I/O ports for awedrv */ - awe_request_region(); - - /* clear all samples */ - awe_reset_samples(); - - /* intialize AWE32 hardware */ - awe_initialize(); - - snprintf(awe_info.name, sizeof(awe_info.name), "AWE32-%s (RAM%dk)", - AWEDRV_VERSION, awe_mem_size/1024); -#if defined(__DragonFly__) || defined(__FreeBSD__) - printk("awe0: ", awe_mem_size/1024); -#elif defined(AWE_DEBUG_ON) - printk("%s\n", awe_info.name); -#endif - - /* set default values */ - awe_init_misc_modes(TRUE); - - /* set reverb & chorus modes */ - awe_set_reverb_mode(reverb_mode); - awe_set_chorus_mode(chorus_mode); - - awe_present = TRUE; - - ret = 1; - return ATTACH_RET; -} - - -#ifdef AWE_DYNAMIC_BUFFER -static void free_tables(void) -{ - my_free(sflists); - sflists = NULL; max_sfs = 0; - my_free(samples); - samples = NULL; max_samples = 0; - my_free(infos); - infos = NULL; max_infos = 0; -} -#else -#define free_buffers() /**/ -#endif - - -#ifdef linux -ATTACH_DECL -void unload_awe(void) -{ - if (awe_present) { - awe_reset_samples(); - awe_release_region(); - my_free(voices); - my_free(channels); - free_tables(); - awe_present = FALSE; - } -} -#endif - - -/*---------------------------------------------------------------- - * old type interface - *----------------------------------------------------------------*/ - -#ifdef AWE_OBSOLETE_VOXWARE - -#if defined(__DragonFly__) || defined(__FreeBSD__) -long attach_awe_obsolete(long mem_start, struct address_info *hw_config) -#else -int attach_awe_obsolete(int mem_start, struct address_info *hw_config) -#endif -{ - my_malloc_init(mem_start); - if (! attach_awe()) - return 0; - return my_malloc_memptr(); -} - -int probe_awe_obsolete(struct address_info *hw_config) -{ - return 1; - /*return awe_detect();*/ -} - -#else -#if defined(__DragonFly__) || defined(__FreeBSD__ ) -int probe_awe(struct address_info *hw_config) -{ - return 1; -} -#endif -#endif /* AWE_OBSOLETE_VOXWARE */ - - -/*================================================================ - * clear sample tables - *================================================================*/ - -static void -awe_reset_samples(void) -{ - int i; - - /* free all bank tables */ - for (i = 0; i < AWE_MAX_PRESETS; i++) - preset_table[i] = -1; - - free_tables(); - - current_sf_id = 0; - locked_sf_id = 0; - patch_opened = 0; -} - - -/*================================================================ - * EMU register access - *================================================================*/ - -/* select a given AWE32 pointer */ -static int awe_cur_cmd = -1; -#define awe_set_cmd(cmd) \ -if (awe_cur_cmd != cmd) { OUTW(cmd, awe_base + 0x802); awe_cur_cmd = cmd; } -#define awe_port(port) (awe_base - 0x620 + port) - -/* write 16bit data */ -INLINE static void -awe_poke(unsigned short cmd, unsigned short port, unsigned short data) -{ - awe_set_cmd(cmd); - OUTW(data, awe_port(port)); -} - -/* write 32bit data */ -INLINE static void -awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data) -{ - awe_set_cmd(cmd); - OUTW(data, awe_port(port)); /* write lower 16 bits */ - OUTW(data >> 16, awe_port(port)+2); /* write higher 16 bits */ -} - -/* read 16bit data */ -INLINE static unsigned short -awe_peek(unsigned short cmd, unsigned short port) -{ - unsigned short k; - awe_set_cmd(cmd); - k = inw(awe_port(port)); - return k; -} - -/* read 32bit data */ -INLINE static unsigned int -awe_peek_dw(unsigned short cmd, unsigned short port) -{ - unsigned int k1, k2; - awe_set_cmd(cmd); - k1 = inw(awe_port(port)); - k2 = inw(awe_port(port)+2); - k1 |= k2 << 16; - return k1; -} - -/* wait delay number of AWE32 44100Hz clocks */ -static void -awe_wait(unsigned short delay) -{ - unsigned short clock, target; - unsigned short port = awe_port(AWE_WC_Port); - int counter; - - /* sample counter */ - awe_set_cmd(AWE_WC_Cmd); - clock = (unsigned short)inw(port); - target = clock + delay; - counter = 0; - if (target < clock) { - for (; (unsigned short)inw(port) > target; counter++) - if (counter > 65536) - break; - } - for (; (unsigned short)inw(port) < target; counter++) - if (counter > 65536) - break; -} - -/* write a word data */ -INLINE static void -awe_write_dram(unsigned short c) -{ - awe_poke(AWE_SMLD, c); -} - - -#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE) - -/*================================================================ - * port check / request - * 0x620-622, 0xA20-A22, 0xE20-E22 - *================================================================*/ - -static int -awe_check_port(void) -{ - return (check_region(awe_port(Data0), 4) || - check_region(awe_port(Data1), 4) || - check_region(awe_port(Data3), 4)); -} - -static void -awe_request_region(void) -{ - request_region(awe_port(Data0), 4, "sound driver (AWE32)"); - request_region(awe_port(Data1), 4, "sound driver (AWE32)"); - request_region(awe_port(Data3), 4, "sound driver (AWE32)"); -} - -static void -awe_release_region(void) -{ - release_region(awe_port(Data0), 4); - release_region(awe_port(Data1), 4); - release_region(awe_port(Data3), 4); -} - -#endif /* !AWE_OBSOLETE_VOXWARE */ - - -/*================================================================ - * AWE32 initialization - *================================================================*/ -static void -awe_initialize(void) -{ - AWE_DEBUG(0,printk("AWE32: initializing..\n")); - - /* initialize hardware configuration */ - awe_poke(AWE_HWCF1, 0x0059); - awe_poke(AWE_HWCF2, 0x0020); - - /* disable audio; this seems to reduce a clicking noise a bit.. */ - awe_poke(AWE_HWCF3, 0); - - /* initialize audio channels */ - awe_init_audio(); - - /* initialize DMA */ - awe_init_dma(); - - /* initialize init array */ - awe_init_array(); - - /* check DRAM memory size */ - awe_mem_size = awe_check_dram(); - - /* initialize the FM section of the AWE32 */ - awe_init_fm(); - - /* set up voice envelopes */ - awe_tweak(); - - /* enable audio */ - awe_poke(AWE_HWCF3, 0x0004); - - /* set equalizer */ - awe_equalizer(5, 9); -} - - -/*================================================================ - * AWE32 voice parameters - *================================================================*/ - -/* initialize voice_info record */ -static void -awe_init_voice_info(awe_voice_info *vp) -{ - vp->sf_id = 0; /* normal mode */ - vp->sample = 0; - vp->rate_offset = 0; - - vp->start = 0; - vp->end = 0; - vp->loopstart = 0; - vp->loopend = 0; - vp->mode = 0; - vp->root = 60; - vp->tune = 0; - vp->low = 0; - vp->high = 127; - vp->vellow = 0; - vp->velhigh = 127; - - vp->fixkey = -1; - vp->fixvel = -1; - vp->fixpan = -1; - vp->pan = -1; - - vp->exclusiveClass = 0; - vp->amplitude = 127; - vp->attenuation = 0; - vp->scaleTuning = 100; - - awe_init_voice_parm(&vp->parm); -} - -/* initialize voice_parm record: - * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0. - * Vibrato and Tremolo effects are zero. - * Cutoff is maximum. - * Chorus and Reverb effects are zero. - */ -static void -awe_init_voice_parm(awe_voice_parm *pp) -{ - pp->moddelay = 0x8000; - pp->modatkhld = 0x7f7f; - pp->moddcysus = 0x7f7f; - pp->modrelease = 0x807f; - pp->modkeyhold = 0; - pp->modkeydecay = 0; - - pp->voldelay = 0x8000; - pp->volatkhld = 0x7f7f; - pp->voldcysus = 0x7f7f; - pp->volrelease = 0x807f; - pp->volkeyhold = 0; - pp->volkeydecay = 0; - - pp->lfo1delay = 0x8000; - pp->lfo2delay = 0x8000; - pp->pefe = 0; - - pp->fmmod = 0; - pp->tremfrq = 0; - pp->fm2frq2 = 0; - - pp->cutoff = 0xff; - pp->filterQ = 0; - - pp->chorus = 0; - pp->reverb = 0; -} - - -#ifdef AWE_HAS_GUS_COMPATIBILITY - -/* convert frequency mHz to abstract cents (= midi key * 100) */ -static int -freq_to_note(int mHz) -{ - /* abscents = log(mHz/8176) / log(2) * 1200 */ - unsigned int max_val = (unsigned int)0xffffffff / 10000; - int i, times; - unsigned int base; - unsigned int freq; - int note, tune; - - if (mHz == 0) - return 0; - if (mHz < 0) - return 12799; /* maximum */ - - freq = mHz; - note = 0; - for (base = 8176 * 2; freq >= base; base *= 2) { - note += 12; - if (note >= 128) /* over maximum */ - return 12799; - } - base /= 2; - - /* to avoid overflow... */ - times = 10000; - while (freq > max_val) { - max_val *= 10; - times /= 10; - base /= 10; - } - - freq = freq * times / base; - for (i = 0; i < 12; i++) { - if (freq < semitone_tuning[i+1]) - break; - note++; - } - - tune = 0; - freq = freq * 10000 / semitone_tuning[i]; - for (i = 0; i < 100; i++) { - if (freq < cent_tuning[i+1]) - break; - tune++; - } - - return note * 100 + tune; -} - - -/* convert Hz to AWE32 rate offset: - * sample pitch offset for the specified sample rate - * rate=44100 is no offset, each 4096 is 1 octave (twice). - * eg, when rate is 22050, this offset becomes -4096. - */ -static int -calc_rate_offset(int Hz) -{ - /* offset = log(Hz / 44100) / log(2) * 4096 */ - int freq, base, i; - - /* maybe smaller than max (44100Hz) */ - if (Hz <= 0 || Hz >= 44100) return 0; - - base = 0; - for (freq = Hz * 2; freq < 44100; freq *= 2) - base++; - base *= 1200; - - freq = 44100 * 10000 / (freq/2); - for (i = 0; i < 12; i++) { - if (freq < semitone_tuning[i+1]) - break; - base += 100; - } - freq = freq * 10000 / semitone_tuning[i]; - for (i = 0; i < 100; i++) { - if (freq < cent_tuning[i+1]) - break; - base++; - } - return -base * 4096 / 1200; -} - - -/*---------------------------------------------------------------- - * convert envelope time parameter to AWE32 raw parameter - *----------------------------------------------------------------*/ - -/* attack & decay/release time table (msec) */ -static short attack_time_tbl[128] = { -32767, 11878, 5939, 3959, 2969, 2375, 1979, 1696, 1484, 1319, 1187, 1079, 989, 913, 848, 791, 742, - 698, 659, 625, 593, 565, 539, 516, 494, 475, 456, 439, 424, 409, 395, 383, 371, - 359, 344, 330, 316, 302, 290, 277, 266, 255, 244, 233, 224, 214, 205, 196, 188, - 180, 173, 165, 158, 152, 145, 139, 133, 127, 122, 117, 112, 107, 103, 98, 94, - 90, 86, 83, 79, 76, 73, 69, 67, 64, 61, 58, 56, 54, 51, 49, 47, - 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 25, 24, 23, - 22, 21, 20, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11, - 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 0, -}; - -static short decay_time_tbl[128] = { -32767, 32766, 4589, 4400, 4219, 4045, 3879, 3719, 3566, 3419, 3279, 3144, 3014, 2890, 2771, 2657, - 2548, 2443, 2343, 2246, 2154, 2065, 1980, 1899, 1820, 1746, 1674, 1605, 1539, 1475, 1415, 1356, - 1301, 1247, 1196, 1146, 1099, 1054, 1011, 969, 929, 891, 854, 819, 785, 753, 722, 692, - 664, 636, 610, 585, 561, 538, 516, 494, 474, 455, 436, 418, 401, 384, 368, 353, - 339, 325, 311, 298, 286, 274, 263, 252, 242, 232, 222, 213, 204, 196, 188, 180, - 173, 166, 159, 152, 146, 140, 134, 129, 123, 118, 113, 109, 104, 100, 96, 92, - 88, 84, 81, 77, 74, 71, 68, 65, 63, 60, 58, 55, 53, 51, 49, 47, - 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 26, 25, 24, -}; - -/* -static int -calc_parm_delay(int msec) -{ - return (0x8000 - msec * 1000 / 725); -} -*/ - -/* delay time = 0x8000 - msec/92 */ -static int -calc_parm_hold(int msec) -{ - int val = (0x7f * 92 - msec) / 92; - if (val < 1) val = 1; - if (val > 127) val = 127; - return val; -} - -/* attack time: search from time table */ -static int -calc_parm_attack(int msec) -{ - return calc_parm_search(msec, attack_time_tbl); -} - -/* decay/release time: search from time table */ -static int -calc_parm_decay(int msec) -{ - return calc_parm_search(msec, decay_time_tbl); -} - -/* search an index for specified time from given time table */ -static int -calc_parm_search(int msec, short *table) -{ - int left = 1, right = 127, mid; - while (left < right) { - mid = (left + right) / 2; - if (msec < (int)table[mid]) - left = mid + 1; - else - right = mid; - } - return left; -} -#endif /* AWE_HAS_GUS_COMPATIBILITY */ - - -/*================================================================ - * effects table - *================================================================*/ - -/* set an effect value */ -#define FX_FLAG_OFF 0 -#define FX_FLAG_SET 1 -#define FX_FLAG_ADD 2 - -#define FX_SET(rec,type,value) \ - ((rec)->flags[type] = FX_FLAG_SET, (rec)->val[type] = (value)) -#define FX_ADD(rec,type,value) \ - ((rec)->flags[type] = FX_FLAG_ADD, (rec)->val[type] = (value)) -#define FX_UNSET(rec,type) \ - ((rec)->flags[type] = FX_FLAG_OFF, (rec)->val[type] = 0) - -/* check the effect value is set */ -#define FX_ON(rec,type) ((rec)->flags[type]) - -#define PARM_BYTE 0 -#define PARM_WORD 1 - -static struct PARM_DEFS { - int type; /* byte or word */ - int low, high; /* value range */ - fx_affect_func realtime; /* realtime paramater change */ -} parm_defs[] = { - {PARM_WORD, 0, 0x8000, NULL}, /* env1 delay */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env1 attack */ - {PARM_BYTE, 0, 0x7e, NULL}, /* env1 hold */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env1 decay */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env1 release */ - {PARM_BYTE, 0, 0x7f, NULL}, /* env1 sustain */ - {PARM_BYTE, 0, 0xff, NULL}, /* env1 pitch */ - {PARM_BYTE, 0, 0xff, NULL}, /* env1 cutoff */ - - {PARM_WORD, 0, 0x8000, NULL}, /* env2 delay */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env2 attack */ - {PARM_BYTE, 0, 0x7e, NULL}, /* env2 hold */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env2 decay */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env2 release */ - {PARM_BYTE, 0, 0x7f, NULL}, /* env2 sustain */ - - {PARM_WORD, 0, 0x8000, NULL}, /* lfo1 delay */ - {PARM_BYTE, 0, 0xff, awe_fx_tremfrq}, /* lfo1 freq */ - {PARM_BYTE, 0, 0x7f, awe_fx_tremfrq}, /* lfo1 volume (positive only)*/ - {PARM_BYTE, 0, 0x7f, awe_fx_fmmod}, /* lfo1 pitch (positive only)*/ - {PARM_BYTE, 0, 0xff, awe_fx_fmmod}, /* lfo1 cutoff (positive only)*/ - - {PARM_WORD, 0, 0x8000, NULL}, /* lfo2 delay */ - {PARM_BYTE, 0, 0xff, awe_fx_fm2frq2}, /* lfo2 freq */ - {PARM_BYTE, 0, 0x7f, awe_fx_fm2frq2}, /* lfo2 pitch (positive only)*/ - - {PARM_WORD, 0, 0xffff, awe_set_voice_pitch}, /* initial pitch */ - {PARM_BYTE, 0, 0xff, NULL}, /* chorus */ - {PARM_BYTE, 0, 0xff, NULL}, /* reverb */ - {PARM_BYTE, 0, 0xff, awe_set_volume}, /* initial cutoff */ - {PARM_BYTE, 0, 15, awe_fx_filterQ}, /* initial resonance */ - - {PARM_WORD, 0, 0xffff, NULL}, /* sample start */ - {PARM_WORD, 0, 0xffff, NULL}, /* loop start */ - {PARM_WORD, 0, 0xffff, NULL}, /* loop end */ - {PARM_WORD, 0, 0xffff, NULL}, /* coarse sample start */ - {PARM_WORD, 0, 0xffff, NULL}, /* coarse loop start */ - {PARM_WORD, 0, 0xffff, NULL}, /* coarse loop end */ - {PARM_BYTE, 0, 0xff, awe_set_volume}, /* initial attenuation */ -}; - - -static unsigned char -FX_BYTE(FX_Rec *rec, FX_Rec *lay, int type, unsigned char value) -{ - int effect = 0; - int on = 0; - if (lay && (on = FX_ON(lay, type)) != 0) - effect = lay->val[type]; - if (!on && (on = FX_ON(rec, type)) != 0) - effect = rec->val[type]; - if (on == FX_FLAG_ADD) - effect += (int)value; - if (on) { - if (effect < parm_defs[type].low) - effect = parm_defs[type].low; - else if (effect > parm_defs[type].high) - effect = parm_defs[type].high; - return (unsigned char)effect; - } - return value; -} - -/* get word effect value */ -static unsigned short -FX_WORD(FX_Rec *rec, FX_Rec *lay, int type, unsigned short value) -{ - int effect = 0; - int on = 0; - if (lay && (on = FX_ON(lay, type)) != 0) - effect = lay->val[type]; - if (!on && (on = FX_ON(rec, type)) != 0) - effect = rec->val[type]; - if (on == FX_FLAG_ADD) - effect += (int)value; - if (on) { - if (effect < parm_defs[type].low) - effect = parm_defs[type].low; - else if (effect > parm_defs[type].high) - effect = parm_defs[type].high; - return (unsigned short)effect; - } - return value; -} - -/* get word (upper=type1/lower=type2) effect value */ -static unsigned short -FX_COMB(FX_Rec *rec, FX_Rec *lay, int type1, int type2, unsigned short value) -{ - unsigned short tmp; - tmp = FX_BYTE(rec, lay, type1, (unsigned char)(value >> 8)); - tmp <<= 8; - tmp |= FX_BYTE(rec, lay, type2, (unsigned char)(value & 0xff)); - return tmp; -} - -/* address offset */ -static int -FX_OFFSET(FX_Rec *rec, FX_Rec *lay, int lo, int hi, int mode) -{ - int addr = 0; - if (lay && FX_ON(lay, hi)) - addr = (short)lay->val[hi]; - else if (FX_ON(rec, hi)) - addr = (short)rec->val[hi]; - addr = addr << 15; - if (lay && FX_ON(lay, lo)) - addr += (short)lay->val[lo]; - else if (FX_ON(rec, lo)) - addr += (short)rec->val[lo]; - if (!(mode & AWE_SAMPLE_8BITS)) - addr /= 2; - return addr; -} - - -/*================================================================ - * turn on/off sample - *================================================================*/ - -static void -awe_note_on(int voice) -{ - unsigned int temp; - int addr; - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - /* A voice sample must assigned before calling */ - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - - /* channel to be silent and idle */ - awe_poke(AWE_DCYSUSV(voice), 0x0080); - awe_poke(AWE_VTFT(voice), 0); - awe_poke(AWE_CVCF(voice), 0); - awe_poke(AWE_PTRX(voice), 0); - awe_poke(AWE_CPF(voice), 0); - - /* modulation & volume envelope */ - awe_poke(AWE_ENVVAL(voice), - FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, vp->parm.moddelay)); - awe_poke(AWE_ATKHLD(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK, - vp->parm.modatkhld)); - awe_poke(AWE_DCYSUS(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY, - vp->parm.moddcysus)); - awe_poke(AWE_ENVVOL(voice), - FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay)); - awe_poke(AWE_ATKHLDV(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK, - vp->parm.volatkhld)); - /* decay/sustain parameter for volume envelope must be set at last */ - - /* pitch offset */ - awe_set_pitch(voice, TRUE); - - /* cutoff and volume */ - awe_set_volume(voice, TRUE); - - /* modulation envelope heights */ - awe_poke(AWE_PEFE(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF, - vp->parm.pefe)); - - /* lfo1/2 delay */ - awe_poke(AWE_LFO1VAL(voice), - FX_WORD(fx, fx_lay, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay)); - awe_poke(AWE_LFO2VAL(voice), - FX_WORD(fx, fx_lay, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay)); - - /* lfo1 pitch & cutoff shift */ - awe_fx_fmmod(voice, TRUE); - /* lfo1 volume & freq */ - awe_fx_tremfrq(voice, TRUE); - /* lfo2 pitch & freq */ - awe_fx_fm2frq2(voice, TRUE); - /* pan & loop start */ - awe_set_pan(voice, TRUE); - - /* chorus & loop end (chorus 8bit, MSB) */ - addr = vp->loopend - 1; - addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_END, - AWE_FX_COARSE_LOOP_END, vp->mode); - temp = FX_BYTE(fx, fx_lay, AWE_FX_CHORUS, vp->parm.chorus); - temp = (temp <<24) | (unsigned int)addr; - awe_poke_dw(AWE_CSL(voice), temp); - AWE_DEBUG(4,printk("AWE32: [-- loopend=%x/%x]\n", vp->loopend, addr)); - - /* Q & current address (Q 4bit value, MSB) */ - addr = vp->start - 1; - addr += FX_OFFSET(fx, fx_lay, AWE_FX_SAMPLE_START, - AWE_FX_COARSE_SAMPLE_START, vp->mode); - temp = FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ); - temp = (temp<<28) | (unsigned int)addr; - awe_poke_dw(AWE_CCCA(voice), temp); - AWE_DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n", vp->start, addr)); - - /* reset volume */ - awe_poke_dw(AWE_VTFT(voice), 0x0000FFFF); - awe_poke_dw(AWE_CVCF(voice), 0x0000FFFF); - - /* turn on envelope */ - awe_poke(AWE_DCYSUSV(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY, - vp->parm.voldcysus)); - /* set reverb */ - temp = FX_BYTE(fx, fx_lay, AWE_FX_REVERB, vp->parm.reverb); - temp = (awe_peek_dw(AWE_PTRX(voice)) & 0xffff0000) | (temp<<8); - awe_poke_dw(AWE_PTRX(voice), temp); - awe_poke_dw(AWE_CPF(voice), 0x40000000); - - voices[voice].state = AWE_ST_ON; - - /* clear voice position for the next note on this channel */ - if (SINGLE_LAYER_MODE()) { - FX_UNSET(fx, AWE_FX_SAMPLE_START); - FX_UNSET(fx, AWE_FX_COARSE_SAMPLE_START); - } -} - - -/* turn off the voice */ -static void -awe_note_off(int voice) -{ - awe_voice_info *vp; - unsigned short tmp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if ((vp = voices[voice].sample) == NULL) { - voices[voice].state = AWE_ST_OFF; - return; - } - - tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV1_RELEASE, - (unsigned char)vp->parm.modrelease); - awe_poke(AWE_DCYSUS(voice), tmp); - tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV2_RELEASE, - (unsigned char)vp->parm.volrelease); - awe_poke(AWE_DCYSUSV(voice), tmp); - voices[voice].state = AWE_ST_RELEASED; -} - -/* force to terminate the voice (no releasing echo) */ -static void -awe_terminate(int voice) -{ - awe_poke(AWE_DCYSUSV(voice), 0x807F); - awe_tweak_voice(voice); - voices[voice].state = AWE_ST_OFF; -} - -/* turn off other voices with the same exclusive class (for drums) */ -static void -awe_exclusive_off(int voice) -{ - int i, exclass; - - if (voices[voice].sample == NULL) - return; - if ((exclass = voices[voice].sample->exclusiveClass) == 0) - return; /* not exclusive */ - - /* turn off voices with the same class */ - for (i = 0; i < awe_max_voices; i++) { - if (i != voice && IS_PLAYING(i) && - voices[i].sample && voices[i].ch == voices[voice].ch && - voices[i].sample->exclusiveClass == exclass) { - AWE_DEBUG(4,printk("AWE32: [exoff(%d)]\n", i)); - awe_terminate(i); - awe_voice_init(i, TRUE); - } - } -} - - -/*================================================================ - * change the parameters of an audible voice - *================================================================*/ - -/* change pitch */ -static void -awe_set_pitch(int voice, int forced) -{ - if (IS_NO_EFFECT(voice) && !forced) return; - awe_poke(AWE_IP(voice), voices[voice].apitch); - AWE_DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch)); -} - -/* calculate & change pitch */ -static void -awe_set_voice_pitch(int voice, int forced) -{ - awe_calc_pitch(voice); - awe_set_pitch(voice, forced); -} - -/* change volume & cutoff */ -static void -awe_set_volume(int voice, int forced) -{ - awe_voice_info *vp; - unsigned short tmp2; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (!IS_PLAYING(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - - tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF, vp->parm.cutoff); - tmp2 = (tmp2 << 8); - tmp2 |= FX_BYTE(fx, fx_lay, AWE_FX_ATTEN, - (unsigned char)voices[voice].avol); - awe_poke(AWE_IFATN(voice), tmp2); -} - -/* calculate & change volume */ -static void -awe_set_voice_vol(int voice, int forced) -{ - if (IS_EMPTY(voice)) - return; - awe_calc_volume(voice); - awe_set_volume(voice, forced); -} - - -/* change pan; this could make a click noise.. */ -static void -awe_set_pan(int voice, int forced) -{ - unsigned int temp; - int addr; - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - - /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */ - if (vp->fixpan > 0) /* 0-127 */ - temp = 255 - (int)vp->fixpan * 2; - else { - int pos = 0; - if (vp->pan >= 0) /* 0-127 */ - pos = (int)vp->pan * 2 - 128; - pos += voices[voice].cinfo->panning; /* -128 - 127 */ - pos = 127 - pos; - if (pos < 0) - temp = 0; - else if (pos > 255) - temp = 255; - else - temp = pos; - } - if (forced || temp != voices[voice].apan) { - addr = vp->loopstart - 1; - addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_START, - AWE_FX_COARSE_LOOP_START, vp->mode); - temp = (temp<<24) | (unsigned int)addr; - awe_poke_dw(AWE_PSST(voice), temp); - voices[voice].apan = temp; - AWE_DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n", vp->loopstart, addr)); - } -} - -/* effects change during playing */ -static void -awe_fx_fmmod(int voice, int forced) -{ - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - awe_poke(AWE_FMMOD(voice), - FX_COMB(fx, fx_lay, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF, - vp->parm.fmmod)); -} - -/* set tremolo (lfo1) volume & frequency */ -static void -awe_fx_tremfrq(int voice, int forced) -{ - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - awe_poke(AWE_TREMFRQ(voice), - FX_COMB(fx, fx_lay, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ, - vp->parm.tremfrq)); -} - -/* set lfo2 pitch & frequency */ -static void -awe_fx_fm2frq2(int voice, int forced) -{ - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - awe_poke(AWE_FM2FRQ2(voice), - FX_COMB(fx, fx_lay, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ, - vp->parm.fm2frq2)); -} - - -/* Q & current address (Q 4bit value, MSB) */ -static void -awe_fx_filterQ(int voice, int forced) -{ - unsigned int addr; - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - - addr = awe_peek_dw(AWE_CCCA(voice)) & 0xffffff; - addr |= (FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ) << 28); - awe_poke_dw(AWE_CCCA(voice), addr); -} - -/*================================================================ - * calculate pitch offset - *---------------------------------------------------------------- - * 0xE000 is no pitch offset at 44100Hz sample. - * Every 4096 is one octave. - *================================================================*/ - -static void -awe_calc_pitch(int voice) -{ - voice_info *vp = &voices[voice]; - awe_voice_info *ap; - awe_chan_info *cp = voices[voice].cinfo; - int offset; - - /* search voice information */ - if ((ap = vp->sample) == NULL) - return; - if (ap->index < 0) { - AWE_DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); - if (awe_set_sample(ap) < 0) - return; - } - - /* calculate offset */ - if (ap->fixkey >= 0) { - AWE_DEBUG(3,printk("AWE32: p-> fixkey(%d) tune(%d)\n", ap->fixkey, ap->tune)); - offset = (ap->fixkey - ap->root) * 4096 / 12; - } else { - AWE_DEBUG(3,printk("AWE32: p(%d)-> root(%d) tune(%d)\n", vp->note, ap->root, ap->tune)); - offset = (vp->note - ap->root) * 4096 / 12; - AWE_DEBUG(4,printk("AWE32: p-> ofs=%d\n", offset)); - } - offset = (offset * ap->scaleTuning) / 100; - AWE_DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset)); - offset += ap->tune * 4096 / 1200; - AWE_DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset)); - if (cp->bender != 0) { - AWE_DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, cp->bender)); - /* (819200: 1 semitone) ==> (4096: 12 semitones) */ - offset += cp->bender * cp->bender_range / 2400; - } - - /* add initial pitch correction */ - if (FX_ON(&cp->fx_layer[vp->layer], AWE_FX_INIT_PITCH)) - offset += cp->fx_layer[vp->layer].val[AWE_FX_INIT_PITCH]; - else if (FX_ON(&cp->fx, AWE_FX_INIT_PITCH)) - offset += cp->fx.val[AWE_FX_INIT_PITCH]; - - /* 0xe000: root pitch */ - vp->apitch = 0xe000 + ap->rate_offset + offset; - AWE_DEBUG(4,printk("AWE32: p-> sum aofs=%x, rate_ofs=%d\n", vp->apitch, ap->rate_offset)); - if (vp->apitch > 0xffff) - vp->apitch = 0xffff; - if (vp->apitch < 0) - vp->apitch = 0; -} - - -#ifdef AWE_HAS_GUS_COMPATIBILITY -/* calculate MIDI key and semitone from the specified frequency */ -static void -awe_calc_pitch_from_freq(int voice, int freq) -{ - voice_info *vp = &voices[voice]; - awe_voice_info *ap; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - int offset; - int note; - - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - /* search voice information */ - if ((ap = vp->sample) == NULL) - return; - if (ap->index < 0) { - AWE_DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); - if (awe_set_sample(ap) < 0) - return; - } - note = freq_to_note(freq); - offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200; - offset = (offset * ap->scaleTuning) / 100; - if (fx_lay && FX_ON(fx_lay, AWE_FX_INIT_PITCH)) - offset += fx_lay->val[AWE_FX_INIT_PITCH]; - else if (FX_ON(fx, AWE_FX_INIT_PITCH)) - offset += fx->val[AWE_FX_INIT_PITCH]; - vp->apitch = 0xe000 + ap->rate_offset + offset; - if (vp->apitch > 0xffff) - vp->apitch = 0xffff; - if (vp->apitch < 0) - vp->apitch = 0; -} -#endif /* AWE_HAS_GUS_COMPATIBILITY */ - - -/*================================================================ - * calculate volume attenuation - *---------------------------------------------------------------- - * Voice volume is controlled by volume attenuation parameter. - * So volume becomes maximum when avol is 0 (no attenuation), and - * minimum when 255 (-96dB or silence). - *================================================================*/ - -static int vol_table[128] = { - 255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49, - 47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32, - 31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22, - 22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16, - 15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10, - 10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6, - 6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3, - 2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0, -}; - -static void -awe_calc_volume(int voice) -{ - voice_info *vp = &voices[voice]; - awe_voice_info *ap; - awe_chan_info *cp = voices[voice].cinfo; - int vol; - - /* search voice information */ - if ((ap = vp->sample) == NULL) - return; - - ap = vp->sample; - if (ap->index < 0) { - AWE_DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); - if (awe_set_sample(ap) < 0) - return; - } - - /* 0 - 127 */ - vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127); - vol = vol * ap->amplitude / 127; - - if (vol < 0) vol = 0; - if (vol > 127) vol = 127; - - /* calc to attenuation */ - vol = vol_table[vol]; - vol = vol + (int)ap->attenuation + init_atten; - if (vol > 255) vol = 255; - - vp->avol = vol; - AWE_DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol)); -} - - -/* set sostenuto on */ -static void awe_sostenuto_on(int voice, int forced) -{ - if (IS_NO_EFFECT(voice) && !forced) return; - voices[voice].sostenuto = 127; -} - - -/* drop sustain */ -static void awe_sustain_off(int voice, int forced) -{ - if (voices[voice].state == AWE_ST_SUSTAINED) { - awe_note_off(voice); - awe_fx_init(voices[voice].ch); - awe_voice_init(voice, FALSE); - } -} - - -/* terminate and initialize voice */ -static void awe_terminate_and_init(int voice, int forced) -{ - awe_terminate(voice); - awe_fx_init(voices[voice].ch); - awe_voice_init(voice, TRUE); -} - - -/*================================================================ - * synth operation routines - *================================================================*/ - -#define AWE_VOICE_KEY(v) (0x8000 | (v)) -#define AWE_CHAN_KEY(c,n) (((c) << 8) | ((n) + 1)) -#define KEY_CHAN_MATCH(key,c) (((key) >> 8) == (c)) - -/* initialize the voice */ -static void -awe_voice_init(int voice, int init_all) -{ - voice_info *vp = &voices[voice]; - - /* reset voice search key */ - if (playing_mode == AWE_PLAY_DIRECT) - vp->key = AWE_VOICE_KEY(voice); - else - vp->key = 0; - - /* clear voice mapping */ - voice_alloc->map[voice] = 0; - - /* touch the timing flag */ - vp->time = current_alloc_time; - - /* initialize other parameters if necessary */ - if (init_all) { - vp->note = -1; - vp->velocity = 0; - vp->sostenuto = 0; - - vp->sample = NULL; - vp->cinfo = &channels[voice]; - vp->ch = voice; - vp->state = AWE_ST_OFF; - - /* emu8000 parameters */ - vp->apitch = 0; - vp->avol = 255; - vp->apan = -1; - } -} - -/* clear effects */ -static void awe_fx_init(int ch) -{ - if (SINGLE_LAYER_MODE() && !misc_modes[AWE_MD_KEEP_EFFECT]) { - BZERO(&channels[ch].fx, sizeof(channels[ch].fx)); - BZERO(&channels[ch].fx_layer, sizeof(&channels[ch].fx_layer)); - } -} - -/* initialize channel info */ -static void awe_channel_init(int ch, int init_all) -{ - awe_chan_info *cp = &channels[ch]; - cp->channel = ch; - if (init_all) { - cp->panning = 0; /* zero center */ - cp->bender_range = 200; /* sense * 100 */ - cp->main_vol = 127; - if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) { - cp->instr = misc_modes[AWE_MD_DEF_DRUM]; - cp->bank = AWE_DRUM_BANK; - } else { - cp->instr = misc_modes[AWE_MD_DEF_PRESET]; - cp->bank = misc_modes[AWE_MD_DEF_BANK]; - } - cp->vrec = -1; - cp->def_vrec = -1; - } - - cp->bender = 0; /* zero tune skew */ - cp->expression_vol = 127; - cp->chan_press = 0; - cp->sustained = 0; - - if (! misc_modes[AWE_MD_KEEP_EFFECT]) { - BZERO(&cp->fx, sizeof(cp->fx)); - BZERO(&cp->fx_layer, sizeof(cp->fx_layer)); - } -} - - -/* change the voice parameters; voice = channel */ -static void awe_voice_change(int voice, fx_affect_func func) -{ - int i; - switch (playing_mode) { - case AWE_PLAY_DIRECT: - func(voice, FALSE); - break; - case AWE_PLAY_INDIRECT: - for (i = 0; i < awe_max_voices; i++) - if (voices[i].key == AWE_VOICE_KEY(voice)) - func(i, FALSE); - break; - default: - for (i = 0; i < awe_max_voices; i++) - if (KEY_CHAN_MATCH(voices[i].key, voice)) - func(i, FALSE); - break; - } -} - - -/*---------------------------------------------------------------- - * device open / close - *----------------------------------------------------------------*/ - -/* open device: - * reset status of all voices, and clear sample position flag - */ -static int -awe_open(int dev, int mode) -{ - if (awe_busy) - return RET_ERROR(EBUSY); - - awe_busy = TRUE; - - /* set default mode */ - awe_init_misc_modes(FALSE); - init_atten = misc_modes[AWE_MD_ZERO_ATTEN]; - drum_flags = DEFAULT_DRUM_FLAGS; - playing_mode = AWE_PLAY_INDIRECT; - - /* reset voices & channels */ - awe_reset(dev); - - patch_opened = 0; - - return 0; -} - - -/* close device: - * reset all voices again (terminate sounds) - */ -static void -awe_close(int dev) -{ - awe_reset(dev); - awe_busy = FALSE; -} - - -/* set miscellaneous mode parameters - */ -static void -awe_init_misc_modes(int init_all) -{ - int i; - for (i = 0; i < AWE_MD_END; i++) { - if (init_all || misc_modes_default[i].init_each_time) - misc_modes[i] = misc_modes_default[i].value; - } -} - - -/* sequencer I/O control: - */ -static int -awe_ioctl(int dev, unsigned int cmd, caddr_t arg) -{ - switch (cmd) { - case SNDCTL_SYNTH_INFO: - if (playing_mode == AWE_PLAY_DIRECT) - awe_info.nr_voices = awe_max_voices; - else - awe_info.nr_voices = AWE_MAX_CHANNELS; - IOCTL_TO_USER((char*)arg, 0, &awe_info, sizeof(awe_info)); - return 0; - break; - - case SNDCTL_SEQ_RESETSAMPLES: - awe_reset_samples(); - awe_reset(dev); - return 0; - break; - - case SNDCTL_SEQ_PERCMODE: - /* what's this? */ - return 0; - break; - - case SNDCTL_SYNTH_MEMAVL: - return awe_mem_size - awe_free_mem_ptr() * 2; - - default: - printk("AWE32: unsupported ioctl %d\n", cmd); - return RET_ERROR(EINVAL); - } -} - - -static int voice_in_range(int voice) -{ - if (playing_mode == AWE_PLAY_DIRECT) { - if (voice < 0 || voice >= awe_max_voices) - return FALSE; - } else { - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return FALSE; - } - return TRUE; -} - -static void release_voice(int voice, int do_sustain) -{ - if (IS_NO_SOUND(voice)) - return; - if (do_sustain && (voices[voice].cinfo->sustained == 127 || - voices[voice].sostenuto == 127)) - voices[voice].state = AWE_ST_SUSTAINED; - else { - awe_note_off(voice); - awe_fx_init(voices[voice].ch); - awe_voice_init(voice, FALSE); - } -} - -/* release all notes */ -static void awe_note_off_all(int do_sustain) -{ - int i; - for (i = 0; i < awe_max_voices; i++) - release_voice(i, do_sustain); -} - -/* kill a voice: - * not terminate, just release the voice. - */ -static int -awe_kill_note(int dev, int voice, int note, int velocity) -{ - int i, v2, key; - - AWE_DEBUG(2,printk("AWE32: [off(%d) nt=%d vl=%d]\n", voice, note, velocity)); - if (! voice_in_range(voice)) - return RET_ERROR(EINVAL); - - switch (playing_mode) { - case AWE_PLAY_DIRECT: - case AWE_PLAY_INDIRECT: - key = AWE_VOICE_KEY(voice); - break; - - case AWE_PLAY_MULTI2: - v2 = voice_alloc->map[voice] >> 8; - voice_alloc->map[voice] = 0; - voice = v2; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return RET_ERROR(EINVAL); - /* continue to below */ - default: - key = AWE_CHAN_KEY(voice, note); - break; - } - - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].key == key) - release_voice(i, TRUE); - } - return 0; -} - - -static void start_or_volume_change(int voice, int velocity) -{ - voices[voice].velocity = velocity; - awe_calc_volume(voice); - if (voices[voice].state == AWE_ST_STANDBY) - awe_note_on(voice); - else if (voices[voice].state == AWE_ST_ON) - awe_set_volume(voice, FALSE); -} - -static void set_and_start_voice(int voice, int state) -{ - /* calculate pitch & volume parameters */ - voices[voice].state = state; - awe_calc_pitch(voice); - awe_calc_volume(voice); - if (state == AWE_ST_ON) - awe_note_on(voice); -} - -/* start a voice: - * if note is 255, identical with aftertouch function. - * Otherwise, start a voice with specified not and volume. - */ -static int -awe_start_note(int dev, int voice, int note, int velocity) -{ - int i, key, state, volonly; - - AWE_DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", voice, note, velocity)); - if (! voice_in_range(voice)) - return RET_ERROR(EINVAL); - - if (velocity == 0) - state = AWE_ST_STANDBY; /* stand by for playing */ - else - state = AWE_ST_ON; /* really play */ - volonly = FALSE; - - switch (playing_mode) { - case AWE_PLAY_DIRECT: - case AWE_PLAY_INDIRECT: - key = AWE_VOICE_KEY(voice); - if (note == 255) - volonly = TRUE; - break; - - case AWE_PLAY_MULTI2: - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return RET_ERROR(EINVAL); - /* continue to below */ - default: - if (note >= 128) { /* key volume mode */ - note -= 128; - volonly = TRUE; - } - key = AWE_CHAN_KEY(voice, note); - break; - } - - /* dynamic volume change */ - if (volonly) { - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].key == key) - start_or_volume_change(i, velocity); - } - return 0; - } - - /* if the same note still playing, stop it */ - for (i = 0; i < awe_max_voices; i++) - if (voices[i].key == key) { - if (voices[i].state == AWE_ST_ON) { - awe_note_off(i); - awe_voice_init(i, FALSE); - } else if (voices[i].state == AWE_ST_STANDBY) - awe_voice_init(i, TRUE); - } - - /* allocate voices */ - if (playing_mode == AWE_PLAY_DIRECT) - awe_alloc_one_voice(voice, note, velocity); - else - awe_alloc_multi_voices(voice, note, velocity, key); - - /* turn off other voices exlusively (for drums) */ - for (i = 0; i < awe_max_voices; i++) - if (voices[i].key == key) - awe_exclusive_off(i); - - /* set up pitch and volume parameters */ - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].key == key && voices[i].state == AWE_ST_OFF) - set_and_start_voice(i, state); - } - - return 0; -} - - -/* search instrument from preset table with the specified bank */ -static int -awe_search_instr(int bank, int preset) -{ - int i; - - for (i = preset_table[preset]; i >= 0; i = infos[i].next_bank) { - if (infos[i].bank == bank) - return i; - } - return -1; -} - - -/* assign the instrument to a voice */ -static int -awe_set_instr_2(int dev, int voice, int instr_no) -{ - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return RET_ERROR(EINVAL); - } - return awe_set_instr(dev, voice, instr_no); -} - -/* assign the instrument to a channel; voice is the channel number */ -static int -awe_set_instr(int dev, int voice, int instr_no) -{ - awe_chan_info *cinfo; - int def_bank; - - if (! voice_in_range(voice)) - return RET_ERROR(EINVAL); - - if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS) - return RET_ERROR(EINVAL); - - cinfo = &channels[voice]; - - if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice)) - def_bank = AWE_DRUM_BANK; /* always search drumset */ - else - def_bank = cinfo->bank; - - cinfo->vrec = -1; - cinfo->def_vrec = -1; - cinfo->vrec = awe_search_instr(def_bank, instr_no); - if (def_bank == AWE_DRUM_BANK) /* search default drumset */ - cinfo->def_vrec = awe_search_instr(def_bank, misc_modes[AWE_MD_DEF_DRUM]); - else /* search default preset */ - cinfo->def_vrec = awe_search_instr(misc_modes[AWE_MD_DEF_BANK], instr_no); - - if (cinfo->vrec < 0 && cinfo->def_vrec < 0) { - AWE_DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no)); - } - - cinfo->instr = instr_no; - - return 0; -} - - -/* reset all voices; terminate sounds and initialize parameters */ -static void -awe_reset(int dev) -{ - int i; - current_alloc_time = 0; - /* don't turn off voice 31 and 32. they are used also for FM voices */ - for (i = 0; i < awe_max_voices; i++) { - awe_terminate(i); - awe_voice_init(i, TRUE); - } - for (i = 0; i < AWE_MAX_CHANNELS; i++) - awe_channel_init(i, TRUE); - for (i = 0; i < 16; i++) { - awe_operations.chn_info[i].controllers[CTL_MAIN_VOLUME] = 127; - awe_operations.chn_info[i].controllers[CTL_EXPRESSION] = 127; - } - awe_init_fm(); - awe_tweak(); -} - - -/* hardware specific control: - * GUS specific and AWE32 specific controls are available. - */ -static void -awe_hw_control(int dev, unsigned char *event) -{ - int cmd = event[2]; - if (cmd & _AWE_MODE_FLAG) - awe_hw_awe_control(dev, cmd & _AWE_MODE_VALUE_MASK, event); -#ifdef AWE_HAS_GUS_COMPATIBILITY - else - awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event); -#endif -} - - -#ifdef AWE_HAS_GUS_COMPATIBILITY - -/* GUS compatible controls */ -static void -awe_hw_gus_control(int dev, int cmd, unsigned char *event) -{ - int voice, i, key; - unsigned short p1; - short p2; - int plong; - - if (MULTI_LAYER_MODE()) - return; - if (cmd == _GUS_NUMVOICES) - return; - - voice = event[3]; - if (! voice_in_range(voice)) - return; - - p1 = *(unsigned short *) &event[4]; - p2 = *(short *) &event[6]; - plong = *(int*) &event[4]; - - switch (cmd) { - case _GUS_VOICESAMPLE: - awe_set_instr(dev, voice, p1); - return; - - case _GUS_VOICEBALA: - /* 0 to 15 --> -128 to 127 */ - awe_panning(dev, voice, ((int)p1 << 4) - 128); - return; - - case _GUS_VOICEVOL: - case _GUS_VOICEVOL2: - /* not supported yet */ - return; - - case _GUS_RAMPRANGE: - case _GUS_RAMPRATE: - case _GUS_RAMPMODE: - case _GUS_RAMPON: - case _GUS_RAMPOFF: - /* volume ramping not supported */ - return; - - case _GUS_VOLUME_SCALE: - return; - - case _GUS_VOICE_POS: - FX_SET(&channels[voice].fx, AWE_FX_SAMPLE_START, - (short)(plong & 0x7fff)); - FX_SET(&channels[voice].fx, AWE_FX_COARSE_SAMPLE_START, - (plong >> 15) & 0xffff); - return; - } - - key = AWE_VOICE_KEY(voice); - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].key == key) { - switch (cmd) { - case _GUS_VOICEON: - awe_note_on(i); - break; - - case _GUS_VOICEOFF: - awe_terminate(i); - awe_fx_init(voices[i].ch); - awe_voice_init(i, TRUE); - break; - - case _GUS_VOICEFADE: - awe_note_off(i); - awe_fx_init(voices[i].ch); - awe_voice_init(i, FALSE); - break; - - case _GUS_VOICEFREQ: - awe_calc_pitch_from_freq(i, plong); - break; - } - } - } -} - -#endif - - -/* AWE32 specific controls */ -static void -awe_hw_awe_control(int dev, int cmd, unsigned char *event) -{ - int voice; - unsigned short p1; - short p2; - awe_chan_info *cinfo; - FX_Rec *fx; - int i; - - voice = event[3]; - if (! voice_in_range(voice)) - return; - - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return; - } - - p1 = *(unsigned short *) &event[4]; - p2 = *(short *) &event[6]; - cinfo = &channels[voice]; - - switch (cmd) { - case _AWE_DEBUG_MODE: - debug_mode = p1; - printk("AWE32: debug mode = %d\n", debug_mode); - break; - case _AWE_REVERB_MODE: - awe_set_reverb_mode(p1); - break; - - case _AWE_CHORUS_MODE: - awe_set_chorus_mode(p1); - break; - - case _AWE_REMOVE_LAST_SAMPLES: - AWE_DEBUG(0,printk("AWE32: remove last samples\n")); - if (locked_sf_id > 0) - awe_remove_samples(locked_sf_id); - break; - - case _AWE_INITIALIZE_CHIP: - awe_initialize(); - break; - - case _AWE_SEND_EFFECT: - fx = &cinfo->fx; - i = FX_FLAG_SET; - if (p1 >= 0x100) { - int layer = (p1 >> 8); - if (layer >= 0 && layer < MAX_LAYERS) - fx = &cinfo->fx_layer[layer]; - p1 &= 0xff; - } - if (p1 & 0x40) i = FX_FLAG_OFF; - if (p1 & 0x80) i = FX_FLAG_ADD; - p1 &= 0x3f; - if (p1 < AWE_FX_END) { - AWE_DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, p2)); - if (i == FX_FLAG_SET) - FX_SET(fx, p1, p2); - else if (i == FX_FLAG_ADD) - FX_ADD(fx, p1, p2); - else - FX_UNSET(fx, p1); - if (i != FX_FLAG_OFF && parm_defs[p1].realtime) { - AWE_DEBUG(0,printk("AWE32: fx_realtime (%d)\n", voice)); - awe_voice_change(voice, parm_defs[p1].realtime); - } - } - break; - - case _AWE_RESET_CHANNEL: - awe_channel_init(voice, !p1); - break; - - case _AWE_TERMINATE_ALL: - awe_reset(0); - break; - - case _AWE_TERMINATE_CHANNEL: - awe_voice_change(voice, awe_terminate_and_init); - break; - - case _AWE_RELEASE_ALL: - awe_note_off_all(FALSE); - break; - case _AWE_NOTEOFF_ALL: - awe_note_off_all(TRUE); - break; - - case _AWE_INITIAL_VOLUME: - AWE_DEBUG(0,printk("AWE32: init attenuation %d\n", p1)); - if (p2 == 0) /* absolute value */ - init_atten = (short)p1; - else /* relative value */ - init_atten = misc_modes[AWE_MD_ZERO_ATTEN] + (short)p1; - if (init_atten < 0) init_atten = 0; - for (i = 0; i < awe_max_voices; i++) - awe_set_voice_vol(i, TRUE); - break; - - case _AWE_CHN_PRESSURE: - cinfo->chan_press = p1; - p1 = p1 * misc_modes[AWE_MD_MOD_SENSE] / 1200; - FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, p1); - awe_voice_change(voice, awe_fx_fmmod); - FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, p1); - awe_voice_change(voice, awe_fx_fm2frq2); - break; - - case _AWE_CHANNEL_MODE: - AWE_DEBUG(0,printk("AWE32: channel mode = %d\n", p1)); - playing_mode = p1; - awe_reset(0); - break; - - case _AWE_DRUM_CHANNELS: - AWE_DEBUG(0,printk("AWE32: drum flags = %x\n", p1)); - drum_flags = *(unsigned int*)&event[4]; - break; - - case _AWE_MISC_MODE: - AWE_DEBUG(0,printk("AWE32: misc mode = %d %d\n", p1, p2)); - if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END) - misc_modes[p1] = p2; - break; - - case _AWE_EQUALIZER: - awe_equalizer((int)p1, (int)p2); - break; - - default: - AWE_DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice)); - break; - } -} - - -/* voice pressure change */ -static void -awe_aftertouch(int dev, int voice, int pressure) -{ - int note; - - AWE_DEBUG(2,printk("AWE32: [after(%d) %d]\n", voice, pressure)); - if (! voice_in_range(voice)) - return; - - switch (playing_mode) { - case AWE_PLAY_DIRECT: - case AWE_PLAY_INDIRECT: - awe_start_note(dev, voice, 255, pressure); - break; - case AWE_PLAY_MULTI2: - note = (voice_alloc->map[voice] & 0xff) - 1; - awe_start_note(dev, voice, note + 0x80, pressure); - break; - } -} - - -/* voice control change */ -static void -awe_controller(int dev, int voice, int ctrl_num, int value) -{ - int i; - awe_chan_info *cinfo; - - if (! voice_in_range(voice)) - return; - - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return; - } - - cinfo = &channels[voice]; - - switch (ctrl_num) { - case CTL_BANK_SELECT: /* MIDI control #0 */ - AWE_DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value)); - if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice) && - !misc_modes[AWE_MD_TOGGLE_DRUM_BANK]) - break; - cinfo->bank = value; - if (cinfo->bank == AWE_DRUM_BANK) - DRUM_CHANNEL_ON(cinfo->channel); - else - DRUM_CHANNEL_OFF(cinfo->channel); - awe_set_instr(dev, voice, cinfo->instr); - break; - - case CTL_MODWHEEL: /* MIDI control #1 */ - AWE_DEBUG(2,printk("AWE32: [modwheel(%d) %d]\n", voice, value)); - i = value * misc_modes[AWE_MD_MOD_SENSE] / 1200; - FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i); - awe_voice_change(voice, awe_fx_fmmod); - FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i); - awe_voice_change(voice, awe_fx_fm2frq2); - break; - - case CTRL_PITCH_BENDER: /* SEQ1 V2 contorl */ - AWE_DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, value)); - /* zero centered */ - cinfo->bender = value; - awe_voice_change(voice, awe_set_voice_pitch); - break; - - case CTRL_PITCH_BENDER_RANGE: /* SEQ1 V2 control */ - AWE_DEBUG(2,printk("AWE32: [range(%d) %d]\n", voice, value)); - /* value = sense x 100 */ - cinfo->bender_range = value; - /* no audible pitch change yet.. */ - break; - - case CTL_EXPRESSION: /* MIDI control #11 */ - if (SINGLE_LAYER_MODE()) - value /= 128; - case CTRL_EXPRESSION: /* SEQ1 V2 control */ - AWE_DEBUG(2,printk("AWE32: [expr(%d) %d]\n", voice, value)); - /* 0 - 127 */ - cinfo->expression_vol = value; - awe_voice_change(voice, awe_set_voice_vol); - break; - - case CTL_PAN: /* MIDI control #10 */ - AWE_DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value)); - /* (0-127) -> signed 8bit */ - cinfo->panning = value * 2 - 128; - if (misc_modes[AWE_MD_REALTIME_PAN]) - awe_voice_change(voice, awe_set_pan); - break; - - case CTL_MAIN_VOLUME: /* MIDI control #7 */ - if (SINGLE_LAYER_MODE()) - value = (value * 100) / 16383; - case CTRL_MAIN_VOLUME: /* SEQ1 V2 control */ - AWE_DEBUG(2,printk("AWE32: [mainvol(%d) %d]\n", voice, value)); - /* 0 - 127 */ - cinfo->main_vol = value; - awe_voice_change(voice, awe_set_voice_vol); - break; - - case CTL_EXT_EFF_DEPTH: /* reverb effects: 0-127 */ - AWE_DEBUG(2,printk("AWE32: [reverb(%d) %d]\n", voice, value)); - FX_SET(&cinfo->fx, AWE_FX_REVERB, value * 2); - break; - - case CTL_CHORUS_DEPTH: /* chorus effects: 0-127 */ - AWE_DEBUG(2,printk("AWE32: [chorus(%d) %d]\n", voice, value)); - FX_SET(&cinfo->fx, AWE_FX_CHORUS, value * 2); - break; - -#ifdef AWE_ACCEPT_ALL_SOUNDS_CONTROLL - case 120: /* all sounds off */ - awe_note_off_all(FALSE); - break; - case 123: /* all notes off */ - awe_note_off_all(TRUE); - break; -#endif - - case CTL_SUSTAIN: /* MIDI control #64 */ - cinfo->sustained = value; - if (value != 127) - awe_voice_change(voice, awe_sustain_off); - break; - - case CTL_SOSTENUTO: /* MIDI control #66 */ - if (value == 127) - awe_voice_change(voice, awe_sostenuto_on); - else - awe_voice_change(voice, awe_sustain_off); - break; - - default: - AWE_DEBUG(0,printk("AWE32: [control(%d) ctrl=%d val=%d]\n", - voice, ctrl_num, value)); - break; - } -} - - -/* voice pan change (value = -128 - 127) */ -static void -awe_panning(int dev, int voice, int value) -{ - awe_chan_info *cinfo; - - if (! voice_in_range(voice)) - return; - - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return; - } - - cinfo = &channels[voice]; - cinfo->panning = value; - AWE_DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, cinfo->panning)); - if (misc_modes[AWE_MD_REALTIME_PAN]) - awe_voice_change(voice, awe_set_pan); -} - - -/* volume mode change */ -static void -awe_volume_method(int dev, int mode) -{ - /* not impremented */ - AWE_DEBUG(0,printk("AWE32: [volmethod mode=%d]\n", mode)); -} - - -#ifndef AWE_NO_PATCHMGR -/* patch manager */ -static int -awe_patchmgr(int dev, struct patmgr_info *rec) -{ - printk("AWE32 Warning: patch manager control not supported\n"); - return 0; -} -#endif - - -/* pitch wheel change: 0-16384 */ -static void -awe_bender(int dev, int voice, int value) -{ - awe_chan_info *cinfo; - - if (! voice_in_range(voice)) - return; - - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return; - } - - /* convert to zero centered value */ - cinfo = &channels[voice]; - cinfo->bender = value - 8192; - AWE_DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, cinfo->bender)); - awe_voice_change(voice, awe_set_voice_pitch); -} - - -/*---------------------------------------------------------------- - * load a sound patch: - * three types of patches are accepted: AWE, GUS, and SYSEX. - *----------------------------------------------------------------*/ - -static int -awe_load_patch(int dev, int format, const char *addr, - int offs, int count, int pmgr_flag) -{ - awe_patch_info patch; - int rc = 0; - -#ifdef AWE_HAS_GUS_COMPATIBILITY - if (format == GUS_PATCH) { - return awe_load_guspatch(addr, offs, count, pmgr_flag); - } else -#endif - if (format == SYSEX_PATCH) { - /* no system exclusive message supported yet */ - return 0; - } else if (format != AWE_PATCH) { - printk("AWE32 Error: Invalid patch format (key) 0x%x\n", format); - return RET_ERROR(EINVAL); - } - - if (count < AWE_PATCH_INFO_SIZE) { - printk("AWE32 Error: Patch header too short\n"); - return RET_ERROR(EINVAL); - } - COPY_FROM_USER(((char*)&patch) + offs, addr, offs, - AWE_PATCH_INFO_SIZE - offs); - - count -= AWE_PATCH_INFO_SIZE; - if (count < patch.len) { - printk("AWE32: sample: Patch record too short (%d<%d)\n", - count, patch.len); - return RET_ERROR(EINVAL); - } - - switch (patch.type) { - case AWE_LOAD_INFO: - rc = awe_load_info(&patch, addr, count); - break; - case AWE_LOAD_DATA: - rc = awe_load_data(&patch, addr, count); - break; - case AWE_OPEN_PATCH: - rc = awe_open_patch(&patch, addr, count); - break; - case AWE_CLOSE_PATCH: - rc = awe_close_patch(&patch, addr, count); - break; - case AWE_UNLOAD_PATCH: - rc = awe_unload_patch(&patch, addr, count); - break; - case AWE_REPLACE_DATA: - rc = awe_replace_data(&patch, addr, count); - break; - case AWE_MAP_PRESET: - rc = awe_load_map(&patch, addr, count); - break; - case AWE_LOAD_CHORUS_FX: - rc = awe_load_chorus_fx(&patch, addr, count); - break; - case AWE_LOAD_REVERB_FX: - rc = awe_load_reverb_fx(&patch, addr, count); - break; - - default: - printk("AWE32 Error: unknown patch format type %d\n", - patch.type); - rc = RET_ERROR(EINVAL); - } - - return rc; -} - - -/* create an sflist record */ -static int -awe_create_sf(int type, char *name) -{ - sf_list *rec; - - /* terminate sounds */ - awe_reset(0); - if (current_sf_id >= max_sfs) { - int newsize = max_sfs + AWE_MAX_SF_LISTS; - sf_list *newlist = my_realloc(sflists, sizeof(sf_list)*max_sfs, - sizeof(sf_list)*newsize); - if (newlist == NULL) - return 1; - sflists = newlist; - max_sfs = newsize; - } - rec = &sflists[current_sf_id]; - rec->sf_id = current_sf_id + 1; - rec->type = type; - if (current_sf_id == 0 || (type & AWE_PAT_LOCKED) != 0) - locked_sf_id = current_sf_id + 1; - /* - if (name) - MEMCPY(rec->name, name, AWE_PATCH_NAME_LEN); - else - BZERO(rec->name, AWE_PATCH_NAME_LEN); - */ - rec->num_info = awe_free_info(); - rec->num_sample = awe_free_sample(); - rec->mem_ptr = awe_free_mem_ptr(); - rec->infos = -1; - rec->samples = -1; - - current_sf_id++; - return 0; -} - - -/* open patch; create sf list and set opened flag */ -static int -awe_open_patch(awe_patch_info *patch, const char *addr, int count) -{ - awe_open_parm parm; - COPY_FROM_USER(&parm, addr, AWE_PATCH_INFO_SIZE, sizeof(parm)); - if (awe_create_sf(parm.type, parm.name)) { - printk("AWE32: can't open: failed to alloc new list\n"); - return RET_ERROR(ENOSPC); - } - patch_opened = TRUE; - return current_sf_id; -} - -/* check if the patch is already opened */ -static int -check_patch_opened(int type, char *name) -{ - if (! patch_opened) { - if (awe_create_sf(type, name)) { - printk("AWE32: failed to alloc new list\n"); - return RET_ERROR(ENOSPC); - } - patch_opened = TRUE; - return current_sf_id; - } - return current_sf_id; -} - -/* close the patch; if no voice is loaded, remove the patch */ -static int -awe_close_patch(awe_patch_info *patch, const char *addr, int count) -{ - if (patch_opened && current_sf_id > 0) { - /* if no voice is loaded, release the current patch */ - if (sflists[current_sf_id-1].infos == -1) - awe_remove_samples(current_sf_id - 1); - } - patch_opened = 0; - return 0; -} - - -/* remove the latest patch */ -static int -awe_unload_patch(awe_patch_info *patch, const char *addr, int count) -{ - if (current_sf_id > 0) - awe_remove_samples(current_sf_id - 1); - return 0; -} - -/* allocate voice info list records */ -static int alloc_new_info(int nvoices) -{ - int newsize, free_info; - awe_voice_list *newlist; - free_info = awe_free_info(); - if (free_info + nvoices >= max_infos) { - do { - newsize = max_infos + AWE_MAX_INFOS; - } while (free_info + nvoices >= newsize); - newlist = my_realloc(infos, sizeof(awe_voice_list)*max_infos, - sizeof(awe_voice_list)*newsize); - if (newlist == NULL) { - printk("AWE32: can't alloc info table\n"); - return RET_ERROR(ENOSPC); - } - infos = newlist; - max_infos = newsize; - } - return 0; -} - -/* allocate sample info list records */ -static int alloc_new_sample(void) -{ - int newsize, free_sample; - awe_sample_list *newlist; - free_sample = awe_free_sample(); - if (free_sample >= max_samples) { - newsize = max_samples + AWE_MAX_SAMPLES; - newlist = my_realloc(samples, - sizeof(awe_sample_list)*max_samples, - sizeof(awe_sample_list)*newsize); - if (newlist == NULL) { - printk("AWE32: can't alloc sample table\n"); - return RET_ERROR(ENOSPC); - } - samples = newlist; - max_samples = newsize; - } - return 0; -} - -/* load voice map */ -static int -awe_load_map(awe_patch_info *patch, const char *addr, int count) -{ - awe_voice_map map; - awe_voice_list *rec; - int free_info; - - if (check_patch_opened(AWE_PAT_TYPE_MAP, NULL) < 0) - return RET_ERROR(ENOSPC); - if (alloc_new_info(1) < 0) - return RET_ERROR(ENOSPC); - - COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map)); - - free_info = awe_free_info(); - rec = &infos[free_info]; - rec->bank = map.map_bank; - rec->instr = map.map_instr; - rec->type = V_ST_MAPPED; - rec->disabled = FALSE; - awe_init_voice_info(&rec->v); - if (map.map_key >= 0) { - rec->v.low = map.map_key; - rec->v.high = map.map_key; - } - rec->v.start = map.src_instr; - rec->v.end = map.src_bank; - rec->v.fixkey = map.src_key; - rec->v.sf_id = current_sf_id; - add_info_list(free_info); - add_sf_info(free_info); - - return 0; -} - -/* load voice information data */ -static int -awe_load_info(awe_patch_info *patch, const char *addr, int count) -{ - int offset; - awe_voice_rec_hdr hdr; - int i; - int total_size; - - if (count < AWE_VOICE_REC_SIZE) { - printk("AWE32 Error: invalid patch info length\n"); - return RET_ERROR(EINVAL); - } - - offset = AWE_PATCH_INFO_SIZE; - COPY_FROM_USER((char*)&hdr, addr, offset, AWE_VOICE_REC_SIZE); - offset += AWE_VOICE_REC_SIZE; - - if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { - printk("AWE32 Error: Illegal voice number %d\n", hdr.nvoices); - return RET_ERROR(EINVAL); - } - total_size = AWE_VOICE_REC_SIZE + AWE_VOICE_INFO_SIZE * hdr.nvoices; - if (count < total_size) { - printk("AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n", - count, hdr.nvoices); - return RET_ERROR(EINVAL); - } - - if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0) - return RET_ERROR(ENOSPC); - -#if 0 /* it looks like not so useful.. */ - /* check if the same preset already exists in the info list */ - for (i = sflists[current_sf_id-1].infos; i >= 0; i = infos[i].next) { - if (infos[i].disabled) continue; - if (infos[i].bank == hdr.bank && infos[i].instr == hdr.instr) { - /* in exclusive mode, do skip loading this */ - if (hdr.write_mode == AWE_WR_EXCLUSIVE) - return 0; - /* in replace mode, disable the old data */ - else if (hdr.write_mode == AWE_WR_REPLACE) - infos[i].disabled = TRUE; - } - } - if (hdr.write_mode == AWE_WR_REPLACE) - rebuild_preset_list(); -#endif - - if (alloc_new_info(hdr.nvoices) < 0) - return RET_ERROR(ENOSPC); - - for (i = 0; i < hdr.nvoices; i++) { - int rec = awe_free_info(); - - infos[rec].bank = hdr.bank; - infos[rec].instr = hdr.instr; - infos[rec].type = V_ST_NORMAL; - infos[rec].disabled = FALSE; - - /* copy awe_voice_info parameters */ - COPY_FROM_USER(&infos[rec].v, addr, offset, AWE_VOICE_INFO_SIZE); - offset += AWE_VOICE_INFO_SIZE; - infos[rec].v.sf_id = current_sf_id; - if (infos[rec].v.mode & AWE_MODE_INIT_PARM) - awe_init_voice_parm(&infos[rec].v.parm); - awe_set_sample(&infos[rec].v); - add_info_list(rec); - add_sf_info(rec); - } - - return 0; -} - -/* load wave sample data */ -static int -awe_load_data(awe_patch_info *patch, const char *addr, int count) -{ - int offset, size; - int rc, free_sample; - awe_sample_info *rec; - - if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0) - return RET_ERROR(ENOSPC); - - if (alloc_new_sample() < 0) - return RET_ERROR(ENOSPC); - - free_sample = awe_free_sample(); - rec = &samples[free_sample].v; - - size = (count - AWE_SAMPLE_INFO_SIZE) / 2; - offset = AWE_PATCH_INFO_SIZE; - COPY_FROM_USER(rec, addr, offset, AWE_SAMPLE_INFO_SIZE); - offset += AWE_SAMPLE_INFO_SIZE; - if (size != rec->size) { - printk("AWE32: load: sample size differed (%d != %d)\n", - rec->size, size); - return RET_ERROR(EINVAL); - } - if (rec->size > 0) - if ((rc = awe_write_wave_data(addr, offset, rec, -1)) != 0) - return rc; - - rec->sf_id = current_sf_id; - - add_sf_sample(free_sample); - - return 0; -} - - -/* replace wave sample data */ -static int -awe_replace_data(awe_patch_info *patch, const char *addr, int count) -{ - int offset; - int size; - int rc, i; - int channels; - awe_sample_info cursmp; - int save_mem_ptr; - - if (! patch_opened) { - printk("AWE32: replace: patch not opened\n"); - return RET_ERROR(EINVAL); - } - - size = (count - AWE_SAMPLE_INFO_SIZE) / 2; - offset = AWE_PATCH_INFO_SIZE; - COPY_FROM_USER(&cursmp, addr, offset, AWE_SAMPLE_INFO_SIZE); - offset += AWE_SAMPLE_INFO_SIZE; - if (cursmp.size == 0 || size != cursmp.size) { - printk("AWE32: replace: illegal sample size (%d!=%d)\n", - cursmp.size, size); - return RET_ERROR(EINVAL); - } - channels = patch->optarg; - if (channels <= 0 || channels > AWE_NORMAL_VOICES) { - printk("AWE32: replace: illegal channels %d\n", channels); - return RET_ERROR(EINVAL); - } - - for (i = sflists[current_sf_id-1].samples; - i >= 0; i = samples[i].next) { - if (samples[i].v.sample == cursmp.sample) - break; - } - if (i < 0) { - printk("AWE32: replace: cannot find existing sample data %d\n", - cursmp.sample); - return RET_ERROR(EINVAL); - } - - if (samples[i].v.size != cursmp.size) { - printk("AWE32: replace: exiting size differed (%d!=%d)\n", - samples[i].v.size, cursmp.size); - return RET_ERROR(EINVAL); - } - - save_mem_ptr = awe_free_mem_ptr(); - sflists[current_sf_id-1].mem_ptr = samples[i].v.start - awe_mem_start; - MEMCPY(&samples[i].v, &cursmp, sizeof(cursmp)); - if ((rc = awe_write_wave_data(addr, offset, &samples[i].v, channels)) != 0) - return rc; - sflists[current_sf_id-1].mem_ptr = save_mem_ptr; - samples[i].v.sf_id = current_sf_id; - - return 0; -} - - -/*----------------------------------------------------------------*/ - -static const char *readbuf_addr; -static int readbuf_offs; -static int readbuf_flags; -#if defined(__DragonFly__) || defined(__FreeBSD__) -static unsigned short *readbuf_loop; -static int readbuf_loopstart, readbuf_loopend; -#endif - -/* initialize read buffer */ -static int -readbuf_init(const char *addr, int offset, awe_sample_info *sp) -{ -#if defined(__DragonFly__) || defined(__FreeBSD__) - readbuf_loop = NULL; - readbuf_loopstart = sp->loopstart; - readbuf_loopend = sp->loopend; - if (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) { - int looplen = sp->loopend - sp->loopstart; - readbuf_loop = my_malloc(looplen * 2); - if (readbuf_loop == NULL) { - printk("AWE32: can't malloc temp buffer\n"); - return RET_ERROR(ENOSPC); - } - } -#endif - readbuf_addr = addr; - readbuf_offs = offset; - readbuf_flags = sp->mode_flags; - return 0; -} - -/* read directly from user buffer */ -static unsigned short -readbuf_word(int pos) -{ - unsigned short c; - /* read from user buffer */ - if (readbuf_flags & AWE_SAMPLE_8BITS) { - unsigned char cc; - GET_BYTE_FROM_USER(cc, readbuf_addr, readbuf_offs + pos); - c = cc << 8; /* convert 8bit -> 16bit */ - } else { - GET_SHORT_FROM_USER(c, readbuf_addr, readbuf_offs + pos * 2); - } - if (readbuf_flags & AWE_SAMPLE_UNSIGNED) - c ^= 0x8000; /* unsigned -> signed */ -#if defined(__DragonFly__) || defined(__FreeBSD__) - /* write on cache for reverse loop */ - if (readbuf_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) { - if (pos >= readbuf_loopstart && pos < readbuf_loopend) - readbuf_loop[pos - readbuf_loopstart] = c; - } -#endif - return c; -} - -#if defined(__DragonFly__) || defined(__FreeBSD__) -/* read from cache */ -static unsigned short -readbuf_word_cache(int pos) -{ - if (pos >= readbuf_loopstart && pos < readbuf_loopend) - return readbuf_loop[pos - readbuf_loopstart]; - return 0; -} - -static void -readbuf_end(void) -{ - if (readbuf_loop) { - my_free(readbuf_loop); - } - readbuf_loop = NULL; -} - -#else - -#define readbuf_word_cache readbuf_word -#define readbuf_end() /**/ - -#endif - -/*----------------------------------------------------------------*/ - -#define BLANK_LOOP_START 8 -#define BLANK_LOOP_END 40 -#define BLANK_LOOP_SIZE 48 - -/* loading onto memory */ -static int -awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels) -{ - int i, truesize, dram_offset; - int rc; - - /* be sure loop points start < end */ - if (sp->loopstart > sp->loopend) { - int tmp = sp->loopstart; - sp->loopstart = sp->loopend; - sp->loopend = tmp; - } - - /* compute true data size to be loaded */ - truesize = sp->size; - if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP) - truesize += sp->loopend - sp->loopstart; - if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) - truesize += BLANK_LOOP_SIZE; - if (awe_free_mem_ptr() + truesize >= awe_mem_size/2) { - printk("AWE32 Error: Sample memory full\n"); - return RET_ERROR(ENOSPC); - } - - /* recalculate address offset */ - sp->end -= sp->start; - sp->loopstart -= sp->start; - sp->loopend -= sp->start; - - dram_offset = awe_free_mem_ptr() + awe_mem_start; - sp->start = dram_offset; - sp->end += dram_offset; - sp->loopstart += dram_offset; - sp->loopend += dram_offset; - - /* set the total size (store onto obsolete checksum value) */ - if (sp->size == 0) - sp->checksum = 0; - else - sp->checksum = truesize; - - if ((rc = awe_open_dram_for_write(dram_offset, channels)) != 0) - return rc; - - if (readbuf_init(addr, offset, sp) < 0) - return RET_ERROR(ENOSPC); - - for (i = 0; i < sp->size; i++) { - unsigned short c; - c = readbuf_word(i); - awe_write_dram(c); - if (i == sp->loopend && - (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP))) { - int looplen = sp->loopend - sp->loopstart; - /* copy reverse loop */ - int k; - for (k = 1; k <= looplen; k++) { - c = readbuf_word_cache(i - k); - awe_write_dram(c); - } - if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP) { - sp->end += looplen; - } else { - sp->start += looplen; - sp->end += looplen; - } - } - } - readbuf_end(); - - /* if no blank loop is attached in the sample, add it */ - if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) { - for (i = 0; i < BLANK_LOOP_SIZE; i++) - awe_write_dram(0); - if (sp->mode_flags & AWE_SAMPLE_SINGLESHOT) { - sp->loopstart = sp->end + BLANK_LOOP_START; - sp->loopend = sp->end + BLANK_LOOP_END; - } - } - - sflists[current_sf_id-1].mem_ptr += truesize; - awe_close_dram(); - - /* initialize FM */ - awe_init_fm(); - - return 0; -} - - -/*----------------------------------------------------------------*/ - -#ifdef AWE_HAS_GUS_COMPATIBILITY - -/* calculate GUS envelope time: - * is this correct? i have no idea.. - */ -static int -calc_gus_envelope_time(int rate, int start, int end) -{ - int r, p, t; - r = (3 - ((rate >> 6) & 3)) * 3; - p = rate & 0x3f; - t = end - start; - if (t < 0) t = -t; - if (13 > r) - t = t << (13 - r); - else - t = t >> (r - 13); - return (t * 10) / (p * 441); -} - -#define calc_gus_sustain(val) (0x7f - vol_table[(val)/2]) -#define calc_gus_attenuation(val) vol_table[(val)/2] - -/* load GUS patch */ -static int -awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag) -{ - struct patch_info patch; - awe_voice_info *rec; - awe_sample_info *smp; - int sizeof_patch; - int note, free_sample, free_info; - int rc; - - sizeof_patch = offsetof(struct patch_info, data); /* header size */ - if (size < sizeof_patch) { - printk("AWE32 Error: Patch header too short\n"); - return RET_ERROR(EINVAL); - } - COPY_FROM_USER(((char*)&patch) + offs, addr, offs, sizeof_patch - offs); - size -= sizeof_patch; - if (size < patch.len) { - printk("AWE32 Warning: Patch record too short (%d<%ld)\n", - size, patch.len); - return RET_ERROR(EINVAL); - } - if (check_patch_opened(AWE_PAT_TYPE_GUS, NULL) < 0) - return RET_ERROR(ENOSPC); - if (alloc_new_sample() < 0) - return RET_ERROR(ENOSPC); - if (alloc_new_info(1)) - return RET_ERROR(ENOSPC); - - free_sample = awe_free_sample(); - smp = &samples[free_sample].v; - - smp->sample = free_sample; - smp->start = 0; - smp->end = patch.len; - smp->loopstart = patch.loop_start; - smp->loopend = patch.loop_end; - smp->size = patch.len; - - /* set up mode flags */ - smp->mode_flags = 0; - if (!(patch.mode & WAVE_16_BITS)) - smp->mode_flags |= AWE_SAMPLE_8BITS; - if (patch.mode & WAVE_UNSIGNED) - smp->mode_flags |= AWE_SAMPLE_UNSIGNED; - smp->mode_flags |= AWE_SAMPLE_NO_BLANK; - if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK))) - smp->mode_flags |= AWE_SAMPLE_SINGLESHOT; - if (patch.mode & WAVE_BIDIR_LOOP) - smp->mode_flags |= AWE_SAMPLE_BIDIR_LOOP; - if (patch.mode & WAVE_LOOP_BACK) - smp->mode_flags |= AWE_SAMPLE_REVERSE_LOOP; - - AWE_DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no, smp->mode_flags)); - if (patch.mode & WAVE_16_BITS) { - /* convert to word offsets */ - smp->size /= 2; - smp->end /= 2; - smp->loopstart /= 2; - smp->loopend /= 2; - } - smp->checksum_flag = 0; - smp->checksum = 0; - - if ((rc = awe_write_wave_data(addr, sizeof_patch, smp, -1)) != 0) - return rc; - - smp->sf_id = current_sf_id; - add_sf_sample(free_sample); - - /* set up voice info */ - free_info = awe_free_info(); - rec = &infos[free_info].v; - awe_init_voice_info(rec); - rec->sample = free_sample; /* the last sample */ - rec->rate_offset = calc_rate_offset(patch.base_freq); - note = freq_to_note(patch.base_note); - rec->root = note / 100; - rec->tune = -(note % 100); - rec->low = freq_to_note(patch.low_note) / 100; - rec->high = freq_to_note(patch.high_note) / 100; - AWE_DEBUG(1,printk("AWE32: [gus base offset=%d, note=%d, range=%d-%d(%lu-%lu)]\n", - rec->rate_offset, note, - rec->low, rec->high, - patch.low_note, patch.high_note)); - /* panning position; -128 - 127 => 0-127 */ - rec->pan = (patch.panning + 128) / 2; - - /* detuning is ignored */ - /* 6points volume envelope */ - if (patch.mode & WAVE_ENVELOPES) { - int attack, hold, decay, release; - attack = calc_gus_envelope_time - (patch.env_rate[0], 0, patch.env_offset[0]); - hold = calc_gus_envelope_time - (patch.env_rate[1], patch.env_offset[0], - patch.env_offset[1]); - decay = calc_gus_envelope_time - (patch.env_rate[2], patch.env_offset[1], - patch.env_offset[2]); - release = calc_gus_envelope_time - (patch.env_rate[3], patch.env_offset[1], - patch.env_offset[4]); - release += calc_gus_envelope_time - (patch.env_rate[4], patch.env_offset[3], - patch.env_offset[4]); - release += calc_gus_envelope_time - (patch.env_rate[5], patch.env_offset[4], - patch.env_offset[5]); - rec->parm.volatkhld = (calc_parm_attack(attack) << 8) | - calc_parm_hold(hold); - rec->parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) | - calc_parm_decay(decay); - rec->parm.volrelease = 0x8000 | calc_parm_decay(release); - AWE_DEBUG(2,printk("AWE32: [gusenv atk=%d, hld=%d, dcy=%d, rel=%d]\n", attack, hold, decay, release)); - rec->attenuation = calc_gus_attenuation(patch.env_offset[0]); - } - - /* tremolo effect */ - if (patch.mode & WAVE_TREMOLO) { - int rate = (patch.tremolo_rate * 1000 / 38) / 42; - rec->parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate; - AWE_DEBUG(2,printk("AWE32: [gusenv tremolo rate=%d, dep=%d, tremfrq=%x]\n", - patch.tremolo_rate, patch.tremolo_depth, - rec->parm.tremfrq)); - } - /* vibrato effect */ - if (patch.mode & WAVE_VIBRATO) { - int rate = (patch.vibrato_rate * 1000 / 38) / 42; - rec->parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate; - AWE_DEBUG(2,printk("AWE32: [gusenv vibrato rate=%d, dep=%d, tremfrq=%x]\n", - patch.tremolo_rate, patch.tremolo_depth, - rec->parm.tremfrq)); - } - - /* scale_freq, scale_factor, volume, and fractions not implemented */ - - /* append to the tail of the list */ - infos[free_info].bank = misc_modes[AWE_MD_GUS_BANK]; - infos[free_info].instr = patch.instr_no; - infos[free_info].disabled = FALSE; - infos[free_info].type = V_ST_NORMAL; - infos[free_info].v.sf_id = current_sf_id; - - add_info_list(free_info); - add_sf_info(free_info); - - /* set the voice index */ - awe_set_sample(rec); - - return 0; -} - -#endif /* AWE_HAS_GUS_COMPATIBILITY */ - -/*---------------------------------------------------------------- - * sample and voice list handlers - *----------------------------------------------------------------*/ - -/* append this to the sf list */ -static void add_sf_info(int rec) -{ - int sf_id = infos[rec].v.sf_id; - if (sf_id == 0) return; - sf_id--; - if (sflists[sf_id].infos < 0) - sflists[sf_id].infos = rec; - else { - int i, prev; - prev = sflists[sf_id].infos; - while ((i = infos[prev].next) >= 0) - prev = i; - infos[prev].next = rec; - } - infos[rec].next = -1; - sflists[sf_id].num_info++; -} - -/* prepend this sample to sf list */ -static void add_sf_sample(int rec) -{ - int sf_id = samples[rec].v.sf_id; - if (sf_id == 0) return; - sf_id--; - samples[rec].next = sflists[sf_id].samples; - sflists[sf_id].samples = rec; - sflists[sf_id].num_sample++; -} - -/* purge the old records which don't belong with the same file id */ -static void purge_old_list(int rec, int next) -{ - infos[rec].next_instr = next; - if (infos[rec].bank == AWE_DRUM_BANK) { - /* remove samples with the same note range */ - int cur, *prevp = &infos[rec].next_instr; - int low = infos[rec].v.low; - int high = infos[rec].v.high; - for (cur = next; cur >= 0; cur = infos[cur].next_instr) { - if (infos[cur].v.low == low && - infos[cur].v.high == high && - infos[cur].v.sf_id != infos[rec].v.sf_id) - *prevp = infos[cur].next_instr; - prevp = &infos[cur].next_instr; - } - } else { - if (infos[next].v.sf_id != infos[rec].v.sf_id) - infos[rec].next_instr = -1; - } -} - -/* prepend to top of the preset table */ -static void add_info_list(int rec) -{ - int *prevp, cur; - int instr = infos[rec].instr; - int bank = infos[rec].bank; - - if (infos[rec].disabled) - return; - - prevp = &preset_table[instr]; - cur = *prevp; - while (cur >= 0) { - /* search the first record with the same bank number */ - if (infos[cur].bank == bank) { - /* replace the list with the new record */ - infos[rec].next_bank = infos[cur].next_bank; - *prevp = rec; - purge_old_list(rec, cur); - return; - } - prevp = &infos[cur].next_bank; - cur = infos[cur].next_bank; - } - - /* this is the first bank record.. just add this */ - infos[rec].next_instr = -1; - infos[rec].next_bank = preset_table[instr]; - preset_table[instr] = rec; -} - -/* remove samples later than the specified sf_id */ -static void -awe_remove_samples(int sf_id) -{ - if (sf_id <= 0) { - awe_reset_samples(); - return; - } - /* already removed? */ - if (current_sf_id <= sf_id) - return; - - current_sf_id = sf_id; - if (locked_sf_id > sf_id) - locked_sf_id = sf_id; - - rebuild_preset_list(); -} - -/* rebuild preset search list */ -static void rebuild_preset_list(void) -{ - int i, j; - - for (i = 0; i < AWE_MAX_PRESETS; i++) - preset_table[i] = -1; - - for (i = 0; i < current_sf_id; i++) { - for (j = sflists[i].infos; j >= 0; j = infos[j].next) - add_info_list(j); - } -} - -/* search the specified sample */ -static short -awe_set_sample(awe_voice_info *vp) -{ - int i; - vp->index = -1; - for (i = sflists[vp->sf_id-1].samples; i >= 0; i = samples[i].next) { - if (samples[i].v.sample == vp->sample) { - /* set the actual sample offsets */ - vp->start += samples[i].v.start; - vp->end += samples[i].v.end; - vp->loopstart += samples[i].v.loopstart; - vp->loopend += samples[i].v.loopend; - /* copy mode flags */ - vp->mode = samples[i].v.mode_flags; - /* set index */ - vp->index = i; - return i; - } - } - return -1; -} - - -/*---------------------------------------------------------------- - * voice allocation - *----------------------------------------------------------------*/ - -/* look for all voices associated with the specified note & velocity */ -static int -awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist) -{ - int nvoices; - - nvoices = 0; - for (; rec >= 0; rec = infos[rec].next_instr) { - if (note >= infos[rec].v.low && - note <= infos[rec].v.high && - velocity >= infos[rec].v.vellow && - velocity <= infos[rec].v.velhigh) { - vlist[nvoices] = &infos[rec].v; - if (infos[rec].type == V_ST_MAPPED) /* mapper */ - return -1; - nvoices++; - if (nvoices >= AWE_MAX_VOICES) - break; - } - } - return nvoices; -} - -/* store the voice list from the specified note and velocity. - if the preset is mapped, seek for the destination preset, and rewrite - the note number if necessary. - */ -static int -really_alloc_voices(int vrec, int def_vrec, int *note, int velocity, awe_voice_info **vlist, int level) -{ - int nvoices; - - nvoices = awe_search_multi_voices(vrec, *note, velocity, vlist); - if (nvoices == 0) - nvoices = awe_search_multi_voices(def_vrec, *note, velocity, vlist); - if (nvoices < 0) { /* mapping */ - int preset = vlist[0]->start; - int bank = vlist[0]->end; - int key = vlist[0]->fixkey; - if (level > 5) { - printk("AWE32: too deep mapping level\n"); - return 0; - } - vrec = awe_search_instr(bank, preset); - if (bank == AWE_DRUM_BANK) - def_vrec = awe_search_instr(bank, 0); - else - def_vrec = awe_search_instr(0, preset); - if (key >= 0) - *note = key; - return really_alloc_voices(vrec, def_vrec, note, velocity, vlist, level+1); - } - - return nvoices; -} - -/* allocate voices corresponding note and velocity; supports multiple insts. */ -static void -awe_alloc_multi_voices(int ch, int note, int velocity, int key) -{ - int i, v, nvoices; - awe_voice_info *vlist[AWE_MAX_VOICES]; - - if (channels[ch].vrec < 0 && channels[ch].def_vrec < 0) - awe_set_instr(0, ch, channels[ch].instr); - - /* check the possible voices; note may be changeable if mapped */ - nvoices = really_alloc_voices(channels[ch].vrec, channels[ch].def_vrec, - ¬e, velocity, vlist, 0); - - /* set the voices */ - current_alloc_time++; - for (i = 0; i < nvoices; i++) { - v = awe_clear_voice(); - voices[v].key = key; - voices[v].ch = ch; - voices[v].note = note; - voices[v].velocity = velocity; - voices[v].time = current_alloc_time; - voices[v].cinfo = &channels[ch]; - voices[v].sample = vlist[i]; - voices[v].state = AWE_ST_MARK; - voices[v].layer = nvoices - i - 1; /* in reverse order */ - } - - /* clear the mark in allocated voices */ - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].state == AWE_ST_MARK) - voices[i].state = AWE_ST_OFF; - - } -} - - -/* search the best voice from the specified status condition */ -static int -search_best_voice(int condition) -{ - int i, time, best; - best = -1; - time = current_alloc_time + 1; - for (i = 0; i < awe_max_voices; i++) { - if ((voices[i].state & condition) && - (best < 0 || voices[i].time < time)) { - best = i; - time = voices[i].time; - } - } - /* clear voice */ - if (best >= 0) { - if (voices[best].state != AWE_ST_OFF) - awe_terminate(best); - awe_voice_init(best, TRUE); - } - - return best; -} - -/* search an empty voice. - if no empty voice is found, at least terminate a voice - */ -static int -awe_clear_voice(void) -{ - int best; - - /* looking for the oldest empty voice */ - if ((best = search_best_voice(AWE_ST_OFF)) >= 0) - return best; - if ((best = search_best_voice(AWE_ST_RELEASED)) >= 0) - return best; - /* looking for the oldest sustained voice */ - if ((best = search_best_voice(AWE_ST_SUSTAINED)) >= 0) - return best; - -#ifdef AWE_LOOKUP_MIDI_PRIORITY - if (MULTI_LAYER_MODE() && misc_modes[AWE_MD_CHN_PRIOR]) { - int ch = -1; - int time = current_alloc_time + 1; - int i; - /* looking for the voices from high channel (except drum ch) */ - for (i = 0; i < awe_max_voices; i++) { - if (IS_DRUM_CHANNEL(voices[i].ch)) continue; - if (voices[i].ch < ch) continue; - if (voices[i].state != AWE_ST_MARK && - (voices[i].ch > ch || voices[i].time < time)) { - best = i; - time = voices[i].time; - ch = voices[i].ch; - } - } - } -#endif - if (best < 0) - best = search_best_voice(~AWE_ST_MARK); - - if (best >= 0) - return best; - - return 0; -} - - -/* search sample for the specified note & velocity and set it on the voice; - * note that voice is the voice index (not channel index) - */ -static void -awe_alloc_one_voice(int voice, int note, int velocity) -{ - int ch, nvoices; - awe_voice_info *vlist[AWE_MAX_VOICES]; - - ch = voices[voice].ch; - if (channels[ch].vrec < 0 && channels[ch].def_vrec < 0) - awe_set_instr(0, ch, channels[ch].instr); - - nvoices = really_alloc_voices(voices[voice].cinfo->vrec, - voices[voice].cinfo->def_vrec, - ¬e, velocity, vlist, 0); - if (nvoices > 0) { - voices[voice].time = ++current_alloc_time; - voices[voice].sample = vlist[0]; /* use the first one */ - voices[voice].layer = 0; - voices[voice].note = note; - voices[voice].velocity = velocity; - } -} - - -/*---------------------------------------------------------------- - * sequencer2 functions - *----------------------------------------------------------------*/ - -/* search an empty voice; used by sequencer2 */ -static int -awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc) -{ - playing_mode = AWE_PLAY_MULTI2; - awe_info.nr_voices = AWE_MAX_CHANNELS; - return awe_clear_voice(); -} - - -/* set up voice; used by sequencer2 */ -static void -awe_setup_voice(int dev, int voice, int chn) -{ - struct channel_info *info; - if (synth_devs[dev] == NULL || - (info = &synth_devs[dev]->chn_info[chn]) == NULL) - return; - - if (voice < 0 || voice >= awe_max_voices) - return; - - AWE_DEBUG(2,printk("AWE32: [setup(%d) ch=%d]\n", voice, chn)); - channels[chn].expression_vol = info->controllers[CTL_EXPRESSION]; - channels[chn].main_vol = info->controllers[CTL_MAIN_VOLUME]; - channels[chn].panning = - info->controllers[CTL_PAN] * 2 - 128; /* signed 8bit */ - channels[chn].bender = info->bender_value; /* zero center */ - channels[chn].bank = info->controllers[CTL_BANK_SELECT]; - channels[chn].sustained = info->controllers[CTL_SUSTAIN]; - if (info->controllers[CTL_EXT_EFF_DEPTH]) { - FX_SET(&channels[chn].fx, AWE_FX_REVERB, - info->controllers[CTL_EXT_EFF_DEPTH] * 2); - } - if (info->controllers[CTL_CHORUS_DEPTH]) { - FX_SET(&channels[chn].fx, AWE_FX_CHORUS, - info->controllers[CTL_CHORUS_DEPTH] * 2); - } - awe_set_instr(dev, chn, info->pgm_num); -} - - -#ifdef CONFIG_AWE32_MIXER -/*================================================================ - * AWE32 mixer device control - *================================================================*/ - -static int -awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) -{ - int i, level; - - if (((cmd >> 8) & 0xff) != 'M') - return RET_ERROR(EINVAL); - - level = (int)IOCTL_IN(arg); - level = ((level & 0xff) + (level >> 8)) / 2; - AWE_DEBUG(0,printk("AWEMix: cmd=%x val=%d\n", cmd & 0xff, level)); - - if (IO_WRITE_CHECK(cmd)) { - switch (cmd & 0xff) { - case SOUND_MIXER_BASS: - awe_bass_level = level * 12 / 100; - if (awe_bass_level >= 12) - awe_bass_level = 11; - awe_equalizer(awe_bass_level, awe_treble_level); - break; - case SOUND_MIXER_TREBLE: - awe_treble_level = level * 12 / 100; - if (awe_treble_level >= 12) - awe_treble_level = 11; - awe_equalizer(awe_bass_level, awe_treble_level); - break; - case SOUND_MIXER_VOLUME: - level = level * 127 / 100; - if (level >= 128) level = 127; - init_atten = vol_table[level]; - for (i = 0; i < awe_max_voices; i++) - awe_set_voice_vol(i, TRUE); - break; - } - } - switch (cmd & 0xff) { - case SOUND_MIXER_BASS: - level = awe_bass_level * 100 / 24; - level = (level << 8) | level; - break; - case SOUND_MIXER_TREBLE: - level = awe_treble_level * 100 / 24; - level = (level << 8) | level; - break; - case SOUND_MIXER_VOLUME: - for (i = 127; i > 0; i--) { - if (init_atten <= vol_table[i]) - break; - } - level = i * 100 / 127; - level = (level << 8) | level; - break; - case SOUND_MIXER_DEVMASK: - level = SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_VOLUME; - break; - default: - level = 0; - break; - } - return IOCTL_OUT(arg, level); -} -#endif /* CONFIG_AWE32_MIXER */ - - -/*================================================================ - * initialization of AWE32 - *================================================================*/ - -/* intiailize audio channels */ -static void -awe_init_audio(void) -{ - int ch; - - /* turn off envelope engines */ - for (ch = 0; ch < AWE_MAX_VOICES; ch++) { - awe_poke(AWE_DCYSUSV(ch), 0x80); - } - - /* reset all other parameters to zero */ - for (ch = 0; ch < AWE_MAX_VOICES; ch++) { - awe_poke(AWE_ENVVOL(ch), 0); - awe_poke(AWE_ENVVAL(ch), 0); - awe_poke(AWE_DCYSUS(ch), 0); - awe_poke(AWE_ATKHLDV(ch), 0); - awe_poke(AWE_LFO1VAL(ch), 0); - awe_poke(AWE_ATKHLD(ch), 0); - awe_poke(AWE_LFO2VAL(ch), 0); - awe_poke(AWE_IP(ch), 0); - awe_poke(AWE_IFATN(ch), 0); - awe_poke(AWE_PEFE(ch), 0); - awe_poke(AWE_FMMOD(ch), 0); - awe_poke(AWE_TREMFRQ(ch), 0); - awe_poke(AWE_FM2FRQ2(ch), 0); - awe_poke_dw(AWE_PTRX(ch), 0); - awe_poke_dw(AWE_VTFT(ch), 0); - awe_poke_dw(AWE_PSST(ch), 0); - awe_poke_dw(AWE_CSL(ch), 0); - awe_poke_dw(AWE_CCCA(ch), 0); - } - - for (ch = 0; ch < AWE_MAX_VOICES; ch++) { - awe_poke_dw(AWE_CPF(ch), 0); - awe_poke_dw(AWE_CVCF(ch), 0); - } -} - - -/* initialize DMA address */ -static void -awe_init_dma(void) -{ - awe_poke_dw(AWE_SMALR, 0); - awe_poke_dw(AWE_SMARR, 0); - awe_poke_dw(AWE_SMALW, 0); - awe_poke_dw(AWE_SMARW, 0); -} - - -/* initialization arrays; from ADIP */ - -static unsigned short init1[128] = { - 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330, - 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730, - 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30, - 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30, - - 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330, - 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730, - 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30, - 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30, - - 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330, - 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730, - 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30, - 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30, - - 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330, - 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730, - 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30, - 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30, -}; - -static unsigned short init2[128] = { - 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330, - 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730, - 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30, - 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30, - - 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330, - 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730, - 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30, - 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30, - - 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330, - 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730, - 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30, - 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30, - - 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330, - 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730, - 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30, - 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30, -}; - -static unsigned short init3[128] = { - 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, - 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254, - 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234, - 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224, - - 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254, - 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264, - 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294, - 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3, - - 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287, - 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7, - 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386, - 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55, - - 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308, - 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F, - 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319, - 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570, -}; - -static unsigned short init4[128] = { - 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, - 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254, - 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234, - 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224, - - 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254, - 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264, - 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294, - 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3, - - 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287, - 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7, - 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386, - 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55, - - 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308, - 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F, - 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319, - 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570, -}; - - -/* send initialization arrays to start up */ -static void -awe_init_array(void) -{ - awe_send_array(init1); - awe_wait(1024); - awe_send_array(init2); - awe_send_array(init3); - awe_poke_dw(AWE_HWCF4, 0); - awe_poke_dw(AWE_HWCF5, 0x83); - awe_poke_dw(AWE_HWCF6, 0x8000); - awe_send_array(init4); -} - -/* send an initialization array */ -static void -awe_send_array(unsigned short *data) -{ - int i; - unsigned short *p; - - p = data; - for (i = 0; i < AWE_MAX_VOICES; i++, p++) - awe_poke(AWE_INIT1(i), *p); - for (i = 0; i < AWE_MAX_VOICES; i++, p++) - awe_poke(AWE_INIT2(i), *p); - for (i = 0; i < AWE_MAX_VOICES; i++, p++) - awe_poke(AWE_INIT3(i), *p); - for (i = 0; i < AWE_MAX_VOICES; i++, p++) - awe_poke(AWE_INIT4(i), *p); -} - - -/* - * set up awe32 channels to some known state. - */ - -/* set the envelope & LFO parameters to the default values; see ADIP */ -static void -awe_tweak_voice(int i) -{ - /* set all mod/vol envelope shape to minimum */ - awe_poke(AWE_ENVVOL(i), 0x8000); - awe_poke(AWE_ENVVAL(i), 0x8000); - awe_poke(AWE_DCYSUS(i), 0x7F7F); - awe_poke(AWE_ATKHLDV(i), 0x7F7F); - awe_poke(AWE_ATKHLD(i), 0x7F7F); - awe_poke(AWE_PEFE(i), 0); /* mod envelope height to zero */ - awe_poke(AWE_LFO1VAL(i), 0x8000); /* no delay for LFO1 */ - awe_poke(AWE_LFO2VAL(i), 0x8000); - awe_poke(AWE_IP(i), 0xE000); /* no pitch shift */ - awe_poke(AWE_IFATN(i), 0xFF00); /* volume to minimum */ - awe_poke(AWE_FMMOD(i), 0); - awe_poke(AWE_TREMFRQ(i), 0); - awe_poke(AWE_FM2FRQ2(i), 0); -} - -static void -awe_tweak(void) -{ - int i; - /* reset all channels */ - for (i = 0; i < awe_max_voices; i++) - awe_tweak_voice(i); -} - - -/* - * initializes the FM section of AWE32; - * see Vince Vu's unofficial AWE32 programming guide - */ - -static void -awe_init_fm(void) -{ -#ifndef AWE_ALWAYS_INIT_FM - /* if no extended memory is on board.. */ - if (awe_mem_size <= 0) - return; -#endif - AWE_DEBUG(3,printk("AWE32: initializing FM\n")); - - /* Initialize the last two channels for DRAM refresh and producing - the reverb and chorus effects for Yamaha OPL-3 synthesizer */ - - /* 31: FM left channel, 0xffffe0-0xffffe8 */ - awe_poke(AWE_DCYSUSV(30), 0x80); - awe_poke_dw(AWE_PSST(30), 0xFFFFFFE0); /* full left */ - awe_poke_dw(AWE_CSL(30), 0x00FFFFE8 | - (DEF_FM_CHORUS_DEPTH << 24)); - awe_poke_dw(AWE_PTRX(30), (DEF_FM_REVERB_DEPTH << 8)); - awe_poke_dw(AWE_CPF(30), 0); - awe_poke_dw(AWE_CCCA(30), 0x00FFFFE3); - - /* 32: FM right channel, 0xfffff0-0xfffff8 */ - awe_poke(AWE_DCYSUSV(31), 0x80); - awe_poke_dw(AWE_PSST(31), 0x00FFFFF0); /* full right */ - awe_poke_dw(AWE_CSL(31), 0x00FFFFF8 | - (DEF_FM_CHORUS_DEPTH << 24)); - awe_poke_dw(AWE_PTRX(31), (DEF_FM_REVERB_DEPTH << 8)); - awe_poke_dw(AWE_CPF(31), 0x8000); - awe_poke_dw(AWE_CCCA(31), 0x00FFFFF3); - - /* skew volume & cutoff */ - awe_poke_dw(AWE_VTFT(30), 0x8000FFFF); - awe_poke_dw(AWE_VTFT(31), 0x8000FFFF); - - voices[30].state = AWE_ST_FM; - voices[31].state = AWE_ST_FM; - - /* change maximum channels to 30 */ - awe_max_voices = AWE_NORMAL_VOICES; - if (playing_mode == AWE_PLAY_DIRECT) - awe_info.nr_voices = awe_max_voices; - else - awe_info.nr_voices = AWE_MAX_CHANNELS; - voice_alloc->max_voice = awe_max_voices; -} - -/* - * AWE32 DRAM access routines - */ - -/* open DRAM write accessing mode */ -static int -awe_open_dram_for_write(int offset, int channels) -{ - int vidx[AWE_NORMAL_VOICES]; - int i; - - if (channels < 0 || channels >= AWE_NORMAL_VOICES) { - channels = AWE_NORMAL_VOICES; - for (i = 0; i < AWE_NORMAL_VOICES; i++) - vidx[i] = i; - } else { - for (i = 0; i < channels; i++) - vidx[i] = awe_clear_voice(); - } - - /* use all channels for DMA transfer */ - for (i = 0; i < channels; i++) { - if (vidx[i] < 0) continue; - awe_poke(AWE_DCYSUSV(vidx[i]), 0x80); - awe_poke_dw(AWE_VTFT(vidx[i]), 0); - awe_poke_dw(AWE_CVCF(vidx[i]), 0); - awe_poke_dw(AWE_PTRX(vidx[i]), 0x40000000); - awe_poke_dw(AWE_CPF(vidx[i]), 0x40000000); - awe_poke_dw(AWE_PSST(vidx[i]), 0); - awe_poke_dw(AWE_CSL(vidx[i]), 0); - awe_poke_dw(AWE_CCCA(vidx[i]), 0x06000000); - voices[vidx[i]].state = AWE_ST_DRAM; - } - /* point channels 31 & 32 to ROM samples for DRAM refresh */ - awe_poke_dw(AWE_VTFT(30), 0); - awe_poke_dw(AWE_PSST(30), 0x1d8); - awe_poke_dw(AWE_CSL(30), 0x1e0); - awe_poke_dw(AWE_CCCA(30), 0x1d8); - awe_poke_dw(AWE_VTFT(31), 0); - awe_poke_dw(AWE_PSST(31), 0x1d8); - awe_poke_dw(AWE_CSL(31), 0x1e0); - awe_poke_dw(AWE_CCCA(31), 0x1d8); - voices[30].state = AWE_ST_FM; - voices[31].state = AWE_ST_FM; - - /* if full bit is on, not ready to write on */ - if (awe_peek_dw(AWE_SMALW) & 0x80000000) { - for (i = 0; i < channels; i++) { - awe_poke_dw(AWE_CCCA(vidx[i]), 0); - voices[i].state = AWE_ST_OFF; - } - return RET_ERROR(ENOSPC); - } - - /* set address to write */ - awe_poke_dw(AWE_SMALW, offset); - - return 0; -} - -/* open DRAM for RAM size detection */ -static void -awe_open_dram_for_check(void) -{ - int i; - for (i = 0; i < AWE_NORMAL_VOICES; i++) { - awe_poke(AWE_DCYSUSV(i), 0x80); - awe_poke_dw(AWE_VTFT(i), 0); - awe_poke_dw(AWE_CVCF(i), 0); - awe_poke_dw(AWE_PTRX(i), 0x40000000); - awe_poke_dw(AWE_CPF(i), 0x40000000); - awe_poke_dw(AWE_PSST(i), 0); - awe_poke_dw(AWE_CSL(i), 0); - if (i & 1) /* DMA write */ - awe_poke_dw(AWE_CCCA(i), 0x06000000); - else /* DMA read */ - awe_poke_dw(AWE_CCCA(i), 0x04000000); - voices[i].state = AWE_ST_DRAM; - } -} - - -/* close dram access */ -static void -awe_close_dram(void) -{ - int i; - /* wait until FULL bit in SMAxW register be false */ - for (i = 0; i < 10000; i++) { - if (!(awe_peek_dw(AWE_SMALW) & 0x80000000)) - break; - awe_wait(10); - } - - for (i = 0; i < AWE_NORMAL_VOICES; i++) { - if (voices[i].state == AWE_ST_DRAM) { - awe_poke_dw(AWE_CCCA(i), 0); - awe_poke(AWE_DCYSUSV(i), 0x807F); - voices[i].state = AWE_ST_OFF; - } - } -} - - -/*================================================================ - * detect presence of AWE32 and check memory size - *================================================================*/ - -/* detect emu8000 chip on the specified address; from VV's guide */ - -static int -awe_detect_base(int addr) -{ - awe_base = addr; - if ((awe_peek(AWE_U1) & 0x000F) != 0x000C) - return 0; - if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058) - return 0; - if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003) - return 0; - AWE_DEBUG(0,printk("AWE32 found at %x\n", awe_base)); - return 1; -} - -static int -awe_detect(void) -{ - int base; - if (awe_base == 0) { - for (base = 0x620; base <= 0x680; base += 0x20) - if (awe_detect_base(base)) - return 1; - AWE_DEBUG(0,printk("AWE32 not found\n")); - return 0; - } - return 1; -} - - -/*================================================================ - * check dram size on AWE board - *================================================================*/ - -/* any three numbers you like */ -#define UNIQUE_ID1 0x1234 -#define UNIQUE_ID2 0x4321 -#define UNIQUE_ID3 0xFFFF - -static int -awe_check_dram(void) -{ - if (awe_mem_size > 0) { - awe_mem_size *= 1024; /* convert to Kbytes */ - return awe_mem_size; - } - - awe_open_dram_for_check(); - - awe_mem_size = 0; - - /* set up unique two id numbers */ - awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET); - awe_poke(AWE_SMLD, UNIQUE_ID1); - awe_poke(AWE_SMLD, UNIQUE_ID2); - - while (awe_mem_size < AWE_MAX_DRAM_SIZE) { - awe_wait(2); - /* read a data on the DRAM start address */ - awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET); - awe_peek(AWE_SMLD); /* discard stale data */ - if (awe_peek(AWE_SMLD) != UNIQUE_ID1) - break; - if (awe_peek(AWE_SMLD) != UNIQUE_ID2) - break; - awe_mem_size += 32; /* increment 32 Kbytes */ - /* Write a unique data on the test address; - * if the address is out of range, the data is written on - * 0x200000(=AWE_DRAM_OFFSET). Then the two id words are - * broken by this data. - */ - awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET + awe_mem_size*512L); - awe_poke(AWE_SMLD, UNIQUE_ID3); - awe_wait(2); - /* read a data on the just written DRAM address */ - awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET + awe_mem_size*512L); - awe_peek(AWE_SMLD); /* discard stale data */ - if (awe_peek(AWE_SMLD) != UNIQUE_ID3) - break; - } - awe_close_dram(); - - AWE_DEBUG(0,printk("AWE32: %d Kbytes memory detected\n", awe_mem_size)); - - /* convert to Kbytes */ - awe_mem_size *= 1024; - return awe_mem_size; -} - - -/*================================================================ - * chorus and reverb controls; from VV's guide - *================================================================*/ - -/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */ -static char chorus_defined[AWE_CHORUS_NUMBERS]; -static awe_chorus_fx_rec chorus_parm[AWE_CHORUS_NUMBERS] = { - {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */ - {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */ - {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */ - {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */ - {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */ - {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */ - {0xE600, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay */ - {0xE6C0, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay + feedback */ -}; - -static int -awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count) -{ - if (patch->optarg < AWE_CHORUS_PREDEFINED || patch->optarg >= AWE_CHORUS_NUMBERS) { - printk("AWE32 Error: illegal chorus mode %d for uploading\n", patch->optarg); - return RET_ERROR(EINVAL); - } - if (count < sizeof(awe_chorus_fx_rec)) { - printk("AWE32 Error: too short chorus fx parameters\n"); - return RET_ERROR(EINVAL); - } - COPY_FROM_USER(&chorus_parm[patch->optarg], addr, AWE_PATCH_INFO_SIZE, - sizeof(awe_chorus_fx_rec)); - chorus_defined[patch->optarg] = TRUE; - return 0; -} - -static void -awe_set_chorus_mode(int effect) -{ - if (effect < 0 || effect >= AWE_CHORUS_NUMBERS || - (effect >= AWE_CHORUS_PREDEFINED && !chorus_defined[effect])) - return; - awe_poke(AWE_INIT3(9), chorus_parm[effect].feedback); - awe_poke(AWE_INIT3(12), chorus_parm[effect].delay_offset); - awe_poke(AWE_INIT4(3), chorus_parm[effect].lfo_depth); - awe_poke_dw(AWE_HWCF4, chorus_parm[effect].delay); - awe_poke_dw(AWE_HWCF5, chorus_parm[effect].lfo_freq); - awe_poke_dw(AWE_HWCF6, 0x8000); - awe_poke_dw(AWE_HWCF7, 0x0000); - chorus_mode = effect; -} - -/*----------------------------------------------------------------*/ - -/* reverb mode settings; write the following 28 data of 16 bit length - * on the corresponding ports in the reverb_cmds array - */ -static char reverb_defined[AWE_CHORUS_NUMBERS]; -static awe_reverb_fx_rec reverb_parm[AWE_REVERB_NUMBERS] = { -{{ /* room 1 */ - 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4, - 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516, - 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* room 2 */ - 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* room 3 */ - 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516, - 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B, - 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A, -}}, -{{ /* hall 1 */ - 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A, - 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529, -}}, -{{ /* hall 2 */ - 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254, - 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3, - 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* plate */ - 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234, - 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* delay */ - 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204, - 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, - 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, - 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, -}}, -{{ /* panning delay */ - 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204, - 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, - 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, - 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, -}}, -}; - -static struct ReverbCmdPair { - unsigned short cmd, port; -} reverb_cmds[28] = { - {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)}, - {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)}, - {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)}, - {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)}, - {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)}, - {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)}, - {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)}, -}; - -static int -awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count) -{ - if (patch->optarg < AWE_REVERB_PREDEFINED || patch->optarg >= AWE_REVERB_NUMBERS) { - printk("AWE32 Error: illegal reverb mode %d for uploading\n", patch->optarg); - return RET_ERROR(EINVAL); - } - if (count < sizeof(awe_reverb_fx_rec)) { - printk("AWE32 Error: too short reverb fx parameters\n"); - return RET_ERROR(EINVAL); - } - COPY_FROM_USER(&reverb_parm[patch->optarg], addr, AWE_PATCH_INFO_SIZE, - sizeof(awe_reverb_fx_rec)); - reverb_defined[patch->optarg] = TRUE; - return 0; -} - -static void -awe_set_reverb_mode(int effect) -{ - int i; - if (effect < 0 || effect >= AWE_REVERB_NUMBERS || - (effect >= AWE_REVERB_PREDEFINED && !reverb_defined[effect])) - return; - for (i = 0; i < 28; i++) - awe_poke(reverb_cmds[i].cmd, reverb_cmds[i].port, - reverb_parm[effect].parms[i]); - reverb_mode = effect; -} - -/*================================================================ - * treble/bass equalizer control - *================================================================*/ - -static unsigned short bass_parm[12][3] = { - {0xD26A, 0xD36A, 0x0000}, /* -12 dB */ - {0xD25B, 0xD35B, 0x0000}, /* -8 */ - {0xD24C, 0xD34C, 0x0000}, /* -6 */ - {0xD23D, 0xD33D, 0x0000}, /* -4 */ - {0xD21F, 0xD31F, 0x0000}, /* -2 */ - {0xC208, 0xC308, 0x0001}, /* 0 (HW default) */ - {0xC219, 0xC319, 0x0001}, /* +2 */ - {0xC22A, 0xC32A, 0x0001}, /* +4 */ - {0xC24C, 0xC34C, 0x0001}, /* +6 */ - {0xC26E, 0xC36E, 0x0001}, /* +8 */ - {0xC248, 0xC348, 0x0002}, /* +10 */ - {0xC26A, 0xC36A, 0x0002}, /* +12 dB */ -}; - -static unsigned short treble_parm[12][9] = { - {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */ - {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */ - {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, - {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +12 dB */ -}; - - -/* - * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB] - */ -static void -awe_equalizer(int bass, int treble) -{ - unsigned short w; - - if (bass < 0 || bass > 11 || treble < 0 || treble > 11) - return; - awe_bass_level = bass; - awe_treble_level = treble; - awe_poke(AWE_INIT4(0x01), bass_parm[bass][0]); - awe_poke(AWE_INIT4(0x11), bass_parm[bass][1]); - awe_poke(AWE_INIT3(0x11), treble_parm[treble][0]); - awe_poke(AWE_INIT3(0x13), treble_parm[treble][1]); - awe_poke(AWE_INIT3(0x1B), treble_parm[treble][2]); - awe_poke(AWE_INIT4(0x07), treble_parm[treble][3]); - awe_poke(AWE_INIT4(0x0B), treble_parm[treble][4]); - awe_poke(AWE_INIT4(0x0D), treble_parm[treble][5]); - awe_poke(AWE_INIT4(0x17), treble_parm[treble][6]); - awe_poke(AWE_INIT4(0x19), treble_parm[treble][7]); - w = bass_parm[bass][2] + treble_parm[treble][8]; - awe_poke(AWE_INIT4(0x15), (unsigned short)(w + 0x0262)); - awe_poke(AWE_INIT4(0x1D), (unsigned short)(w + 0x8362)); -} - - -#endif /* CONFIG_AWE32_SYNTH */ diff --git a/sys/i386/i386/userconfig.c b/sys/i386/i386/userconfig.c index 2a686b5831..2043d1a636 100644 --- a/sys/i386/i386/userconfig.c +++ b/sys/i386/i386/userconfig.c @@ -47,7 +47,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ** $FreeBSD: src/sys/i386/i386/userconfig.c,v 1.175.2.10 2002/10/05 18:31:48 scottl Exp $ - ** $DragonFly: src/sys/i386/i386/Attic/userconfig.c,v 1.3 2003/08/07 21:17:22 dillon Exp $ + ** $DragonFly: src/sys/i386/i386/Attic/userconfig.c,v 1.4 2005/01/31 23:44:35 joerg Exp $ **/ /** @@ -390,7 +390,6 @@ static DEV_INFO device_info[] = { {"sb", "VOXWARE Soundblaster PCM (SB/Pro/16, ProAudio Spectrum)",0,CLS_MMEDIA}, {"sbxvi", "VOXWARE Soundblaster 16", 0, CLS_MMEDIA}, {"sbmidi", "VOXWARE Soundblaster MIDI interface", 0, CLS_MMEDIA}, -{"awe", "VOXWARE AWE32 MIDI", 0, CLS_MMEDIA}, {"pas", "VOXWARE ProAudio Spectrum PCM and MIDI", 0, CLS_MMEDIA}, {"gus", "VOXWARE Gravis Ultrasound, Ultrasound 16 and Ultrasound MAX",0,CLS_MMEDIA}, {"gusxvi", "VOXWARE Gravis Ultrasound 16-bit PCM", 0, CLS_MMEDIA}, diff --git a/sys/i386/isa/ic/i82365.h b/sys/i386/isa/ic/i82365.h deleted file mode 100644 index e95de537eb..0000000000 --- a/sys/i386/isa/ic/i82365.h +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef __83265_H__ -#define __83265_H__ - -/*********************************************************************** - * 82365.h -- information necessary for direct manipulation of PCMCIA - * cards and controllers - * - * Support is included for Intel 82365SL PCIC controllers and clones - * thereof. - * - * originally by Barry Jaspan; hacked over by Keith Moore - * - * $FreeBSD: src/sys/i386/isa/ic/i82365.h,v 1.2.16.1 2000/08/03 18:55:42 peter Exp $ - * $DragonFly: src/sys/i386/isa/ic/Attic/i82365.h,v 1.2 2003/06/17 04:28:37 dillon Exp $ - ***********************************************************************/ - -/* - * PCIC Registers - * Each register is given a name, and most of the bits are named too. - * I should really name them all. - * - * Finally, since the banks can be addressed with a regular syntax, - * some macros are provided for that purpose. - */ - -#define PCIC_BASE 0x03e0 /* base adddress of pcic register set */ - -/* First, all the registers */ -#define PCIC_ID_REV 0x00 /* Identification and Revision */ -#define PCIC_STATUS 0x01 /* Interface Status */ -#define PCIC_POWER 0x02 /* Power and RESETDRV control */ -#define PCIC_INT_GEN 0x03 /* Interrupt and General Control */ -#define PCIC_STAT_CHG 0x04 /* Card Status Change */ -#define PCIC_STAT_INT 0x05 /* Card Status Change Interrupt Config */ -#define PCIC_ADDRWINE 0x06 /* Address Window Enable */ -#define PCIC_IOCTL 0x07 /* I/O Control */ -#define PCIC_IO0_STL 0x08 /* I/O Address 0 Start Low Byte */ -#define PCIC_IO0_STH 0x09 /* I/O Address 0 Start High Byte */ -#define PCIC_IO0_SPL 0x0a /* I/O Address 0 Stop Low Byte */ -#define PCIC_IO0_SPH 0x0b /* I/O Address 0 Stop High Byte */ -#define PCIC_IO1_STL 0x0c /* I/O Address 1 Start Low Byte */ -#define PCIC_IO1_STH 0x0d /* I/O Address 1 Start High Byte */ -#define PCIC_IO1_SPL 0x0e /* I/O Address 1 Stop Low Byte */ -#define PCIC_IO1_SPH 0x0f /* I/O Address 1 Stop High Byte */ -#define PCIC_SM0_STL 0x10 /* System Memory Address 0 Mapping Start Low Byte */ -#define PCIC_SM0_STH 0x11 /* System Memory Address 0 Mapping Start High Byte */ -#define PCIC_SM0_SPL 0x12 /* System Memory Address 0 Mapping Stop Low Byte */ -#define PCIC_SM0_SPH 0x13 /* System Memory Address 0 Mapping Stop High Byte */ -#define PCIC_CM0_L 0x14 /* Card Memory Offset Address 0 Low Byte */ -#define PCIC_CM0_H 0x15 /* Card Memory Offset Address 0 High Byte */ -#define PCIC_CDGC 0x16 /* Card Detect and General Control */ -#define PCIC_RES17 0x17 /* Reserved */ -#define PCIC_SM1_STL 0x18 /* System Memory Address 1 Mapping Start Low Byte */ -#define PCIC_SM1_STH 0x19 /* System Memory Address 1 Mapping Start High Byte */ -#define PCIC_SM1_SPL 0x1a /* System Memory Address 1 Mapping Stop Low Byte */ -#define PCIC_SM1_SPH 0x1b /* System Memory Address 1 Mapping Stop High Byte */ -#define PCIC_CM1_L 0x1c /* Card Memory Offset Address 1 Low Byte */ -#define PCIC_CM1_H 0x1d /* Card Memory Offset Address 1 High Byte */ -#define PCIC_GLO_CTRL 0x1e /* Global Control Register */ -#define PCIC_RES1F 0x1f /* Reserved */ -#define PCIC_SM2_STL 0x20 /* System Memory Address 2 Mapping Start Low Byte */ -#define PCIC_SM2_STH 0x21 /* System Memory Address 2 Mapping Start High Byte */ -#define PCIC_SM2_SPL 0x22 /* System Memory Address 2 Mapping Stop Low Byte */ -#define PCIC_SM2_SPH 0x23 /* System Memory Address 2 Mapping Stop High Byte */ -#define PCIC_CM2_L 0x24 /* Card Memory Offset Address 2 Low Byte */ -#define PCIC_CM2_H 0x25 /* Card Memory Offset Address 2 High Byte */ -#define PCIC_RES26 0x26 /* Reserved */ -#define PCIC_RES27 0x27 /* Reserved */ -#define PCIC_SM3_STL 0x28 /* System Memory Address 3 Mapping Start Low Byte */ -#define PCIC_SM3_STH 0x29 /* System Memory Address 3 Mapping Start High Byte */ -#define PCIC_SM3_SPL 0x2a /* System Memory Address 3 Mapping Stop Low Byte */ -#define PCIC_SM3_SPH 0x2b /* System Memory Address 3 Mapping Stop High Byte */ -#define PCIC_CM3_L 0x2c /* Card Memory Offset Address 3 Low Byte */ -#define PCIC_CM3_H 0x2d /* Card Memory Offset Address 3 High Byte */ -#define PCIC_RES2E 0x2e /* Reserved */ -#define PCIC_RES2F 0x2f /* Reserved */ -#define PCIC_SM4_STL 0x30 /* System Memory Address 4 Mapping Start Low Byte */ -#define PCIC_SM4_STH 0x31 /* System Memory Address 4 Mapping Start High Byte */ -#define PCIC_SM4_SPL 0x32 /* System Memory Address 4 Mapping Stop Low Byte */ -#define PCIC_SM4_SPH 0x33 /* System Memory Address 4 Mapping Stop High Byte */ -#define PCIC_CM4_L 0x34 /* Card Memory Offset Address 4 Low Byte */ -#define PCIC_CM4_H 0x35 /* Card Memory Offset Address 4 High Byte */ -#define PCIC_RES36 0x36 /* Reserved */ -#define PCIC_RES37 0x37 /* Reserved */ -#define PCIC_RES38 0x38 /* Reserved */ -#define PCIC_RES39 0x39 /* Reserved */ -#define PCIC_RES3A 0x3a /* Reserved */ -#define PCIC_RES3B 0x3b /* Reserved */ -#define PCIC_RES3C 0x3c /* Reserved */ -#define PCIC_RES3D 0x3d /* Reserved */ -#define PCIC_RES3E 0x3e /* Reserved */ -#define PCIC_RES3F 0x3f /* Reserved */ - -/* Now register bits, ordered by reg # */ - -/* For Identification and Revision (PCIC_ID_REV) */ -#define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */ -#define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */ -#define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */ -#define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */ - -/* For Interface Status register (PCIC_STATUS) */ -#define PCIC_VPPV 0x80 /* Vpp_valid */ -#define PCIC_POW 0x40 /* PC Card power active */ -#define PCIC_READY 0x20 /* Ready/~Busy */ -#define PCIC_MWP 0x10 /* Memory Write Protect */ -#define PCIC_CD 0x0C /* Both card detect bits */ -#define PCIC_BVD 0x03 /* Both Battery Voltage Detect bits */ - -/* For the Power and RESETDRV register (PCIC_POWER) */ -#define PCIC_OUTENA 0x80 /* Output Enable */ -#define PCIC_DISRST 0x40 /* Disable RESETDRV */ -#define PCIC_APSENA 0x20 /* Auto Pwer Switch Enable */ -#define PCIC_PCPWRE 0x10 /* PC Card Power Enable */ - -/* For the Interrupt and General Control register (PCIC_INT_GEN) */ -#define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */ -#define PCIC_IOCARD 0x20 -#define PCIC_MEMCARD 0x00 -#define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */ - -/* For the Card Status Change register (PCIC_STAT_CHG) */ -#define PCIC_CDTCH 0x08 /* Card Detect Change */ -#define PCIC_RDYCH 0x04 /* Ready Change */ -#define PCIC_BATWRN 0x02 /* Battery Warning */ -#define PCIC_BATDED 0x01 /* Battery Dead */ - -/* For the Address Window Enable Register (PCIC_ADDRWINE) */ -#define PCIC_SM0_EN 0x01 /* Memory Window 0 Enable */ -#define PCIC_SM1_EN 0x02 /* Memory Window 1 Enable */ -#define PCIC_SM2_EN 0x04 /* Memory Window 2 Enable */ -#define PCIC_SM3_EN 0x08 /* Memory Window 3 Enable */ -#define PCIC_SM4_EN 0x10 /* Memory Window 4 Enable */ -#define PCIC_MEMCS16 0x20 /* ~MEMCS16 Decode A23-A12 */ -#define PCIC_IO0_EN 0x40 /* I/O Window 0 Enable */ -#define PCIC_IO1_EN 0x80 /* I/O Window 1 Enable */ - -/* For the I/O Control Register (PCIC_IOCTL) */ -#define PCIC_IO0_16BIT 0x01 /* I/O to this segment is 16 bit */ -#define PCIC_IO0_CS16 0x02 /* I/O cs16 source is the card */ -#define PCIC_IO0_0WS 0x04 /* zero wait states added on 8 bit cycles */ -#define PCIC_IO0_WS 0x08 /* Wait states added for 16 bit cycles */ -#define PCIC_IO1_16BIT 0x10 /* I/O to this segment is 16 bit */ -#define PCIC_IO1_CS16 0x20 /* I/O cs16 source is the card */ -#define PCIC_IO1_0WS 0x04 /* zero wait states added on 8 bit cycles */ -#define PCIC_IO1_WS 0x80 /* Wait states added for 16 bit cycles */ - -/* For the various I/O and Memory windows */ -#define PCIC_ADDR_LOW 0 -#define PCIC_ADDR_HIGH 1 -#define PCIC_START 0x00 /* Start of mapping region */ -#define PCIC_END 0x02 /* End of mapping region */ -#define PCIC_MOFF 0x04 /* Card Memory Mapping region offset */ -#define PCIC_IO0 0x08 /* I/O Address 0 */ -#define PCIC_IO1 0x0c /* I/O Address 1 */ -#define PCIC_SM0 0x10 /* System Memory Address 0 Mapping */ -#define PCIC_SM1 0x18 /* System Memory Address 1 Mapping */ -#define PCIC_SM2 0x20 /* System Memory Address 2 Mapping */ -#define PCIC_SM3 0x28 /* System Memory Address 3 Mapping */ -#define PCIC_SM4 0x30 /* System Memory Address 4 Mapping */ - -/* For System Memory Window start registers - (PCIC_SMx|PCIC_START|PCIC_ADDR_HIGH) */ -#define PCIC_ZEROWS 0x40 /* Zero wait states */ -#define PCIC_DATA16 0x80 /* Data width is 16 bits */ - -/* For System Memory Window stop registers - (PCIC_SMx|PCIC_END|PCIC_ADDR_HIGH) */ -#define PCIC_MW0 0x40 /* Wait state bit 0 */ -#define PCIC_MW1 0x80 /* Wait state bit 1 */ - -/* For System Memory Window offset registers - (PCIC_SMx|PCIC_MOFF|PCIC_ADDR_HIGH) */ -#define PCIC_REG 0x40 /* Attribute/Common select (why called Reg?) */ -#define PCIC_WP 0x80 /* Write-protect this window */ - -/* For Card Detect and General Control register (PCIC_CDGC) */ -#define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */ -#define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */ -#define PCIC_GPI_EN 0x04 /* GPI Enable */ -#define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */ -#define PCIC_CDRES_EN 0x10 /* card detect resume enable */ -#define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */ - -/* For Global Control register (PCIC_GLO_CTRL) */ -#define PCIC_PWR_DOWN 0x01 /* power down */ -#define PCIC_LVL_MODE 0x02 /* level mode interrupt enable */ -#define PCIC_WB_CSCINT 0x04 /* explicit write-back csc intr */ -#define PCIC_IRQ14_PULSE 0x08 /* irq 14 pulse mode enable */ - -/* DON'T ADD ANYTHING AFTER THIS #endif */ -#endif /* __83265_H__ */ diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index 973de2d2b0..818685205f 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -33,7 +33,7 @@ * * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 * $FreeBSD: src/sys/i386/isa/npx.c,v 1.80.2.3 2001/10/20 19:04:38 tegge Exp $ - * $DragonFly: src/sys/i386/isa/Attic/npx.c,v 1.21 2004/06/17 19:37:29 drhodus Exp $ + * $DragonFly: src/sys/i386/isa/Attic/npx.c,v 1.22 2005/01/31 23:44:35 joerg Exp $ */ #include "opt_cpu.h" @@ -440,7 +440,7 @@ npx_attach(device_t dev) if (npx_irq13) { device_printf(dev, "using IRQ 13 interface\n"); } else { -#if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) +#if defined(MATH_EMULATE) if (npx_ex16) { if (!(flags & NPX_PREFER_EMULATOR)) device_printf(dev, "INT 16 interface\n"); diff --git a/sys/i386/isa/sound/local.h b/sys/i386/isa/sound/local.h index 80a4cc9f8c..b79b6341e9 100644 --- a/sys/i386/isa/sound/local.h +++ b/sys/i386/isa/sound/local.h @@ -6,7 +6,7 @@ * will become more like that of standard bsd code. * lr 970714 * - * $DragonFly: src/sys/i386/isa/sound/Attic/local.h,v 1.2 2003/08/07 21:17:23 dillon Exp $ + * $DragonFly: src/sys/i386/isa/sound/Attic/local.h,v 1.3 2005/01/31 23:44:35 joerg Exp $ */ /* build hex2hex /tmp/foo.x trix_boot.h trix_boot */ @@ -82,11 +82,6 @@ #define CONFIG_SB16MIDI #endif -#include "use_awe.h" -#if NAWE != 0 && !defined(CONFIG_AWE32) -#define CONFIG_AWE32 -#endif - #include "use_pas.h" #if NPAS != 0 && !defined(CONFIG_PAS) #define CONFIG_PAS diff --git a/sys/platform/pc32/gnu/fpemul/Changelog b/sys/platform/pc32/gnu/fpemul/Changelog deleted file mode 100644 index 22cae1eab3..0000000000 --- a/sys/platform/pc32/gnu/fpemul/Changelog +++ /dev/null @@ -1,39 +0,0 @@ -$FreeBSD: src/sys/gnu/i386/fpemul/Changelog,v 1.1.20.1 2000/08/03 00:53:55 peter Exp $ -$DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/Changelog,v 1.2 2003/06/17 04:28:34 dillon Exp $ - -This file contains the changes made to W. Metzenthem's 387 FPU -emulator to make it work under NetBSD. - -a, Changes to make it compile: - - 1 - Changed the #include's to get the appropriate .h files. - 2 - Renamed .S to .s, to satisfy the kernel Makefile. - 3 - Changed the C++ style // comments to /* */ - 4 - Changed the FPU_ORIG_EIP macro. A letter from bde included - in the package suggested using tf_isp for using instead - of the linux __orig_eip. This later turned out to interfere - with the user stack, so i created a separate variable, stored - in the i387_union. - 5 - Changed the get_fs_.. put_fs_.. fns to fubyte,fuword,subyte, - suword. - 6 - Removed the verify_area fns. I don't really know what they do, - i suppose they verify access to memory. The sufu routines - should do this. - -b, Changes to make it work: - - 1 - Made math_emulate() to return 0 when successful, so trap() won't - try to generate a signal. - 2 - Changed the size of the save87 struct in /sys/arch/i387/include/ - npx.h to accomodate the i387_union. - -d, Other changes: - - 1 - Removed obsolate and/or linux specific stuff. - 2 - Changed the RE_ENTRANT_CHECK_[ON|OFF] macro to - REENTRANT_CHECK([ON|OFF]) so indent can grok it. - 3 - Re-indented to Berkeley style. - 4 - Limited max no of lookaheads. LOOKAHEAD_LIMIT in fpu_entry.c - - - Szabolcs Szigeti (pink@fsz.bme.hu) diff --git a/sys/platform/pc32/gnu/fpemul/README b/sys/platform/pc32/gnu/fpemul/README deleted file mode 100644 index a0797dab17..0000000000 --- a/sys/platform/pc32/gnu/fpemul/README +++ /dev/null @@ -1,279 +0,0 @@ -/* - * wm-FPU-emu an FPU emulator for 80386 and 80486SX microprocessors. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD: src/sys/gnu/i386/fpemul/README,v 1.2.20.1 2000/08/03 00:53:55 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/README,v 1.2 2003/06/17 04:28:34 dillon Exp $ - */ - -wm-FPU-emu is an FPU emulator for Linux. It is derived from wm-emu387 -which is my 80387 emulator for djgpp (gcc under msdos); wm-emu387 was -in turn based upon emu387 which was written by DJ Delorie for djgpp. -The interface to the Linux kernel is based upon the original Linux -math emulator by Linus Torvalds. - -My target FPU for wm-FPU-emu is that described in the Intel486 -Programmer's Reference Manual (1992 edition). Numerous facets of the -functioning of the FPU are not well covered in the Reference Manual; -in the absence of clear details I have made guesses about the most -reasonable behaviour. Recently, this situation has improved because -I now have some access to the results produced by a real 80486 FPU. - -wm-FPU-emu does not implement all of the behaviour of the 80486 FPU. -See "Limitations" later in this file for a partial list of some -differences. I believe that the missing features are never used by -normal C or FORTRAN programs. - - -Please report bugs, etc to me at: - apm233m@vaxc.cc.monash.edu.au - - ---Bill Metzenthen - May 1993 - - ------------------------ Internals of wm-FPU-emu ----------------------- - -Numeric algorithms: -(1) Add, subtract, and multiply. Nothing remarkable in these. -(2) Divide has been tuned to get reasonable performance. The algorithm - is not the obvious one which most people seem to use, but is designed - to take advantage of the characteristics of the 80386. I expect that - it has been invented many times before I discovered it, but I have not - seen it. It is based upon one of those ideas which one carries around - for years without ever bothering to check it out. -(3) The sqrt function has been tuned to get good performance. It is based - upon Newton's classic method. Performance was improved by capitalizing - upon the properties of Newton's method, and the code is once again - structured taking account of the 80386 characteristics. -(4) The trig, log, and exp functions are based in each case upon quasi- - "optimal" polynomial approximations. My definition of "optimal" was - based upon getting good accuracy with reasonable speed. - -The code of the emulator is complicated slightly by the need to -account for a limited form of re-entrancy. Normally, the emulator will -emulate each FPU instruction to completion without interruption. -However, it may happen that when the emulator is accessing the user -memory space, swapping may be needed. In this case the emulator may be -temporarily suspended while disk i/o takes place. During this time -another process may use the emulator, thereby changing some static -variables (eg FPU_st0_ptr, etc). The code which accesses user memory -is confined to five files: - fpu_entry.c - reg_ld_str.c - load_store.c - get_address.c - errors.c - ------------------------ Limitations of wm-FPU-emu ----------------------- - -There are a number of differences between the current wm-FPU-emu -(version beta 1.4) and the 80486 FPU (apart from bugs). Some of the -more important differences are listed below: - -All internal computations are performed at 64 bit or higher precision -and rounded etc as required by the PC bits of the FPU control word. -Under the crt0 version for Linux current at March 1993, the FPU PC -bits specify 53 bits precision. - -The precision flag (PE of the FPU status word) and the Roundup flag -(C1 of the status word) are now partially implemented. Does anyone -write code which uses these features? - -The functions which load/store the FPU state are partially implemented, -but the implementation should be sufficient for handling FPU errors etc -in 32 bit protected mode. - -The implementation of the exception mechanism is flawed for unmasked -interrupts. - -Detection of certain conditions, such as denormal operands, is not yet -complete. - ------------------------ Performance of wm-FPU-emu ----------------------- - -Speed. ------ - -The speed of floating point computation with the emulator will depend -upon instruction mix. Relative performance is best for the instructions -which require most computation. The simple instructions are adversely -affected by the fpu instruction trap overhead. - - -Timing: Some simple timing tests have been made on the emulator functions. -The times include load/store instructions. All times are in microseconds -measured on a 33MHz 386 with 64k cache. The Turbo C tests were under -ms-dos, the next two columns are for emulators running with the djgpp -ms-dos extender. The final column is for wm-FPU-emu in Linux 0.97, -using libm4.0 (hard). - -function Turbo C djgpp 1.06 WM-emu387 wm-FPU-emu - - + 60.5 154.8 76.5 139.4 - - 61.1-65.5 157.3-160.8 76.2-79.5 142.9-144.7 - * 71.0 190.8 79.6 146.6 - / 61.2-75.0 261.4-266.9 75.3-91.6 142.2-158.1 - - sin() 310.8 4692.0 319.0 398.5 - cos() 284.4 4855.2 308.0 388.7 - tan() 495.0 8807.1 394.9 504.7 - atan() 328.9 4866.4 601.1 419.5-491.9 - - sqrt() 128.7 crashed 145.2 227.0 - log() 413.1-419.1 5103.4-5354.21 254.7-282.2 409.4-437.1 - exp() 479.1 6619.2 469.1 850.8 - - -The performance under Linux is improved by the use of look-ahead code. -The following results show the improvement which is obtained under -Linux due to the look-ahead code. Also given are the times for the -original Linux emulator with the 4.1 'soft' lib. - - [ Linus' note: I changed look-ahead to be the default under linux, as - there was no reason not to use it after I had edited it to be - disabled during tracing ] - - wm-FPU-emu w original w - look-ahead 'soft' lib - + 106.4 190.2 - - 108.6-111.6 192.4-216.2 - * 113.4 193.1 - / 108.8-124.4 700.1-706.2 - - sin() 390.5 2642.0 - cos() 381.5 2767.4 - tan() 496.5 3153.3 - atan() 367.2-435.5 2439.4-3396.8 - - sqrt() 195.1 4732.5 - log() 358.0-387.5 3359.2-3390.3 - exp() 619.3 4046.4 - - -These figures are now somewhat out-of-date. The emulator has become -progressively slower for most functions as more of the 80486 features -have been implemented. - - ------------------------ Accuracy of wm-FPU-emu ----------------------- - - -Accuracy: The following table gives the accuracy of the sqrt(), trig -and log functions. Each function was tested at about 400 points. Ideal -results would be 64 bits. The reduced accuracy of cos() and tan() for -arguments greater than pi/4 can be thought of as being due to the -precision of the argument x; e.g. an argument of pi/2-(1e-10) which is -accurate to 64 bits can result in a relative accuracy in cos() of about -64 + log2(cos(x)) = 31 bits. Results for the Turbo C emulator are given -in the last column. - - -Function Tested x range Worst result (bits) Turbo C - -sqrt(x) 1 .. 2 64.1 63.2 -atan(x) 1e-10 .. 200 62.6 62.8 -cos(x) 0 .. pi/2-(1e-10) 63.2 (x <= pi/4) 62.4 - 35.2 (x = pi/2-(1e-10)) 31.9 -sin(x) 1e-10 .. pi/2 63.0 62.8 -tan(x) 1e-10 .. pi/2-(1e-10) 62.4 (x <= pi/4) 62.1 - 35.2 (x = pi/2-(1e-10)) 31.9 -exp(x) 0 .. 1 63.1 62.9 -log(x) 1+1e-6 .. 2 62.4 62.1 - - -As of version 1.3 of the emulator, the accuracy of the basic -arithmetic has been improved (by a small fraction of a bit). Care has -been taken to ensure full accuracy of the rounding of the basic -arithmetic functions (+,-,*,/,and fsqrt), and they all now produce -results which are exact to the 64th bit (unless there are any bugs -left). To ensure this, it was necessary to effectively get information -of up to about 128 bits precision. The emulator now passes the -"paranoia" tests (compiled with gcc 2.3.3) for 'float' variables (24 -bit precision numbers) when precision control is set to 24, 53 or 64 -bits, and for 'double' variables (53 bit precision numbers) when -precision control is set to 53 bits (a properly performing FPU cannot -pass the 'paranoia' tests for 'double' variables when precision -control is set to 64 bits). - -------------------------- Contributors ------------------------------- - -A number of people have contributed to the development of the -emulator, often by just reporting bugs, sometimes with a suggested -fix, and a few kind people have provided me with access in one way or -another to an 80486 machine. Contributors include (to those people who -I have forgotten, please excuse me): - -Linus Torvalds -Tommy.Thorn@daimi.aau.dk -Andrew.Tridgell@anu.edu.au -Nick Holloway alfie@dcs.warwick.ac.uk -Hermano Moura moura@dcs.gla.ac.uk -Jon Jagger J.Jagger@scp.ac.uk -Lennart Benschop -Brian Gallew geek+@CMU.EDU -Thomas Staniszewski ts3v+@andrew.cmu.edu -Martin Howell mph@plasma.apana.org.au -M Saggaf alsaggaf@athena.mit.edu -Peter Barker PETER@socpsy.sci.fau.edu -tom@vlsivie.tuwien.ac.at -Dan Russel russed@rpi.edu -Daniel Carosone danielce@ee.mu.oz.au -cae@jpmorgan.com -Hamish Coleman t933093@minyos.xx.rmit.oz.au - -...and numerous others who responded to my request for help with -a real 80486. - diff --git a/sys/platform/pc32/gnu/fpemul/control_w.h b/sys/platform/pc32/gnu/fpemul/control_w.h deleted file mode 100644 index 3ec0a26b6c..0000000000 --- a/sys/platform/pc32/gnu/fpemul/control_w.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * control_w.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/control_w.h,v 1.7 1999/08/28 00:42:48 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/control_w.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - -#ifndef _CONTROLW_H_ -#define _CONTROLW_H_ - -#ifdef LOCORE -#define _Const_(x) $/**/x -#else -#define _Const_(x) x -#endif - -#define CW_RC _Const_(0x0C00) /* rounding control */ -#define CW_PC _Const_(0x0300) /* precision control */ - -#define CW_Precision Const_(0x0020) /* loss of precision mask */ -#define CW_Underflow Const_(0x0010) /* underflow mask */ -#define CW_Overflow Const_(0x0008) /* overflow mask */ -#define CW_ZeroDiv Const_(0x0004) /* divide by zero mask */ -#define CW_Denormal Const_(0x0002) /* denormalized operand mask */ -#define CW_Invalid Const_(0x0001) /* invalid operation mask */ - -#define CW_Exceptions _Const_(0x003f) /* all masks */ - -#define RC_RND _Const_(0x0000) -#define RC_DOWN _Const_(0x0400) -#define RC_UP _Const_(0x0800) -#define RC_CHOP _Const_(0x0C00) - -/* p 15-5: Precision control bits affect only the following: - ADD, SUB(R), MUL, DIV(R), and SQRT */ -#define PR_24_BITS _Const_(0x000) -#define PR_53_BITS _Const_(0x200) -#define PR_64_BITS _Const_(0x300) -/* FULL_PRECISION simulates all exceptions masked */ -#define FULL_PRECISION (PR_64_BITS | RC_RND | 0x3f) - -#endif /* _CONTROLW_H_ */ diff --git a/sys/platform/pc32/gnu/fpemul/div_small.s b/sys/platform/pc32/gnu/fpemul/div_small.s deleted file mode 100644 index a6c8d142bb..0000000000 --- a/sys/platform/pc32/gnu/fpemul/div_small.s +++ /dev/null @@ -1,98 +0,0 @@ - .file "div_small.S" -/* - * div_small.S - * - * Divide a 64 bit integer by a 32 bit integer & return remainder. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/div_small.s,v 1.8 1999/08/28 00:42:48 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/div_small.s,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | unsigned long div_small(unsigned long long *x, unsigned long y) | - +---------------------------------------------------------------------------*/ - -#include "fpu_asm.h" - -.text -ENTRY(div_small) - pushl %ebp - movl %esp,%ebp - - pushl %esi - - movl PARAM1,%esi /* pointer to num */ - movl PARAM2,%ecx /* The denominator */ - - movl 4(%esi),%eax /* Get the current num msw */ - xorl %edx,%edx - divl %ecx - - movl %eax,4(%esi) - - movl (%esi),%eax /* Get the num lsw */ - divl %ecx - - movl %eax,(%esi) - - movl %edx,%eax /* Return the remainder in eax */ - - popl %esi - - leave - ret - diff --git a/sys/platform/pc32/gnu/fpemul/errors.c b/sys/platform/pc32/gnu/fpemul/errors.c deleted file mode 100644 index 80404de525..0000000000 --- a/sys/platform/pc32/gnu/fpemul/errors.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * errors.c - * - * The error handling functions for wm-FPU-emu - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/errors.c,v 1.10 1999/08/28 00:42:49 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/errors.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - - - - - -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" -#include "control_w.h" -#include "reg_constant.h" -#include "version.h" - -/* */ -#undef PRINT_MESSAGES -/* */ - - -void -Un_impl(void) -{ - unsigned char byte1, FPU_modrm; - - REENTRANT_CHECK(OFF); - byte1 = fubyte((unsigned char *) FPU_ORIG_EIP); - FPU_modrm = fubyte(1 + (unsigned char *) FPU_ORIG_EIP); - - printf("Unimplemented FPU Opcode at eip=%#08x : %02x ", - FPU_ORIG_EIP, byte1); - - if (FPU_modrm >= 0300) - printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); - else - printf("/%d\n", (FPU_modrm >> 3) & 7); - REENTRANT_CHECK(ON); - - EXCEPTION(EX_Invalid); - -} - - - - -void -emu_printall() -{ - int i; - static char *tag_desc[] = {"Valid", "Zero", "ERROR", "ERROR", - "DeNorm", "Inf", "NaN", "Empty"}; - unsigned char byte1, FPU_modrm; - - REENTRANT_CHECK(OFF); - byte1 = fubyte((unsigned char *) FPU_ORIG_EIP); - FPU_modrm = fubyte(1 + (unsigned char *) FPU_ORIG_EIP); - -#ifdef DEBUGGING - if (status_word & SW_Backward) - printf("SW: backward compatibility\n"); - if (status_word & SW_C3) - printf("SW: condition bit 3\n"); - if (status_word & SW_C2) - printf("SW: condition bit 2\n"); - if (status_word & SW_C1) - printf("SW: condition bit 1\n"); - if (status_word & SW_C0) - printf("SW: condition bit 0\n"); - if (status_word & SW_Summary) - printf("SW: exception summary\n"); - if (status_word & SW_Stack_Fault) - printf("SW: stack fault\n"); - if (status_word & SW_Precision) - printf("SW: loss of precision\n"); - if (status_word & SW_Underflow) - printf("SW: underflow\n"); - if (status_word & SW_Overflow) - printf("SW: overflow\n"); - if (status_word & SW_Zero_Div) - printf("SW: divide by zero\n"); - if (status_word & SW_Denorm_Op) - printf("SW: denormalized operand\n"); - if (status_word & SW_Invalid) - printf("SW: invalid operation\n"); -#endif /* DEBUGGING */ - - status_word = status_word & ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - - printf("At %#08x: %02x ", FPU_ORIG_EIP, byte1); - if (FPU_modrm >= 0300) - printf("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7); - else - printf("/%d, mod=%d rm=%d\n", - (FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7); - - printf(" SW: b=%d st=%d es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", - status_word & 0x8000 ? 1 : 0, /* busy */ - (int)((status_word & 0x3800) >> 11), /* stack top pointer */ - status_word & 0x80 ? 1 : 0, /* Error summary status */ - status_word & 0x40 ? 1 : 0, /* Stack flag */ - status_word & SW_C3 ? 1 : 0, status_word & SW_C2 ? 1 : 0, /* cc */ - status_word & SW_C1 ? 1 : 0, status_word & SW_C0 ? 1 : 0, /* cc */ - status_word & SW_Precision ? 1 : 0, status_word & SW_Underflow ? 1 : 0, - status_word & SW_Overflow ? 1 : 0, status_word & SW_Zero_Div ? 1 : 0, - status_word & SW_Denorm_Op ? 1 : 0, status_word & SW_Invalid ? 1 : 0); - - printf(" CW: ic=%d rc=%d%d pc=%d%d iem=%d ef=%d%d%d%d%d%d\n", - control_word & 0x1000 ? 1 : 0, - (int)((control_word & 0x800) >> 11), - (int)((control_word & 0x400) >> 10), - (int)((control_word & 0x200) >> 9), - (int)((control_word & 0x100) >> 8), - control_word & 0x80 ? 1 : 0, - control_word & SW_Precision ? 1 : 0, control_word & SW_Underflow ? 1 : 0, - control_word & SW_Overflow ? 1 : 0, control_word & SW_Zero_Div ? 1 : 0, - control_word & SW_Denorm_Op ? 1 : 0, control_word & SW_Invalid ? 1 : 0); - - for (i = 0; i < 8; i++) { - FPU_REG *r = &st(i); - switch (r->tag) { - case TW_Empty: - continue; - break; - case TW_Zero: - printf("st(%d) %c .0000 0000 0000 0000 ", - i, r->sign ? '-' : '+'); - break; - case TW_Valid: - case TW_NaN: - case TW_Denormal: - case TW_Infinity: - printf("st(%d) %c .%04lx %04lx %04lx %04lx e%+-6ld ", - i, r->sign ? '-' : '+', r->sigh >> 16, - r->sigh & 0xFFFF, r->sigl >> 16, r->sigl & 0xFFFF, - r->exp - EXP_BIAS + 1); - break; - default: - printf("Whoops! Error in errors.c "); - break; - } - printf("%s\n", tag_desc[(int) (unsigned) r->tag]); - } - - printf("[data] %c .%04lx %04lx %04lx %04lx e%+-6ld ", - FPU_loaded_data.sign ? '-' : '+', FPU_loaded_data.sigh >> 16, - FPU_loaded_data.sigh & 0xFFFF, FPU_loaded_data.sigl >> 16, - FPU_loaded_data.sigl & 0xFFFF, FPU_loaded_data.exp - EXP_BIAS + 1); - printf("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]); - REENTRANT_CHECK(ON); - -} - -static struct { - int type; - char *name; -} exception_names[] = { - { - EX_StackOver, "stack overflow" - }, - { - EX_StackUnder, "stack underflow" - }, - { - EX_Precision, "loss of precision" - }, - { - EX_Underflow, "underflow" - }, - { - EX_Overflow, "overflow" - }, - { - EX_ZeroDiv, "divide by zero" - }, - { - EX_Denormal, "denormalized operand" - }, - { - EX_Invalid, "invalid operation" - }, - { - EX_INTERNAL, "INTERNAL BUG in " FPU_VERSION - }, - { - 0, NULL - } -}; -/* - EX_INTERNAL is always given with a code which indicates where the - error was detected. - - Internal error types: - 0x14 in e14.c - 0x1nn in a *.c file: - 0x101 in reg_add_sub.c - 0x102 in reg_mul.c - 0x103 in poly_sin.c - 0x104 in poly_tan.c - 0x105 in reg_mul.c - 0x106 in reg_mov.c - 0x107 in fpu_trig.c - 0x108 in reg_compare.c - 0x109 in reg_compare.c - 0x110 in reg_add_sub.c - 0x111 in interface.c - 0x112 in fpu_trig.c - 0x113 in reg_add_sub.c - 0x114 in reg_ld_str.c - 0x115 in fpu_trig.c - 0x116 in fpu_trig.c - 0x117 in fpu_trig.c - 0x118 in fpu_trig.c - 0x119 in fpu_trig.c - 0x120 in poly_atan.c - 0x121 in reg_compare.c - 0x122 in reg_compare.c - 0x123 in reg_compare.c - 0x2nn in an *.s file: - 0x201 in reg_u_add.S - 0x202 in reg_u_div.S - 0x203 in reg_u_div.S - 0x204 in reg_u_div.S - 0x205 in reg_u_mul.S - 0x206 in reg_u_sub.S - 0x207 in wm_sqrt.S - 0x208 in reg_div.S - 0x209 in reg_u_sub.S - 0x210 in reg_u_sub.S - 0x211 in reg_u_sub.S - 0x212 in reg_u_sub.S - 0x213 in wm_sqrt.S - 0x214 in wm_sqrt.S - 0x215 in wm_sqrt.S - 0x216 in reg_round.S - 0x217 in reg_round.S - 0x218 in reg_round.S - */ - -void -exception(int n) -{ - int i, int_type; - - int_type = 0; /* Needed only to stop compiler warnings */ - if (n & EX_INTERNAL) { - int_type = n - EX_INTERNAL; - n = EX_INTERNAL; - /* Set lots of exception bits! */ - status_word |= (SW_Exc_Mask | SW_Summary | FPU_BUSY); - } else { - /* Extract only the bits which we use to set the status word */ - n &= (SW_Exc_Mask); - /* Set the corresponding exception bit */ - status_word |= n; - if (status_word & ~control_word & CW_Exceptions) - status_word |= SW_Summary; - if (n & (SW_Stack_Fault | EX_Precision)) { - if (!(n & SW_C1)) - /* This bit distinguishes over- from underflow - * for a stack fault, and roundup from - * round-down for precision loss. */ - status_word &= ~SW_C1; - } - } - - REENTRANT_CHECK(OFF); - if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) { -#ifdef PRINT_MESSAGES - /* My message from the sponsor */ - printf(FPU_VERSION " " __DATE__ " (C) W. Metzenthen.\n"); -#endif /* PRINT_MESSAGES */ - - /* Get a name string for error reporting */ - for (i = 0; exception_names[i].type; i++) - if ((exception_names[i].type & n) == exception_names[i].type) - break; - - if (exception_names[i].type) { -#ifdef PRINT_MESSAGES - printf("FP Exception: %s!\n", exception_names[i].name); -#endif /* PRINT_MESSAGES */ - } else - printf("FP emulator: Unknown Exception: 0x%04x!\n", n); - - if (n == EX_INTERNAL) { - printf("FP emulator: Internal error type 0x%04x\n", int_type); - emu_printall(); - } -#ifdef PRINT_MESSAGES - else - emu_printall(); -#endif /* PRINT_MESSAGES */ - - /* The 80486 generates an interrupt on the next non-control - * FPU instruction. So we need some means of flagging it. We - * use the ES (Error Summary) bit for this, assuming that this - * is the way a real FPU does it (until I can check it out), - * if not, then some method such as the following kludge might - * be needed. */ -/* regs[0].tag |= TW_FPU_Interrupt; */ - } - REENTRANT_CHECK(ON); - -#ifdef __DEBUG__ - math_abort(SIGFPE); -#endif /* __DEBUG__ */ - -} - - -/* Real operation attempted on two operands, one a NaN */ -void -real_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest) -{ - FPU_REG *x; - int signalling; - - x = a; - if (a->tag == TW_NaN) { - if (b->tag == TW_NaN) { - signalling = !(a->sigh & b->sigh & 0x40000000); - /* find the "larger" */ - if (*(long long *) &(a->sigl) < *(long long *) &(b->sigl)) - x = b; - } else { - /* return the quiet version of the NaN in a */ - signalling = !(a->sigh & 0x40000000); - } - } else -#ifdef PARANOID - if (b->tag == TW_NaN) -#endif /* PARANOID */ - { - signalling = !(b->sigh & 0x40000000); - x = b; - } -#ifdef PARANOID - else { - signalling = 0; - EXCEPTION(EX_INTERNAL | 0x113); - x = &CONST_QNaN; - } -#endif /* PARANOID */ - - if (!signalling) { - if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ - x = &CONST_QNaN; - reg_move(x, dest); - return; - } - if (control_word & CW_Invalid) { - /* The masked response */ - if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */ - x = &CONST_QNaN; - reg_move(x, dest); - /* ensure a Quiet NaN */ - dest->sigh |= 0x40000000; - } - EXCEPTION(EX_Invalid); - - return; -} -/* Invalid arith operation on Valid registers */ -void -arith_invalid(FPU_REG * dest) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, dest); - } - EXCEPTION(EX_Invalid); - - return; - -} - - -/* Divide a finite number by zero */ -void -divide_by_zero(int sign, FPU_REG * dest) -{ - - if (control_word & CW_ZeroDiv) { - /* The masked response */ - reg_move(&CONST_INF, dest); - dest->sign = (unsigned char) sign; - } - EXCEPTION(EX_ZeroDiv); - - return; - -} - - -/* This may be called often, so keep it lean */ -void -set_precision_flag_up(void) -{ - if (control_word & CW_Precision) - status_word |= (SW_Precision | SW_C1); /* The masked response */ - else - exception(EX_Precision | SW_C1); - -} - - -/* This may be called often, so keep it lean */ -void -set_precision_flag_down(void) -{ - if (control_word & CW_Precision) { /* The masked response */ - status_word &= ~SW_C1; - status_word |= SW_Precision; - } else - exception(EX_Precision); -} - - -int -denormal_operand(void) -{ - if (control_word & CW_Denormal) { /* The masked response */ - status_word |= SW_Denorm_Op; - return 0; - } else { - exception(EX_Denormal); - return 1; - } -} - - -void -arith_overflow(FPU_REG * dest) -{ - - if (control_word & CW_Overflow) { - char sign; - /* The masked response */ -/* **** The response here depends upon the rounding mode */ - sign = dest->sign; - reg_move(&CONST_INF, dest); - dest->sign = sign; - } else { - /* Subtract the magic number from the exponent */ - dest->exp -= (3 * (1 << 13)); - } - - /* By definition, precision is lost. It appears that the roundup bit - * (C1) is also set by convention. */ - EXCEPTION(EX_Overflow | EX_Precision | SW_C1); - - return; - -} - - -void -arith_underflow(FPU_REG * dest) -{ - - if (control_word & CW_Underflow) { - /* The masked response */ - if (dest->exp <= EXP_UNDER - 63) - reg_move(&CONST_Z, dest); - } else { - /* Add the magic number to the exponent */ - dest->exp += (3 * (1 << 13)); - } - - EXCEPTION(EX_Underflow); - - return; -} - - -void -stack_overflow(void) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - top--; - reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0)); - } - EXCEPTION(EX_StackOver); - - return; - -} - - -void -stack_underflow(void) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, FPU_st0_ptr); - } - EXCEPTION(EX_StackUnder); - - return; - -} - - -void -stack_underflow_i(int i) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, &(st(i))); - } - EXCEPTION(EX_StackUnder); - - return; - -} - - -void -stack_underflow_pop(int i) -{ - - if (control_word & CW_Invalid) { - /* The masked response */ - reg_move(&CONST_QNaN, &(st(i))); - pop(); - } - EXCEPTION(EX_StackUnder); - - return; - -} diff --git a/sys/platform/pc32/gnu/fpemul/exception.h b/sys/platform/pc32/gnu/fpemul/exception.h deleted file mode 100644 index 0ba368e076..0000000000 --- a/sys/platform/pc32/gnu/fpemul/exception.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * exception.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/exception.h,v 1.9 1999/08/28 00:42:49 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/exception.h,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - * - */ - -#ifndef _EXCEPTION_H_ -#define _EXCEPTION_H_ - - -#ifdef LOCORE -#define Const_(x) $/**/x -#else -#define Const_(x) x -#endif - -#ifndef SW_C1 -#include "fpu_emu.h" -#endif /* SW_C1 */ - -#define FPU_BUSY Const_(0x8000) /* FPU busy bit (8087 compatibility) */ -#define EX_ErrorSummary Const_(0x0080) /* Error summary status */ -/* Special exceptions: */ -#define EX_INTERNAL Const_(0x8000) /* Internal error in wm-FPU-emu */ -#define EX_StackOver Const_(0x0041|SW_C1) /* stack overflow */ -#define EX_StackUnder Const_(0x0041) /* stack underflow */ -/* Exception flags: */ -#define EX_Precision Const_(0x0020) /* loss of precision */ -#define EX_Underflow Const_(0x0010) /* underflow */ -#define EX_Overflow Const_(0x0008) /* overflow */ -#define EX_ZeroDiv Const_(0x0004) /* divide by zero */ -#define EX_Denormal Const_(0x0002) /* denormalized operand */ -#define EX_Invalid Const_(0x0001) /* invalid operation */ - - -#ifndef LOCORE - -#ifdef DEBUG -#define EXCEPTION(x) \ - do { \ - printf("exception in %s at line %d\n", __FILE__, __LINE__); \ - exception(x); \ - } while (0) -#else -#define EXCEPTION(x) exception(x) -#endif - -#endif /* LOCORE */ - -#endif /* _EXCEPTION_H_ */ diff --git a/sys/platform/pc32/gnu/fpemul/fpu_arith.c b/sys/platform/pc32/gnu/fpemul/fpu_arith.c deleted file mode 100644 index b9854a50b9..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_arith.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * fpu_arith.c - * - * Code to implement the FPU register/register arithmetic instructions - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_arith.c,v 1.9 1999/08/28 00:42:49 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_arith.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - - - -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" - - -void -fadd__() -{ - /* fadd st,st(i) */ - reg_add(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fmul__() -{ - /* fmul st,st(i) */ - reg_mul(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - - -void -fsub__() -{ - /* fsub st,st(i) */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fsubr_() -{ - /* fsubr st,st(i) */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word); -} - - -void -fdiv__() -{ - /* fdiv st,st(i) */ - reg_div(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); -} - - -void -fdivr_() -{ - /* fdivr st,st(i) */ - reg_div(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word); -} - - - -void -fadd_i() -{ - /* fadd st(i),st */ - reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fmul_i() -{ - /* fmul st(i),st */ - reg_mul(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - -void -fsubri() -{ - /* fsubr st(i),st */ - /* This is the sense of the 80486 manual reg_sub(&st(FPU_rm), - * FPU_st0_ptr, &st(FPU_rm), control_word); */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fsub_i() -{ - /* fsub st(i),st */ - /* This is the sense of the 80486 manual reg_sub(FPU_st0_ptr, - * &st(FPU_rm), &st(FPU_rm), control_word); */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - -void -fdivri() -{ - /* fdivr st(i),st */ - reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); -} - - -void -fdiv_i() -{ - /* fdiv st(i),st */ - reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); -} - - - -void -faddp_() -{ - /* faddp st(i),st */ - reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fmulp_() -{ - /* fmulp st(i),st */ - reg_mul(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} - - - -void -fsubrp() -{ - /* fsubrp st(i),st */ - /* This is the sense of the 80486 manual reg_sub(&st(FPU_rm), - * FPU_st0_ptr, &st(FPU_rm), control_word); */ - reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fsubp_() -{ - /* fsubp st(i),st */ - /* This is the sense of the 80486 manual reg_sub(FPU_st0_ptr, - * &st(FPU_rm), &st(FPU_rm), control_word); */ - reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} - - -void -fdivrp() -{ - /* fdivrp st(i),st */ - reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); - pop(); -} - - -void -fdivp_() -{ - /* fdivp st(i),st */ - reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); - pop(); -} diff --git a/sys/platform/pc32/gnu/fpemul/fpu_asm.h b/sys/platform/pc32/gnu/fpemul/fpu_asm.h deleted file mode 100644 index b28413e384..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_asm.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * fpu_asm.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_asm.h,v 1.8 1999/08/28 00:42:50 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_asm.h,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#ifndef _FPU_ASM_H_ -#define _FPU_ASM_H_ - -#include -#include "fpu_emu.h" - -#define EXCEPTION exception - - -#define PARAM1 8(%ebp) -#define PARAM2 12(%ebp) -#define PARAM3 16(%ebp) -#define PARAM4 20(%ebp) - -#define SIGL_OFFSET 8 -#define SIGN(x) (x) -#define TAG(x) 1(x) -#define EXP(x) 4(x) -#define SIG(x) SIGL_OFFSET/**/(x) -#define SIGL(x) SIGL_OFFSET/**/(x) -#define SIGH(x) 12(x) - -#endif /* _FPU_ASM_H_ */ diff --git a/sys/platform/pc32/gnu/fpemul/fpu_aux.c b/sys/platform/pc32/gnu/fpemul/fpu_aux.c deleted file mode 100644 index 9e929569c3..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_aux.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * fpu_aux.c - * - * Code to implement some of the FPU auxiliary instructions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_aux.c,v 1.11 1999/10/12 02:23:14 msmith Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_aux.c,v 1.4 2005/01/06 08:33:11 asmodai Exp $ - * - */ - - -#include -#ifdef DEBUG -#include /* for printf() in EXCEPTION() */ -#endif -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" - - -static void -fclex(void) -{ - status_word &= ~(SW_Backward | SW_Summary | SW_Stack_Fault | SW_Precision | - SW_Underflow | SW_Overflow | SW_Zero_Div | SW_Denorm_Op | - SW_Invalid); - FPU_entry_eip = ip_offset; /* We want no net effect */ -} -/* Needs to be externally visible */ -void -finit() -{ - int r; - control_word = 0x037f; - status_word = 0; - top = 0; /* We don't keep top in the status word - * internally. */ - for (r = 0; r < 8; r++) { - regs[r].tag = TW_Empty; - } - FPU_entry_eip = ip_offset = 0; -} - -static FUNC finit_table[] = { - Un_impl, Un_impl, fclex, finit, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -finit_() -{ - (finit_table[FPU_rm]) (); -} - - -static void -fstsw_ax(void) -{ - - status_word &= ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - - *(short *) &FPU_EAX = status_word; - -} - -static FUNC fstsw_table[] = { - fstsw_ax, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -fstsw_() -{ - (fstsw_table[FPU_rm]) (); -} - - - -static void -fnop(void) -{ -} - -static FUNC fp_nop_table[] = { - fnop, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl, Un_impl -}; - -void -fp_nop() -{ - (fp_nop_table[FPU_rm]) (); -} - - -void -fld_i_() -{ - FPU_REG *st_new_ptr; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - /* fld st(i) */ - if (NOT_EMPTY(FPU_rm)) { - reg_move(&st(FPU_rm), st_new_ptr); - push(); - } else { - if (control_word & EX_Invalid) { - /* The masked response */ - push(); - stack_underflow(); - } else - EXCEPTION(EX_StackUnder); - } - -} - - -void -fxch_i() -{ - /* fxch st(i) */ - FPU_REG t; - FPU_REG *sti_ptr = &st(FPU_rm); - - if (FPU_st0_tag == TW_Empty) { - if (sti_ptr->tag == TW_Empty) { - stack_underflow(); - stack_underflow_i(FPU_rm); - return; - } - reg_move(sti_ptr, FPU_st0_ptr); - stack_underflow_i(FPU_rm); - return; - } - if (sti_ptr->tag == TW_Empty) { - reg_move(FPU_st0_ptr, sti_ptr); - stack_underflow(); - return; - } - reg_move(FPU_st0_ptr, &t); - reg_move(sti_ptr, FPU_st0_ptr); - reg_move(&t, sti_ptr); -} - - -void -ffree_() -{ - /* ffree st(i) */ - st(FPU_rm).tag = TW_Empty; -} - - -void -ffreep() -{ - /* ffree st(i) + pop - unofficial code */ - st(FPU_rm).tag = TW_Empty; - pop(); -} - - -void -fst_i_() -{ - /* fst st(i) */ - reg_move(FPU_st0_ptr, &st(FPU_rm)); -} - - -void -fstp_i() -{ - /* fstp st(i) */ - reg_move(FPU_st0_ptr, &st(FPU_rm)); - pop(); -} diff --git a/sys/platform/pc32/gnu/fpemul/fpu_emu.h b/sys/platform/pc32/gnu/fpemul/fpu_emu.h deleted file mode 100644 index 4b50a0f3af..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_emu.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * fpu_emu.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_emu.h,v 1.7 1999/08/28 00:42:50 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_emu.h,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -#ifndef _FPU_EMU_H_ -#define _FPU_EMU_H_ - -/* - * Define DENORM_OPERAND to make the emulator detect denormals - * and use the denormal flag of the status word. Note: this only - * affects the flag and corresponding interrupt, the emulator - * will always generate denormals and operate upon them as required. - */ -#define DENORM_OPERAND - -/* - * Define PECULIAR_486 to get a closer approximation to 80486 behaviour, - * rather than behaviour which appears to be cleaner. - * This is a matter of opinion: for all I know, the 80486 may simply - * be complying with the IEEE spec. Maybe one day I'll get to see the - * spec... - */ -#define PECULIAR_486 - -#ifdef LOCORE -#include "fpu_asm.h" -#define Const(x) $/**/x -#else -#define Const(x) x -#endif - -#define EXP_BIAS Const(0) -#define EXP_OVER Const(0x4000) /* smallest invalid large exponent */ -#define EXP_UNDER Const(-0x3fff) /* largest invalid small exponent */ - -#define SIGN_POS Const(0) -#define SIGN_NEG Const(1) - -/* Keep the order TW_Valid, TW_Zero, TW_Denormal */ -#define TW_Valid Const(0)/* valid */ -#define TW_Zero Const(1)/* zero */ -/* The following fold to 2 (Special) in the Tag Word */ -#define TW_Denormal Const(4)/* De-normal */ -#define TW_Infinity Const(5)/* + or - infinity */ -#define TW_NaN Const(6)/* Not a Number */ - -#define TW_Empty Const(7)/* empty */ - - /* #define TW_FPU_Interrupt Const(0x80) *//* Signals an interrupt */ - - -#ifndef LOCORE - -#include -#include "math_emu.h" - -#ifdef PARANOID -extern char emulating; -#define REENTRANT_CHECK(state) emulating = (state) -#define ON 1 -#define OFF 0 -#else -#define REENTRANT_CHECK(state) -#endif /* PARANOID */ - -typedef void (*FUNC) (void); -typedef struct fpu_reg FPU_REG; - -#define st(x) ( regs[((top+x) &7 )] ) - -#define STACK_OVERFLOW (st_new_ptr = &st(-1), st_new_ptr->tag != TW_Empty) -#define NOT_EMPTY(i) (st(i).tag != TW_Empty) -#define NOT_EMPTY_0 (FPU_st0_tag ^ TW_Empty) - -extern unsigned char FPU_rm; - -extern char FPU_st0_tag; -extern FPU_REG *FPU_st0_ptr; - -extern void *FPU_data_address; - -extern FPU_REG FPU_loaded_data; - -#define pop() { FPU_st0_ptr->tag = TW_Empty; top++; } - -/* push() does not affect the tags */ -#define push() { top--; FPU_st0_ptr = st_new_ptr; } - - -#define reg_move(x, y) { \ - *(short *)&((y)->sign) = *(short *)&((x)->sign); \ - *(long *)&((y)->exp) = *(long *)&((x)->exp); \ - *(long long *)&((y)->sigl) = *(long long *)&((x)->sigl); } - - -/*----- Prototypes for functions written in assembler -----*/ -/* extern void reg_move(FPU_REG *a, FPU_REG *b); */ - -extern void mul64(long long *a, long long *b, long long *result); -extern void poly_div2(long long *x); -extern void poly_div4(long long *x); -extern void poly_div16(long long *x); -extern void -polynomial(unsigned accum[], unsigned x[], - unsigned short terms[][4], int n); - extern void normalize(FPU_REG * x); - extern void normalize_nuo(FPU_REG * x); - extern void reg_div(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_sub(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_mul(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_div(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void reg_u_add(FPU_REG * arg1, FPU_REG * arg2, FPU_REG * answ, - unsigned int control_w); - extern void wm_sqrt(FPU_REG * n, unsigned int control_w); - extern unsigned shrx(void *l, unsigned x); - extern unsigned shrxs(void *v, unsigned x); - extern unsigned long div_small(unsigned long long *x, unsigned long y); - extern void round_reg(FPU_REG * arg, unsigned int extent, - unsigned int control_w); - -#ifndef MAKING_PROTO -#include "fpu_proto.h" -#endif - -#endif /* LOCORE */ - -#endif /* _FPU_EMU_H_ */ diff --git a/sys/platform/pc32/gnu/fpemul/fpu_entry.c b/sys/platform/pc32/gnu/fpemul/fpu_entry.c deleted file mode 100644 index b2f0b3eb29..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_entry.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * fpu_entry.c - * - * The entry function for wm-FPU-emu - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_entry.c,v 1.23 1999/10/12 02:23:14 msmith Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_entry.c,v 1.5 2004/12/08 20:36:39 joerg Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------+ - | math_emulate() is the sole entry point for wm-FPU-emu | - +---------------------------------------------------------------------------*/ - -#include "opt_depricated.h" -#ifndef I_WANT_DEPRICATED_STUFF -#error "Add options I_WANT_DEPRICATED_STUFF to your kernel config and send a mail to kernel@" -#endif - -#include -#include -#include -#include - -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" - - -#define __BAD__ Un_impl /* Not implemented */ - -#define FPU_LOOKAHEAD 1 /* For performance boost */ - -#if FPU_LOOKAHEAD != 0 /* I think thet we have to limit the */ -#define LOOKAHEAD_LIMIT 7 /* Max number of lookahead instructions*/ -#endif /* Or else a prog consisting of a million */ - /* fnops will spend all its time in kernel*/ - -#ifndef NO_UNDOC_CODE /* Un-documented FPU op-codes supported by - * default. */ - -/* WARNING: These codes are not documented by Intel in their 80486 manual - and may not work on FPU clones or later Intel FPUs. */ - -/* Changes to support the un-doc codes provided by Linus Torvalds. */ - -#define _d9_d8_ fstp_i /* unofficial code (19) */ -#define _dc_d0_ fcom_st /* unofficial code (14) */ -#define _dc_d8_ fcompst /* unofficial code (1c) */ -#define _dd_c8_ fxch_i /* unofficial code (0d) */ -#define _de_d0_ fcompst /* unofficial code (16) */ -#define _df_c0_ ffreep /* unofficial code (07) ffree + pop */ -#define _df_c8_ fxch_i /* unofficial code (0f) */ -#define _df_d0_ fstp_i /* unofficial code (17) */ -#define _df_d8_ fstp_i /* unofficial code (1f) */ - -static FUNC st_instr_table[64] = { - fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, _df_c0_, - fmul__, fxch_i, __BAD__, __BAD__, fmul_i, _dd_c8_, fmulp_, _df_c8_, - fcom_st, fp_nop, __BAD__, __BAD__, _dc_d0_, fst_i_, _de_d0_, _df_d0_, - fcompst, _d9_d8_, __BAD__, __BAD__, _dc_d8_, fstp_i, fcompp, _df_d8_, - fsub__, fp_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, - fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, - fdiv__, trig_a, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, - fdivr_, trig_b, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, -}; -#else /* Support only documented FPU op-codes */ - -static FUNC st_instr_table[64] = { - fadd__, fld_i_, __BAD__, __BAD__, fadd_i, ffree_, faddp_, __BAD__, - fmul__, fxch_i, __BAD__, __BAD__, fmul_i, __BAD__, fmulp_, __BAD__, - fcom_st, fp_nop, __BAD__, __BAD__, __BAD__, fst_i_, __BAD__, __BAD__, - fcompst, __BAD__, __BAD__, __BAD__, __BAD__, fstp_i, fcompp, __BAD__, - fsub__, fp_etc, __BAD__, finit_, fsubri, fucom_, fsubrp, fstsw_, - fsubr_, fconst, fucompp, __BAD__, fsub_i, fucomp, fsubp_, __BAD__, - fdiv__, trig_a, __BAD__, __BAD__, fdivri, __BAD__, fdivrp, __BAD__, - fdivr_, trig_b, __BAD__, __BAD__, fdiv_i, __BAD__, fdivp_, __BAD__, -}; -#endif /* NO_UNDOC_CODE */ - - -#define _NONE_ 0 /* Take no special action */ -#define _REG0_ 1 /* Need to check for not empty st(0) */ -#define _REGI_ 2 /* Need to check for not empty st(0) and - * st(rm) */ -#define _REGi_ 0 /* Uses st(rm) */ -#define _PUSH_ 3 /* Need to check for space to push onto stack */ -#define _null_ 4 /* Function illegal or not implemented */ -#define _REGIi 5 /* Uses st(0) and st(rm), result to st(rm) */ -#define _REGIp 6 /* Uses st(0) and st(rm), result to st(rm) - * then pop */ -#define _REGIc 0 /* Compare st(0) and st(rm) */ -#define _REGIn 0 /* Uses st(0) and st(rm), but handle checks - * later */ - -#ifndef NO_UNDOC_CODE - -/* Un-documented FPU op-codes supported by default. (see above) */ - -static unsigned char type_table[64] = { - _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _REGi_, - _REGI_, _REGIn, _null_, _null_, _REGIi, _REGI_, _REGIp, _REGI_, - _REGIc, _NONE_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, - _REGIc, _REG0_, _null_, _null_, _REGIc, _REG0_, _REGIc, _REG0_, - _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, - _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ -}; -#else /* Support only documented FPU op-codes */ - -static unsigned char type_table[64] = { - _REGI_, _NONE_, _null_, _null_, _REGIi, _REGi_, _REGIp, _null_, - _REGI_, _REGIn, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGIc, _NONE_, _null_, _null_, _null_, _REG0_, _null_, _null_, - _REGIc, _null_, _null_, _null_, _null_, _REG0_, _REGIc, _null_, - _REGI_, _NONE_, _null_, _NONE_, _REGIi, _REGIc, _REGIp, _NONE_, - _REGI_, _NONE_, _REGIc, _null_, _REGIi, _REGIc, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_, - _REGI_, _NONE_, _null_, _null_, _REGIi, _null_, _REGIp, _null_ -}; -#endif /* NO_UNDOC_CODE */ - -/* Be careful when using any of these global variables... - they might change if swapping is triggered */ -unsigned char FPU_rm; -char FPU_st0_tag; -FPU_REG *FPU_st0_ptr; - -#ifdef PARANOID -char emulating = 0; -#endif /* PARANOID */ - -#define bswapw(x) __asm__("xchgb %%al,%%ah":"=a" (x):"0" ((short)x)) -#define math_abort(signo) \ - FPU_EIP = FPU_ORIG_EIP;REENTRANT_CHECK(OFF);return(signo); - -static int -math_emulate(struct trapframe * tframe) -{ - - unsigned char FPU_modrm; - unsigned short code; -#ifdef LOOKAHEAD_LIMIT - int lookahead_limit = LOOKAHEAD_LIMIT; -#endif -#ifdef PARANOID - if (emulating) { - printf("ERROR: wm-FPU-emu is not RE-ENTRANT!\n"); - } - REENTRANT_CHECK(ON); -#endif /* PARANOID */ - - KKASSERT(curproc); - if ((((struct pcb *) curproc->p_addr)->pcb_flags & FP_SOFTFP) == 0) { - finit(); - control_word = __INITIAL_NPXCW__; - ((struct pcb *) curproc->p_addr)->pcb_flags |= FP_SOFTFP; - } - FPU_info = tframe; - FPU_ORIG_EIP = FPU_EIP; /* --pink-- */ - - if (FPU_CS != 0x001f) { - printf("math_emulate: %x : %x\n", FPU_CS, FPU_EIP); - panic("FPU emulation in kernel"); - } -#ifdef notyet - /* We cannot handle emulation in v86-mode */ - if (FPU_EFLAGS & 0x00020000) { - FPU_ORIG_EIP = FPU_EIP; - math_abort(FPU_info, SIGILL); - } -#endif - - FPU_lookahead = FPU_LOOKAHEAD; - if (curproc->p_flag & P_TRACED) - FPU_lookahead = 0; - -do_another_FPU_instruction: - - REENTRANT_CHECK(OFF); - code = fuword((u_int *) FPU_EIP); - REENTRANT_CHECK(ON); - if ((code & 0xff) == 0x9b) { /* fwait */ - if (status_word & SW_Summary) - goto do_the_FPU_interrupt; - else { - FPU_EIP++; - goto FPU_instruction_done; - } - } - if (status_word & SW_Summary) { - /* Ignore the error for now if the current instruction is a - * no-wait control instruction */ - /* The 80486 manual contradicts itself on this topic, so I use - * the following list of such instructions until I can check - * on a real 80486: fninit, fnstenv, fnsave, fnstsw, fnstenv, - * fnclex. */ - if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, - * fnstsw */ - (((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, - * fnstenv, fnstsw */ - ((code & 0xc000) != 0xc000))))) { - /* This is a guess about what a real FPU might do to - * this bit: */ -/* status_word &= ~SW_Summary; ****/ - - /* We need to simulate the action of the kernel to FPU - * interrupts here. Currently, the "real FPU" part of - * the kernel (0.99.10) clears the exception flags, - * sets the registers to empty, and passes information - * back to the interrupted process via the cs selector - * and operand selector, so we do the same. */ - do_the_FPU_interrupt: - cs_selector &= 0xffff0000; - cs_selector |= (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift); - operand_selector = tag_word(); - status_word = 0; - top = 0; - { - int r; - for (r = 0; r < 8; r++) { - regs[r].tag = TW_Empty; - } - } - REENTRANT_CHECK(OFF); - math_abort(SIGFPE); - } - } - FPU_entry_eip = FPU_ORIG_EIP = FPU_EIP; - - if ((code & 0xff) == 0x66) { /* size prefix */ - FPU_EIP++; - REENTRANT_CHECK(OFF); - code = fuword((u_int *) FPU_EIP); - REENTRANT_CHECK(ON); - } - FPU_EIP += 2; - - FPU_modrm = code >> 8; - FPU_rm = FPU_modrm & 7; - - if (FPU_modrm < 0300) { - /* All of these instructions use the mod/rm byte to get a data - * address */ - get_address(FPU_modrm); - if (!(code & 1)) { - unsigned short status1 = status_word; - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - - /* Stack underflow has priority */ - if (NOT_EMPTY_0) { - switch ((code >> 1) & 3) { - case 0: - reg_load_single(); - break; - case 1: - reg_load_int32(); - break; - case 2: - reg_load_double(); - break; - case 3: - reg_load_int16(); - break; - } - - /* No more access to user memory, it is safe - * to use static data now */ - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - - /* NaN operands have the next priority. */ - /* We have to delay looking at st(0) until - * after loading the data, because that data - * might contain an SNaN */ - if ((FPU_st0_tag == TW_NaN) || - (FPU_loaded_data.tag == TW_NaN)) { - /* Restore the status word; we might - * have loaded a denormal. */ - status_word = status1; - if ((FPU_modrm & 0x30) == 0x10) { - /* fcom or fcomp */ - EXCEPTION(EX_Invalid); - setcc(SW_C3 | SW_C2 | SW_C0); - if (FPU_modrm & 0x08) - pop(); /* fcomp, so we pop. */ - } else - real_2op_NaN(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr); - goto reg_mem_instr_done; - } - switch ((FPU_modrm >> 3) & 7) { - case 0: /* fadd */ - reg_add(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 1: /* fmul */ - reg_mul(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 2: /* fcom */ - compare_st_data(); - break; - case 3: /* fcomp */ - compare_st_data(); - pop(); - break; - case 4: /* fsub */ - reg_sub(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 5: /* fsubr */ - reg_sub(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr, control_word); - break; - case 6: /* fdiv */ - reg_div(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr, control_word); - break; - case 7: /* fdivr */ - if (FPU_st0_tag == TW_Zero) - status_word = status1; /* Undo any denorm tag, - * zero-divide has - * priority. */ - reg_div(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr, control_word); - break; - } - } else { - if ((FPU_modrm & 0x30) == 0x10) { - /* The instruction is fcom or fcomp */ - EXCEPTION(EX_StackUnder); - setcc(SW_C3 | SW_C2 | SW_C0); - if (FPU_modrm & 0x08) - pop(); /* fcomp, Empty or not, - * we pop. */ - } else - stack_underflow(); - } - } else { - load_store_instr(((FPU_modrm & 0x38) | (code & 6)) >> 1); - } - -reg_mem_instr_done: - - data_operand_offset = (intptr_t) (void *) FPU_data_address; - } else { - /* None of these instructions access user memory */ - unsigned char instr_index = (FPU_modrm & 0x38) | (code & 7); - - FPU_st0_ptr = &st(0); - FPU_st0_tag = FPU_st0_ptr->tag; - switch (type_table[(int) instr_index]) { - case _NONE_: /* also _REGIc: _REGIn */ - break; - case _REG0_: - if (!NOT_EMPTY_0) { - stack_underflow(); - goto FPU_instruction_done; - } - break; - case _REGIi: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow_i(FPU_rm); - goto FPU_instruction_done; - } - break; - case _REGIp: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow_i(FPU_rm); - pop(); - goto FPU_instruction_done; - } - break; - case _REGI_: - if (!NOT_EMPTY_0 || !NOT_EMPTY(FPU_rm)) { - stack_underflow(); - goto FPU_instruction_done; - } - break; - case _PUSH_: /* Only used by the fld st(i) instruction */ - break; - case _null_: - Un_impl(); - goto FPU_instruction_done; - default: - EXCEPTION(EX_INTERNAL | 0x111); - goto FPU_instruction_done; - } - (*st_instr_table[(int) instr_index]) (); - } - -FPU_instruction_done: - - ip_offset = FPU_entry_eip; - bswapw(code); - *(1 + (unsigned short *) &cs_selector) = code & 0x7ff; - -#ifdef DEBUG - REENTRANT_CHECK(OFF); - emu_printall(); - REENTRANT_CHECK(ON); -#endif /* DEBUG */ -#ifdef LOOKAHEAD_LIMIT -if (--lookahead_limit) -#endif - if (FPU_lookahead) { - unsigned char next; - - /* (This test should generate no machine code) */ - while (1) { - REENTRANT_CHECK(OFF); - next = fubyte((u_char *) FPU_EIP); - REENTRANT_CHECK(ON); - if (((next & 0xf8) == 0xd8) || (next == 0x9b)) { /* fwait */ - goto do_another_FPU_instruction; - } else - if (next == 0x66) { /* size prefix */ - REENTRANT_CHECK(OFF); - next = fubyte((u_char *) (FPU_EIP + 1)); - REENTRANT_CHECK(ON); - if ((next & 0xf8) == 0xd8) { - FPU_EIP++; - goto do_another_FPU_instruction; - } - } - break; - } - } - REENTRANT_CHECK(OFF); - return (0); /* --pink-- */ -} - -static int -gnufpu_modevent(module_t mod, int type, void *unused) -{ - switch (type) { - case MOD_LOAD: - if (pmath_emulate) { - printf("Another Math emulator already present\n"); - return EACCES; - } - pmath_emulate = math_emulate; - if (bootverbose) - printf("GPL Math emulator present\n"); - break; - case MOD_UNLOAD: - if (pmath_emulate != math_emulate) { - printf("Cannot unload another math emulator\n"); - return EACCES; - } - pmath_emulate = 0; - if (bootverbose) - printf("GPL Math emulator unloaded\n"); - break; - default: - break; - } - return 0; - -} -static moduledata_t gnufpumod = { - "gnufpu", - gnufpu_modevent, - 0 -}; -DECLARE_MODULE(gnufpu, gnufpumod, SI_SUB_DRIVERS, SI_ORDER_ANY); diff --git a/sys/platform/pc32/gnu/fpemul/fpu_etc.c b/sys/platform/pc32/gnu/fpemul/fpu_etc.c deleted file mode 100644 index 8218bebf36..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_etc.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * fpu_etc.c - * - * Implement a few FPU instructions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_etc.c,v 1.8 1999/08/28 00:42:51 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_etc.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include -#ifdef DEBUG -#include /* for printf() in EXCEPTION() */ -#endif -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" - - -static void -fchs(void) -{ - if (NOT_EMPTY_0) { - FPU_st0_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - status_word &= ~SW_C1; - } else - stack_underflow(); -} - -static void -fabs(void) -{ - if (FPU_st0_tag ^ TW_Empty) { - FPU_st0_ptr->sign = SIGN_POS; - status_word &= ~SW_C1; - } else - stack_underflow(); -} - - -static void -ftst_(void) -{ - switch (FPU_st0_tag) { - case TW_Zero: - setcc(SW_C3); - break; - case TW_Valid: - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - break; - case TW_NaN: - setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ - EXCEPTION(EX_Invalid); - break; - case TW_Infinity: - if (FPU_st0_ptr->sign == SIGN_POS) - setcc(0); - else - setcc(SW_C0); - EXCEPTION(EX_Invalid); - break; - case TW_Empty: - setcc(SW_C0 | SW_C2 | SW_C3); - EXCEPTION(EX_StackUnder); - break; - default: - setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ - EXCEPTION(EX_INTERNAL | 0x14); - break; - } -} - -static void -fxam(void) -{ - int c = 0; - switch (FPU_st0_tag) { - case TW_Empty: - c = SW_C3 | SW_C0; - break; - case TW_Zero: - c = SW_C3; - break; - case TW_Valid: - /* This will need to be changed if TW_Denormal is ever used. */ - if (FPU_st0_ptr->exp <= EXP_UNDER) - c = SW_C2 | SW_C3; /* Denormal */ - else - c = SW_C3; - break; - case TW_NaN: - c = SW_C0; - break; - case TW_Infinity: - c = SW_C2 | SW_C0; - break; - } - if (FPU_st0_ptr->sign == SIGN_NEG) - c |= SW_C1; - setcc(c); -} - -static FUNC fp_etc_table[] = { - fchs, fabs, Un_impl, Un_impl, ftst_, fxam, Un_impl, Un_impl -}; - -void -fp_etc() -{ - (fp_etc_table[FPU_rm]) (); -} diff --git a/sys/platform/pc32/gnu/fpemul/fpu_proto.h b/sys/platform/pc32/gnu/fpemul/fpu_proto.h deleted file mode 100644 index 10d1856c58..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_proto.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_proto.h,v 1.8 1999/08/28 00:42:51 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_proto.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - - -/* errors.c */ -extern void Un_impl(void); -extern void emu_printall(void); -extern void exception(int n); -extern void real_2op_NaN(FPU_REG * a, FPU_REG * b, FPU_REG * dest); -extern void arith_invalid(FPU_REG * dest); -extern void divide_by_zero(int sign, FPU_REG * dest); -extern void set_precision_flag_up(void); -extern void set_precision_flag_down(void); -extern int denormal_operand(void); -extern void arith_overflow(FPU_REG * dest); -extern void arith_underflow(FPU_REG * dest); -extern void stack_overflow(void); -extern void stack_underflow(void); -extern void stack_underflow_i(int i); -extern void stack_underflow_pop(int i); -/* fpu_arith.c */ -extern void fadd__(void); -extern void fmul__(void); -extern void fsub__(void); -extern void fsubr_(void); -extern void fdiv__(void); -extern void fdivr_(void); -extern void fadd_i(void); -extern void fmul_i(void); -extern void fsubri(void); -extern void fsub_i(void); -extern void fdivri(void); -extern void fdiv_i(void); -extern void faddp_(void); -extern void fmulp_(void); -extern void fsubrp(void); -extern void fsubp_(void); -extern void fdivrp(void); -extern void fdivp_(void); -/* fpu_aux.c */ -extern void finit(void); -extern void finit_(void); -extern void fstsw_(void); -extern void fp_nop(void); -extern void fld_i_(void); -extern void fxch_i(void); -extern void ffree_(void); -extern void ffreep(void); -extern void fst_i_(void); -extern void fstp_i(void); -/* fpu_entry.c */ -#if 0 -extern int math_emulate(struct trapframe * info); -#endif -/* fpu_etc.c */ -extern void fp_etc(void); -/* fpu_trig.c */ -extern void trig_a(void); -extern void trig_b(void); -/* get_address.c */ -extern void get_address(unsigned char FPU_modrm); -/* load_store.c */ -extern void load_store_instr(char type); -/* poly_2xm1.c */ -extern int poly_2xm1(FPU_REG * arg, FPU_REG * result); -/* poly_atan.c */ -extern void poly_atan(FPU_REG * arg); -/* poly_l2.c */ -extern void poly_l2(FPU_REG * arg, FPU_REG * result); -extern int poly_l2p1(FPU_REG * arg, FPU_REG * result); -/* poly_sin.c */ -extern void poly_sine(FPU_REG * arg, FPU_REG * result); -/* poly_tan.c */ -extern void poly_tan(FPU_REG * arg, FPU_REG * y_reg); -/* reg_add_sub.c */ -extern void reg_add(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w); -extern void reg_sub(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w); -/* reg_compare.c */ -extern int compare(FPU_REG * b); -extern int compare_st_data(void); -extern void fcom_st(void); -extern void fcompst(void); -extern void fcompp(void); -extern void fucom_(void); -extern void fucomp(void); -extern void fucompp(void); -/* reg_constant.c */ -extern void fconst(void); -/* reg_ld_str.c */ -extern void reg_load_extended(void); -extern void reg_load_double(void); -extern void reg_load_single(void); -extern void reg_load_int64(void); -extern void reg_load_int32(void); -extern void reg_load_int16(void); -extern void reg_load_bcd(void); -extern int reg_store_extended(void); -extern int reg_store_double(void); -extern int reg_store_single(void); -extern int reg_store_int64(void); -extern int reg_store_int32(void); -extern int reg_store_int16(void); -extern int reg_store_bcd(void); -extern int round_to_int(FPU_REG * r); -extern char *fldenv(void); -extern void frstor(void); -extern unsigned short tag_word(void); -extern char *fstenv(void); -extern void fsave(void); -/* reg_mul.c */ -extern void reg_mul(FPU_REG * a, FPU_REG * b, FPU_REG * dest, unsigned int control_w); diff --git a/sys/platform/pc32/gnu/fpemul/fpu_system.h b/sys/platform/pc32/gnu/fpemul/fpu_system.h deleted file mode 100644 index 65f38e866b..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_system.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * fpu_system.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_system.h,v 1.7.2.1 2001/08/15 01:23:49 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_system.h,v 1.3 2004/04/30 00:59:48 dillon Exp $ - * - */ - - -#ifndef _FPU_SYSTEM_H -#define _FPU_SYSTEM_H - -/* system dependent definitions */ - -/* -#include -#include -*/ - -#define I387 (*(union i387_union *)(&curthread->td_savefpu->sv_87)) -#define FPU_info (I387.soft.frame) - -#define FPU_CS (*(unsigned short *) &(FPU_info->tf_cs)) -#define FPU_DS (*(unsigned short *) &(FPU_info->tf_ds)) -#define FPU_EAX (FPU_info->tf_eax) -#define FPU_EFLAGS (FPU_info->tf_eflags) -#define FPU_EIP (FPU_info->tf_eip) -/*#define FPU_ORIG_EIP (FPU_info->___orig_eip) */ -/*#define FPU_ORIG_EIP (FPU_info->tf_isp)*/ -#define FPU_ORIG_EIP (I387.soft.orig_eip) - -#define FPU_lookahead (I387.soft.lookahead) -#define FPU_entry_eip (I387.soft.entry_eip) - -#define status_word (I387.soft.swd) -#define control_word (I387.soft.cwd) -#define regs (I387.soft.regs) -#define top (I387.soft.top) - -#define ip_offset (I387.soft.fip) -#define cs_selector (I387.soft.fcs) -#define data_operand_offset (I387.soft.foo) -#define operand_selector (I387.soft.fos) - -#endif diff --git a/sys/platform/pc32/gnu/fpemul/fpu_trig.c b/sys/platform/pc32/gnu/fpemul/fpu_trig.c deleted file mode 100644 index bcff7c95cb..0000000000 --- a/sys/platform/pc32/gnu/fpemul/fpu_trig.c +++ /dev/null @@ -1,1372 +0,0 @@ -/* - * fpu_trig.c - * - * Implementation of the FPU "transcendental" functions. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/fpu_trig.c,v 1.10 1999/08/28 00:42:52 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/fpu_trig.c,v 1.4 2005/01/06 08:33:11 asmodai Exp $ - * - */ - - -#include -#ifdef DEBUG -#include /* for printf() in EXCEPTION() */ -#endif -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "status_w.h" -#include "reg_constant.h" -#include "control_w.h" - -static void convert_l2reg(long *arg, FPU_REG * dest); - -static int -trig_arg(FPU_REG * X) -{ - FPU_REG tmp, quot; - int rv; - long long q; - int old_cw = control_word; - - control_word &= ~CW_RC; - control_word |= RC_CHOP; - - reg_move(X, "); - reg_div(", &CONST_PI2, ", FULL_PRECISION); - - reg_move(", &tmp); - round_to_int(&tmp); - if (tmp.sigh & 0x80000000) - return -1; /* |Arg| is >= 2^63 */ - tmp.exp = EXP_BIAS + 63; - q = *(long long *) &(tmp.sigl); - normalize(&tmp); - - reg_sub(", &tmp, X, FULL_PRECISION); - rv = q & 7; - - control_word = old_cw; - return rv;; -} - - -/* Convert a long to register */ -static void -convert_l2reg(long *arg, FPU_REG * dest) -{ - long num = *arg; - - if (num == 0) { - reg_move(&CONST_Z, dest); - return; - } - if (num > 0) - dest->sign = SIGN_POS; - else { - num = -num; - dest->sign = SIGN_NEG; - } - - dest->sigh = num; - dest->sigl = 0; - dest->exp = EXP_BIAS + 31; - dest->tag = TW_Valid; - normalize(dest); -} - - -static void -single_arg_error(void) -{ - switch (FPU_st0_tag) { - case TW_NaN: - if (!(FPU_st0_ptr->sigh & 0x40000000)) { /* Signaling ? */ - EXCEPTION(EX_Invalid); - /* Convert to a QNaN */ - FPU_st0_ptr->sigh |= 0x40000000; - } - break; /* return with a NaN in st(0) */ - case TW_Empty: - stack_underflow(); /* Puts a QNaN in st(0) */ - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x0112); -#endif /* PARANOID */ - } -} - - -/*---------------------------------------------------------------------------*/ - -static void -f2xm1(void) -{ - switch (FPU_st0_tag) { - case TW_Valid: - { - FPU_REG rv, tmp; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - /* poly_2xm1(x) requires 0 < x < 1. */ - if (poly_2xm1(FPU_st0_ptr, &rv)) - return; /* error */ - reg_mul(&rv, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - } else { -/* **** Should change poly_2xm1() to at least handle numbers near 0 */ - /* poly_2xm1(x) doesn't handle negative - * numbers. */ - /* So we compute (poly_2xm1(x+1)-1)/2, for -1 - * < x < 0 */ - reg_add(FPU_st0_ptr, &CONST_1, &tmp, FULL_PRECISION); - poly_2xm1(&tmp, &rv); - reg_mul(&rv, &tmp, &tmp, FULL_PRECISION); - reg_sub(&tmp, &CONST_1, FPU_st0_ptr, FULL_PRECISION); - FPU_st0_ptr->exp--; - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - } - return; - } - case TW_Zero: - return; - case TW_Infinity: - if (FPU_st0_ptr->sign == SIGN_NEG) { - /* -infinity gives -1 (p16-10) */ - reg_move(&CONST_1, FPU_st0_ptr); - FPU_st0_ptr->sign = SIGN_NEG; - } - return; - default: - single_arg_error(); - } -} - -static void -fptan(void) -{ - FPU_REG *st_new_ptr; - int q; - char arg_sign = FPU_st0_ptr->sign; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - switch (FPU_st0_tag) { - case TW_Valid: - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - FPU_st0_ptr->sign = SIGN_POS; - if ((q = trig_arg(FPU_st0_ptr)) != -1) { - if (q & 1) - reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - - poly_tan(FPU_st0_ptr, FPU_st0_ptr); - - FPU_st0_ptr->sign = (q & 1) ^ arg_sign; - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - - push(); - reg_move(&CONST_1, FPU_st0_ptr); - setcc(0); - } else { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } - break; - case TW_Infinity: - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - case TW_Zero: - push(); - reg_move(&CONST_1, FPU_st0_ptr); - setcc(0); - break; - default: - single_arg_error(); - break; - } -} - - -static void -fxtract(void) -{ - FPU_REG *st_new_ptr; - FPU_REG *st1_ptr = FPU_st0_ptr; /* anticipate */ - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - if (!(FPU_st0_tag ^ TW_Valid)) { - long e; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - push(); - reg_move(st1_ptr, FPU_st0_ptr); - FPU_st0_ptr->exp = EXP_BIAS; - e = st1_ptr->exp - EXP_BIAS; - convert_l2reg(&e, st1_ptr); - return; - } else - if (FPU_st0_tag == TW_Zero) { - char sign = FPU_st0_ptr->sign; - divide_by_zero(SIGN_NEG, FPU_st0_ptr); - push(); - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } else - if (FPU_st0_tag == TW_Infinity) { - char sign = FPU_st0_ptr->sign; - FPU_st0_ptr->sign = SIGN_POS; - push(); - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } else - if (FPU_st0_tag == TW_NaN) { - if (!(FPU_st0_ptr->sigh & 0x40000000)) { /* Signaling ? */ - EXCEPTION(EX_Invalid); - /* Convert to a QNaN */ - FPU_st0_ptr->sigh |= 0x40000000; - } - push(); - reg_move(st1_ptr, FPU_st0_ptr); - return; - } else - if (FPU_st0_tag == TW_Empty) { - /* Is this the correct - * behaviour? */ - if (control_word & EX_Invalid) { - stack_underflow(); - push(); - stack_underflow(); - } else - EXCEPTION(EX_StackUnder); - } -#ifdef PARANOID - else - EXCEPTION(EX_INTERNAL | 0x119); -#endif /* PARANOID */ -} - - -static void -fdecstp(void) -{ - top--; /* FPU_st0_ptr will be fixed in math_emulate() - * before the next instr */ -} - -static void -fincstp(void) -{ - top++; /* FPU_st0_ptr will be fixed in math_emulate() - * before the next instr */ -} - - -static void -fsqrt_(void) -{ - if (!(FPU_st0_tag ^ TW_Valid)) { - int expon; - - if (FPU_st0_ptr->sign == SIGN_NEG) { - arith_invalid(FPU_st0_ptr); /* sqrt(negative) is - * invalid */ - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - expon = FPU_st0_ptr->exp - EXP_BIAS; - FPU_st0_ptr->exp = EXP_BIAS + (expon & 1); /* make st(0) in [1.0 - * .. 4.0) */ - - wm_sqrt(FPU_st0_ptr, control_word); /* Do the computation */ - - FPU_st0_ptr->exp += expon >> 1; - FPU_st0_ptr->sign = SIGN_POS; - } else - if (FPU_st0_tag == TW_Zero) - return; - else - if (FPU_st0_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_NEG) - arith_invalid(FPU_st0_ptr); /* sqrt(-Infinity) is - * invalid */ - return; - } else { - single_arg_error(); - return; - } - -} - - -static void -frndint_(void) -{ - if (!(FPU_st0_tag ^ TW_Valid)) { - if (FPU_st0_ptr->exp > EXP_BIAS + 63) - return; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - round_to_int(FPU_st0_ptr); /* Fortunately, this can't - * overflow to 2^64 */ - FPU_st0_ptr->exp = EXP_BIAS + 63; - normalize(FPU_st0_ptr); - return; - } else - if ((FPU_st0_tag == TW_Zero) || (FPU_st0_tag == TW_Infinity)) - return; - else - single_arg_error(); -} - - -static void -fsin(void) -{ - char arg_sign = FPU_st0_ptr->sign; - - if (FPU_st0_tag == TW_Valid) { - int q; - FPU_st0_ptr->sign = SIGN_POS; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if ((q = trig_arg(FPU_st0_ptr)) != -1) { - FPU_REG rv; - - if (q & 1) - reg_sub(&CONST_1, FPU_st0_ptr, FPU_st0_ptr, FULL_PRECISION); - - poly_sine(FPU_st0_ptr, &rv); - - setcc(0); - if (q & 2) - rv.sign ^= SIGN_POS ^ SIGN_NEG; - rv.sign ^= arg_sign; - reg_move(&rv, FPU_st0_ptr); - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - - set_precision_flag_up(); /* We do not really know - * if up or down */ - - return; - } else { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } - } else - if (FPU_st0_tag == TW_Zero) { - setcc(0); - return; - } else - if (FPU_st0_tag == TW_Infinity) { - /* Operand is out of range */ - setcc(SW_C2); - FPU_st0_ptr->sign = arg_sign; /* restore st(0) */ - return; - } else - single_arg_error(); -} - - -static int -f_cos(FPU_REG * arg) -{ - char arg_sign = arg->sign; - - if (arg->tag == TW_Valid) { - int q; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return 1; -#endif /* DENORM_OPERAND */ - - arg->sign = SIGN_POS; - if ((q = trig_arg(arg)) != -1) { - FPU_REG rv; - - if (!(q & 1)) - reg_sub(&CONST_1, arg, arg, FULL_PRECISION); - - poly_sine(arg, &rv); - - setcc(0); - if ((q + 1) & 2) - rv.sign ^= SIGN_POS ^ SIGN_NEG; - reg_move(&rv, arg); - - set_precision_flag_up(); /* We do not really know - * if up or down */ - - return 0; - } else { - /* Operand is out of range */ - setcc(SW_C2); - arg->sign = arg_sign; /* restore st(0) */ - return 1; - } - } else - if (arg->tag == TW_Zero) { - reg_move(&CONST_1, arg); - setcc(0); - return 0; - } else - if (FPU_st0_tag == TW_Infinity) { - /* Operand is out of range */ - setcc(SW_C2); - arg->sign = arg_sign; /* restore st(0) */ - return 1; - } else { - single_arg_error(); /* requires arg == - * &st(0) */ - return 1; - } -} - - -static void -fcos(void) -{ - f_cos(FPU_st0_ptr); -} - - -static void -fsincos(void) -{ - FPU_REG *st_new_ptr; - FPU_REG arg; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - reg_move(FPU_st0_ptr, &arg); - if (!f_cos(&arg)) { - fsin(); - push(); - reg_move(&arg, FPU_st0_ptr); - } -} - - -/*---------------------------------------------------------------------------*/ -/* The following all require two arguments: st(0) and st(1) */ - -/* remainder of st(0) / st(1) */ -/* Assumes that st(0) and st(1) are both TW_Valid */ -static void -fprem_kernel(int round) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - FPU_REG tmp; - int old_cw = control_word; - int expdif = FPU_st0_ptr->exp - (st1_ptr)->exp; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - control_word &= ~CW_RC; - control_word |= round; - - if (expdif < 64) { - /* This should be the most common case */ - long long q; - int c = 0; - - reg_div(FPU_st0_ptr, st1_ptr, &tmp, FULL_PRECISION); - - round_to_int(&tmp); /* Fortunately, this can't - * overflow to 2^64 */ - tmp.exp = EXP_BIAS + 63; - q = *(long long *) &(tmp.sigl); - normalize(&tmp); - - reg_mul(st1_ptr, &tmp, &tmp, FULL_PRECISION); - reg_sub(FPU_st0_ptr, &tmp, FPU_st0_ptr, FULL_PRECISION); - - if (q & 4) - c |= SW_C3; - if (q & 2) - c |= SW_C1; - if (q & 1) - c |= SW_C0; - - setcc(c); - } else { - /* There is a large exponent difference ( >= 64 ) */ - int N_exp; - - reg_div(FPU_st0_ptr, st1_ptr, &tmp, FULL_PRECISION); - /* N is 'a number between 32 and 63' (p26-113) */ - N_exp = (tmp.exp & 31) + 32; - tmp.exp = EXP_BIAS + N_exp; - - round_to_int(&tmp); /* Fortunately, this can't - * overflow to 2^64 */ - tmp.exp = EXP_BIAS + 63; - normalize(&tmp); - - tmp.exp = EXP_BIAS + expdif - N_exp; - - reg_mul(st1_ptr, &tmp, &tmp, FULL_PRECISION); - reg_sub(FPU_st0_ptr, &tmp, FPU_st0_ptr, FULL_PRECISION); - - setcc(SW_C2); - } - control_word = old_cw; - - if (FPU_st0_ptr->exp <= EXP_UNDER) - arith_underflow(FPU_st0_ptr); - return; - } else - if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) { - stack_underflow(); - return; - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - setcc(0); - return; - } else - if (st1_tag == TW_Zero) { - arith_invalid(FPU_st0_ptr); - return; - } - /* fprem(?,0) always invalid */ - else - if (st1_tag == TW_Infinity) { - setcc(0); - return; - } - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - arith_invalid(FPU_st0_ptr); /* fprem(Valid,Zero) is - * invalid */ - return; - } else - if (st1_tag != TW_NaN) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (st1_tag == TW_Infinity) { - /* fprem(Valid, - * Infinity) - * is o.k. */ - setcc(0); - return; - } - } - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag != TW_NaN) { - arith_invalid(FPU_st0_ptr); /* fprem(Infinity,?) is - * invalid */ - return; - } - } - /* One of the registers must contain a NaN is we got here. */ - -#ifdef PARANOID - if ((FPU_st0_tag != TW_NaN) && (st1_tag != TW_NaN)) - EXCEPTION(EX_INTERNAL | 0x118); -#endif /* PARANOID */ - - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - -} - - -/* ST(1) <- ST(1) * log ST; pop ST */ -static void -fyl2x(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - if (FPU_st0_ptr->sign == SIGN_POS) { - int saved_control, saved_status; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic, so we need - * to save these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - poly_l2(FPU_st0_ptr, FPU_st0_ptr); - - /* Enough of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - /* Let the multiply set the flags */ - reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION); - - pop(); - FPU_st0_ptr = &st(0); - } else { - /* negative */ - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* st(0) cannot be - * negative */ - return; - } - } else - if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_tag <= TW_Zero) && (st1_tag <= TW_Zero)) { - /* one of the args is zero, the other - * valid, or both zero */ - if (FPU_st0_tag == TW_Zero) { - pop(); - FPU_st0_ptr = &st(0); - if (FPU_st0_ptr->tag == TW_Zero) - arith_invalid(FPU_st0_ptr); /* Both args zero is - * invalid */ -#ifdef PECULIAR_486 - /* This case is not - * specifically covered in the - * manual, but divide-by-zero - * would seem to be the best - * response. However, a real - * 80486 does it this way... */ - else - if (FPU_st0_ptr->tag == TW_Infinity) { - reg_move(&CONST_INF, FPU_st0_ptr); - return; - } -#endif /* PECULIAR_486 */ - else - divide_by_zero(st1_ptr->sign ^ SIGN_NEG ^ SIGN_POS, FPU_st0_ptr); - return; - } else { - /* st(1) contains zero, st(0) - * valid <> 0 */ - /* Zero is the valid answer */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - if (FPU_st0_ptr->sign == SIGN_NEG) { - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* log(negative) */ - return; - } - if (FPU_st0_ptr->exp < EXP_BIAS) - sign ^= SIGN_NEG ^ SIGN_POS; - pop(); - FPU_st0_ptr = &st(0); - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - } - /* One or both arg must be an infinity */ - else - if (FPU_st0_tag == TW_Infinity) { - if ((FPU_st0_ptr->sign == SIGN_NEG) || (st1_tag == TW_Zero)) { - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* log(-infinity) or - * 0*log(infinity) */ - return; - } else { - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - pop(); - FPU_st0_ptr = &st(0); - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - } - /* st(1) must be infinity here */ - else - if ((FPU_st0_tag == TW_Valid) && (FPU_st0_ptr->sign == SIGN_POS)) { - if (FPU_st0_ptr->exp >= EXP_BIAS) { - if ((FPU_st0_ptr->exp == EXP_BIAS) && - (FPU_st0_ptr->sigh == 0x80000000) && - (FPU_st0_ptr->sigl == 0)) { - /* st(0 - * ) - * hold - * s - * 1.0 */ - pop(); - FPU_st0_ptr = &st(0); - arith_invalid(FPU_st0_ptr); /* infinity*log(1) */ - return; - } - /* st(0) is - * positive - * and > 1.0 */ - pop(); - } else { - /* st(0) is - * positive - * and < 1.0 */ - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - st1_ptr->sign ^= SIGN_NEG; - pop(); - } - return; - } else { - /* st(0) must be zero - * or negative */ - if (FPU_st0_ptr->tag == TW_Zero) { - pop(); - FPU_st0_ptr = st1_ptr; - st1_ptr->sign ^= SIGN_NEG ^ SIGN_POS; - /* This should - * be invalid, - * but a real - * 80486 is - * happy with - * it. */ -#ifndef PECULIAR_486 - divide_by_zero(st1_ptr->sign, FPU_st0_ptr); -#endif /* PECULIAR_486 */ - } else { - pop(); - FPU_st0_ptr = st1_ptr; - arith_invalid(FPU_st0_ptr); /* log(negative) */ - } - return; - } -} - - -static void -fpatan(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - int saved_control, saved_status; - FPU_REG sum; - int quadrant = st1_ptr->sign | ((FPU_st0_ptr->sign) << 1); - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic so we need to save - * these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - st1_ptr->sign = FPU_st0_ptr->sign = SIGN_POS; - if (compare(st1_ptr) == COMP_A_lt_B) { - quadrant |= 4; - reg_div(FPU_st0_ptr, st1_ptr, &sum, FULL_PRECISION); - } else - reg_div(st1_ptr, FPU_st0_ptr, &sum, FULL_PRECISION); - - poly_atan(&sum); - - if (quadrant & 4) { - reg_sub(&CONST_PI2, &sum, &sum, FULL_PRECISION); - } - if (quadrant & 2) { - reg_sub(&CONST_PI, &sum, &sum, FULL_PRECISION); - } - if (quadrant & 1) - sum.sign ^= SIGN_POS ^ SIGN_NEG; - - /* All of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - reg_move(&sum, st1_ptr); - } else - if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_tag == TW_Infinity) || (st1_tag == TW_Infinity)) { - char sign = st1_ptr->sign; - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_PI4, st1_ptr); - } else - reg_add(&CONST_PI4, &CONST_PI2, st1_ptr, FULL_PRECISION); - } else { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_Z, st1_ptr); - pop(); - return; - } else - reg_move(&CONST_PI, st1_ptr); - } - } else { - /* st(1) is infinity, st(0) - * not infinity */ -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - reg_move(&CONST_PI2, st1_ptr); - } - st1_ptr->sign = sign; - } else - if (st1_tag == TW_Zero) { - /* st(0) must be valid or zero */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign == SIGN_POS) { - reg_move(&CONST_Z, st1_ptr); - pop(); - return; - } else - reg_move(&CONST_PI, st1_ptr); - st1_ptr->sign = sign; - } else - if (FPU_st0_tag == TW_Zero) { - /* st(1) must be - * TW_Valid here */ - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - reg_move(&CONST_PI2, st1_ptr); - st1_ptr->sign = sign; - } -#ifdef PARANOID - else - EXCEPTION(EX_INTERNAL | 0x220); -#endif /* PARANOID */ - - pop(); - set_precision_flag_up();/* We do not really know if up or down */ -} - - -static void -fprem(void) -{ - fprem_kernel(RC_CHOP); -} - - -static void -fprem1(void) -{ - fprem_kernel(RC_RND); -} - - -static void -fyl2xp1(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - int saved_control, saved_status; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* We use the general purpose arithmetic so we need to save - * these. */ - saved_status = status_word; - saved_control = control_word; - control_word = FULL_PRECISION; - - if (poly_l2p1(FPU_st0_ptr, FPU_st0_ptr)) { - arith_invalid(st1_ptr); /* poly_l2p1() returned - * invalid */ - pop(); - return; - } - /* Enough of the basic arithmetic is done now */ - control_word = saved_control; - status_word = saved_status; - - /* Let the multiply set the flags */ - reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION); - - pop(); - } else - if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) { - stack_underflow_pop(1); - return; - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag <= TW_Zero) { - -#ifdef DENORM_OPERAND - if ((st1_tag == TW_Valid) && (st1_ptr->exp <= EXP_UNDER) && - (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - st1_ptr->sign ^= FPU_st0_ptr->sign; - reg_move(FPU_st0_ptr, st1_ptr); - } else - if (st1_tag == TW_Infinity) { - arith_invalid(st1_ptr); /* Infinity*log(1) */ - pop(); - return; - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x116); - return; - } -#endif /* PARANOID */ - pop(); - return; - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - if (FPU_st0_ptr->sign == SIGN_NEG) { - if (FPU_st0_ptr->exp >= EXP_BIAS) { - /* st(0) holds - * <= -1.0 */ - arith_invalid(st1_ptr); /* infinity*log(1) */ - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - pop(); - return; - } - if (st1_tag == TW_Infinity) { - if (FPU_st0_ptr->sign == SIGN_NEG) { - if ((FPU_st0_ptr->exp >= EXP_BIAS) && - !((FPU_st0_ptr->sigh == 0x80000000) && - (FPU_st0_ptr->sigl == 0))) { - /* st(0) holds - * < -1.0 */ - arith_invalid(st1_ptr); - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG; - pop(); - return; - } -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - pop(); - return; - } - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } - } else - if (FPU_st0_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr); - pop(); - return; - } else - if ((FPU_st0_ptr->sign == SIGN_NEG) || - (st1_tag == TW_Zero)) { - arith_invalid(st1_ptr); /* log(infinity) */ - pop(); - return; - } - /* st(1) must be valid - * here. */ - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - /* The Manual says - * that log(Infinity) - * is invalid, but a - * real 80486 sensibly - * says that it is - * o.k. */ - { - char sign = st1_ptr->sign; - reg_move(&CONST_INF, st1_ptr); - st1_ptr->sign = sign; - } - pop(); - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x117); - } -#endif /* PARANOID */ -} - - -static void -emu_fscale(void) -{ - FPU_REG *st1_ptr = &st(1); - char st1_tag = st1_ptr->tag; - int old_cw = control_word; - - if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) { - long scale; - FPU_REG tmp; - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (st1_ptr->exp <= EXP_UNDER)) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (st1_ptr->exp > EXP_BIAS + 30) { - /* 2^31 is far too large, would require 2^(2^30) or - * 2^(-2^30) */ - char sign; - - if (st1_ptr->sign == SIGN_POS) { - EXCEPTION(EX_Overflow); - sign = FPU_st0_ptr->sign; - reg_move(&CONST_INF, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - } else { - EXCEPTION(EX_Underflow); - sign = FPU_st0_ptr->sign; - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - } - return; - } - control_word &= ~CW_RC; - control_word |= RC_CHOP; - reg_move(st1_ptr, &tmp); - round_to_int(&tmp); /* This can never overflow here */ - control_word = old_cw; - scale = st1_ptr->sign ? -tmp.sigl : tmp.sigl; - scale += FPU_st0_ptr->exp; - FPU_st0_ptr->exp = scale; - - /* Use round_reg() to properly detect under/overflow etc */ - round_reg(FPU_st0_ptr, 0, control_word); - - return; - } else - if (FPU_st0_tag == TW_Valid) { - if (st1_tag == TW_Zero) { - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } - if (st1_tag == TW_Infinity) { - char sign = st1_ptr->sign; - -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - if (sign == SIGN_POS) { - reg_move(&CONST_INF, FPU_st0_ptr); - } else - reg_move(&CONST_Z, FPU_st0_ptr); - FPU_st0_ptr->sign = sign; - return; - } - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_Zero) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } else - if (st1_tag == TW_Zero) { - return; - } else - if (st1_tag == TW_Infinity) { - if (st1_ptr->sign == SIGN_NEG) - return; - else { - arith_invalid(FPU_st0_ptr); /* Zero scaled by - * +Infinity */ - return; - } - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_Infinity) { - if (st1_tag == TW_Valid) { - -#ifdef DENORM_OPERAND - if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return; -#endif /* DENORM_OPERAND */ - - return; - } - if (((st1_tag == TW_Infinity) && (st1_ptr->sign == SIGN_POS)) - || (st1_tag == TW_Zero)) - return; - else - if (st1_tag == TW_Infinity) { - arith_invalid(FPU_st0_ptr); /* Infinity scaled by - * -Infinity */ - return; - } else - if (st1_tag == TW_NaN) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } else - if (FPU_st0_tag == TW_NaN) { - if (st1_tag != TW_Empty) { - real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr); - return; - } - } -#ifdef PARANOID - if (!((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty))) { - EXCEPTION(EX_INTERNAL | 0x115); - return; - } -#endif - - /* At least one of st(0), st(1) must be empty */ - stack_underflow(); - -} - - -/*---------------------------------------------------------------------------*/ - -static FUNC trig_table_a[] = { - f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp -}; - -void -trig_a(void) -{ - (trig_table_a[FPU_rm]) (); -} - - -static FUNC trig_table_b[] = -{ - fprem, fyl2xp1, fsqrt_, fsincos, frndint_, emu_fscale, fsin, fcos -}; - -void -trig_b(void) -{ - (trig_table_b[FPU_rm]) (); -} diff --git a/sys/platform/pc32/gnu/fpemul/get_address.c b/sys/platform/pc32/gnu/fpemul/get_address.c deleted file mode 100644 index 57f5992b36..0000000000 --- a/sys/platform/pc32/gnu/fpemul/get_address.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * get_address.c - * - * Get the effective address from an FPU instruction. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/get_address.c,v 1.10 1999/10/12 02:23:14 msmith Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/get_address.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" - -static int reg_offset[] = { -tEAX, tECX, tEDX, tEBX, tESP, tEBP, tESI, tEDI}; -#define REG_(x) (*(((int*)FPU_info) + reg_offset[(x)])) - -void *FPU_data_address; - - -/* Decode the SIB byte. This function assumes mod != 0 */ -static void * -sib(int mod) -{ - unsigned char ss, index, base; - long offset; - - REENTRANT_CHECK(OFF); - base = fubyte((char *) FPU_EIP); /* The SIB byte */ - REENTRANT_CHECK(ON); - FPU_EIP++; - ss = base >> 6; - index = (base >> 3) & 7; - base &= 7; - - if ((mod == 0) && (base == 5)) - offset = 0; /* No base register */ - else - offset = REG_(base); - - if (index == 4) { - /* No index register */ - /* A non-zero ss is illegal */ - if (ss) - EXCEPTION(EX_Invalid); - } else { - offset += (REG_(index)) << ss; - } - - if (mod == 1) { - /* 8 bit signed displacement */ - REENTRANT_CHECK(OFF); - offset += (signed char) fubyte((char *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP++; - } else - if (mod == 2 || base == 5) { /* The second condition also - * has mod==0 */ - /* 32 bit displacment */ - REENTRANT_CHECK(OFF); - offset += (signed) fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - } - return (void *) (intptr_t) offset; -} - - -/* - MOD R/M byte: MOD == 3 has a special use for the FPU - SIB byte used iff R/M = 100b - - 7 6 5 4 3 2 1 0 - ..... ......... ......... - MOD OPCODE(2) R/M - - - SIB byte - - 7 6 5 4 3 2 1 0 - ..... ......... ......... - SS INDEX BASE - -*/ - -void -get_address(unsigned char FPU_modrm) -{ - unsigned char mod; - long *cpu_reg_ptr; - int offset = 0; /* Initialized just to stop compiler warnings. */ - - mod = (FPU_modrm >> 6) & 3; - - if (FPU_rm == 4 && mod != 3) { - FPU_data_address = sib(mod); - return; - } - cpu_reg_ptr = (long *) ®_(FPU_rm); - switch (mod) { - case 0: - if (FPU_rm == 5) { - /* Special case: disp32 */ - REENTRANT_CHECK(OFF); - offset = fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - FPU_data_address = (void *) offset; - return; - } else { - /* Just return the contents of the cpu register */ - FPU_data_address = (void *) (intptr_t) *cpu_reg_ptr; - return; - } - case 1: - /* 8 bit signed displacement */ - REENTRANT_CHECK(OFF); - offset = (signed char) fubyte((char *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP++; - break; - case 2: - /* 32 bit displacement */ - REENTRANT_CHECK(OFF); - offset = (signed) fuword((unsigned long *) FPU_EIP); - REENTRANT_CHECK(ON); - FPU_EIP += 4; - break; - case 3: - /* Not legal for the FPU */ - EXCEPTION(EX_Invalid); - } - - FPU_data_address = (void *) (intptr_t) (offset + *cpu_reg_ptr); -} diff --git a/sys/platform/pc32/gnu/fpemul/load_store.c b/sys/platform/pc32/gnu/fpemul/load_store.c deleted file mode 100644 index 2b7ddeebdf..0000000000 --- a/sys/platform/pc32/gnu/fpemul/load_store.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * load_store.c - * - * This file contains most of the code to interpret the FPU instructions - * which load and store from user memory. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/load_store.c,v 1.13 1999/08/28 00:42:52 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/load_store.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ - -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "status_w.h" - - -#define _NONE_ 0 /* FPU_st0_ptr etc not needed */ -#define _REG0_ 1 /* Will be storing st(0) */ -#define _PUSH_ 3 /* Need to check for space to push onto stack */ -#define _null_ 4 /* Function illegal or not implemented */ - -#define pop_0() { pop_ptr->tag = TW_Empty; top++; } - - -static unsigned char type_table[32] = { - _PUSH_, _PUSH_, _PUSH_, _PUSH_, - _null_, _null_, _null_, _null_, - _REG0_, _REG0_, _REG0_, _REG0_, - _REG0_, _REG0_, _REG0_, _REG0_, - _NONE_, _null_, _NONE_, _PUSH_, - _NONE_, _PUSH_, _null_, _PUSH_, - _NONE_, _null_, _NONE_, _REG0_, - _NONE_, _REG0_, _NONE_, _REG0_ -}; - -void -load_store_instr(char type) -{ - FPU_REG *pop_ptr; /* We need a version of FPU_st0_ptr which - * won't change. */ - - pop_ptr = NULL; /* Initialized just to stop compiler warnings. */ - - - switch (type_table[(int) (unsigned) type]) { - case _NONE_: - break; - case _REG0_: - pop_ptr = &st(0); /* Some of these instructions pop - * after storing */ - - FPU_st0_ptr = pop_ptr; /* Set the global variables. */ - FPU_st0_tag = FPU_st0_ptr->tag; - break; - case _PUSH_: - { - pop_ptr = &st(-1); - if (pop_ptr->tag != TW_Empty) { - stack_overflow(); - return; - } - top--; - } - break; - case _null_: - Un_impl(); - return; -#ifdef PARANOID - default: - return EXCEPTION(EX_INTERNAL); -#endif /* PARANOID */ - } - - switch (type) { - case 000: /* fld m32real */ - reg_load_single(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 001: /* fild m32int */ - reg_load_int32(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 002: /* fld m64real */ - reg_load_double(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 003: /* fild m16int */ - reg_load_int16(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 010: /* fst m32real */ - reg_store_single(); - break; - case 011: /* fist m32int */ - reg_store_int32(); - break; - case 012: /* fst m64real */ - reg_store_double(); - break; - case 013: /* fist m16int */ - reg_store_int16(); - break; - case 014: /* fstp m32real */ - if (reg_store_single()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 015: /* fistp m32int */ - if (reg_store_int32()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 016: /* fstp m64real */ - if (reg_store_double()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 017: /* fistp m16int */ - if (reg_store_int16()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 020: /* fldenv m14/28byte */ - fldenv(); - break; - case 022: /* frstor m94/108byte */ - frstor(); - break; - case 023: /* fbld m80dec */ - reg_load_bcd(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 024: /* fldcw */ - REENTRANT_CHECK(OFF); - control_word = fusword((unsigned short *) FPU_data_address); - REENTRANT_CHECK(ON); -#ifdef NO_UNDERFLOW_TRAP - if (!(control_word & EX_Underflow)) { - control_word |= EX_Underflow; - } -#endif - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 025: /* fld m80real */ - reg_load_extended(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 027: /* fild m64int */ - reg_load_int64(); - setcc(0); /* Clear the SW_C1 bit, "other bits undefined" */ - reg_move(&FPU_loaded_data, pop_ptr); - break; - case 030: /* fstenv m14/28byte */ - fstenv(); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 032: /* fsave */ - fsave(); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 033: /* fbstp m80dec */ - if (reg_store_bcd()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 034: /* fstcw m16int */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, FPU_data_address, 2);*/ - susword( (short *) FPU_data_address,control_word); - REENTRANT_CHECK(ON); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t ) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 035: /* fstp m80real */ - if (reg_store_extended()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - case 036: /* fstsw m2byte */ - status_word &= ~SW_Top; - status_word |= (top & 7) << SW_Top_Shift; - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, FPU_data_address, 2);*/ - susword( (short *) FPU_data_address,status_word); - REENTRANT_CHECK(ON); - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - break; - case 037: /* fistp m64int */ - if (reg_store_int64()) - pop_0();/* pop only if the number was actually stored - * (see the 80486 manual p16-28) */ - break; - } -} diff --git a/sys/platform/pc32/gnu/fpemul/math_emu.h b/sys/platform/pc32/gnu/fpemul/math_emu.h deleted file mode 100644 index dd23603aa5..0000000000 --- a/sys/platform/pc32/gnu/fpemul/math_emu.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * $FreeBSD: src/sys/gnu/i386/fpemul/math_emu.h,v 1.5 1999/08/28 00:42:52 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/math_emu.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - -#ifndef _MATH_EMU_H -#define _MATH_EMU_H - -struct fpu_reg { - char sign; - char tag; - long exp; - u_long sigl; - u_long sigh; -}; - -union i387_union { - struct i387_hard_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long st_space[20]; /* 8*10 bytes for each FP-reg = 80 - * bytes */ - } hard; - struct i387_soft_struct { - long cwd; - long swd; - long twd; - long fip; - long fcs; - long foo; - long fos; - long top; - struct fpu_reg regs[8]; /* 8*16 bytes for each FP-reg = 128 - * bytes */ - unsigned char lookahead; - struct trapframe *frame; - unsigned long entry_eip; - int orig_eip; - } soft; -}; -#endif diff --git a/sys/platform/pc32/gnu/fpemul/poly_2xm1.c b/sys/platform/pc32/gnu/fpemul/poly_2xm1.c deleted file mode 100644 index 95e4dce60a..0000000000 --- a/sys/platform/pc32/gnu/fpemul/poly_2xm1.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * poly_2xm1.c - * - * Function to compute 2^x-1 by a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_2xm1.c,v 1.8 1999/08/28 00:42:53 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/poly_2xm1.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "reg_constant.h" - - - -#define HIPOWER 13 -static unsigned short lterms[HIPOWER][4] = -{ - {0x79b5, 0xd1cf, 0x17f7, 0xb172}, - {0x1b56, 0x058b, 0x7bff, 0x3d7f}, - {0x8bb0, 0x8250, 0x846b, 0x0e35}, - {0xbc65, 0xf747, 0x556d, 0x0276}, - {0x17cb, 0x9e39, 0x61ff, 0x0057}, - {0xe018, 0x9776, 0x1848, 0x000a}, - {0x66f2, 0xff30, 0xffe5, 0x0000}, - {0x682f, 0xffb6, 0x162b, 0x0000}, - {0xb7ca, 0x2956, 0x01b5, 0x0000}, - {0xcd3e, 0x4817, 0x001e, 0x0000}, - {0xb7e2, 0xecbe, 0x0001, 0x0000}, - {0x0ed5, 0x1a27, 0x0000, 0x0000}, - {0x101d, 0x0222, 0x0000, 0x0000}, -}; - - -/*--- poly_2xm1() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -int -poly_2xm1(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - long long Xll; - FPU_REG accum; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, result); - return 0; - } - if (exponent >= 0) { /* Can't hack a number >= 1.0 */ - arith_invalid(result); /* Number too large */ - return 1; - } - if (arg->sign != SIGN_POS) { /* Can't hack a number < 0.0 */ - arith_invalid(result); /* Number negative */ - return 1; - } - if (exponent < -64) { - reg_move(&CONST_LN2, result); - return 0; - } - *(unsigned *) &Xll = arg->sigl; - *(((unsigned *) &Xll) + 1) = arg->sigh; - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&Xll, -1 - exponent) >= (unsigned)0x80000000) - Xll++; /* round up */ - } - *(short *) &(accum.sign) = 0; /* will be a valid positive nr with - * expon = 0 */ - accum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((unsigned *) &accum.sigl, (unsigned *) &Xll, lterms, HIPOWER - 1); - - /* Convert to 64 bit signed-compatible */ - accum.exp += EXP_BIAS - 1; - - reg_move(&accum, result); - - normalize(result); - - return 0; - -} diff --git a/sys/platform/pc32/gnu/fpemul/poly_atan.c b/sys/platform/pc32/gnu/fpemul/poly_atan.c deleted file mode 100644 index 76694ce858..0000000000 --- a/sys/platform/pc32/gnu/fpemul/poly_atan.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * p_atan.c - * - * Compute the tan of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_atan.c,v 1.10 1999/08/28 00:42:53 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/poly_atan.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "reg_constant.h" -#include "control_w.h" - - -#define HIPOWERon 6 /* odd poly, negative terms */ -static unsigned oddnegterms[HIPOWERon][2] = -{ - {0x00000000, 0x00000000}, /* for + 1.0 */ - {0x763b6f3d, 0x1adc4428}, - {0x20f0630b, 0x0502909d}, - {0x4e825578, 0x0198ce38}, - {0x22b7cb87, 0x008da6e3}, - {0x9b30ca03, 0x00239c79} -}; -#define HIPOWERop 6 /* odd poly, positive terms */ -static unsigned oddplterms[HIPOWERop][2] = -{ - {0xa6f67cb8, 0x94d910bd}, - {0xa02ffab4, 0x0a43cb45}, - {0x04265e6b, 0x02bf5655}, - {0x0a728914, 0x00f280f7}, - {0x6d640e01, 0x004d6556}, - {0xf1dd2dbf, 0x000a530a} -}; - - -static unsigned denomterm[2] = -{0xfc4bd208, 0xea2e6612}; - - -static void poly_add_1(FPU_REG * src); - -/*--- poly_atan() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_atan(FPU_REG * arg) -{ - char recursions = 0; - short exponent; - FPU_REG odd_poly, even_poly, pos_poly, neg_poly; - FPU_REG argSq; - long long arg_signif, argSqSq; - - -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - arith_invalid(arg); - return; - } /* Need a positive number */ -#endif /* PARANOID */ - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, arg); - return; - } - if (exponent >= -2) { - /* argument is in the range [0.25 .. 1.0] */ - if (exponent >= 0) { -#ifdef PARANOID - if ((exponent == 0) && - (arg->sigl == 0) && (arg->sigh == 0x80000000)) -#endif /* PARANOID */ - { - reg_move(&CONST_PI4, arg); - return; - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic - * error */ -#endif /* PARANOID */ - } - /* If the argument is greater than sqrt(2)-1 (=0.414213562...) */ - /* convert the argument by an identity for atan */ - if ((exponent >= -1) || (arg->sigh > 0xd413ccd0)) { - FPU_REG numerator, denom; - - recursions++; - - arg_signif = *(long long *) &(arg->sigl); - if (exponent < -1) { - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - } - *(long long *) &(numerator.sigl) = -arg_signif; - numerator.exp = EXP_BIAS - 1; - normalize(&numerator); /* 1 - arg */ - - arg_signif = *(long long *) &(arg->sigl); - if (shrx(&arg_signif, -exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - *(long long *) &(denom.sigl) = arg_signif; - denom.sigh |= 0x80000000; /* 1 + arg */ - - arg->exp = numerator.exp; - reg_u_div(&numerator, &denom, arg, FULL_PRECISION); - - exponent = arg->exp - EXP_BIAS; - } - } - *(long long *) &arg_signif = *(long long *) &(arg->sigl); - -#ifdef PARANOID - /* This must always be true */ - if (exponent >= -1) { - EXCEPTION(EX_INTERNAL | 0x120); /* There must be a logic error */ - } -#endif /* PARANOID */ - - /* shift the argument right by the required places */ - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - - /* Now have arg_signif with binary point at the left .1xxxxxxxx */ - mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl)); - mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, - (unsigned short (*)[4]) oddplterms, HIPOWERop - 1); - mul64((long long *) (&argSq.sigl), (long long *) (&pos_poly.sigl), - (long long *) (&pos_poly.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, - (unsigned short (*)[4]) oddnegterms, HIPOWERon - 1); - - /* Subtract the mantissas */ - *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl)); - - reg_move(&pos_poly, &odd_poly); - poly_add_1(&odd_poly); - - /* The complete odd polynomial */ - reg_u_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(even_poly.sign) = 0; - - mul64((long long *) (&argSq.sigl), - (long long *) (&denomterm), (long long *) (&even_poly.sigl)); - - poly_add_1(&even_poly); - - reg_div(&odd_poly, &even_poly, arg, FULL_PRECISION); - - if (recursions) - reg_sub(&CONST_PI4, arg, arg, FULL_PRECISION); -} - - -/* The argument to this function must be polynomial() compatible, - i.e. have an exponent (not checked) of EXP_BIAS-1 but need not - be normalized. - This function adds 1.0 to the (assumed positive) argument. */ -static void -poly_add_1(FPU_REG * src) -{ -/* Rounding in a consistent direction produces better results - for the use of this function in poly_atan. Simple truncation - is used here instead of round-to-nearest. */ - -#ifdef OBSOLETE - char round = (src->sigl & 3) == 3; -#endif /* OBSOLETE */ - - shrx(&src->sigl, 1); - -#ifdef OBSOLETE - if (round) - (*(long long *) &src->sigl)++; /* Round to even */ -#endif /* OBSOLETE */ - - src->sigh |= 0x80000000; - - src->exp = EXP_BIAS; - -} diff --git a/sys/platform/pc32/gnu/fpemul/poly_div.s b/sys/platform/pc32/gnu/fpemul/poly_div.s deleted file mode 100644 index 1ea24b494b..0000000000 --- a/sys/platform/pc32/gnu/fpemul/poly_div.s +++ /dev/null @@ -1,139 +0,0 @@ - .file "poly_div.S" -/* - * poly_div.S - * - * A set of functions to divide 64 bit integers by fixed numbers. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_div.s,v 1.8 1999/08/28 00:42:53 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/poly_div.s,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "fpu_asm.h" - -.text - -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div2) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - shrl $1,4(%ecx) - rcrl $1,(%ecx) - - testw $1,%ax - je poly_div2_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div2_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div4) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - movl 4(%ecx),%edx - shll $30,%edx - - shrl $2,4(%ecx) - shrl $2,(%ecx) - - orl %edx,(%ecx) - - testw $2,%ax - je poly_div4_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div4_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ -ENTRY(poly_div16) - pushl %ebp - movl %esp,%ebp - - movl PARAM1,%ecx - movw (%ecx),%ax - - movl 4(%ecx),%edx - shll $28,%edx - - shrl $4,4(%ecx) - shrl $4,(%ecx) - - orl %edx,(%ecx) - - testw $8,%ax - je poly_div16_exit - - addl $1,(%ecx) - adcl $0,4(%ecx) -poly_div16_exit: - - leave - ret -/*---------------------------------------------------------------------------*/ diff --git a/sys/platform/pc32/gnu/fpemul/poly_l2.c b/sys/platform/pc32/gnu/fpemul/poly_l2.c deleted file mode 100644 index 1f23cd02c3..0000000000 --- a/sys/platform/pc32/gnu/fpemul/poly_l2.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * poly_l2.c - * - * Compute the base 2 log of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_l2.c,v 1.10 1999/08/28 00:42:53 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/poly_l2.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -#include "reg_constant.h" -#include "control_w.h" - - - -#define HIPOWER 9 -static unsigned short lterms[HIPOWER][4] = -{ - /* Ideal computation with these coeffs gives about 64.6 bit rel - * accuracy. */ - {0xe177, 0xb82f, 0x7652, 0x7154}, - {0xee0f, 0xe80f, 0x2770, 0x7b1c}, - {0x0fc0, 0xbe87, 0xb143, 0x49dd}, - {0x78b9, 0xdadd, 0xec54, 0x34c2}, - {0x003a, 0x5de9, 0x628b, 0x2909}, - {0x5588, 0xed16, 0x4abf, 0x2193}, - {0xb461, 0x85f7, 0x347a, 0x1c6a}, - {0x0975, 0x87b3, 0xd5bf, 0x1876}, - {0xe85c, 0xcec9, 0x84e7, 0x187d} -}; - - - - -/*--- poly_l2() -------------------------------------------------------------+ - | Base 2 logarithm by a polynomial approximation. | - +---------------------------------------------------------------------------*/ -void -poly_l2(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - char zero; /* flag for an Xx == 0 */ - unsigned short bits, shift; - long long Xsq; - FPU_REG accum, denom, num, Xx; - - - exponent = arg->exp - EXP_BIAS; - - accum.tag = TW_Valid; /* set the tags to Valid */ - - if (arg->sigh > (unsigned) 0xb504f334) { - /* This is good enough for the computation of the polynomial - * sum, but actually results in a loss of precision for the - * computation of Xx. This will matter only if exponent - * becomes zero. */ - exponent++; - accum.sign = 1; /* sign to negative */ - num.exp = EXP_BIAS; /* needed to prevent errors in div - * routine */ - reg_u_div(&CONST_1, arg, &num, FULL_PRECISION); - } else { - accum.sign = 0; /* set the sign to positive */ - num.sigl = arg->sigl; /* copy the mantissa */ - num.sigh = arg->sigh; - } - - - /* shift num left, lose the ms bit */ - num.sigh <<= 1; - if (num.sigl & 0x80000000) - num.sigh |= 1; - num.sigl <<= 1; - - denom.sigl = num.sigl; - denom.sigh = num.sigh; - poly_div4((long long *) &(denom.sigl)); - denom.sigh += 0x80000000; /* set the msb */ - Xx.exp = EXP_BIAS; /* needed to prevent errors in div routine */ - reg_u_div(&num, &denom, &Xx, FULL_PRECISION); - - zero = !(Xx.sigh | Xx.sigl); - - mul64((long long *) &Xx.sigl, (long long *) &Xx.sigl, &Xsq); - poly_div16(&Xsq); - - accum.exp = -1; /* exponent of accum */ - - /* Do the basic fixed point polynomial evaluation */ - polynomial((unsigned *) &accum.sigl, (unsigned *) &Xsq, lterms, HIPOWER - 1); - - if (!exponent) { - /* If the exponent is zero, then we would lose precision by - * sticking to fixed point computation here */ - /* We need to re-compute Xx because of loss of precision. */ - FPU_REG lXx; - char sign; - - sign = accum.sign; - accum.sign = 0; - - /* make accum compatible and normalize */ - accum.exp = EXP_BIAS + accum.exp; - normalize(&accum); - - if (zero) { - reg_move(&CONST_Z, result); - } else { - /* we need to re-compute lXx to better accuracy */ - num.tag = TW_Valid; /* set the tags to Vaild */ - num.sign = 0; /* set the sign to positive */ - num.exp = EXP_BIAS - 1; - if (sign) { - /* The argument is of the form 1-x */ - /* Use 1-1/(1-x) = x/(1-x) */ - *((long long *) &num.sigl) = -*((long long *) &(arg->sigl)); - normalize(&num); - reg_div(&num, arg, &num, FULL_PRECISION); - } else { - normalize(&num); - } - - denom.tag = TW_Valid; /* set the tags to Valid */ - denom.sign = SIGN_POS; /* set the sign to positive */ - denom.exp = EXP_BIAS; - - reg_div(&num, &denom, &lXx, FULL_PRECISION); - - reg_u_mul(&lXx, &accum, &accum, FULL_PRECISION); - - reg_u_add(&lXx, &accum, result, FULL_PRECISION); - - normalize(result); - } - - result->sign = sign; - return; - } - mul64((long long *) &accum.sigl, - (long long *) &Xx.sigl, (long long *) &accum.sigl); - - *((long long *) (&accum.sigl)) += *((long long *) (&Xx.sigl)); - - if (Xx.sigh > accum.sigh) { - /* There was an overflow */ - - poly_div2((long long *) &accum.sigl); - accum.sigh |= 0x80000000; - accum.exp++; - } - /* When we add the exponent to the accum result later, we will require - * that their signs are the same. Here we ensure that this is so. */ - if (exponent && ((exponent < 0) ^ (accum.sign))) { - /* signs are different */ - - accum.sign = !accum.sign; - - /* An exceptional case is when accum is zero */ - if (accum.sigl | accum.sigh) { - /* find 1-accum */ - /* Shift to get exponent == 0 */ - if (accum.exp < 0) { - poly_div2((long long *) &accum.sigl); - accum.exp++; - } - /* Just negate, but throw away the sign */ - *((long long *) &(accum.sigl)) = -*((long long *) &(accum.sigl)); - if (exponent < 0) - exponent++; - else - exponent--; - } - } - shift = exponent >= 0 ? exponent : -exponent; - bits = 0; - if (shift) { - if (accum.exp) { - accum.exp++; - poly_div2((long long *) &accum.sigl); - } - while (shift) { - poly_div2((long long *) &accum.sigl); - if (shift & 1) - accum.sigh |= 0x80000000; - shift >>= 1; - bits++; - } - } - /* Convert to 64 bit signed-compatible */ - accum.exp += bits + EXP_BIAS - 1; - - reg_move(&accum, result); - normalize(result); - - return; -} - - -/*--- poly_l2p1() -----------------------------------------------------------+ - | Base 2 logarithm by a polynomial approximation. | - | log2(x+1) | - +---------------------------------------------------------------------------*/ -int -poly_l2p1(FPU_REG * arg, FPU_REG * result) -{ - char sign = 0; - long long Xsq; - FPU_REG arg_pl1, denom, accum, local_arg, poly_arg; - - - sign = arg->sign; - - reg_add(arg, &CONST_1, &arg_pl1, FULL_PRECISION); - - if ((arg_pl1.sign) | (arg_pl1.tag)) { /* We need a valid positive - * number! */ - return 1; - } - reg_add(&CONST_1, &arg_pl1, &denom, FULL_PRECISION); - reg_div(arg, &denom, &local_arg, FULL_PRECISION); - local_arg.sign = 0; /* Make the sign positive */ - - /* Now we need to check that |local_arg| is less than 3-2*sqrt(2) = - * 0.17157.. = .0xafb0ccc0 * 2^-2 */ - - if (local_arg.exp >= EXP_BIAS - 3) { - if ((local_arg.exp > EXP_BIAS - 3) || - (local_arg.sigh > (unsigned) 0xafb0ccc0)) { - /* The argument is large */ - poly_l2(&arg_pl1, result); - return 0; - } - } - /* Make a copy of local_arg */ - reg_move(&local_arg, &poly_arg); - - /* Get poly_arg bits aligned as required */ - shrx((unsigned *) &(poly_arg.sigl), -(poly_arg.exp - EXP_BIAS + 3)); - - mul64((long long *) &(poly_arg.sigl), (long long *) &(poly_arg.sigl), &Xsq); - poly_div16(&Xsq); - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &accum.sigl, (unsigned *) &Xsq, lterms, HIPOWER - 1); - - accum.tag = TW_Valid; /* set the tags to Valid */ - accum.sign = SIGN_POS; /* and make accum positive */ - - /* make accum compatible and normalize */ - accum.exp = EXP_BIAS - 1; - normalize(&accum); - - reg_u_mul(&local_arg, &accum, &accum, FULL_PRECISION); - - reg_u_add(&local_arg, &accum, result, FULL_PRECISION); - - /* Multiply the result by 2 */ - result->exp++; - - result->sign = sign; - - return 0; -} diff --git a/sys/platform/pc32/gnu/fpemul/poly_mul64.s b/sys/platform/pc32/gnu/fpemul/poly_mul64.s deleted file mode 100644 index 1ac9ec8944..0000000000 --- a/sys/platform/pc32/gnu/fpemul/poly_mul64.s +++ /dev/null @@ -1,123 +0,0 @@ -/* - * poly_mul64.S - * - * Multiply two 64 bit integers. - * - * Call from C as: - * void mul64(long long *a, long long *b, long long *result) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_mul64.s,v 1.8 1999/08/28 00:42:54 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/poly_mul64.s,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -#include "fpu_asm.h" - -.text -ENTRY(mul64) - pushl %ebp - movl %esp,%ebp - subl $16,%esp - pushl %esi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%ecx - movl PARAM3,%ebx - - xor %eax,%eax - movl %eax,-4(%ebp) - movl %eax,-8(%ebp) - - movl (%esi),%eax - mull (%ecx) - movl %eax,-16(%ebp) /* Not used */ - movl %edx,-12(%ebp) - - movl (%esi),%eax - mull 4(%ecx) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl 4(%esi),%eax - mull (%ecx) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl 4(%esi),%eax - mull 4(%ecx) - addl %eax,-8(%ebp) - adcl %edx,-4(%ebp) - - testb $128,-9(%ebp) - je L_no_round - - addl $1,-8(%ebp) - adcl $0,-4(%ebp) - -L_no_round: - movl -8(%ebp),%esi - movl %esi,(%ebx) - movl -4(%ebp),%esi - movl %esi,4(%ebx) - - popl %ebx - popl %esi - leave - ret diff --git a/sys/platform/pc32/gnu/fpemul/poly_sin.c b/sys/platform/pc32/gnu/fpemul/poly_sin.c deleted file mode 100644 index b56448fe63..0000000000 --- a/sys/platform/pc32/gnu/fpemul/poly_sin.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * poly_sin.c - * - * Computation of an approximation of the sin function by a polynomial - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_sin.c,v 1.10 1999/08/28 00:42:54 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/poly_sin.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#ifdef DEBUG -#include -#include /* for printf() in EXCEPTION() */ -#endif - -#include "exception.h" -#include "reg_constant.h" -#include "control_w.h" - - -#define HIPOWER 5 -static unsigned short lterms[HIPOWER][4] = -{ - {0x846a, 0x42d1, 0xb544, 0x921f}, - {0xe110, 0x75aa, 0xbc67, 0x1466}, - {0x503d, 0xa43f, 0x83c1, 0x000a}, - {0x8f9d, 0x7a19, 0x00f4, 0x0000}, - {0xda03, 0x06aa, 0x0000, 0x0000}, -}; - -static unsigned short negterms[HIPOWER][4] = -{ - {0x95ed, 0x2df2, 0xe731, 0xa55d}, - {0xd159, 0xe62b, 0xd2cc, 0x0132}, - {0x6342, 0xe9fb, 0x3c60, 0x0000}, - {0x6256, 0xdf5a, 0x0002, 0x0000}, - {0xf279, 0x000b, 0x0000, 0x0000}, -}; - - -/*--- poly_sine() -----------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_sine(FPU_REG * arg, FPU_REG * result) -{ - short exponent; - FPU_REG Xx, Xx2, Xx4, accum, negaccum; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, result); - return; - } -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - EXCEPTION(EX_Invalid); - reg_move(&CONST_QNaN, result); - return; - } - if (exponent >= 0) { /* Can't hack a number > 1.0 */ - if ((exponent == 0) && (arg->sigl == 0) && (arg->sigh == 0x80000000)) { - reg_move(&CONST_1, result); - return; - } - EXCEPTION(EX_Invalid); - reg_move(&CONST_QNaN, result); - return; - } -#endif /* PARANOID */ - - Xx.sigl = arg->sigl; - Xx.sigh = arg->sigh; - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&(Xx.sigl), -1 - exponent) >= (unsigned)0x80000000) - (*((long long *) (&(Xx.sigl))))++; /* round up */ - } - mul64((long long *) &(Xx.sigl), (long long *) &(Xx.sigl), - (long long *) &(Xx2.sigl)); - mul64((long long *) &(Xx2.sigl), (long long *) &(Xx2.sigl), - (long long *) &(Xx4.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(accum.sign) = 0; - accum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &(accum.sigl), (u_int *)&(Xx4.sigl), lterms, HIPOWER - 1); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(negaccum.sign) = 0; - negaccum.exp = 0; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &(negaccum.sigl), (u_int *)&(Xx4.sigl), negterms, HIPOWER - 1); - mul64((long long *) &(Xx2.sigl), (long long *) &(negaccum.sigl), - (long long *) &(negaccum.sigl)); - - /* Subtract the mantissas */ - *((long long *) (&(accum.sigl))) -= *((long long *) (&(negaccum.sigl))); - - /* Convert to 64 bit signed-compatible */ - accum.exp = EXP_BIAS - 1 + accum.exp; - - *(short *) &(result->sign) = *(short *) &(accum.sign); - result->exp = accum.exp; - result->sigl = accum.sigl; - result->sigh = accum.sigh; - - normalize(result); - - reg_mul(result, arg, result, FULL_PRECISION); - reg_u_add(result, arg, result, FULL_PRECISION); - - /* A small overflow may be possible... but an illegal result. */ - if (result->exp >= EXP_BIAS) { - if ((result->exp > EXP_BIAS) /* Larger or equal 2.0 */ - ||(result->sigl > 1) /* Larger than 1.0+msb */ - ||(result->sigh != 0x80000000) /* Much > 1.0 */ - ) { -#ifdef DEBUGGING - RE_ENTRANT_CHECK_OFF - printk("\nEXP=%d, MS=%08x, LS=%08x\n", result->exp, - result->sigh, result->sigl); - RE_ENTRANT_CHECK_ON -#endif /* DEBUGGING */ - EXCEPTION(EX_INTERNAL | 0x103); - } -#ifdef DEBUGGING - RE_ENTRANT_CHECK_OFF - printk("\n***CORRECTING ILLEGAL RESULT*** in poly_sin() computation\n"); - printk("EXP=%d, MS=%08x, LS=%08x\n", result->exp, - result->sigh, result->sigl); - RE_ENTRANT_CHECK_ON -#endif /* DEBUGGING */ - - result->sigl = 0; /* Truncate the result to 1.00 */ - } -} diff --git a/sys/platform/pc32/gnu/fpemul/poly_tan.c b/sys/platform/pc32/gnu/fpemul/poly_tan.c deleted file mode 100644 index 284764cfc7..0000000000 --- a/sys/platform/pc32/gnu/fpemul/poly_tan.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * poly_tan.c - * - * Compute the tan of a FPU_REG, using a polynomial approximation. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/poly_tan.c,v 1.10 1999/08/28 00:42:54 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/poly_tan.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "reg_constant.h" -#include "control_w.h" - - -#define HIPOWERop 3 /* odd poly, positive terms */ -static unsigned short oddplterms[HIPOWERop][4] = -{ - {0x846a, 0x42d1, 0xb544, 0x921f}, - {0x6fb2, 0x0215, 0x95c0, 0x099c}, - {0xfce6, 0x0cc8, 0x1c9a, 0x0000} -}; -#define HIPOWERon 2 /* odd poly, negative terms */ -static unsigned short oddnegterms[HIPOWERon][4] = -{ - {0x6906, 0xe205, 0x25c8, 0x8838}, - {0x1dd7, 0x3fe3, 0x944e, 0x002c} -}; -#define HIPOWERep 2 /* even poly, positive terms */ -static unsigned short evenplterms[HIPOWERep][4] = -{ - {0xdb8f, 0x3761, 0x1432, 0x2acf}, - {0x16eb, 0x13c1, 0x3099, 0x0003} -}; -#define HIPOWERen 2 /* even poly, negative terms */ -static unsigned short evennegterms[HIPOWERen][4] = -{ - {0x3a7c, 0xe4c5, 0x7f87, 0x2945}, - {0x572b, 0x664c, 0xc543, 0x018c} -}; - - -/*--- poly_tan() ------------------------------------------------------------+ - | | - +---------------------------------------------------------------------------*/ -void -poly_tan(FPU_REG * arg, FPU_REG * y_reg) -{ - char invert = 0; - short exponent; - FPU_REG odd_poly, even_poly, pos_poly, neg_poly; - FPU_REG argSq; - long long arg_signif, argSqSq; - - - exponent = arg->exp - EXP_BIAS; - - if (arg->tag == TW_Zero) { - /* Return 0.0 */ - reg_move(&CONST_Z, y_reg); - return; - } - if (exponent >= -1) { - /* argument is in the range [0.5 .. 1.0] */ - if (exponent >= 0) { -#ifdef PARANOID - if ((exponent == 0) && - (arg->sigl == 0) && (arg->sigh == 0x80000000)) -#endif /* PARANOID */ - { - arith_overflow(y_reg); - return; - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic - * error */ - return; -#endif /* PARANOID */ - } - /* The argument is in the range [0.5 .. 1.0) */ - /* Convert the argument to a number in the range (0.0 .. 0.5] */ - *((long long *) (&arg->sigl)) = -*((long long *) (&arg->sigl)); - normalize(arg); /* Needed later */ - exponent = arg->exp - EXP_BIAS; - invert = 1; - } -#ifdef PARANOID - if (arg->sign != 0) { /* Can't hack a number < 0.0 */ - arith_invalid(y_reg); - return; - } /* Need a positive number */ -#endif /* PARANOID */ - - *(long long *) &arg_signif = *(long long *) &(arg->sigl); - if (exponent < -1) { - /* shift the argument right by the required places */ - if (shrx(&arg_signif, -1 - exponent) >= (unsigned)0x80000000) - arg_signif++; /* round up */ - } - mul64(&arg_signif, &arg_signif, (long long *) (&argSq.sigl)); - mul64((long long *) (&argSq.sigl), (long long *) (&argSq.sigl), &argSqSq); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, oddplterms, HIPOWERop - 1); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, oddnegterms, HIPOWERon - 1); - mul64((long long *) (&argSq.sigl), (long long *) (&neg_poly.sigl), - (long long *) (&neg_poly.sigl)); - - /* Subtract the mantissas */ - *((long long *) (&pos_poly.sigl)) -= *((long long *) (&neg_poly.sigl)); - - /* Convert to 64 bit signed-compatible */ - pos_poly.exp -= 1; - - reg_move(&pos_poly, &odd_poly); - normalize(&odd_poly); - - reg_mul(&odd_poly, arg, &odd_poly, FULL_PRECISION); - reg_u_add(&odd_poly, arg, &odd_poly, FULL_PRECISION); /* This is just the odd - * polynomial */ - - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(pos_poly.sign) = 0; - pos_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &pos_poly.sigl, (unsigned *) &argSqSq, evenplterms, HIPOWERep - 1); - mul64((long long *) (&argSq.sigl), - (long long *) (&pos_poly.sigl), (long long *) (&pos_poly.sigl)); - - /* will be a valid positive nr with expon = 0 */ - *(short *) &(neg_poly.sign) = 0; - neg_poly.exp = EXP_BIAS; - - /* Do the basic fixed point polynomial evaluation */ - polynomial((u_int *) &neg_poly.sigl, (unsigned *) &argSqSq, evennegterms, HIPOWERen - 1); - - /* Subtract the mantissas */ - *((long long *) (&neg_poly.sigl)) -= *((long long *) (&pos_poly.sigl)); - /* and multiply by argSq */ - - /* Convert argSq to a valid reg number */ - *(short *) &(argSq.sign) = 0; - argSq.exp = EXP_BIAS - 1; - normalize(&argSq); - - /* Convert to 64 bit signed-compatible */ - neg_poly.exp -= 1; - - reg_move(&neg_poly, &even_poly); - normalize(&even_poly); - - reg_mul(&even_poly, &argSq, &even_poly, FULL_PRECISION); - reg_add(&even_poly, &argSq, &even_poly, FULL_PRECISION); - reg_sub(&CONST_1, &even_poly, &even_poly, FULL_PRECISION); /* This is just the even - * polynomial */ - - /* Now ready to copy the results */ - if (invert) { - reg_div(&even_poly, &odd_poly, y_reg, FULL_PRECISION); - } else { - reg_div(&odd_poly, &even_poly, y_reg, FULL_PRECISION); - } - -} diff --git a/sys/platform/pc32/gnu/fpemul/polynomial.s b/sys/platform/pc32/gnu/fpemul/polynomial.s deleted file mode 100644 index 3dc3c767ad..0000000000 --- a/sys/platform/pc32/gnu/fpemul/polynomial.s +++ /dev/null @@ -1,191 +0,0 @@ -/* - * polynomial.S - * - * Fixed point arithmetic polynomial evaluation. - * - * Call from C as: - * void polynomial(unsigned accum[], unsigned x[], unsigned terms[][2], - * int n) - * - * Computes: - * terms[0] + (terms[1] + (terms[2] + ... + (terms[n-1]*x)*x)*x)*x) ... )*x - * The result is returned in accum. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/polynomial.s,v 1.8 1999/08/28 00:42:55 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/polynomial.s,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - .file "fpolynom.s" - -#include "fpu_asm.h" - - -/* #define EXTRA_PRECISE*/ - -#define TERM_SIZE $8 - - -.text -ENTRY(polynomial) - pushl %ebp - movl %esp,%ebp - subl $32,%esp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* accum */ - movl PARAM2,%edi /* x */ - movl PARAM3,%ebx /* terms */ - movl PARAM4,%ecx /* n */ - - movl TERM_SIZE,%eax - mull %ecx - movl %eax,%ecx - - movl 4(%ebx,%ecx,1),%edx /* terms[n] */ - movl %edx,-20(%ebp) - movl (%ebx,%ecx,1),%edx /* terms[n] */ - movl %edx,-24(%ebp) - xor %eax,%eax - movl %eax,-28(%ebp) - - subl TERM_SIZE,%ecx - js L_accum_done - -L_accum_loop: - xor %eax,%eax - movl %eax,-4(%ebp) - movl %eax,-8(%ebp) - -#ifdef EXTRA_PRECISE - movl -28(%ebp),%eax - mull 4(%edi) /* x ms long */ - movl %edx,-12(%ebp) -#endif EXTRA_PRECISE - - movl -24(%ebp),%eax - mull (%edi) /* x ls long */ -/* movl %eax,-16(%ebp) */ /* Not needed */ - addl %edx,-12(%ebp) - adcl $0,-8(%ebp) - - movl -24(%ebp),%eax - mull 4(%edi) /* x ms long */ - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl -20(%ebp),%eax - mull (%edi) - addl %eax,-12(%ebp) - adcl %edx,-8(%ebp) - adcl $0,-4(%ebp) - - movl -20(%ebp),%eax - mull 4(%edi) - addl %eax,-8(%ebp) - adcl %edx,-4(%ebp) - -/* Now add the next term */ - movl (%ebx,%ecx,1),%eax - addl %eax,-8(%ebp) - movl 4(%ebx,%ecx,1),%eax - adcl %eax,-4(%ebp) - -/* And put into the second register */ - movl -4(%ebp),%eax - movl %eax,-20(%ebp) - movl -8(%ebp),%eax - movl %eax,-24(%ebp) - -#ifdef EXTRA_PRECISE - movl -12(%ebp),%eax - movl %eax,-28(%ebp) -#else - testb $128,-25(%ebp) - je L_no_poly_round - - addl $1,-24(%ebp) - adcl $0,-20(%ebp) -L_no_poly_round: -#endif EXTRA_PRECISE - - subl TERM_SIZE,%ecx - jns L_accum_loop - -L_accum_done: -#ifdef EXTRA_PRECISE -/* And round the result */ - testb $128,-25(%ebp) - je L_poly_done - - addl $1,-24(%ebp) - adcl $0,-20(%ebp) -#endif EXTRA_PRECISE - -L_poly_done: - movl -24(%ebp),%eax - movl %eax,(%esi) - movl -20(%ebp),%eax - movl %eax,4(%esi) - - popl %ebx - popl %edi - popl %esi - leave - ret diff --git a/sys/platform/pc32/gnu/fpemul/reg_add_sub.c b/sys/platform/pc32/gnu/fpemul/reg_add_sub.c deleted file mode 100644 index 7694e9884d..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_add_sub.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * reg_add_sub.c - * - * Functions to add or subtract two registers and put the result in a third. - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_add_sub.c,v 1.8 1999/08/28 00:42:55 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_add_sub.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | For each function, the destination may be any FPU_REG, including one of | - | the source FPU_REGs. | - +---------------------------------------------------------------------------*/ - -#include "reg_constant.h" -#include "control_w.h" - - -void -reg_add(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w) -{ - int diff; - - if (!(a->tag | b->tag)) { - /* Both registers are valid */ - if (!(a->sign ^ b->sign)) { - /* signs are the same */ - reg_u_add(a, b, dest, control_w); - dest->sign = a->sign; - return; - } - /* The signs are different, so do a subtraction */ - diff = a->exp - b->exp; - if (!diff) { - diff = a->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (!diff) { - diff = a->sigl > b->sigl; - if (!diff) - diff = -(a->sigl < b->sigl); - } - } - if (diff > 0) { - reg_u_sub(a, b, dest, control_w); - dest->sign = a->sign; - } else - if (diff == 0) { - reg_move(&CONST_Z, dest); - /* sign depends upon rounding mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } else { - reg_u_sub(b, a, dest, control_w); - dest->sign = b->sign; - } - return; - } else { - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (a->tag == TW_Zero) { - if (b->tag == TW_Zero) { - char different_signs = a->sign ^ b->sign; - /* Both are zero, result will be zero. */ - reg_move(a, dest); - if (different_signs) { - /* Signs are different. */ - /* Sign of answer depends upon - * rounding mode. */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } - } else { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - } - return; - } else - if (b->tag == TW_Zero) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag != TW_Infinity) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } - if (a->sign == b->sign) { - /* They are both + or - * - infinity */ - reg_move(a, dest); - return; - } - arith_invalid(dest); /* Infinity-Infinity is - * undefined. */ - return; - } else - if (b->tag == TW_Infinity) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - return; - } - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x101); -#endif -} - - -/* Subtract b from a. (a-b) -> dest */ -void -reg_sub(FPU_REG * a, FPU_REG * b, FPU_REG * dest, int control_w) -{ - int diff; - - if (!(a->tag | b->tag)) { - /* Both registers are valid */ - diff = a->exp - b->exp; - if (!diff) { - diff = a->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (!diff) { - diff = a->sigl > b->sigl; - if (!diff) - diff = -(a->sigl < b->sigl); - } - } - switch (a->sign * 2 + b->sign) { - case 0: /* P - P */ - case 3: /* N - N */ - if (diff > 0) { - reg_u_sub(a, b, dest, control_w); - dest->sign = a->sign; - } else - if (diff == 0) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(&CONST_Z, dest); - /* sign depends upon rounding mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } else { - reg_u_sub(b, a, dest, control_w); - dest->sign = a->sign ^ SIGN_POS ^ SIGN_NEG; - } - return; - case 1: /* P - N */ - reg_u_add(a, b, dest, control_w); - dest->sign = SIGN_POS; - return; - case 2: /* N - P */ - reg_u_add(a, b, dest, control_w); - dest->sign = SIGN_NEG; - return; - } - } else { - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (b->tag == TW_Zero) { - if (a->tag == TW_Zero) { - char same_signs = !(a->sign ^ b->sign); - /* Both are zero, result will be zero. */ - reg_move(a, dest); /* Answer for different - * signs. */ - if (same_signs) { - /* Sign depends upon rounding - * mode */ - dest->sign = ((control_w & CW_RC) != RC_DOWN) - ? SIGN_POS : SIGN_NEG; - } - } else { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - } - return; - } else - if (a->tag == TW_Zero) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign ^= SIGN_POS ^ SIGN_NEG; - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag != TW_Infinity) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - return; - } - /* Both args are Infinity */ - if (a->sign == b->sign) { - arith_invalid(dest); /* Infinity-Infinity is - * undefined. */ - return; - } - reg_move(a, dest); - return; - } else - if (b->tag == TW_Infinity) { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign ^= SIGN_POS ^ SIGN_NEG; - return; - } - } -#ifdef PARANOID - EXCEPTION(EX_INTERNAL | 0x110); -#endif -} diff --git a/sys/platform/pc32/gnu/fpemul/reg_compare.c b/sys/platform/pc32/gnu/fpemul/reg_compare.c deleted file mode 100644 index 357cc1de63..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_compare.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * reg_compare.c - * - * Compare two floating point registers - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_compare.c,v 1.11 1999/08/28 00:42:55 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_compare.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | compare() is the core FPU_REG comparison function | - +---------------------------------------------------------------------------*/ -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "control_w.h" -#include "status_w.h" - - -int -compare(FPU_REG * b) -{ - int diff; - - if (FPU_st0_ptr->tag | b->tag) { - if (FPU_st0_ptr->tag == TW_Zero) { - if (b->tag == TW_Zero) - return COMP_A_eq_B; - if (b->tag == TW_Valid) { -#ifdef DENORM_OPERAND - if ((b->exp <= EXP_UNDER) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - } - } else - if (b->tag == TW_Zero) { - if (FPU_st0_ptr->tag == TW_Valid) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - } - } - if (FPU_st0_ptr->tag == TW_Infinity) { - if ((b->tag == TW_Valid) || (b->tag == TW_Zero)) { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) - && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - } else - if (b->tag == TW_Infinity) { - /* The 80486 book says that infinities - * can be equal! */ - return (FPU_st0_ptr->sign == b->sign) ? COMP_A_eq_B : - ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); - } - /* Fall through to the NaN code */ - } else - if (b->tag == TW_Infinity) { - if ((FPU_st0_ptr->tag == TW_Valid) || (FPU_st0_ptr->tag == TW_Zero)) { -#ifdef DENORM_OPERAND - if ((FPU_st0_ptr->tag == TW_Valid) - && (FPU_st0_ptr->exp <= EXP_UNDER) - && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - return (b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - } - /* Fall through to the NaN code */ - } - /* The only possibility now should be that one of the - * arguments is a NaN */ - if ((FPU_st0_ptr->tag == TW_NaN) || (b->tag == TW_NaN)) { - if (((FPU_st0_ptr->tag == TW_NaN) && !(FPU_st0_ptr->sigh & 0x40000000)) - || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000))) - /* At least one arg is a signaling NaN */ - return COMP_No_Comp | COMP_SNaN | COMP_NaN; - else - /* Neither is a signaling NaN */ - return COMP_No_Comp | COMP_NaN; - } - EXCEPTION(EX_Invalid); - } -#ifdef PARANOID - if (!(FPU_st0_ptr->sigh & 0x80000000)) - EXCEPTION(EX_Invalid); - if (!(b->sigh & 0x80000000)) - EXCEPTION(EX_Invalid); -#endif /* PARANOID */ - -#ifdef DENORM_OPERAND - if (((FPU_st0_ptr->exp <= EXP_UNDER) || - (b->exp <= EXP_UNDER)) && (denormal_operand())) - return COMP_Denormal; -#endif /* DENORM_OPERAND */ - - if (FPU_st0_ptr->sign != b->sign) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - - diff = FPU_st0_ptr->exp - b->exp; - if (diff == 0) { - diff = FPU_st0_ptr->sigh - b->sigh; /* Works only if ms bits - * are identical */ - if (diff == 0) { - diff = FPU_st0_ptr->sigl > b->sigl; - if (diff == 0) - diff = -(FPU_st0_ptr->sigl < b->sigl); - } - } - if (diff > 0) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B; - if (diff < 0) - return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B; - return COMP_A_eq_B; - -} - - -/* This function requires that st(0) is not empty */ -int -compare_st_data(void) -{ - int f = 0, c; - - c = compare(&FPU_loaded_data); - - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - EXCEPTION(EX_Invalid); - f = SW_C3 | SW_C2 | SW_C0; - } else { - /* One of the operands is a de-normal */ - return 0; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x121); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} - - -static int -compare_st_st(int nr) -{ - int f = 0, c; - - if (!NOT_EMPTY_0 || !NOT_EMPTY(nr)) { - setcc(SW_C3 | SW_C2 | SW_C0); - /* Stack fault */ - EXCEPTION(EX_StackUnder); - return control_word & CW_Invalid; - } - c = compare(&st(nr)); - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - setcc(SW_C3 | SW_C2 | SW_C0); - EXCEPTION(EX_Invalid); - return control_word & CW_Invalid; - } else { - /* One of the operands is a de-normal */ - return control_word & CW_Denormal; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x122); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} - - -static int -compare_u_st_st(int nr) -{ - int f = 0, c; - - if (!NOT_EMPTY_0 || !NOT_EMPTY(nr)) { - setcc(SW_C3 | SW_C2 | SW_C0); - /* Stack fault */ - EXCEPTION(EX_StackUnder); - return control_word & CW_Invalid; - } - c = compare(&st(nr)); - if (c & (COMP_NaN | COMP_Denormal)) { - if (c & COMP_NaN) { - setcc(SW_C3 | SW_C2 | SW_C0); - if (c & COMP_SNaN) { /* This is the only difference - * between un-ordered and - * ordinary comparisons */ - EXCEPTION(EX_Invalid); - return control_word & CW_Invalid; - } - return 1; - } else { - /* One of the operands is a de-normal */ - return control_word & CW_Denormal; - } - } else - switch (c) { - case COMP_A_lt_B: - f = SW_C0; - break; - case COMP_A_eq_B: - f = SW_C3; - break; - case COMP_A_gt_B: - f = 0; - break; - case COMP_No_Comp: - f = SW_C3 | SW_C2 | SW_C0; - break; -#ifdef PARANOID - default: - EXCEPTION(EX_INTERNAL | 0x123); - f = SW_C3 | SW_C2 | SW_C0; - break; -#endif /* PARANOID */ - } - setcc(f); - return 1; -} -/*---------------------------------------------------------------------------*/ - -void -fcom_st() -{ - /* fcom st(i) */ - compare_st_st(FPU_rm); -} - - -void -fcompst() -{ - /* fcomp st(i) */ - if (compare_st_st(FPU_rm)) - pop(); -} - - -void -fcompp() -{ - /* fcompp */ - if (FPU_rm != 1) { - Un_impl(); - return; - } - if (compare_st_st(1)) { - pop(); - FPU_st0_ptr = &st(0); - pop(); - } -} - - -void -fucom_() -{ - /* fucom st(i) */ - compare_u_st_st(FPU_rm); - -} - - -void -fucomp() -{ - /* fucomp st(i) */ - if (compare_u_st_st(FPU_rm)) - pop(); -} - - -void -fucompp() -{ - /* fucompp */ - if (FPU_rm == 1) { - if (compare_u_st_st(1)) { - pop(); - FPU_st0_ptr = &st(0); - pop(); - } - } else - Un_impl(); -} diff --git a/sys/platform/pc32/gnu/fpemul/reg_constant.c b/sys/platform/pc32/gnu/fpemul/reg_constant.c deleted file mode 100644 index 2f5327bdfb..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_constant.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * reg_constant.c - * - * All of the constant FPU_REGs - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_constant.c,v 1.6.8.1 2000/08/03 00:53:55 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_constant.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - */ - - - -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "status_w.h" - - -FPU_REG CONST_1 = {SIGN_POS, TW_Valid, EXP_BIAS, -0x00000000, 0x80000000}; -static FPU_REG CONST_L2T = {SIGN_POS, TW_Valid, EXP_BIAS + 1, -0xcd1b8afe, 0xd49a784b}; -static FPU_REG CONST_L2E = {SIGN_POS, TW_Valid, EXP_BIAS, -0x5c17f0bc, 0xb8aa3b29}; -FPU_REG CONST_PI = {SIGN_POS, TW_Valid, EXP_BIAS + 1, -0x2168c235, 0xc90fdaa2}; -FPU_REG CONST_PI2 = {SIGN_POS, TW_Valid, EXP_BIAS, -0x2168c235, 0xc90fdaa2}; -FPU_REG CONST_PI4 = {SIGN_POS, TW_Valid, EXP_BIAS - 1, -0x2168c235, 0xc90fdaa2}; -static FPU_REG CONST_LG2 = {SIGN_POS, TW_Valid, EXP_BIAS - 2, -0xfbcff799, 0x9a209a84}; -FPU_REG CONST_LN2 = {SIGN_POS, TW_Valid, EXP_BIAS - 1, -0xd1cf79ac, 0xb17217f7}; -/* Only the sign (and tag) is used in internal zeroes */ -FPU_REG CONST_Z = {SIGN_POS, TW_Zero, 0, 0x0, 0x0}; -/* Only the sign and significand (and tag) are used in internal NaNs */ -/* The 80486 never generates one of these -FPU_REG CONST_SNAN = { SIGN_POS, TW_NaN, EXP_OVER, 0x00000001, 0x80000000 }; - */ -/* This is the real indefinite QNaN */ -FPU_REG CONST_QNaN = {SIGN_NEG, TW_NaN, EXP_OVER, 0x00000000, 0xC0000000}; -/* Only the sign (and tag) is used in internal infinities */ -FPU_REG CONST_INF = {SIGN_POS, TW_Infinity, EXP_OVER, 0x00000000, 0x80000000}; - - - -static void -fld_const(FPU_REG * c) -{ - FPU_REG *st_new_ptr; - - if (STACK_OVERFLOW) { - stack_overflow(); - return; - } - push(); - reg_move(c, FPU_st0_ptr); - status_word &= ~SW_C1; -} - - -static void -fld1(void) -{ - fld_const(&CONST_1); -} - -static void -fldl2t(void) -{ - fld_const(&CONST_L2T); -} - -static void -fldl2e(void) -{ - fld_const(&CONST_L2E); -} - -static void -fldpi(void) -{ - fld_const(&CONST_PI); -} - -static void -fldlg2(void) -{ - fld_const(&CONST_LG2); -} - -static void -fldln2(void) -{ - fld_const(&CONST_LN2); -} - -static void -fldz(void) -{ - fld_const(&CONST_Z); -} - -static FUNC constants_table[] = { - fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, Un_impl -}; - -void -fconst(void) -{ - (constants_table[FPU_rm]) (); -} diff --git a/sys/platform/pc32/gnu/fpemul/reg_constant.h b/sys/platform/pc32/gnu/fpemul/reg_constant.h deleted file mode 100644 index 99550f116b..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_constant.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * reg_constant.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_constant.h,v 1.7 1999/08/28 00:42:55 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_constant.h,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#ifndef _REG_CONSTANT_H_ -#define _REG_CONSTANT_H_ - -#include "fpu_emu.h" - -extern FPU_REG CONST_1; -extern FPU_REG CONST_2; -extern FPU_REG CONST_HALF; -extern FPU_REG CONST_L2T; -extern FPU_REG CONST_L2E; -extern FPU_REG CONST_PI; -extern FPU_REG CONST_PI2; -extern FPU_REG CONST_PI4; -extern FPU_REG CONST_LG2; -extern FPU_REG CONST_LN2; -extern FPU_REG CONST_Z; -extern FPU_REG CONST_PINF; -extern FPU_REG CONST_INF; -extern FPU_REG CONST_MINF; -extern FPU_REG CONST_QNaN; - -#endif /* _REG_CONSTANT_H_ */ diff --git a/sys/platform/pc32/gnu/fpemul/reg_div.s b/sys/platform/pc32/gnu/fpemul/reg_div.s deleted file mode 100644 index a6dcfdf6df..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_div.s +++ /dev/null @@ -1,291 +0,0 @@ - .file "reg_div.S" -/* - * reg_div.S - * - * Divide one FPU_REG by another and put the result in a destination FPU_REG. - * - * Call from C as: - * void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest, - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_div.s,v 1.9.2.1 2000/07/07 00:38:42 obrien Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_div.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - -#include "fpu_asm.h" - -.text -ENTRY(reg_div) - pushl %ebp - movl %esp,%ebp - - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%ebx - movl PARAM3,%edi - - movb TAG(%esi),%al - orb TAG(%ebx),%al - - jne L_div_special /* Not (both numbers TW_Valid) */ - -#ifdef DENORM_OPERAND -/* Check for denormals */ - cmpl EXP_UNDER,EXP(%esi) - jg xL_arg1_not_denormal - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xL_arg1_not_denormal: - cmpl EXP_UNDER,EXP(%ebx) - jg xL_arg2_not_denormal - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xL_arg2_not_denormal: -#endif DENORM_OPERAND - -/* Both arguments are TW_Valid */ - movb TW_Valid,TAG(%edi) - - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%ebx) - setne (%edi) /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */ - - movl EXP(%esi),%edx - movl EXP(%ebx),%eax - subl %eax,%edx - addl EXP_BIAS,%edx - movl %edx,EXP(%edi) - - jmp _divide_kernel - - -/*-----------------------------------------------------------------------*/ -L_div_special: - cmpb TW_NaN,TAG(%esi) /* A NaN with anything to give NaN */ - je L_arg1_NaN - - cmpb TW_NaN,TAG(%ebx) /* A NaN with anything to give NaN */ - jne L_no_NaN_arg - -/* Operations on NaNs */ -L_arg1_NaN: -L_arg2_NaN: - pushl %edi /* Destination */ - pushl %ebx - pushl %esi - call real_2op_NaN - jmp LDiv_exit - -/* Invalid operations */ -L_zero_zero: -L_inf_inf: - pushl %edi /* Destination */ - call arith_invalid /* 0/0 or Infinity/Infinity */ - jmp LDiv_exit - -L_no_NaN_arg: - cmpb TW_Infinity,TAG(%esi) - jne L_arg1_not_inf - - cmpb TW_Infinity,TAG(%ebx) - je L_inf_inf /* invalid operation */ - - cmpb TW_Valid,TAG(%ebx) - je L_inf_valid - -#ifdef PARANOID - /* arg2 must be zero or valid */ - cmpb TW_Zero,TAG(%ebx) - ja L_unknown_tags -#endif PARANOID - - /* Note that p16-9 says that infinity/0 returns infinity */ - jmp L_copy_arg1 /* Answer is Inf */ - -L_inf_valid: -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%ebx) - jg L_copy_arg1 /* Answer is Inf */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif DENORM_OPERAND - - jmp L_copy_arg1 /* Answer is Inf */ - -L_arg1_not_inf: - cmpb TW_Zero,TAG(%ebx) /* Priority to div-by-zero error */ - jne L_arg2_not_zero - - cmpb TW_Zero,TAG(%esi) - je L_zero_zero /* invalid operation */ - -#ifdef PARANOID - /* arg1 must be valid */ - cmpb TW_Valid,TAG(%esi) - ja L_unknown_tags -#endif PARANOID - -/* Division by zero error */ - pushl %edi /* destination */ - movb SIGN(%esi),%al - xorb SIGN(%ebx),%al - pushl %eax /* lower 8 bits have the sign */ - call divide_by_zero - jmp LDiv_exit - -L_arg2_not_zero: - cmpb TW_Infinity,TAG(%ebx) - jne L_arg2_not_inf - -#ifdef DENORM_OPERAND - cmpb TW_Valid,TAG(%esi) - jne L_return_zero - - cmpl EXP_UNDER,EXP(%esi) - jg L_return_zero /* Answer is zero */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif DENORM_OPERAND - - jmp L_return_zero /* Answer is zero */ - -L_arg2_not_inf: - -#ifdef PARANOID - cmpb TW_Zero,TAG(%esi) - jne L_unknown_tags -#endif PARANOID - - /* arg1 is zero, arg2 is not Infinity or a NaN */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%ebx) - jg L_copy_arg1 /* Answer is zero */ - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit -#endif DENORM_OPERAND - -L_copy_arg1: - movb TAG(%esi),%al - movb %al,TAG(%edi) - movl EXP(%esi),%eax - movl %eax,EXP(%edi) - movl SIGL(%esi),%eax - movl %eax,SIGL(%edi) - movl SIGH(%esi),%eax - movl %eax,SIGH(%edi) - - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%ebx) - jne LDiv_negative_result - - movb SIGN_POS,SIGN(%edi) - jmp LDiv_exit - -LDiv_set_result_sign: - movb SIGN(%esi),%cl - cmpb %cl,SIGN(%edi) - jne LDiv_negative_result - - movb SIGN_POS,SIGN(%ebx) - jmp LDiv_exit - -LDiv_negative_result: - movb SIGN_NEG,SIGN(%edi) - -LDiv_exit: - leal -12(%ebp),%esp - - popl %ebx - popl %edi - popl %esi - leave - ret - - -L_return_zero: - movb TW_Zero,TAG(%edi) - jmp LDiv_set_result_sign - -#ifdef PARANOID -L_unknown_tags: - push EX_INTERNAL | 0x208 - call EXCEPTION - - /* Generate a NaN for unknown tags */ - movl _CONST_QNaN,%eax - movl %eax,(%edi) - movl _CONST_QNaN+4,%eax - movl %eax,SIGL(%edi) - movl _CONST_QNaN+8,%eax - movl %eax,SIGH(%edi) - jmp LDiv_exit -#endif PARANOID diff --git a/sys/platform/pc32/gnu/fpemul/reg_ld_str.c b/sys/platform/pc32/gnu/fpemul/reg_ld_str.c deleted file mode 100644 index 6a019a6681..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_ld_str.c +++ /dev/null @@ -1,1389 +0,0 @@ -/* - * reg_ld_str.c - * - * All of the functions which transfer data between user memory and FPU_REGs. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_ld_str.c,v 1.13 1999/08/28 00:42:56 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_ld_str.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -/*---------------------------------------------------------------------------+ - | Note: | - | The file contains code which accesses user memory. | - | Emulator static data may change when user memory is accessed, due to | - | other processes using the emulator while swapping is in progress. | - +---------------------------------------------------------------------------*/ -#include -#include -#include -#include - -#include "fpu_emu.h" -#include "fpu_system.h" -#include "exception.h" -#include "reg_constant.h" -#include "control_w.h" -#include "status_w.h" - - -#define EXTENDED_Emax 0x3fff /* largest valid exponent */ -#define EXTENDED_Ebias 0x3fff -#define EXTENDED_Emin (-0x3ffe) /* smallest valid exponent */ - -#define DOUBLE_Emax 1023 /* largest valid exponent */ -#define DOUBLE_Ebias 1023 -#define DOUBLE_Emin (-1022) /* smallest valid exponent */ - -#define SINGLE_Emax 127 /* largest valid exponent */ -#define SINGLE_Ebias 127 -#define SINGLE_Emin (-126) /* smallest valid exponent */ - -#define LOST_UP (EX_Precision | SW_C1) -#define LOST_DOWN EX_Precision - -FPU_REG FPU_loaded_data; - - -/* Get a long double from user memory */ -void -reg_load_extended(void) -{ - long double *s = (long double *) FPU_data_address; - unsigned long sigl, sigh, exp; - - REENTRANT_CHECK(OFF); - /* Use temporary variables here because FPU_loaded data is static and - * hence re-entrancy problems can arise */ - sigl = fuword((unsigned long *) s); - sigh = fuword(1 + (unsigned long *) s); - exp = fusword(4 + (unsigned short *) s); - REENTRANT_CHECK(ON); - - FPU_loaded_data.sigl = sigl; - FPU_loaded_data.sigh = sigh; - FPU_loaded_data.exp = exp; - - if (FPU_loaded_data.exp & 0x8000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - if ((FPU_loaded_data.exp &= 0x7fff) == 0) { - if (!(FPU_loaded_data.sigl | FPU_loaded_data.sigh)) { - FPU_loaded_data.tag = TW_Zero; - return; - } - /* The number is a de-normal or pseudodenormal. */ - /* The 80486 doesn't regard pseudodenormals as denormals here. */ - if (!(FPU_loaded_data.sigh & 0x80000000)) - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp++; - - /* The default behaviour will now take care of it. */ - } else - if (FPU_loaded_data.exp == 0x7fff) { - FPU_loaded_data.exp = EXTENDED_Emax; - if ((FPU_loaded_data.sigh == 0x80000000) - && (FPU_loaded_data.sigl == 0)) { - FPU_loaded_data.tag = TW_Infinity; - return; - } else - if (!(FPU_loaded_data.sigh & 0x80000000)) { - /* Unsupported NaN data type */ - EXCEPTION(EX_Invalid); - FPU_loaded_data.tag = TW_NaN; - return; - } - FPU_loaded_data.tag = TW_NaN; - return; - } - FPU_loaded_data.exp = (FPU_loaded_data.exp & 0x7fff) - EXTENDED_Ebias - + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - - if (!(sigh & 0x80000000)) { - /* Unsupported data type */ - EXCEPTION(EX_Invalid); - normalize_nuo(&FPU_loaded_data); - } -} - - -/* Get a double from user memory */ -void -reg_load_double(void) -{ - double *dfloat = (double *) FPU_data_address; - int exp; - unsigned m64, l64; - - REENTRANT_CHECK(OFF); - m64 = fuword(1 + (unsigned long *) dfloat); - l64 = fuword((unsigned long *) dfloat); - REENTRANT_CHECK(ON); - - if (m64 & 0x80000000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias; - m64 &= 0xfffff; - if (exp > DOUBLE_Emax) { - /* Infinity or NaN */ - if ((m64 == 0) && (l64 == 0)) { - /* +- infinity */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_Infinity; - return; - } else { - /* Must be a signaling or quiet NaN */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_NaN; - FPU_loaded_data.sigh = (m64 << 11) | 0x80000000; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - return; - } - } else - if (exp < DOUBLE_Emin) { - /* Zero or de-normal */ - if ((m64 == 0) && (l64 == 0)) { - /* Zero */ - int c = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = c; - return; - } else { - /* De-normal */ - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp = DOUBLE_Emin + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = m64 << 11; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - normalize_nuo(&FPU_loaded_data); - return; - } - } else { - FPU_loaded_data.exp = exp + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = (m64 << 11) | 0x80000000; - FPU_loaded_data.sigh |= l64 >> 21; - FPU_loaded_data.sigl = l64 << 11; - - return; - } -} - - -/* Get a float from user memory */ -void -reg_load_single(void) -{ - float *single = (float *) FPU_data_address; - unsigned m32; - int exp; - - REENTRANT_CHECK(OFF); - m32 = fuword((unsigned long *) single); - REENTRANT_CHECK(ON); - - if (m32 & 0x80000000) - FPU_loaded_data.sign = SIGN_NEG; - else - FPU_loaded_data.sign = SIGN_POS; - if (!(m32 & 0x7fffffff)) { - /* Zero */ - int c = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = c; - return; - } - exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias; - m32 = (m32 & 0x7fffff) << 8; - if (exp < SINGLE_Emin) { - /* De-normals */ - EXCEPTION(EX_Denormal); - FPU_loaded_data.exp = SINGLE_Emin + EXP_BIAS; - FPU_loaded_data.tag = TW_Valid; - FPU_loaded_data.sigh = m32; - FPU_loaded_data.sigl = 0; - normalize_nuo(&FPU_loaded_data); - return; - } else - if (exp > SINGLE_Emax) { - /* Infinity or NaN */ - if (m32 == 0) { - /* +- infinity */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_Infinity; - return; - } else { - /* Must be a signaling or quiet NaN */ - FPU_loaded_data.exp = EXTENDED_Emax; - FPU_loaded_data.tag = TW_NaN; - FPU_loaded_data.sigh = m32 | 0x80000000; - FPU_loaded_data.sigl = 0; - return; - } - } else { - FPU_loaded_data.exp = exp + EXP_BIAS; - FPU_loaded_data.sigh = m32 | 0x80000000; - FPU_loaded_data.sigl = 0; - FPU_loaded_data.tag = TW_Valid; - } -} - - -/* Get a long long from user memory */ -void -reg_load_int64(void) -{ - long long *_s = (long long *) FPU_data_address; - int e; - long long s; - - REENTRANT_CHECK(OFF); - ((unsigned long *) &s)[0] = fuword((unsigned long *) _s); - ((unsigned long *) &s)[1] = fuword(1 + (unsigned long *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 63; - *((long long *) &FPU_loaded_data.sigl) = s; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a long from user memory */ -void -reg_load_int32(void) -{ - long *_s = (long *) FPU_data_address; - long s; - int e; - - REENTRANT_CHECK(OFF); - s = (long) fuword((unsigned long *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 31; - FPU_loaded_data.sigh = s; - FPU_loaded_data.sigl = 0; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a short from user memory */ -void -reg_load_int16(void) -{ - short *_s = (short *) FPU_data_address; - int s, e; - - REENTRANT_CHECK(OFF); - /* Cast as short to get the sign extended. */ - s = (short) fusword((unsigned short *) _s); - REENTRANT_CHECK(ON); - - if (s == 0) { - reg_move(&CONST_Z, &FPU_loaded_data); - return; - } - if (s > 0) - FPU_loaded_data.sign = SIGN_POS; - else { - s = -s; - FPU_loaded_data.sign = SIGN_NEG; - } - - e = EXP_BIAS + 15; - FPU_loaded_data.sigh = s << 16; - - FPU_loaded_data.sigl = 0; - FPU_loaded_data.exp = e; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); -} - - -/* Get a packed bcd array from user memory */ -void -reg_load_bcd(void) -{ - char *s = (char *) FPU_data_address; - int pos; - unsigned char bcd; - long long l = 0; - - for (pos = 8; pos >= 0; pos--) { - l *= 10; - REENTRANT_CHECK(OFF); - bcd = (unsigned char) fubyte((unsigned char *) s + pos); - REENTRANT_CHECK(ON); - l += bcd >> 4; - l *= 10; - l += bcd & 0x0f; - } - - /* Finish all access to user memory before putting stuff into the - * static FPU_loaded_data */ - REENTRANT_CHECK(OFF); - FPU_loaded_data.sign = - ((unsigned char) fubyte((unsigned char *) s + 9)) & 0x80 ? - SIGN_NEG : SIGN_POS; - REENTRANT_CHECK(ON); - - if (l == 0) { - char sign = FPU_loaded_data.sign; - reg_move(&CONST_Z, &FPU_loaded_data); - FPU_loaded_data.sign = sign; - } else { - *((long long *) &FPU_loaded_data.sigl) = l; - FPU_loaded_data.exp = EXP_BIAS + 63; - FPU_loaded_data.tag = TW_Valid; - normalize_nuo(&FPU_loaded_data); - } -} -/*===========================================================================*/ - -/* Put a long double into user memory */ -int -reg_store_extended(void) -{ - long double *d = (long double *) FPU_data_address; - long e = FPU_st0_ptr->exp - EXP_BIAS + EXTENDED_Ebias; - unsigned short sign = FPU_st0_ptr->sign * 0x8000; - unsigned long ls, ms; - - - if (FPU_st0_tag == TW_Valid) { - if (e >= 0x7fff) { - EXCEPTION(EX_Overflow); /* Overflow */ - /* This is a special case: see sec 16.2.5.1 of the - * 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - ls = 0; - ms = 0x80000000; - e = 0x7fff; - } else - return 0; - } else - if (e <= 0) { - if (e > -63) { - /* Correctly format the de-normal */ - int precision_loss; - FPU_REG tmp; - - EXCEPTION(EX_Denormal); - reg_move(FPU_st0_ptr, &tmp); - tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */ - if ((precision_loss = round_to_int(&tmp))) { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see - * sec 16.2.5.1 of the 80486 - * book */ - if (!(control_word & EX_Underflow)) - return 0; - } - e = 0; - ls = tmp.sigl; - ms = tmp.sigh; - } else { - /* ****** ??? This should not be - * possible */ - EXCEPTION(EX_Underflow); /* Underflow */ - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (control_word & EX_Underflow) { - /* Underflow to zero */ - ls = 0; - ms = 0; - e = FPU_st0_ptr->sign == SIGN_POS ? 0x7fff : 0xffff; - } else - return 0; - } - } else { - ls = FPU_st0_ptr->sigl; - ms = FPU_st0_ptr->sigh; - } - } else - if (FPU_st0_tag == TW_Zero) { - ls = ms = 0; - e = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - ls = 0; - ms = 0x80000000; - e = 0x7fff; - } else - if (FPU_st0_tag == TW_NaN) { - ls = FPU_st0_ptr->sigl; - ms = FPU_st0_ptr->sigh; - e = 0x7fff; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - ls = 0; - ms = 0xc0000000; - e = 0xffff; - } else - return 0; - } else { - /* We don't use TW_Denormal - * yet ... perhaps never! */ - EXCEPTION(EX_Invalid); - /* Store a NaN */ - e = 0x7fff; - ls = 1; - ms = 0x80000000; - } - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 10); */ - suword((unsigned long *) d, ls); - suword(1 + (unsigned long *) d, ms); - susword(4 + (short *) d, (unsigned short) e | sign); - REENTRANT_CHECK(ON); - - return 1; - -} - - -/* Put a double into user memory */ -int -reg_store_double(void) -{ - double *dfloat = (double *) FPU_data_address; - unsigned long l[2]; - if (FPU_st0_tag == TW_Valid) { - int exp; - FPU_REG tmp; - - reg_move(FPU_st0_ptr, &tmp); - exp = tmp.exp - EXP_BIAS; - - if (exp < DOUBLE_Emin) { /* It may be a denormal */ - /* Make a de-normal */ - int precision_loss; - - if (exp <= -EXTENDED_Ebias) - EXCEPTION(EX_Denormal); - - tmp.exp += -DOUBLE_Emin + 52; /* largest exp to be 51 */ - - if ((precision_loss = round_to_int(&tmp))) { -#ifdef PECULIAR_486 - /* Did it round to a non-denormal ? */ - /* This behaviour might be regarded as - * peculiar, it appears that the 80486 rounds - * to the dest precision, then converts to - * decide underflow. */ - if ((tmp.sigh == 0x00100000) && (tmp.sigl == 0) && - (FPU_st0_ptr->sigl & 0x000007ff)) - EXCEPTION(precision_loss); - else -#endif /* PECULIAR_486 */ - { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (!(control_word & EX_Underflow)) - return 0; - } - } - l[0] = tmp.sigl; - l[1] = tmp.sigh; - } else { - if (tmp.sigl & 0x000007ff) { - unsigned long increment = 0; /* avoid gcc warnings */ - - switch (control_word & CW_RC) { - case RC_RND: - /* Rounding can get a little messy.. */ - increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */ - ((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */ - break; - case RC_DOWN: /* towards -infinity */ - increment = (tmp.sign == SIGN_POS) ? 0 : tmp.sigl & 0x7ff; - break; - case RC_UP: /* towards +infinity */ - increment = (tmp.sign == SIGN_POS) ? tmp.sigl & 0x7ff : 0; - break; - case RC_CHOP: - increment = 0; - break; - } - - /* Truncate the mantissa */ - tmp.sigl &= 0xfffff800; - - if (increment) { - set_precision_flag_up(); - - if (tmp.sigl >= 0xfffff800) { - /* the sigl part overflows */ - if (tmp.sigh == 0xffffffff) { - /* The sigh part - * overflows */ - tmp.sigh = 0x80000000; - exp++; - if (exp >= EXP_OVER) - goto overflow; - } else { - tmp.sigh++; - } - tmp.sigl = 0x00000000; - } else { - /* We only need to increment - * sigl */ - tmp.sigl += 0x00000800; - } - } else - set_precision_flag_down(); - } - l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21); - l[1] = ((tmp.sigh >> 11) & 0xfffff); - - if (exp > DOUBLE_Emax) { - overflow: - EXCEPTION(EX_Overflow); - /* This is a special case: see sec 16.2.5.1 of - * the 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - l[0] = 0x00000000; /* Set to */ - l[1] = 0x7ff00000; /* + INF */ - } else - return 0; - } else { - /* Add the exponent */ - l[1] |= (((exp + DOUBLE_Ebias) & 0x7ff) << 20); - } - } - } else - if (FPU_st0_tag == TW_Zero) { - /* Number is zero */ - l[0] = 0; - l[1] = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - l[0] = 0; - l[1] = 0x7ff00000; - } else - if (FPU_st0_tag == TW_NaN) { - /* See if we can get a valid NaN from - * the FPU_REG */ - l[0] = (FPU_st0_ptr->sigl >> 11) | (FPU_st0_ptr->sigh << 21); - l[1] = ((FPU_st0_ptr->sigh >> 11) & 0xfffff); - if (!(l[0] | l[1])) { - /* This case does not seem to - * be handled by the 80486 - * specs */ - EXCEPTION(EX_Invalid); - /* Make the quiet NaN "real - * indefinite" */ - goto put_indefinite; - } - l[1] |= 0x7ff00000; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - put_indefinite: - REENTRANT_CHECK(OFF); - /* verify_area(VERIFY_W - * RITE, (void *) - * dfloat, 8); */ - suword((unsigned long *) dfloat, 0); - suword(1 + (unsigned long *) dfloat, 0xfff80000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - else - if (FPU_st0_tag == TW_Denormal) { - /* Extended real -> - * double real will - * always underflow */ - l[0] = l[1] = 0; - EXCEPTION(EX_Underflow); - } -#endif - if (FPU_st0_ptr->sign) - l[1] |= 0x80000000; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) dfloat, 8);*/ - suword((u_long *) dfloat, l[0]); - suword((u_long *) dfloat + 1, l[1]); -/* - suword(l[0], (unsigned long *) dfloat); - suword(l[1], 1 + (unsigned long *) dfloat);*/ - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a float into user memory */ -int -reg_store_single(void) -{ - float *single = (float *) FPU_data_address; - long templ = 0; - - if (FPU_st0_tag == TW_Valid) { - int exp; - FPU_REG tmp; - - reg_move(FPU_st0_ptr, &tmp); - exp = tmp.exp - EXP_BIAS; - - if (exp < SINGLE_Emin) { - /* Make a de-normal */ - int precision_loss; - - if (exp <= -EXTENDED_Ebias) - EXCEPTION(EX_Denormal); - - tmp.exp += -SINGLE_Emin + 23; /* largest exp to be 22 */ - - if ((precision_loss = round_to_int(&tmp))) { -#ifdef PECULIAR_486 - /* Did it round to a non-denormal ? */ - /* This behaviour might be regarded as - * peculiar, it appears that the 80486 rounds - * to the dest precision, then converts to - * decide underflow. */ - if ((tmp.sigl == 0x00800000) && - ((FPU_st0_ptr->sigh & 0x000000ff) || FPU_st0_ptr->sigl)) - EXCEPTION(precision_loss); - else -#endif /* PECULIAR_486 */ - { - EXCEPTION(EX_Underflow | precision_loss); - /* This is a special case: see sec - * 16.2.5.1 of the 80486 book */ - if (!(control_word & EX_Underflow)) - return 0; - } - } - templ = tmp.sigl; - } else { - if (tmp.sigl | (tmp.sigh & 0x000000ff)) { - unsigned long increment = 0; /* avoid gcc warnings */ - unsigned long sigh = tmp.sigh; - unsigned long sigl = tmp.sigl; - - switch (control_word & CW_RC) { - case RC_RND: - increment = ((sigh & 0xff) > 0x80) /* more than half */ - ||(((sigh & 0xff) == 0x80) && sigl) /* more than half */ - ||((sigh & 0x180) == 0x180); /* round to even */ - break; - case RC_DOWN: /* towards -infinity */ - increment = (tmp.sign == SIGN_POS) - ? 0 : (sigl | (sigh & 0xff)); - break; - case RC_UP: /* towards +infinity */ - increment = (tmp.sign == SIGN_POS) - ? (sigl | (sigh & 0xff)) : 0; - break; - case RC_CHOP: - increment = 0; - break; - } - - /* Truncate part of the mantissa */ - tmp.sigl = 0; - - if (increment) { - set_precision_flag_up(); - - if (sigh >= 0xffffff00) { - /* The sigh part overflows */ - tmp.sigh = 0x80000000; - exp++; - if (exp >= EXP_OVER) - goto overflow; - } else { - tmp.sigh &= 0xffffff00; - tmp.sigh += 0x100; - } - } else { - set_precision_flag_down(); - tmp.sigh &= 0xffffff00; /* Finish the truncation */ - } - } - templ = (tmp.sigh >> 8) & 0x007fffff; - - if (exp > SINGLE_Emax) { - overflow: - EXCEPTION(EX_Overflow); - /* This is a special case: see sec 16.2.5.1 of - * the 80486 book */ - if (control_word & EX_Overflow) { - /* Overflow to infinity */ - templ = 0x7f800000; - } else - return 0; - } else - templ |= ((exp + SINGLE_Ebias) & 0xff) << 23; - } - } else - if (FPU_st0_tag == TW_Zero) { - templ = 0; - } else - if (FPU_st0_tag == TW_Infinity) { - templ = 0x7f800000; - } else - if (FPU_st0_tag == TW_NaN) { - /* See if we can get a valid NaN from - * the FPU_REG */ - templ = FPU_st0_ptr->sigh >> 8; - if (!(templ & 0x3fffff)) { - /* This case does not seem to - * be handled by the 80486 - * specs */ - EXCEPTION(EX_Invalid); - /* Make the quiet NaN "real - * indefinite" */ - goto put_indefinite; - } - templ |= 0x7f800000; - } else - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack - * underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN - * indefinite */ - put_indefinite: - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) single, 4); */ - suword((unsigned long *) single, 0xffc00000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - else - if (FPU_st0_tag == TW_Denormal) { - /* Extended real -> - * real will always - * underflow */ - templ = 0; - EXCEPTION(EX_Underflow); - } -#endif -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x106); - return 0; - } -#endif - if (FPU_st0_ptr->sign) - templ |= 0x80000000; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) single, 4); */ - suword((unsigned long *) single, templ); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a long long into user memory */ -int -reg_store_int64(void) -{ - long long *d = (long long *) FPU_data_address; - FPU_REG t; - long long tll; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - goto put_indefinite; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - ((long *) &tll)[0] = t.sigl; - ((long *) &tll)[1] = t.sigh; - if ((t.sigh & 0x80000000) && - !((t.sigh == 0x80000000) && (t.sigl == 0) && (t.sign == SIGN_NEG))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - put_indefinite: - ((long *) &tll)[1] = 0x80000000; - ((long *) &tll)[0] = 0; - } else - return 0; - } else - if (t.sign) - tll = -tll; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, (void *) d, 8); */ - suword((unsigned long *) d, ((long *) &tll)[0]); - suword(1 + (unsigned long *) d, ((long *) &tll)[1]); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a long into user memory */ -int -reg_store_int32(void) -{ - long *d = (long *) FPU_data_address; - FPU_REG t; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 4);*/ - suword((unsigned long *) d, 0x80000000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - if (t.sigh || - ((t.sigl & 0x80000000) && - !((t.sigl == 0x80000000) && (t.sign == SIGN_NEG)))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - t.sigl = 0x80000000; - } else - return 0; - } else - if (t.sign) - t.sigl = -(long) t.sigl; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 4); */ - suword((unsigned long *) d, t.sigl); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a short into user memory */ -int -reg_store_int16(void) -{ - short *d = (short *) FPU_data_address; - FPU_REG t; - short ts; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 2);*/ - susword((unsigned short *) d, 0x8000); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - if (t.sigh || - ((t.sigl & 0xffff8000) && - !((t.sigl == 0x8000) && (t.sign == SIGN_NEG)))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - /* Produce "indefinite" */ - ts = 0x8000; - } else - return 0; - } else - if (t.sign) - t.sigl = -t.sigl; - - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 2); */ - susword((short *) d, (short) t.sigl); - REENTRANT_CHECK(ON); - - return 1; -} - - -/* Put a packed bcd array into user memory */ -int -reg_store_bcd(void) -{ - char *d = (char *) FPU_data_address; - FPU_REG t; - long long ll; - unsigned char b; - int i; - unsigned char sign = (FPU_st0_ptr->sign == SIGN_NEG) ? 0x80 : 0; - - if (FPU_st0_tag == TW_Empty) { - /* Empty register (stack underflow) */ - EXCEPTION(EX_StackUnder); - if (control_word & EX_Invalid) { - /* The masked response */ - /* Put out the QNaN indefinite */ - goto put_indefinite; - } else - return 0; - } - reg_move(FPU_st0_ptr, &t); - round_to_int(&t); - ll = *(long long *) (&t.sigl); - - /* Check for overflow, by comparing with 999999999999999999 decimal. */ - if ((t.sigh > 0x0de0b6b3) || - ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) { - EXCEPTION(EX_Invalid); - /* This is a special case: see sec 16.2.5.1 of the 80486 book */ - if (control_word & EX_Invalid) { - put_indefinite: - /* Produce "indefinite" */ - REENTRANT_CHECK(OFF); -/* verify_area(VERIFY_WRITE, d, 10);*/ - subyte((unsigned char *) d + 7, 0xff); - subyte((unsigned char *) d + 8, 0xff); - subyte((unsigned char *) d + 9, 0xff); - REENTRANT_CHECK(ON); - return 1; - } else - return 0; - } -/* verify_area(VERIFY_WRITE, d, 10);*/ - for (i = 0; i < 9; i++) { - b = div_small(&ll, 10); - b |= (div_small(&ll, 10)) << 4; - REENTRANT_CHECK(OFF); - subyte((unsigned char *) d + i, b); - REENTRANT_CHECK(ON); - } - REENTRANT_CHECK(OFF); - subyte((unsigned char *) d + 9, sign); - REENTRANT_CHECK(ON); - - return 1; -} -/*===========================================================================*/ - -/* r gets mangled such that sig is int, sign: - it is NOT normalized */ -/* The return value (in eax) is zero if the result is exact, - if bits are changed due to rounding, truncation, etc, then - a non-zero value is returned */ -/* Overflow is signalled by a non-zero return value (in eax). - In the case of overflow, the returned significand always has the - the largest possible value */ -/* The value returned in eax is never actually needed :-) */ -int -round_to_int(FPU_REG * r) -{ - char very_big; - unsigned eax; - - if (r->tag == TW_Zero) { - /* Make sure that zero is returned */ - *(long long *) &r->sigl = 0; - return 0; /* o.k. */ - } - if (r->exp > EXP_BIAS + 63) { - r->sigl = r->sigh = ~0; /* The largest representable number */ - return 1; /* overflow */ - } - eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp); - very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */ -#define half_or_more (eax & 0x80000000) -#define frac_part (eax) -#define more_than_half ((eax & 0x80000001) == 0x80000001) - switch (control_word & CW_RC) { - case RC_RND: - if (more_than_half /* nearest */ - || (half_or_more && (r->sigl & 1))) { /* odd -> even */ - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_DOWN: - if (frac_part && r->sign) { - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_UP: - if (frac_part && !r->sign) { - if (very_big) - return 1; /* overflow */ - (*(long long *) (&r->sigl))++; - return LOST_UP; - } - break; - case RC_CHOP: - break; - } - - return eax ? LOST_DOWN : 0; - -} -/*===========================================================================*/ - -char * -fldenv(void) -{ - char *s = (char *) FPU_data_address; - unsigned short tag_word = 0; - unsigned char tag; - int i; - - REENTRANT_CHECK(OFF); - control_word = fusword((unsigned short *) s); - status_word = fusword((unsigned short *) (s + 4)); - tag_word = fusword((unsigned short *) (s + 8)); - ip_offset = fuword((unsigned long *) (s + 0x0c)); - cs_selector = fuword((unsigned long *) (s + 0x10)); - data_operand_offset = fuword((unsigned long *) (s + 0x14)); - operand_selector = fuword((unsigned long *) (s + 0x18)); - REENTRANT_CHECK(ON); - - top = (status_word >> SW_Top_Shift) & 7; - - for (i = 0; i < 8; i++) { - tag = tag_word & 3; - tag_word >>= 2; - - switch (tag) { - case 0: - regs[i].tag = TW_Valid; - break; - case 1: - regs[i].tag = TW_Zero; - break; - case 2: - regs[i].tag = TW_NaN; - break; - case 3: - regs[i].tag = TW_Empty; - break; - } - } - - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; - FPU_entry_eip = ip_offset; /* We want no net effect */ - - return s + 0x1c; -} - - -void -frstor(void) -{ - int i, stnr; - unsigned char tag; - unsigned short saved_status, saved_control; - char *s = (char *) fldenv(); - - saved_status = status_word; - saved_control = control_word; - control_word = 0x037f; /* Mask all interrupts while we load. */ - for (i = 0; i < 8; i++) { - /* load each register */ - FPU_data_address = (void *) (s + i * 10); - reg_load_extended(); - stnr = (i + top) & 7; - tag = regs[stnr].tag; /* derived from the loaded tag word */ - reg_move(&FPU_loaded_data, ®s[stnr]); - if (tag == TW_NaN) { - /* The current data is a special, i.e. NaN, - * unsupported, infinity, or denormal */ - unsigned char t = regs[stnr].tag; /* derived from the new - * data */ - if ( /* (t == TW_Valid) || *** */ (t == TW_Zero)) - regs[stnr].tag = TW_NaN; - } else - regs[stnr].tag = tag; - } - control_word = saved_control; - status_word = saved_status; - - /* We want no net effect: */ - FPU_data_address = (void *) (intptr_t) data_operand_offset; -} - - -unsigned short -tag_word(void) -{ - unsigned short word = 0; - unsigned char tag; - int i; - - for (i = 7; i >= 0; i--) { - switch (tag = regs[i].tag) { -#if 0 /* TW_Denormal is not used yet, and probably - * won't be */ - case TW_Denormal: -#endif - case TW_Valid: - if (regs[i].exp <= (EXP_BIAS - EXTENDED_Ebias)) - tag = 2; - break; - case TW_Infinity: - case TW_NaN: - tag = 2; - break; - case TW_Empty: - tag = 3; - break; - /* TW_Valid and TW_Zero already have the correct value */ - } - word <<= 2; - word |= tag; - } - return word; -} - - -char * -fstenv(void) -{ - char *d = (char *) FPU_data_address; - -/* verify_area(VERIFY_WRITE, d, 28);*/ - -#if 0 /****/ - *(unsigned short *) &cs_selector = fpu_cs; - *(unsigned short *) &operand_selector = fpu_os; -#endif /****/ - - REENTRANT_CHECK(OFF); - susword((unsigned short *) d, control_word); - susword((unsigned short *) (d + 4), (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift)); - susword((unsigned short *) (d + 8), tag_word()); - suword((unsigned long *) (d + 0x0c), ip_offset); - suword((unsigned long *) (d + 0x10), cs_selector); - suword((unsigned long *) (d + 0x14), data_operand_offset); - suword((unsigned long *) (d + 0x18), operand_selector); - REENTRANT_CHECK(ON); - - return d + 0x1c; -} - - -void -fsave(void) -{ - char *d; - FPU_REG tmp, *rp; - int i; - short e; - - d = fstenv(); -/* verify_area(VERIFY_WRITE, d, 80);*/ - for (i = 0; i < 8; i++) { - /* Store each register in the order: st(0), st(1), ... */ - rp = ®s[(top + i) & 7]; - - e = rp->exp - EXP_BIAS + EXTENDED_Ebias; - - if (rp->tag == TW_Valid) { - if (e >= 0x7fff) { - /* Overflow to infinity */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (e <= 0) { - if (e > -63) { - /* Make a de-normal */ - reg_move(rp, &tmp); - tmp.exp += -EXTENDED_Emin + 63; /* largest exp to be 62 */ - round_to_int(&tmp); - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), tmp.sigl); - suword((unsigned long *) (d + i * 10 + 4), tmp.sigh); - REENTRANT_CHECK(ON); - } else { - /* Underflow to zero */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - } - e = 0; - } else { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - } - } else - if (rp->tag == TW_Zero) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0); - REENTRANT_CHECK(ON); - e = 0; - } else - if (rp->tag == TW_Infinity) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), 0); - suword((unsigned long *) (d + i * 10 + 4), 0x80000000); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (rp->tag == TW_NaN) { - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - e = 0x7fff; - } else - if (rp->tag == TW_Empty) { - /* just copy the reg */ - REENTRANT_CHECK(OFF); - suword((unsigned long *) (d + i * 10), rp->sigl); - suword((unsigned long *) (d + i * 10 + 4), rp->sigh); - REENTRANT_CHECK(ON); - } - e |= rp->sign == SIGN_POS ? 0 : 0x8000; - REENTRANT_CHECK(OFF); - susword((unsigned short *) (d + i * 10 + 8), e); - REENTRANT_CHECK(ON); - } - - finit(); - -} -/*===========================================================================*/ diff --git a/sys/platform/pc32/gnu/fpemul/reg_mul.c b/sys/platform/pc32/gnu/fpemul/reg_mul.c deleted file mode 100644 index 780f479e14..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_mul.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * reg_mul.c - * - * Multiply one FPU_REG by another, put the result in a destination FPU_REG. - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_mul.c,v 1.8 1999/08/28 00:42:56 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_mul.c,v 1.3 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | The destination may be any FPU_REG, including one of the source FPU_REGs. | - +---------------------------------------------------------------------------*/ - -#include "reg_constant.h" - - -/* This routine must be called with non-empty source registers */ -void -reg_mul(FPU_REG * a, FPU_REG * b, FPU_REG * dest, unsigned int control_w) -{ - char sign = (a->sign ^ b->sign); - - if (!(a->tag | b->tag)) { - /* This should be the most common case */ - reg_u_mul(a, b, dest, control_w); - dest->sign = sign; - return; - } else - if ((a->tag <= TW_Zero) && (b->tag <= TW_Zero)) { -#ifdef DENORM_OPERAND - if (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) || - ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER))) { - if (denormal_operand()) - return; - } -#endif /* DENORM_OPERAND */ - /* Must have either both arguments == zero, or one - * valid and the other zero. The result is therefore - * zero. */ - reg_move(&CONST_Z, dest); -#ifdef PECULIAR_486 - /* The 80486 book says that the answer is +0, but a - * real 80486 appears to behave this way... */ - dest->sign = sign; -#endif /* PECULIAR_486 */ - return; - } -#if 0 /* TW_Denormal is not used yet... perhaps - * never will be. */ - else - if ((a->tag <= TW_Denormal) && (b->tag <= TW_Denormal)) { - /* One or both arguments are de-normalized */ - /* Internal de-normalized numbers are not - * supported yet */ - EXCEPTION(EX_INTERNAL | 0x105); - reg_move(&CONST_Z, dest); - } -#endif - else { - /* Must have infinities, NaNs, etc */ - if ((a->tag == TW_NaN) || (b->tag == TW_NaN)) { - real_2op_NaN(a, b, dest); - return; - } else - if (a->tag == TW_Infinity) { - if (b->tag == TW_Zero) { - arith_invalid(dest); - return; - } - /* Zero*Infinity is invalid */ - else { -#ifdef DENORM_OPERAND - if ((b->tag == TW_Valid) && (b->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(a, dest); - dest->sign = sign; - } - return; - } else - if (b->tag == TW_Infinity) { - if (a->tag == TW_Zero) { - arith_invalid(dest); - return; - } - /* Zero*Infinity is - * invalid */ - else { -#ifdef DENORM_OPERAND - if ((a->tag == TW_Valid) && (a->exp <= EXP_UNDER) && - denormal_operand()) - return; -#endif /* DENORM_OPERAND */ - reg_move(b, dest); - dest->sign = sign; - } - return; - } -#ifdef PARANOID - else { - EXCEPTION(EX_INTERNAL | 0x102); - } -#endif /* PARANOID */ - } -} diff --git a/sys/platform/pc32/gnu/fpemul/reg_norm.s b/sys/platform/pc32/gnu/fpemul/reg_norm.s deleted file mode 100644 index 6ac1cf630b..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_norm.s +++ /dev/null @@ -1,177 +0,0 @@ -/* - * reg_norm.s - * - * Normalize the value in a FPU_REG. - * - * Call from C as: - * void normalize(FPU_REG *n) - * - * void normalize_nuo(FPU_REG *n) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_norm.s,v 1.8 1999/08/28 00:42:57 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_norm.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -#include "fpu_asm.h" - - -.text - -ENTRY(normalize) - pushl %ebp - movl %esp,%ebp - pushl %ebx - - movl PARAM1,%ebx - - movl SIGH(%ebx),%edx - movl SIGL(%ebx),%eax - - orl %edx,%edx /* ms bits */ - js L_done /* Already normalized */ - jnz L_shift_1 /* Shift left 1 - 31 bits */ - - orl %eax,%eax - jz L_zero /* The contents are zero */ - -/* L_shift_32: */ - movl %eax,%edx - xorl %eax,%eax - subl $32,EXP(%ebx) /* This can cause an underflow */ - -/* We need to shift left by 1 - 31 bits */ -L_shift_1: - bsrl %edx,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%eax,%edx - shl %cl,%eax - subl %ecx,EXP(%ebx) /* This can cause an underflow */ - - movl %edx,SIGH(%ebx) - movl %eax,SIGL(%ebx) - -L_done: - cmpl EXP_OVER,EXP(%ebx) - jge L_overflow - - cmpl EXP_UNDER,EXP(%ebx) - jle L_underflow - -L_exit: - popl %ebx - leave - ret - - -L_zero: - movl EXP_UNDER,EXP(%ebx) - movb TW_Zero,TAG(%ebx) - jmp L_exit - -L_underflow: - push %ebx - call arith_underflow - pop %ebx - jmp L_exit - -L_overflow: - push %ebx - call arith_overflow - pop %ebx - jmp L_exit - - - -/* Normalise without reporting underflow or overflow */ -ENTRY(normalize_nuo) - pushl %ebp - movl %esp,%ebp - pushl %ebx - - movl PARAM1,%ebx - - movl SIGH(%ebx),%edx - movl SIGL(%ebx),%eax - - orl %edx,%edx /* ms bits */ - js L_exit /* Already normalized */ - jnz L_nuo_shift_1 /* Shift left 1 - 31 bits */ - - orl %eax,%eax - jz L_zero /* The contents are zero */ - -/* L_nuo_shift_32: */ - movl %eax,%edx - xorl %eax,%eax - subl $32,EXP(%ebx) /* This can cause an underflow */ - -/* We need to shift left by 1 - 31 bits */ -L_nuo_shift_1: - bsrl %edx,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%eax,%edx - shl %cl,%eax - subl %ecx,EXP(%ebx) /* This can cause an underflow */ - - movl %edx,SIGH(%ebx) - movl %eax,SIGL(%ebx) - jmp L_exit - - diff --git a/sys/platform/pc32/gnu/fpemul/reg_round.s b/sys/platform/pc32/gnu/fpemul/reg_round.s deleted file mode 100644 index 49331c071e..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_round.s +++ /dev/null @@ -1,651 +0,0 @@ - .file "reg_round.S" -/* - * reg_round.S - * - * Rounding/truncation/etc for FPU basic arithmetic functions. - * - * This code has four possible entry points. - * The following must be entered by a jmp intruction: - * FPU_round, FPU_round_sqrt, and FPU_Arith_exit. - * - * The _round_reg entry point is intended to be used by C code. - * From C, call as: - * void round_reg(FPU_REG *arg, unsigned int extent, unsigned int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_round.s,v 1.9.2.1 2000/07/07 00:38:42 obrien Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_round.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -/*---------------------------------------------------------------------------+ - | Four entry points. | - | | - | Needed by both the FPU_round and FPU_round_sqrt entry points: | - | %eax:%ebx 64 bit significand | - | %edx 32 bit extension of the significand | - | %edi pointer to an FPU_REG for the result to be stored | - | stack calling function must have set up a C stack frame and | - | pushed %esi, %edi, and %ebx | - | | - | Needed just for the FPU_round_sqrt entry point: | - | %cx A control word in the same format as the FPU control word. | - | Otherwise, PARAM4 must give such a value. | - | | - | | - | The significand and its extension are assumed to be exact in the | - | following sense: | - | If the significand by itself is the exact result then the significand | - | extension (%edx) must contain 0, otherwise the significand extension | - | must be non-zero. | - | If the significand extension is non-zero then the significand is | - | smaller than the magnitude of the correct exact result by an amount | - | greater than zero and less than one ls bit of the significand. | - | The significand extension is only required to have three possible | - | non-zero values: | - | less than 0x80000000 <=> the significand is less than 1/2 an ls | - | bit smaller than the magnitude of the | - | true exact result. | - | exactly 0x80000000 <=> the significand is exactly 1/2 an ls bit | - | smaller than the magnitude of the true | - | exact result. | - | greater than 0x80000000 <=> the significand is more than 1/2 an ls | - | bit smaller than the magnitude of the | - | true exact result. | - | | - +---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------+ - | The code in this module has become quite complex, but it should handle | - | all of the FPU flags which are set at this stage of the basic arithmetic | - | computations. | - | There are a few rare cases where the results are not set identically to | - | a real FPU. These require a bit more thought because at this stage the | - | results of the code here appear to be more consistent... | - | This may be changed in a future version. | - +---------------------------------------------------------------------------*/ - - -#include "exception.h" -#include "control_w.h" - -#define LOST_DOWN $1 -#define LOST_UP $2 -#define DENORMAL $1 -#define UNMASKED_UNDERFLOW $2 - -.data - ALIGN_DATA -FPU_bits_lost: - .byte 0 -FPU_denormal: - .byte 0 - -.text -.globl FPU_round -.globl FPU_round_sqrt -.globl FPU_Arith_exit - -/* Entry point when called from C */ -ENTRY(round_reg) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%edi - movl SIGH(%edi),%eax - movl SIGL(%edi),%ebx - movl PARAM2,%edx - movl PARAM3,%ecx - jmp FPU_round_sqrt - -FPU_round: /* Normal entry point */ - movl PARAM4,%ecx - -FPU_round_sqrt: /* Entry point from wm_sqrt.S */ - -#ifdef PARANOID -/* Cannot use this here yet */ -/* orl %eax,%eax */ -/* jns L_entry_bugged */ -#endif PARANOID - - cmpl EXP_UNDER,EXP(%edi) - jle xMake_denorm /* The number is a de-normal*/ - - movb $0,FPU_denormal /* 0 -> not a de-normal*/ - -xDenorm_done: - movb $0,FPU_bits_lost /*No bits yet lost in rounding*/ - - movl %ecx,%esi - andl CW_PC,%ecx - cmpl PR_64_BITS,%ecx - je LRound_To_64 - - cmpl PR_53_BITS,%ecx - je LRound_To_53 - - cmpl PR_24_BITS,%ecx - je LRound_To_24 - -#ifdef PARANOID - jmp L_bugged /* There is no bug, just a bad control word */ -#endif PARANOID - - -/* Round etc to 24 bit precision */ -LRound_To_24: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_24 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_24 - - cmpl RC_UP,%ecx /* Towards +infinity */ - je LUp_24 - - cmpl RC_DOWN,%ecx /* Towards -infinity */ - je LDown_24 - -#ifdef PARANOID - jmp L_bugged -#endif PARANOID - -LUp_24: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_24 /* If negative then up==truncate */ - - jmp LCheck_24_round_up - -LDown_24: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_24 /* If positive then down==truncate */ - -LCheck_24_round_up: - movl %eax,%ecx - andl $0x000000ff,%ecx - orl %ebx,%ecx - orl %edx,%ecx - jnz LDo_24_round_up - jmp LRe_normalise - -LRound_nearest_24: - /* Do rounding of the 24th bit if needed (nearest or even) */ - movl %eax,%ecx - andl $0x000000ff,%ecx - cmpl $0x00000080,%ecx - jc LCheck_truncate_24 /*less than half, no increment needed*/ - - jne LGreater_Half_24 /* greater than half, increment needed*/ - - /* Possibly half, we need to check the ls bits */ - orl %ebx,%ebx - jnz LGreater_Half_24 /* greater than half, increment needed*/ - - orl %edx,%edx - jnz LGreater_Half_24 /* greater than half, increment needed*/ - - /* Exactly half, increment only if 24th bit is 1 (round to even)*/ - testl $0x00000100,%eax - jz LDo_truncate_24 - -LGreater_Half_24: /*Rounding: increment at the 24th bit*/ -LDo_24_round_up: - andl $0xffffff00,%eax /*Truncate to 24 bits*/ - xorl %ebx,%ebx - movb LOST_UP,FPU_bits_lost - addl $0x00000100,%eax - jmp LCheck_Round_Overflow - -LCheck_truncate_24: - movl %eax,%ecx - andl $0x000000ff,%ecx - orl %ebx,%ecx - orl %edx,%ecx - jz LRe_normalise /* No truncation needed*/ - -LDo_truncate_24: - andl $0xffffff00,%eax /* Truncate to 24 bits*/ - xorl %ebx,%ebx - movb LOST_DOWN,FPU_bits_lost - jmp LRe_normalise - - -/* Round etc to 53 bit precision */ -LRound_To_53: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_53 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_53 - - cmpl RC_UP,%ecx /* Towards +infinity*/ - je LUp_53 - - cmpl RC_DOWN,%ecx /* Towards -infinity*/ - je LDown_53 - -#ifdef PARANOID - jmp L_bugged -#endif PARANOID - -LUp_53: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_53 /* If negative then up==truncate*/ - - jmp LCheck_53_round_up - -LDown_53: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_53 /* If positive then down==truncate*/ - -LCheck_53_round_up: - movl %ebx,%ecx - andl $0x000007ff,%ecx - orl %edx,%ecx - jnz LDo_53_round_up - jmp LRe_normalise - -LRound_nearest_53: - /*Do rounding of the 53rd bit if needed (nearest or even)*/ - movl %ebx,%ecx - andl $0x000007ff,%ecx - cmpl $0x00000400,%ecx - jc LCheck_truncate_53 /* less than half, no increment needed*/ - - jnz LGreater_Half_53 /* greater than half, increment needed*/ - - /*Possibly half, we need to check the ls bits*/ - orl %edx,%edx - jnz LGreater_Half_53 /* greater than half, increment needed*/ - - /* Exactly half, increment only if 53rd bit is 1 (round to even)*/ - testl $0x00000800,%ebx - jz LTruncate_53 - -LGreater_Half_53: /*Rounding: increment at the 53rd bit*/ -LDo_53_round_up: - movb LOST_UP,FPU_bits_lost - andl $0xfffff800,%ebx /* Truncate to 53 bits*/ - addl $0x00000800,%ebx - adcl $0,%eax - jmp LCheck_Round_Overflow - -LCheck_truncate_53: - movl %ebx,%ecx - andl $0x000007ff,%ecx - orl %edx,%ecx - jz LRe_normalise - -LTruncate_53: - movb LOST_DOWN,FPU_bits_lost - andl $0xfffff800,%ebx /* Truncate to 53 bits*/ - jmp LRe_normalise - - -/* Round etc to 64 bit precision*/ -LRound_To_64: - movl %esi,%ecx - andl CW_RC,%ecx - cmpl RC_RND,%ecx - je LRound_nearest_64 - - cmpl RC_CHOP,%ecx - je LCheck_truncate_64 - - cmpl RC_UP,%ecx /* Towards +infinity*/ - je LUp_64 - - cmpl RC_DOWN,%ecx /* Towards -infinity*/ - je LDown_64 - -#ifdef PARANOID - jmp L_bugged -#endif PARANOID - -LUp_64: - cmpb SIGN_POS,SIGN(%edi) - jne LCheck_truncate_64 /* If negative then up==truncate*/ - - orl %edx,%edx - jnz LDo_64_round_up - jmp LRe_normalise - -LDown_64: - cmpb SIGN_POS,SIGN(%edi) - je LCheck_truncate_64 /*If positive then down==truncate*/ - - orl %edx,%edx - jnz LDo_64_round_up - jmp LRe_normalise - -LRound_nearest_64: - cmpl $0x80000000,%edx - jc LCheck_truncate_64 - - jne LDo_64_round_up - - /* Now test for round-to-even */ - testb $1,%bl - jz LCheck_truncate_64 - -LDo_64_round_up: - movb LOST_UP,FPU_bits_lost - addl $1,%ebx - adcl $0,%eax - -LCheck_Round_Overflow: - jnc LRe_normalise /* Rounding done, no overflow */ - - /* Overflow, adjust the result (to 1.0) */ - rcrl $1,%eax - rcrl $1,%ebx - incl EXP(%edi) - jmp LRe_normalise - -LCheck_truncate_64: - orl %edx,%edx - jz LRe_normalise - -LTruncate_64: - movb LOST_DOWN,FPU_bits_lost - -LRe_normalise: - testb $0xff,FPU_denormal - jnz xNormalise_result - -xL_Normalised: - cmpb LOST_UP,FPU_bits_lost - je xL_precision_lost_up - - cmpb LOST_DOWN,FPU_bits_lost - je xL_precision_lost_down - -xL_no_precision_loss: - cmpl EXP_OVER,EXP(%edi) - jge L_overflow - - /* store the result */ - movb TW_Valid,TAG(%edi) - -xL_Store_significand: - movl %eax,SIGH(%edi) - movl %ebx,SIGL(%edi) - -FPU_Arith_exit: - popl %ebx - popl %edi - popl %esi - leave - ret - - -/* Set the FPU status flags to represent precision loss due to*/ -/* round-up.*/ -xL_precision_lost_up: - push %eax - call set_precision_flag_up - popl %eax - jmp xL_no_precision_loss - -/* Set the FPU status flags to represent precision loss due to*/ -/* truncation.*/ -xL_precision_lost_down: - push %eax - call set_precision_flag_down - popl %eax - jmp xL_no_precision_loss - - -/* The number is a denormal (which might get rounded up to a normal) -// Shift the number right the required number of bits, which will -// have to be undone later...*/ -xMake_denorm: - /* The action to be taken depends upon whether the underflow - // exception is masked*/ - testb CW_Underflow,%cl /* Underflow mask.*/ - jz xUnmasked_underflow /* Do not make a denormal.*/ - - movb DENORMAL,FPU_denormal - - pushl %ecx /* Save*/ - movl EXP(%edi),%ecx - subl EXP_UNDER+1,%ecx - negl %ecx - - cmpl $64,%ecx /* shrd only works for 0..31 bits */ - jnc xDenorm_shift_more_than_63 - - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc xDenorm_shift_more_than_32 - -/* We got here without jumps by assuming that the most common requirement -// is for a small de-normalising shift. -// Shift by [1..31] bits */ - addl %ecx,EXP(%edi) - orl %edx,%edx /* extension*/ - setne %ch - xorl %edx,%edx - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orb %ch,%dl - popl %ecx - jmp xDenorm_done - -/* Shift by [32..63] bits*/ -xDenorm_shift_more_than_32: - addl %ecx,EXP(%edi) - subb $32,%cl - orl %edx,%edx - setne %ch - orb %ch,%bl - xorl %edx,%edx - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orl %edx,%edx /*test these 32 bits*/ - setne %cl - orb %ch,%bl - orb %cl,%bl - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - popl %ecx - jmp xDenorm_done - -/* Shift by [64..) bits*/ -xDenorm_shift_more_than_63: - cmpl $64,%ecx - jne xDenorm_shift_more_than_64 - -/* Exactly 64 bit shift*/ - addl %ecx,EXP(%edi) - xorl %ecx,%ecx - orl %edx,%edx - setne %cl - orl %ebx,%ebx - setne %ch - orb %ch,%cl - orb %cl,%al - movl %eax,%edx - xorl %eax,%eax - xorl %ebx,%ebx - popl %ecx - jmp xDenorm_done - -xDenorm_shift_more_than_64: - movl EXP_UNDER+1,EXP(%edi) -/* This is easy, %eax must be non-zero, so..*/ - movl $1,%edx - xorl %eax,%eax - xorl %ebx,%ebx - popl %ecx - jmp xDenorm_done - - -xUnmasked_underflow: - /* Increase the exponent by the magic number*/ - addl $(3*(1<<13)),EXP(%edi) - movb UNMASKED_UNDERFLOW,FPU_denormal - jmp xDenorm_done - - -/* Undo the de-normalisation.*/ -xNormalise_result: - cmpb UNMASKED_UNDERFLOW,FPU_denormal - je xSignal_underflow - -/* The number must be a denormal if we got here.*/ -#ifdef PARANOID - /* But check it... just in case.*/ - cmpl EXP_UNDER+1,EXP(%edi) - jne L_norm_bugged -#endif PARANOID - - orl %eax,%eax /* ms bits*/ - jnz LNormalise_shift_up_to_31 /* Shift left 0 - 31 bits*/ - - orl %ebx,%ebx - jz L_underflow_to_zero /* The contents are zero*/ - -/* Shift left 32 - 63 bits*/ - movl %ebx,%eax - xorl %ebx,%ebx - subl $32,EXP(%edi) - -LNormalise_shift_up_to_31: - bsrl %eax,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%ebx,%eax - shl %cl,%ebx - subl %ecx,EXP(%edi) - -LNormalise_shift_done: - testb $0xff,FPU_bits_lost /* bits lost == underflow*/ - jz xL_Normalised - - /* There must be a masked underflow*/ - push %eax - pushl EX_Underflow - call exception - popl %eax - popl %eax - jmp xL_Normalised - - -/* The operations resulted in a number too small to represent. -// Masked response.*/ -L_underflow_to_zero: - push %eax - call set_precision_flag_down - popl %eax - - push %eax - pushl EX_Underflow - call exception - popl %eax - popl %eax - - movb TW_Zero,TAG(%edi) - jmp xL_Store_significand - - -/* The operations resulted in a number too large to represent.*/ -L_overflow: - push %edi - call arith_overflow - pop %edi - jmp FPU_Arith_exit - - -xSignal_underflow: - push %eax - pushl EX_Underflow - call EXCEPTION - popl %eax - popl %eax - jmp xL_Normalised - - -#ifdef PARANOID -/* If we ever get here then we have problems! */ -L_bugged: - pushl EX_INTERNAL|0x201 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit - -L_norm_bugged: - pushl EX_INTERNAL|0x216 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit - -L_entry_bugged: - pushl EX_INTERNAL|0x217 - call EXCEPTION - popl %ebx - jmp FPU_Arith_exit -#endif PARANOID diff --git a/sys/platform/pc32/gnu/fpemul/reg_u_add.s b/sys/platform/pc32/gnu/fpemul/reg_u_add.s deleted file mode 100644 index d393ab9e99..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_u_add.s +++ /dev/null @@ -1,241 +0,0 @@ - .file "reg_u_add.S" -/* - * reg_u_add.S - * - * Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the - * result in a destination FPU_REG. - * - * Call from C as: - * void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, - * int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_add.s,v 1.9 1999/08/28 00:42:57 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_u_add.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - - -/* - | Kernel addition routine reg_u_add(reg *arg1, reg *arg2, reg *answ). - | Takes two valid reg f.p. numbers (TW_Valid), which are - | treated as unsigned numbers, - | and returns their sum as a TW_Valid or TW_S f.p. number. - | The returned number is normalized. - | Basic checks are performed if PARANOID is defined. - */ - -#include "fpu_asm.h" - -.text -ENTRY(reg_u_add) - pushl %ebp - movl %esp,%ebp -/* subl $16,%esp*/ - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* source 1 */ - movl PARAM2,%edi /* source 2 */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%esi) - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - cmpl EXP_UNDER,EXP(%edi) - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif DENORM_OPERAND - -/* xorl %ecx,%ecx*/ - movl EXP(%esi),%ecx - subl EXP(%edi),%ecx /* exp1 - exp2 */ -/* jnc L_arg1_larger*/ - jge L_arg1_larger - - /* num1 is smaller */ - movl SIGL(%esi),%ebx - movl SIGH(%esi),%eax - - movl %edi,%esi - negw %cx - jmp L_accum_loaded - -L_arg1_larger: - /* num1 has larger or equal exponent */ - movl SIGL(%edi),%ebx - movl SIGH(%edi),%eax - -L_accum_loaded: - movl PARAM3,%edi /* destination */ - movb SIGN(%esi),%dl - movb %dl,SIGN(%edi) /* Copy the sign from the first arg */ - - - movl EXP(%esi),%edx - movl %edx,EXP(%edi) /* Copy exponent to destination */ - - xorl %edx,%edx /* clear the extension */ - -#ifdef PARANOID - testl $0x80000000,%eax - je L_bugged - - testl $0x80000000,SIGH(%esi) - je L_bugged -#endif PARANOID - -/* The number to be shifted is in %eax:%ebx:%edx*/ - cmpw $32,%cx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - jmp L_shift_done - -L_more_than_31: - cmpw $64,%cx - jnc L_more_than_63 - - subb $32,%cl - jz L_exactly_32 - - shrd %cl,%eax,%edx - shr %cl,%eax - orl %ebx,%ebx - jz L_more_31_no_low /* none of the lowest bits is set*/ - - orl $1,%edx /* record the fact in the extension*/ - -L_more_31_no_low: - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_exactly_32: - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_more_than_63: - cmpw $65,%cx - jnc L_more_than_64 - - movl %eax,%edx - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_64: - movl $1,%edx /* The shifted nr always at least one '1'*/ - -L_more_63_no_low: - xorl %ebx,%ebx - xorl %eax,%eax - -L_shift_done: - /* Now do the addition */ - addl SIGL(%esi),%ebx - adcl SIGH(%esi),%eax - jnc L_round_the_result - - /* Overflow, adjust the result */ - rcrl $1,%eax - rcrl $1,%ebx - rcrl $1,%edx - jnc L_no_bit_lost - - orl $1,%edx - -L_no_bit_lost: - incl EXP(%edi) - -L_round_the_result: - jmp FPU_round /* Round the result*/ - - - -#ifdef PARANOID -/* If we ever get here then we have problems! */ -L_bugged: - pushl EX_INTERNAL|0x201 - call EXCEPTION - pop %ebx - jmp L_exit -#endif PARANOID - - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret diff --git a/sys/platform/pc32/gnu/fpemul/reg_u_div.s b/sys/platform/pc32/gnu/fpemul/reg_u_div.s deleted file mode 100644 index a6ee3c1689..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_u_div.s +++ /dev/null @@ -1,502 +0,0 @@ - .file "reg_u_div.S" -/* - * reg_u_div.S - * - * Core division routines - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_div.s,v 1.9 1999/08/28 00:42:58 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_u_div.s,v 1.4 2003/08/07 21:17:20 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Kernel for the division routines. | - | | - | void reg_u_div(FPU_REG *a, FPU_REG *a, | - | FPU_REG *dest, unsigned int control_word) | - | | - | Does not compute the destination exponent, but does adjust it. | - +---------------------------------------------------------------------------*/ - -#include "fpu_asm.h" - - -/* #define dSIGL(x) (x) */ -/* #define dSIGH(x) 4(x) */ - - -.data -/* - Local storage: - Result: accum_3:accum_2:accum_1:accum_0 - Overflow flag: ovfl_flag - */ - ALIGN_DATA -accum_3: - .long 0 -accum_2: - .long 0 -accum_1: - .long 0 -accum_0: - .long 0 -result_1: - .long 0 -result_2: - .long 0 -ovfl_flag: - .byte 0 - - -.text - -.globl _divide_kernel - -ENTRY(reg_u_div) - pushl %ebp - movl %esp,%ebp - - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* pointer to num */ - movl PARAM2,%ebx /* pointer to denom */ - movl PARAM3,%edi /* pointer to answer */ - -#ifdef DENORM_OPERAND - movl EXP(%esi),%eax - cmpl EXP_UNDER,%eax - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - movl EXP(%ebx),%eax - cmpl EXP_UNDER,%eax - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif DENORM_OPERAND - -_divide_kernel: -#ifdef PARANOID -/* testl $0x80000000, SIGH(%esi) *//* Dividend */ -/* je L_bugged */ - testl $0x80000000, SIGH(%ebx) /* Divisor*/ - je L_bugged -#endif PARANOID - -/* Check if the divisor can be treated as having just 32 bits */ - cmpl $0,SIGL(%ebx) - jnz L_Full_Division /* Can't do a quick divide */ - -/* We should be able to zip through the division here */ - movl SIGH(%ebx),%ecx /* The divisor */ - movl SIGH(%esi),%edx /* Dividend */ - movl SIGL(%esi),%eax /* Dividend */ - - cmpl %ecx,%edx - setaeb ovfl_flag /* Keep a record */ - jb L_no_adjust - - subl %ecx,%edx /* Prevent the overflow */ - -L_no_adjust: - /* Divide the 64 bit number by the 32 bit denominator */ - divl %ecx - movl %eax,result_2 - - /* Work on the remainder of the first division */ - xorl %eax,%eax - divl %ecx - movl %eax,result_1 - - /* Work on the remainder of the 64 bit division */ - xorl %eax,%eax - divl %ecx - - testb $255,ovfl_flag /* was the num > denom ? */ - je L_no_overflow - - /* Do the shifting here */ - /* increase the exponent */ - incl EXP(%edi) - - /* shift the mantissa right one bit */ - stc /* To set the ms bit */ - rcrl result_2 - rcrl result_1 - rcrl %eax - -L_no_overflow: - jmp LRound_precision /* Do the rounding as required*/ - - -/*---------------------------------------------------------------------------+ - | Divide: Return arg1/arg2 to arg3. | - | | - | This routine does not use the exponents of arg1 and arg2, but does | - | adjust the exponent of arg3. | - | | - | The maximum returned value is (ignoring exponents) | - | .ffffffff ffffffff | - | ------------------ = 1.ffffffff fffffffe | - | .80000000 00000000 | - | and the minimum is | - | .80000000 00000000 | - | ------------------ = .80000000 00000001 (rounded) | - | .ffffffff ffffffff | - | | - +---------------------------------------------------------------------------*/ - - -L_Full_Division: - /* Save extended dividend in local register*/ - movl SIGL(%esi),%eax - movl %eax,accum_2 - movl SIGH(%esi),%eax - movl %eax,accum_3 - xorl %eax,%eax - movl %eax,accum_1 /* zero the extension */ - movl %eax,accum_0 /* zero the extension */ - - movl SIGL(%esi),%eax /* Get the current num */ - movl SIGH(%esi),%edx - -/*----------------------------------------------------------------------*/ -/* Initialization done */ -/* Do the first 32 bits */ - - movb $0,ovfl_flag - cmpl SIGH(%ebx),%edx /* Test for imminent overflow */ - jb LLess_than_1 - ja LGreater_than_1 - - cmpl SIGL(%ebx),%eax - jb LLess_than_1 - -LGreater_than_1: -/* The dividend is greater or equal, would cause overflow */ - setaeb ovfl_flag /* Keep a record */ - - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx /* Prevent the overflow */ - movl %eax,accum_2 - movl %edx,accum_3 - -LLess_than_1: -/* At this point, we have a dividend < divisor, with a record of - adjustment in ovfl_flag */ - - /* We will divide by a number which is too large */ - movl SIGH(%ebx),%ecx - addl $1,%ecx - jnc LFirst_div_not_1 - - /* here we need to divide by 100000000h, - i.e., no division at all.. */ - mov %edx,%eax - jmp LFirst_div_done - -LFirst_div_not_1: - divl %ecx /* Divide the numerator by the augmented - denom ms dw */ - -LFirst_div_done: - movl %eax,result_2 /* Put the result in the answer */ - - mull SIGH(%ebx) /* mul by the ms dw of the denom */ - - subl %eax,accum_2 /* Subtract from the num local reg */ - sbbl %edx,accum_3 - - movl result_2,%eax /* Get the result back */ - mull SIGL(%ebx) /* now mul the ls dw of the denom */ - - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - sbbl $0,accum_3 - je LDo_2nd_32_bits /* Must check for non-zero result here */ - -#ifdef PARANOID - jb L_bugged_1 -#endif PARANOID - - /* need to subtract another once of the denom */ - incl result_2 /* Correct the answer */ - - movl SIGL(%ebx),%eax - movl SIGH(%ebx),%edx - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - -#ifdef PARANOID - sbbl $0,accum_3 - jne L_bugged_1 /* Must check for non-zero result here */ -#endif PARANOID - -/*----------------------------------------------------------------------*/ -/* Half of the main problem is done, there is just a reduced numerator - to handle now */ -/* Work with the second 32 bits, accum_0 not used from now on */ -LDo_2nd_32_bits: - movl accum_2,%edx /* get the reduced num */ - movl accum_1,%eax - - /* need to check for possible subsequent overflow */ - cmpl SIGH(%ebx),%edx - jb LDo_2nd_div - ja LPrevent_2nd_overflow - - cmpl SIGL(%ebx),%eax - jb LDo_2nd_div - -LPrevent_2nd_overflow: -/* The numerator is greater or equal, would cause overflow */ - /* prevent overflow */ - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx - movl %edx,accum_2 - movl %eax,accum_1 - - incl result_2 /* Reflect the subtraction in the answer */ - -#ifdef PARANOID - je L_bugged_2 /* Can't bump the result to 1.0 */ -#endif PARANOID - -LDo_2nd_div: - cmpl $0,%ecx /* augmented denom msw*/ - jnz LSecond_div_not_1 - - /* %ecx == 0, we are dividing by 1.0 */ - mov %edx,%eax - jmp LSecond_div_done - -LSecond_div_not_1: - divl %ecx /* Divide the numerator by the denom ms dw */ - -LSecond_div_done: - movl %eax,result_1 /* Put the result in the answer */ - - mull SIGH(%ebx) /* mul by the ms dw of the denom */ - - subl %eax,accum_1 /* Subtract from the num local reg */ - sbbl %edx,accum_2 - -#ifdef PARANOID - jc L_bugged_2 -#endif PARANOID - - movl result_1,%eax /* Get the result back */ - mull SIGL(%ebx) /* now mul the ls dw of the denom */ - - subl %eax,accum_0 /* Subtract from the num local reg */ - sbbl %edx,accum_1 /* Subtract from the num local reg */ - sbbl $0,accum_2 - -#ifdef PARANOID - jc L_bugged_2 -#endif PARANOID - - jz LDo_3rd_32_bits - -#ifdef PARANOID - cmpl $1,accum_2 - jne L_bugged_2 -#endif PARANOID - - /* need to subtract another once of the denom */ - movl SIGL(%ebx),%eax - movl SIGH(%ebx),%edx - subl %eax,accum_0 /* Subtract from the num local reg */ - sbbl %edx,accum_1 - sbbl $0,accum_2 - -#ifdef PARANOID - jc L_bugged_2 - jne L_bugged_2 -#endif PARANOID - - addl $1,result_1 /* Correct the answer */ - adcl $0,result_2 - -#ifdef PARANOID - jc L_bugged_2 /* Must check for non-zero result here */ -#endif PARANOID - -/*----------------------------------------------------------------------*/ -/* The division is essentially finished here, we just need to perform - tidying operations. */ -/* deal with the 3rd 32 bits */ -LDo_3rd_32_bits: - movl accum_1,%edx /* get the reduced num */ - movl accum_0,%eax - - /* need to check for possible subsequent overflow */ - cmpl SIGH(%ebx),%edx /* denom*/ - jb LRound_prep - ja LPrevent_3rd_overflow - - cmpl SIGL(%ebx),%eax /* denom */ - jb LRound_prep - -LPrevent_3rd_overflow: - /* prevent overflow */ - subl SIGL(%ebx),%eax - sbbl SIGH(%ebx),%edx - movl %edx,accum_1 - movl %eax,accum_0 - - addl $1,result_1 /* Reflect the subtraction in the answer */ - adcl $0,result_2 - jne LRound_prep - jnc LRound_prep - - /* This is a tricky spot, there is an overflow of the answer */ - movb $255,ovfl_flag /* Overflow -> 1.000 */ - -LRound_prep: -/* Prepare for rounding. -// To test for rounding, we just need to compare 2*accum with the -// denom. */ - movl accum_0,%ecx - movl accum_1,%edx - movl %ecx,%eax - orl %edx,%eax - jz LRound_ovfl /* The accumulator contains zero.*/ - - /* Multiply by 2 */ - clc - rcll $1,%ecx - rcll $1,%edx - jc LRound_large /* No need to compare, denom smaller */ - - subl SIGL(%ebx),%ecx - sbbl SIGH(%ebx),%edx - jnc LRound_not_small - - movl $0x70000000,%eax /* Denom was larger */ - jmp LRound_ovfl - -LRound_not_small: - jnz LRound_large - - movl $0x80000000,%eax /* Remainder was exactly 1/2 denom */ - jmp LRound_ovfl - -LRound_large: - movl $0xff000000,%eax /* Denom was smaller */ - -LRound_ovfl: -/* We are now ready to deal with rounding, but first we must get - the bits properly aligned */ - testb $255,ovfl_flag /* was the num > denom ? */ - je LRound_precision - - incl EXP(%edi) - - /* shift the mantissa right one bit */ - stc /* Will set the ms bit */ - rcrl result_2 - rcrl result_1 - rcrl %eax - -/* Round the result as required */ -LRound_precision: - decl EXP(%edi) /* binary point between 1st & 2nd bits */ - - movl %eax,%edx - movl result_1,%ebx - movl result_2,%eax - jmp FPU_round - - -#ifdef PARANOID -/* The logic is wrong if we got here */ -L_bugged: - pushl EX_INTERNAL|0x202 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_1: - pushl EX_INTERNAL|0x203 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_2: - pushl EX_INTERNAL|0x204 - call EXCEPTION - pop %ebx - jmp L_exit - -L_exit: - popl %ebx - popl %edi - popl %esi - - leave - ret -#endif PARANOID diff --git a/sys/platform/pc32/gnu/fpemul/reg_u_mul.s b/sys/platform/pc32/gnu/fpemul/reg_u_mul.s deleted file mode 100644 index 7b6bfe4624..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_u_mul.s +++ /dev/null @@ -1,195 +0,0 @@ - .file "reg_u_mul.S" -/* - * reg_u_mul.S - * - * Core multiplication routine - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_mul.s,v 1.9 1999/08/28 00:42:58 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_u_mul.s,v 1.4 2003/08/07 21:17:21 dillon Exp $ - * - */ - -/*---------------------------------------------------------------------------+ - | Basic multiplication routine. | - | Does not check the resulting exponent for overflow/underflow | - | | - | reg_u_mul(FPU_REG *a, FPU_REG *b, FPU_REG *c, unsigned int cw); | - | | - | Internal working is at approx 128 bits. | - | Result is rounded to nearest 53 or 64 bits, using "nearest or even". | - +---------------------------------------------------------------------------*/ - -#include "fpu_asm.h" - - -.data - ALIGN_DATA -accum_0: - .long 0 -accum_1: - .long 0 - - -.text -ENTRY(reg_u_mul) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - movl PARAM2,%edi - -#ifdef PARANOID - testl $0x80000000,SIGH(%esi) - jz L_bugged - testl $0x80000000,SIGH(%edi) - jz L_bugged -#endif PARANOID - -#ifdef DENORM_OPERAND - movl EXP(%esi),%eax - cmpl EXP_UNDER,%eax - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - movl EXP(%edi),%eax - cmpl EXP_UNDER,%eax - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif DENORM_OPERAND - - xorl %ecx,%ecx - xorl %ebx,%ebx - - movl SIGL(%esi),%eax - mull SIGL(%edi) - movl %eax,accum_0 - movl %edx,accum_1 - - movl SIGL(%esi),%eax - mull SIGH(%edi) - addl %eax,accum_1 - adcl %edx,%ebx -/* adcl $0,%ecx *//* overflow here is not possible */ - - movl SIGH(%esi),%eax - mull SIGL(%edi) - addl %eax,accum_1 - adcl %edx,%ebx - adcl $0,%ecx - - movl SIGH(%esi),%eax - mull SIGH(%edi) - addl %eax,%ebx - adcl %edx,%ecx - - movl EXP(%esi),%eax /* Compute the exponent */ - addl EXP(%edi),%eax - subl EXP_BIAS-1,%eax -/* Have now finished with the sources */ - movl PARAM3,%edi /* Point to the destination */ - movl %eax,EXP(%edi) - -/* Now make sure that the result is normalized */ - testl $0x80000000,%ecx - jnz LResult_Normalised - - /* Normalize by shifting left one bit */ - shll $1,accum_0 - rcll $1,accum_1 - rcll $1,%ebx - rcll $1,%ecx - decl EXP(%edi) - -LResult_Normalised: - movl accum_0,%eax - movl accum_1,%edx - orl %eax,%eax - jz L_extent_zero - - orl $1,%edx - -L_extent_zero: - movl %ecx,%eax - jmp FPU_round - - -#ifdef PARANOID -L_bugged: - pushl EX_INTERNAL|0x205 - call EXCEPTION - pop %ebx - jmp L_exit - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret -#endif PARANOID - diff --git a/sys/platform/pc32/gnu/fpemul/reg_u_sub.s b/sys/platform/pc32/gnu/fpemul/reg_u_sub.s deleted file mode 100644 index 03b0a94ef8..0000000000 --- a/sys/platform/pc32/gnu/fpemul/reg_u_sub.s +++ /dev/null @@ -1,358 +0,0 @@ - .file "reg_u_sub.S" -/* - * reg_u_sub.S - * - * Core floating point subtraction routine. - * - * Call from C as: - * void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, - * int control_w) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/reg_u_sub.s,v 1.9 1999/08/28 00:42:58 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/reg_u_sub.s,v 1.4 2003/08/07 21:17:21 dillon Exp $ - * - */ - -/* - | Kernel subtraction routine reg_u_sub(reg *arg1, reg *arg2, reg *answ). - | Takes two valid reg f.p. numbers (TW_Valid), which are - | treated as unsigned numbers, - | and returns their difference as a TW_Valid or TW_Zero f.p. - | number. - | The first number (arg1) must be the larger. - | The returned number is normalized. - | Basic checks are performed if PARANOID is defined. - */ - -#include "fpu_asm.h" - -.text -ENTRY(reg_u_sub) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi /* source 1 */ - movl PARAM2,%edi /* source 2 */ - -#ifdef DENORM_OPERAND - cmpl EXP_UNDER,EXP(%esi) - jg xOp1_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp1_not_denorm: - cmpl EXP_UNDER,EXP(%edi) - jg xOp2_not_denorm - - call denormal_operand - orl %eax,%eax - jnz FPU_Arith_exit - -xOp2_not_denorm: -#endif DENORM_OPERAND - -/* xorl %ecx,%ecx */ - movl EXP(%esi),%ecx - subl EXP(%edi),%ecx /* exp1 - exp2 */ - -#ifdef PARANOID - /* source 2 is always smaller than source 1 */ -/* jc L_bugged */ - js L_bugged_1 - - testl $0x80000000,SIGH(%edi) /* The args are assumed to be be normalized */ - je L_bugged_2 - - testl $0x80000000,SIGH(%esi) - je L_bugged_2 -#endif PARANOID - -/*--------------------------------------+ - | Form a register holding the | - | smaller number | - +--------------------------------------*/ - movl SIGH(%edi),%eax /* register ms word */ - movl SIGL(%edi),%ebx /* register ls word */ - - movl PARAM3,%edi /* destination */ - movl EXP(%esi),%edx - movl %edx,EXP(%edi) /* Copy exponent to destination */ - movb SIGN(%esi),%dl - movb %dl,SIGN(%edi) /* Copy the sign from the first arg */ - - xorl %edx,%edx /* register extension */ - -/*--------------------------------------+ - | Shift the temporary register | - | right the required number of | - | places. | - +--------------------------------------*/ -L_shift_r: - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - jmp L_shift_done - -L_more_than_31: - cmpl $64,%ecx - jnc L_more_than_63 - - subb $32,%cl - jz L_exactly_32 - - shrd %cl,%eax,%edx - shr %cl,%eax - orl %ebx,%ebx - jz L_more_31_no_low /* none of the lowest bits is set */ - - orl $1,%edx /* record the fact in the extension */ - -L_more_31_no_low: - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_exactly_32: - movl %ebx,%edx - movl %eax,%ebx - xorl %eax,%eax - jmp L_shift_done - -L_more_than_63: - cmpw $65,%cx - jnc L_more_than_64 - - /* Shift right by 64 bits */ - movl %eax,%edx - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_64: - jne L_more_than_65 - - /* Shift right by 65 bits */ - /* Carry is clear if we get here */ - movl %eax,%edx - rcrl %edx - jnc L_shift_65_nc - - orl $1,%edx - jmp L_more_63_no_low - -L_shift_65_nc: - orl %ebx,%ebx - jz L_more_63_no_low - - orl $1,%edx - jmp L_more_63_no_low - -L_more_than_65: - movl $1,%edx /* The shifted nr always at least one '1' */ - -L_more_63_no_low: - xorl %ebx,%ebx - xorl %eax,%eax - -L_shift_done: -L_subtr: -/*------------------------------+ - | Do the subtraction | - +------------------------------*/ - xorl %ecx,%ecx - subl %edx,%ecx - movl %ecx,%edx - movl SIGL(%esi),%ecx - sbbl %ebx,%ecx - movl %ecx,%ebx - movl SIGH(%esi),%ecx - sbbl %eax,%ecx - movl %ecx,%eax - -#ifdef PARANOID - /* We can never get a borrow */ - jc L_bugged -#endif PARANOID - -/*--------------------------------------+ - | Normalize the result | - +--------------------------------------*/ - testl $0x80000000,%eax - jnz L_round /* no shifting needed */ - - orl %eax,%eax - jnz L_shift_1 /* shift left 1 - 31 bits */ - - orl %ebx,%ebx - jnz L_shift_32 /* shift left 32 - 63 bits */ - -/* A rare case, the only one which is non-zero if we got here -// is: 1000000 .... 0000 -// -0111111 .... 1111 1 -// -------------------- -// 0000000 .... 0000 1 */ - - cmpl $0x80000000,%edx - jnz L_must_be_zero - - /* Shift left 64 bits */ - subl $64,EXP(%edi) - movl %edx,%eax - jmp L_store - -L_must_be_zero: -#ifdef PARANOID - orl %edx,%edx - jnz L_bugged_3 -#endif PARANOID - - /* The result is zero */ - movb TW_Zero,TAG(%edi) - movl $0,EXP(%edi) /* exponent */ - movl $0,SIGL(%edi) - movl $0,SIGH(%edi) - jmp L_exit /* Does not underflow */ - -L_shift_32: - movl %ebx,%eax - movl %edx,%ebx - movl $0,%edx - subl $32,EXP(%edi) /* Can get underflow here */ - -/* We need to shift left by 1 - 31 bits */ -L_shift_1: - bsrl %eax,%ecx /* get the required shift in %ecx */ - subl $31,%ecx - negl %ecx - shld %cl,%ebx,%eax - shld %cl,%edx,%ebx - shl %cl,%edx - subl %ecx,EXP(%edi) /* Can get underflow here */ - -L_round: - jmp FPU_round /* Round the result */ - - -#ifdef PARANOID -L_bugged_1: - pushl EX_INTERNAL|0x206 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_2: - pushl EX_INTERNAL|0x209 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_3: - pushl EX_INTERNAL|0x210 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged_4: - pushl EX_INTERNAL|0x211 - call EXCEPTION - pop %ebx - jmp L_exit - -L_bugged: - pushl EX_INTERNAL|0x212 - call EXCEPTION - pop %ebx - jmp L_exit -#endif PARANOID - - -L_store: -/*------------------------------+ - | Store the result | - +------------------------------*/ - movl %eax,SIGH(%edi) - movl %ebx,SIGL(%edi) - - movb TW_Valid,TAG(%edi) /* Set the tags to TW_Valid */ - - cmpl EXP_UNDER,EXP(%edi) - jle L_underflow - -L_exit: - popl %ebx - popl %edi - popl %esi - leave - ret - - -L_underflow: - push %edi - call arith_underflow - pop %ebx - jmp L_exit - diff --git a/sys/platform/pc32/gnu/fpemul/status_w.h b/sys/platform/pc32/gnu/fpemul/status_w.h deleted file mode 100644 index 13c4732c84..0000000000 --- a/sys/platform/pc32/gnu/fpemul/status_w.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * status_w.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/status_w.h,v 1.6 1999/08/28 00:42:59 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/status_w.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - - -#ifndef _STATUS_H_ -#define _STATUS_H_ - - -#ifdef LOCORE -#define Const__(x) $/**/x -#else -#define Const__(x) x -#endif - -#define SW_Backward Const__(0x8000) /* backward compatibility */ -#define SW_C3 Const__(0x4000) /* condition bit 3 */ -#define SW_Top Const__(0x3800) /* top of stack */ -#define SW_Top_Shift Const__(11) /* shift for top of stack bits */ -#define SW_C2 Const__(0x0400) /* condition bit 2 */ -#define SW_C1 Const__(0x0200) /* condition bit 1 */ -#define SW_C0 Const__(0x0100) /* condition bit 0 */ -#define SW_Summary Const__(0x0080) /* exception summary */ -#define SW_Stack_Fault Const__(0x0040) /* stack fault */ -#define SW_Precision Const__(0x0020) /* loss of precision */ -#define SW_Underflow Const__(0x0010) /* underflow */ -#define SW_Overflow Const__(0x0008) /* overflow */ -#define SW_Zero_Div Const__(0x0004) /* divide by zero */ -#define SW_Denorm_Op Const__(0x0002) /* denormalized operand */ -#define SW_Invalid Const__(0x0001) /* invalid operation */ - -#define SW_Exc_Mask Const__(0x27f) /* Status word exception bit mask */ - -#ifndef LOCORE - -#define COMP_A_gt_B 1 -#define COMP_A_eq_B 2 -#define COMP_A_lt_B 3 -#define COMP_No_Comp 4 -#define COMP_Denormal 0x20 -#define COMP_NaN 0x40 -#define COMP_SNaN 0x80 - -#define setcc(cc) ({ \ - status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \ - status_word |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); }) - -#endif /* LOCORE */ - -#endif /* _STATUS_H_ */ diff --git a/sys/platform/pc32/gnu/fpemul/version.h b/sys/platform/pc32/gnu/fpemul/version.h deleted file mode 100644 index 836ad292b1..0000000000 --- a/sys/platform/pc32/gnu/fpemul/version.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * version.h - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/version.h,v 1.6 1999/08/28 00:42:59 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/version.h,v 1.2 2003/06/17 04:28:34 dillon Exp $ - * - */ - -#define FPU_VERSION "wm-FPU-emu version BETA 1.4" diff --git a/sys/platform/pc32/gnu/fpemul/wm_shrx.s b/sys/platform/pc32/gnu/fpemul/wm_shrx.s deleted file mode 100644 index c936777c8c..0000000000 --- a/sys/platform/pc32/gnu/fpemul/wm_shrx.s +++ /dev/null @@ -1,259 +0,0 @@ - .file "wm_shrx.S" -/* - * wm_shrx.S - * - * 64 bit right shift functions - * - * Call from C as: - * unsigned shrx(void *arg1, unsigned arg2) - * and - * unsigned shrxs(void *arg1, unsigned arg2) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/wm_shrx.s,v 1.8 1999/08/28 00:42:59 peter Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/wm_shrx.s,v 1.4 2003/08/07 21:17:21 dillon Exp $ - * - */ - - -#include "fpu_asm.h" - -.text - -/*---------------------------------------------------------------------------+ - | unsigned shrx(void *arg1, unsigned arg2) | - | | - | Extended shift right function. | - | Fastest for small shifts. | - | Shifts the 64 bit quantity pointed to by the first arg (arg1) | - | right by the number of bits specified by the second arg (arg2). | - | Forms a 96 bit quantity from the 64 bit arg and eax: | - | [ 64 bit arg ][ eax ] | - | shift right ---------> | - | The eax register is initialized to 0 before the shifting. | - | Results returned in the 64 bit arg and eax. | - +---------------------------------------------------------------------------*/ - -ENTRY(shrx) - push %ebp - movl %esp,%ebp - pushl %esi - movl PARAM2,%ecx - movl PARAM1,%esi - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jnc L_more_than_31 - -/* less than 32 bits */ - pushl %ebx - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %eax,%eax /* extension */ - shrd %cl,%ebx,%eax - shrd %cl,%edx,%ebx - shr %cl,%edx - movl %ebx,(%esi) - movl %edx,4(%esi) - popl %ebx - popl %esi - leave - ret - -L_more_than_31: - cmpl $64,%ecx - jnc L_more_than_63 - - subb $32,%cl - movl (%esi),%eax /* lsl */ - movl 4(%esi),%edx /* msl */ - shrd %cl,%edx,%eax - shr %cl,%edx - movl %edx,(%esi) - movl $0,4(%esi) - popl %esi - leave - ret - -L_more_than_63: - cmpl $96,%ecx - jnc L_more_than_95 - - subb $64,%cl - movl 4(%esi),%eax /* msl */ - shr %cl,%eax - xorl %edx,%edx - movl %edx,(%esi) - movl %edx,4(%esi) - popl %esi - leave - ret - -L_more_than_95: - xorl %eax,%eax - movl %eax,(%esi) - movl %eax,4(%esi) - popl %esi - leave - ret - - -/*---------------------------------------------------------------------------+ - | unsigned shrxs(void *arg1, unsigned arg2) | - | | - | Extended shift right function (optimized for small floating point | - | integers). | - | Shifts the 64 bit quantity pointed to by the first arg (arg1) | - | right by the number of bits specified by the second arg (arg2). | - | Forms a 96 bit quantity from the 64 bit arg and eax: | - | [ 64 bit arg ][ eax ] | - | shift right ---------> | - | The eax register is initialized to 0 before the shifting. | - | The lower 8 bits of eax are lost and replaced by a flag which is | - | set (to 0x01) if any bit, apart from the first one, is set in the | - | part which has been shifted out of the arg. | - | Results returned in the 64 bit arg and eax. | - +---------------------------------------------------------------------------*/ - .globl shrxs -shrxs: - push %ebp - movl %esp,%ebp - pushl %esi - pushl %ebx - movl PARAM2,%ecx - movl PARAM1,%esi - cmpl $64,%ecx /* shrd only works for 0..31 bits */ - jnc Ls_more_than_63 - - cmpl $32,%ecx /* shrd only works for 0..31 bits */ - jc Ls_less_than_32 - -/* We got here without jumps by assuming that the most common requirement - is for small integers */ -/* Shift by [32..63] bits */ - subb $32,%cl - movl (%esi),%eax /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %ebx,%ebx - shrd %cl,%eax,%ebx - shrd %cl,%edx,%eax - shr %cl,%edx - orl %ebx,%ebx /* test these 32 bits */ - setne %bl - test $0x7fffffff,%eax /* and 31 bits here */ - setne %bh - orw %bx,%bx /* Any of the 63 bit set ? */ - setne %al - movl %edx,(%esi) - movl $0,4(%esi) - popl %ebx - popl %esi - leave - ret - -/* Shift by [0..31] bits */ -Ls_less_than_32: - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%edx /* msl */ - xorl %eax,%eax /* extension */ - shrd %cl,%ebx,%eax - shrd %cl,%edx,%ebx - shr %cl,%edx - test $0x7fffffff,%eax /* only need to look at eax here */ - setne %al - movl %ebx,(%esi) - movl %edx,4(%esi) - popl %ebx - popl %esi - leave - ret - -/* Shift by [64..95] bits */ -Ls_more_than_63: - cmpl $96,%ecx - jnc Ls_more_than_95 - - subb $64,%cl - movl (%esi),%ebx /* lsl */ - movl 4(%esi),%eax /* msl */ - xorl %edx,%edx /* extension */ - shrd %cl,%ebx,%edx - shrd %cl,%eax,%ebx - shr %cl,%eax - orl %ebx,%edx - setne %bl - test $0x7fffffff,%eax /* only need to look at eax here */ - setne %bh - orw %bx,%bx - setne %al - xorl %edx,%edx - movl %edx,(%esi) /* set to zero */ - movl %edx,4(%esi) /* set to zero */ - popl %ebx - popl %esi - leave - ret - -Ls_more_than_95: -/* Shift by [96..inf) bits */ - xorl %eax,%eax - movl (%esi),%ebx - orl 4(%esi),%ebx - setne %al - xorl %ebx,%ebx - movl %ebx,(%esi) - movl %ebx,4(%esi) - popl %ebx - popl %esi - leave - ret diff --git a/sys/platform/pc32/gnu/fpemul/wm_sqrt.s b/sys/platform/pc32/gnu/fpemul/wm_sqrt.s deleted file mode 100644 index 3a891f5b02..0000000000 --- a/sys/platform/pc32/gnu/fpemul/wm_sqrt.s +++ /dev/null @@ -1,493 +0,0 @@ - .file "wm_sqrt.S" -/* - * wm_sqrt.S - * - * Fixed point arithmetic square root evaluation. - * - * Call from C as: - * void wm_sqrt(FPU_REG *n, unsigned int control_word) - * - * - * Copyright (C) 1992,1993,1994 - * W. Metzenthen, 22 Parker St, Ormond, Vic 3163, - * Australia. E-mail billm@vaxc.cc.monash.edu.au - * All rights reserved. - * - * This copyright notice covers the redistribution and use of the - * FPU emulator developed by W. Metzenthen. It covers only its use - * in the 386BSD, FreeBSD and NetBSD operating systems. Any other - * use is not permitted under this copyright. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must include information specifying - * that source code for the emulator is freely available and include - * either: - * a) an offer to provide the source code for a nominal distribution - * fee, or - * b) list at least two alternative methods whereby the source - * can be obtained, e.g. a publically accessible bulletin board - * and an anonymous ftp site from which the software can be - * downloaded. - * 3. All advertising materials specifically mentioning features or use of - * this emulator must acknowledge that it was developed by W. Metzenthen. - * 4. The name of W. Metzenthen may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * W. METZENTHEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * The purpose of this copyright, based upon the Berkeley copyright, is to - * ensure that the covered software remains freely available to everyone. - * - * The software (with necessary differences) is also available, but under - * the terms of the GNU copyleft, for the Linux operating system and for - * the djgpp ms-dos extender. - * - * W. Metzenthen June 1994. - * - * - * $FreeBSD: src/sys/gnu/i386/fpemul/wm_sqrt.s,v 1.9.2.1 2000/07/07 00:38:42 obrien Exp $ - * $DragonFly: src/sys/platform/pc32/gnu/fpemul/Attic/wm_sqrt.s,v 1.3 2003/08/07 21:17:21 dillon Exp $ - * - */ - - -/*---------------------------------------------------------------------------+ - | wm_sqrt(FPU_REG *n, unsigned int control_word) | - | returns the square root of n in n. | - | | - | Use Newton's method to compute the square root of a number, which must | - | be in the range [1.0 .. 4.0), to 64 bits accuracy. | - | Does not check the sign or tag of the argument. | - | Sets the exponent, but not the sign or tag of the result. | - | | - | The guess is kept in %esi:%edi | - +---------------------------------------------------------------------------*/ - -#include "fpu_asm.h" - - -.data -/* - Local storage: - */ - ALIGN_DATA -accum_3: - .long 0 /* ms word */ -accum_2: - .long 0 -accum_1: - .long 0 -accum_0: - .long 0 - -/* The de-normalised argument: -// sq_2 sq_1 sq_0 -// b b b b b b b ... b b b b b b .... b b b b 0 0 0 ... 0 -// ^ binary point here */ -fsqrt_arg_2: - .long 0 /* ms word */ -fsqrt_arg_1: - .long 0 -fsqrt_arg_0: - .long 0 /* ls word, at most the ms bit is set */ - -.text - -ENTRY(wm_sqrt) - pushl %ebp - movl %esp,%ebp - pushl %esi - pushl %edi - pushl %ebx - - movl PARAM1,%esi - - movl SIGH(%esi),%eax - movl SIGL(%esi),%ecx - xorl %edx,%edx - -/* We use a rough linear estimate for the first guess.. */ - - cmpl EXP_BIAS,EXP(%esi) - jnz sqrt_arg_ge_2 - - shrl $1,%eax /* arg is in the range [1.0 .. 2.0) */ - rcrl $1,%ecx - rcrl $1,%edx - -sqrt_arg_ge_2: -/* From here on, n is never accessed directly again until it is -// replaced by the answer. */ - - movl %eax,fsqrt_arg_2 /* ms word of n */ - movl %ecx,fsqrt_arg_1 - movl %edx,fsqrt_arg_0 - -/* Make a linear first estimate */ - shrl $1,%eax - addl $0x40000000,%eax - movl $0xaaaaaaaa,%ecx - mull %ecx - shll %edx /* max result was 7fff... */ - testl $0x80000000,%edx /* but min was 3fff... */ - jnz sqrt_prelim_no_adjust - - movl $0x80000000,%edx /* round up */ - -sqrt_prelim_no_adjust: - movl %edx,%esi /* Our first guess */ - -/* We have now computed (approx) (2 + x) / 3, which forms the basis - for a few iterations of Newton's method */ - - movl fsqrt_arg_2,%ecx /* ms word */ - -/* From our initial estimate, three iterations are enough to get us -// to 30 bits or so. This will then allow two iterations at better -// precision to complete the process. - -// Compute (g + n/g)/2 at each iteration (g is the guess). */ - shrl %ecx /* Doing this first will prevent a divide */ - /* overflow later. */ - - movl %ecx,%edx /* msw of the arg / 2 */ - divl %esi /* current estimate */ - shrl %esi /* divide by 2 */ - addl %eax,%esi /* the new estimate */ - - movl %ecx,%edx - divl %esi - shrl %esi - addl %eax,%esi - - movl %ecx,%edx - divl %esi - shrl %esi - addl %eax,%esi - -/* Now that an estimate accurate to about 30 bits has been obtained (in %esi), -// we improve it to 60 bits or so. - -// The strategy from now on is to compute new estimates from -// guess := guess + (n - guess^2) / (2 * guess) */ - -/* First, find the square of the guess */ - movl %esi,%eax - mull %esi -/* guess^2 now in %edx:%eax */ - - movl fsqrt_arg_1,%ecx - subl %ecx,%eax - movl fsqrt_arg_2,%ecx /* ms word of normalized n */ - sbbl %ecx,%edx - jnc sqrt_stage_2_positive -/* subtraction gives a negative result -// negate the result before division */ - notl %edx - notl %eax - addl $1,%eax - adcl $0,%edx - - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - jmp sqrt_stage_2_finish - -sqrt_stage_2_positive: - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - notl %ecx - notl %eax - addl $1,%eax - adcl $0,%ecx - -sqrt_stage_2_finish: - sarl $1,%ecx /* divide by 2 */ - rcrl $1,%eax - - /* Form the new estimate in %esi:%edi */ - movl %eax,%edi - addl %ecx,%esi - - jnz sqrt_stage_2_done /* result should be [1..2) */ - -#ifdef PARANOID -/* It should be possible to get here only if the arg is ffff....ffff*/ - cmp $0xffffffff,fsqrt_arg_1 - jnz sqrt_stage_2_error -#endif PARANOID - -/* The best rounded result.*/ - xorl %eax,%eax - decl %eax - movl %eax,%edi - movl %eax,%esi - movl $0x7fffffff,%eax - jmp sqrt_round_result - -#ifdef PARANOID -sqrt_stage_2_error: - pushl EX_INTERNAL|0x213 - call EXCEPTION -#endif PARANOID - -sqrt_stage_2_done: - -/* Now the square root has been computed to better than 60 bits */ - -/* Find the square of the guess*/ - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,accum_1 - - movl %esi,%eax - mull %esi - movl %edx,accum_3 - movl %eax,accum_2 - - movl %edi,%eax - mull %esi - addl %eax,accum_1 - adcl %edx,accum_2 - adcl $0,accum_3 - -/* movl %esi,%eax*/ -/* mull %edi*/ - addl %eax,accum_1 - adcl %edx,accum_2 - adcl $0,accum_3 - -/* guess^2 now in accum_3:accum_2:accum_1*/ - - movl fsqrt_arg_0,%eax /* get normalized n*/ - subl %eax,accum_1 - movl fsqrt_arg_1,%eax - sbbl %eax,accum_2 - movl fsqrt_arg_2,%eax /* ms word of normalized n*/ - sbbl %eax,accum_3 - jnc sqrt_stage_3_positive - -/* subtraction gives a negative result*/ -/* negate the result before division */ - notl accum_1 - notl accum_2 - notl accum_3 - addl $1,accum_1 - adcl $0,accum_2 - -#ifdef PARANOID - adcl $0,accum_3 /* This must be zero */ - jz sqrt_stage_3_no_error - -sqrt_stage_3_error: - pushl EX_INTERNAL|0x207 - call EXCEPTION - -sqrt_stage_3_no_error: -#endif PARANOID - - movl accum_2,%edx - movl accum_1,%eax - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - sarl $1,%ecx /* divide by 2*/ - rcrl $1,%eax - - /* prepare to round the result*/ - - addl %ecx,%edi - adcl $0,%esi - - jmp sqrt_stage_3_finished - -sqrt_stage_3_positive: - movl accum_2,%edx - movl accum_1,%eax - divl %esi - movl %eax,%ecx - - movl %edx,%eax - divl %esi - - sarl $1,%ecx /* divide by 2*/ - rcrl $1,%eax - - /* prepare to round the result*/ - - notl %eax /* Negate the correction term*/ - notl %ecx - addl $1,%eax - adcl $0,%ecx /* carry here ==> correction == 0*/ - adcl $0xffffffff,%esi - - addl %ecx,%edi - adcl $0,%esi - -sqrt_stage_3_finished: - -/* The result in %esi:%edi:%esi should be good to about 90 bits here, -// and the rounding information here does not have sufficient accuracy -// in a few rare cases. */ - cmpl $0xffffffe0,%eax - ja sqrt_near_exact_x - - cmpl $0x00000020,%eax - jb sqrt_near_exact - - cmpl $0x7fffffe0,%eax - jb sqrt_round_result - - cmpl $0x80000020,%eax - jb sqrt_get_more_precision - -sqrt_round_result: -/* Set up for rounding operations*/ - movl %eax,%edx - movl %esi,%eax - movl %edi,%ebx - movl PARAM1,%edi - movl EXP_BIAS,EXP(%edi) /* Result is in [1.0 .. 2.0)*/ - movl PARAM2,%ecx - jmp FPU_round_sqrt - - -sqrt_near_exact_x: -/* First, the estimate must be rounded up.*/ - addl $1,%edi - adcl $0,%esi - -sqrt_near_exact: -/* This is an easy case because x^1/2 is monotonic. -// We need just find the square of our estimate, compare it -// with the argument, and deduce whether our estimate is -// above, below, or exact. We use the fact that the estimate -// is known to be accurate to about 90 bits. */ - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,%ebx /* 2nd ls word of square*/ - movl %eax,%ecx /* ls word of square*/ - - movl %edi,%eax - mull %esi - addl %eax,%ebx - addl %eax,%ebx - -#ifdef PARANOID - cmp $0xffffffb0,%ebx - jb sqrt_near_exact_ok - - cmp $0x00000050,%ebx - ja sqrt_near_exact_ok - - pushl EX_INTERNAL|0x214 - call EXCEPTION - -sqrt_near_exact_ok: -#endif PARANOID - - or %ebx,%ebx - js sqrt_near_exact_small - - jnz sqrt_near_exact_large - - or %ebx,%edx - jnz sqrt_near_exact_large - -/* Our estimate is exactly the right answer*/ - xorl %eax,%eax - jmp sqrt_round_result - -sqrt_near_exact_small: -/* Our estimate is too small*/ - movl $0x000000ff,%eax - jmp sqrt_round_result - -sqrt_near_exact_large: -/* Our estimate is too large, we need to decrement it*/ - subl $1,%edi - sbbl $0,%esi - movl $0xffffff00,%eax - jmp sqrt_round_result - - -sqrt_get_more_precision: -/* This case is almost the same as the above, except we start*/ -/* with an extra bit of precision in the estimate.*/ - stc /* The extra bit.*/ - rcll $1,%edi /* Shift the estimate left one bit*/ - rcll $1,%esi - - movl %edi,%eax /* ls word of guess*/ - mull %edi - movl %edx,%ebx /* 2nd ls word of square*/ - movl %eax,%ecx /* ls word of square*/ - - movl %edi,%eax - mull %esi - addl %eax,%ebx - addl %eax,%ebx - -/* Put our estimate back to its original value*/ - stc /* The ms bit.*/ - rcrl $1,%esi /* Shift the estimate left one bit*/ - rcrl $1,%edi - -#ifdef PARANOID - cmp $0xffffff60,%ebx - jb sqrt_more_prec_ok - - cmp $0x000000a0,%ebx - ja sqrt_more_prec_ok - - pushl EX_INTERNAL|0x215 - call EXCEPTION - -sqrt_more_prec_ok: -#endif PARANOID - - or %ebx,%ebx - js sqrt_more_prec_small - - jnz sqrt_more_prec_large - - or %ebx,%ecx - jnz sqrt_more_prec_large - -/* Our estimate is exactly the right answer*/ - movl $0x80000000,%eax - jmp sqrt_round_result - -sqrt_more_prec_small: -/* Our estimate is too small*/ - movl $0x800000ff,%eax - jmp sqrt_round_result - -sqrt_more_prec_large: -/* Our estimate is too large*/ - movl $0x7fffff00,%eax - jmp sqrt_round_result diff --git a/sys/platform/pc32/gnu/isa/dgb.c b/sys/platform/pc32/gnu/isa/dgb.c index 0240b34308..9af303ddb5 100644 --- a/sys/platform/pc32/gnu/isa/dgb.c +++ b/sys/platform/pc32/gnu/isa/dgb.c @@ -1,6 +1,6 @@ /*- * dgb.c $FreeBSD: src/sys/gnu/i386/isa/dgb.c,v 1.56.2.1 2001/02/26 04:23:09 jlemon Exp $ - * dgb.c $DragonFly: src/sys/platform/pc32/gnu/isa/dgb.c,v 1.14 2004/12/08 20:36:39 joerg Exp $ + * dgb.c $DragonFly: src/sys/platform/pc32/gnu/isa/dgb.c,v 1.15 2005/01/31 23:44:35 joerg Exp $ * * Digiboard driver. * @@ -31,8 +31,8 @@ #include "opt_compat.h" #include "opt_dgb.h" #include "opt_depricated.h" -#ifndef I_WANT_DEPRICATED_STUFF -#error "Add options I_WANT_DEPRICATED_STUFF to your kernel config and send a mail to kernel@" +#ifndef I_WANT_DEPRECATED_STUFF +#error "Add options I_WANT_DEPRECATED_STUFF to your kernel config and send a mail to kernel@" #endif #include "use_dgb.h" diff --git a/sys/platform/pc32/gnu/isa/sound/awe_compat.h b/sys/platform/pc32/gnu/isa/sound/awe_compat.h deleted file mode 100644 index 6a420c3164..0000000000 --- a/sys/platform/pc32/gnu/isa/sound/awe_compat.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * sound/awe_compat.h - * - * Compat defines for the AWE32/Sound Blaster 32 wave table synth. driver - * version 0.4.2c; Oct. 7, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $DragonFly: src/sys/platform/pc32/gnu/isa/sound/Attic/awe_compat.h,v 1.2 2004/02/12 23:33:26 joerg Exp $ - */ - -/*---------------------------------------------------------------- - * compatibility macros for AWE32 driver - *----------------------------------------------------------------*/ - -/* redefine following macros */ -#undef IOCTL_IN -#undef IOCTL_OUT -#undef OUTW -#undef COPY_FROM_USER -#undef COPY_TO_USER -#undef GET_BYTE_FROM_USER -#undef GET_SHORT_FROM_USER -#undef IOCTL_TO_USER - -#ifdef linux - -/*================================================================ - * Linux macros - *================================================================*/ - -/* use inline prefix */ -#define INLINE inline - -/*---------------------------------------------------------------- - * memory management for linux - *----------------------------------------------------------------*/ - -#ifdef AWE_OBSOLETE_VOXWARE -/* old type linux system */ - -/* i/o requests; nothing */ -#define awe_check_port() 0 /* always false */ -#define awe_request_region() /* nothing */ -#define awe_release_region() /* nothing */ - -static int _mem_start; /* memory pointer for permanent buffers */ - -#define my_malloc_init(memptr) _mem_start = (memptr) -#define my_malloc_memptr() _mem_start -#define my_free(ptr) /* do nothing */ -#define my_realloc(buf,oldsize,size) NULL /* no realloc */ - -static void *my_malloc(int size) -{ - char *ptr; - PERMANENT_MALLOC(ptr, char*, size, _mem_start); - return (void*)ptr; -} - -/* allocate buffer only once */ -#define INIT_TABLE(buffer,index,nums,type) {\ -buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\ -} - -#else - -#define AWE_DYNAMIC_BUFFER - -#define my_malloc_init(ptr) /* nothing */ -#define my_malloc_memptr() 0 -#define my_malloc(size) vmalloc(size) -#define my_free(ptr) if (ptr) {vfree(ptr);} - -static void *my_realloc(void *buf, int oldsize, int size) -{ - void *ptr; - if ((ptr = vmalloc(size)) == NULL) - return NULL; - memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) ); - vfree(buf); - return ptr; -} - -/* do not allocate buffer at beginning */ -#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;} - -/* old type macro */ -#define RET_ERROR(err) -err - -#endif - -/*---------------------------------------------------------------- - * i/o interfaces for linux - *----------------------------------------------------------------*/ - -#define OUTW(data,addr) outw(data, addr) - -#ifdef AWE_NEW_KERNEL_INTERFACE -#define COPY_FROM_USER(target,source,offs,count) \ - copy_from_user(target, (source)+(offs), count) -#define GET_BYTE_FROM_USER(target,addr,offs) \ - get_user(target, (unsigned char*)&((addr)[offs])) -#define GET_SHORT_FROM_USER(target,addr,offs) \ - get_user(target, (unsigned short*)&((addr)[offs])) -#ifdef AWE_OSS38 -#define IOCTL_TO_USER(target,offs,source,count) \ - memcpy(target, (source)+(offs), count) -#define IO_WRITE_CHECK(cmd) (_SIOC_DIR(cmd) & _IOC_WRITE) -#else -#define IOCTL_TO_USER(target,offs,source,count) \ - copy_to_user(target, (source)+(offs), count) -#define IO_WRITE_CHECK(cmd) (_IOC_DIR(cmd) & _IOC_WRITE) -#endif /* AWE_OSS38 */ -#define COPY_TO_USER IOCTL_TO_USER -#define IOCTL_IN(arg) (*(int*)(arg)) -#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val)) - -#else /* old type i/o */ -#define COPY_FROM_USER(target,source,offs,count) \ - memcpy_fromfs(target, (source)+(offs), (count)) -#define GET_BYTE_FROM_USER(target,addr,offs) \ - *((char *)&(target)) = get_fs_byte((addr)+(offs)) -#define GET_SHORT_FROM_USER(target,addr,offs) \ - *((short *)&(target)) = get_fs_word((addr)+(offs)) -#define IOCTL_TO_USER(target,offs,source,count) \ - memcpy_tofs(target, (source)+(offs), (count)) -#define COPY_TO_USER IOCTL_TO_USER -#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN) -#define IOCTL_IN(arg) get_fs_long((long *)(arg)) -#define IOCTL_OUT(arg,ret) snd_ioctl_return((int *)arg, ret) - -#endif /* AWE_NEW_KERNEL_INTERFACE */ - -#define BZERO(target,len) memset(target, 0, len) -#define MEMCPY(dst,src,len) memcpy(dst, src, len) - - -#elif defined(__DragonFly__) || defined(__FreeBSD__) - -/*================================================================ - * FreeBSD macros - *================================================================*/ - -/* inline is not checked yet.. maybe it'll work */ -#define INLINE /*inline*/ - -/*---------------------------------------------------------------- - * memory management for freebsd - *----------------------------------------------------------------*/ - -/* i/o requests; nothing */ -#define awe_check_port() 0 /* always false */ -#define awe_request_region() /* nothing */ -#define awe_release_region() /* nothing */ - -#define AWE_DYNAMIC_BUFFER - -#define my_malloc_init(ptr) /* nothing */ -#define my_malloc_memptr() 0 -#define my_malloc(size) malloc(size, M_TEMP, M_WAITOK) -#define my_free(ptr) if (ptr) {free(ptr, M_TEMP);} - -#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;} - -/* it should be realloc? */ -static void *my_realloc(void *buf, int oldsize, int size) -{ - void *ptr; - if ((ptr = my_malloc(size)) == NULL) - return NULL; - memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) ); - my_free(buf); - return ptr; -} - -/*---------------------------------------------------------------- - * i/o interfaces for freebsd - *----------------------------------------------------------------*/ - -/* according to linux rule; the arguments are swapped */ -#define OUTW(data,addr) outw(addr, data) - -#define COPY_FROM_USER(target,source,offs,count) \ - uiomove(((caddr_t)(target)),(count),((struct uio *)(source))) -#define COPY_TO_USER(target,source,offs,count) \ - uiomove(((caddr_t)(source)),(count),((struct uio *)(target))) -#define GET_BYTE_FROM_USER(target,addr,offs) \ - uiomove(((char*)&(target)), 1, ((struct uio *)(addr))) -#define GET_SHORT_FROM_USER(target,addr,offs) \ - uiomove(((char*)&(target)), 2, ((struct uio *)(addr))) -#define IOCTL_TO_USER(target,offs,source,count) \ - memcpy(&((target)[offs]), (source), (count)) -#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN) -#define IOCTL_IN(arg) (*(int*)(arg)) -#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val)) -#define BZERO(target,len) bzero((caddr_t)target, len) -#define MEMCPY(dst,src,len) bcopy((caddr_t)src, (caddr_t)dst, len) - -#ifndef AWE_OBSOLETE_VOXWARE -# define printk printf -# define RET_ERROR(err) -err -#endif - -#endif - diff --git a/sys/platform/pc32/gnu/isa/sound/awe_config.h b/sys/platform/pc32/gnu/isa/sound/awe_config.h deleted file mode 100644 index 8af95d0cba..0000000000 --- a/sys/platform/pc32/gnu/isa/sound/awe_config.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * sound/awe_config.h - * - * Configuration of AWE32 sound driver - * version 0.4.2; Sep. 15, 1997 - * - * Copyright (C) 1996 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $DragonFly: src/sys/platform/pc32/gnu/isa/sound/Attic/awe_config.h,v 1.2 2004/02/12 23:33:26 joerg Exp $ - */ - -#ifndef AWE_CONFIG_H_DEF -#define AWE_CONFIG_H_DEF - -/*---------------------------------------------------------------- - * system configuration - *----------------------------------------------------------------*/ - -/* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or pre-Voxware 3.5 - * versions of FreeBSD), define the following line. - */ -#undef AWE_OBSOLETE_VOXWARE - -/* if you're using OSS-Lite on Linux 2.1.6 or later, define the - * following line. - */ -#undef AWE_NEW_KERNEL_INTERFACE - -/* if you have lowlevel.h in the lowlevel directory (OSS-Lite), define - * the following line. - */ -#undef HAS_LOWLEVEL_H - -/* if your system doesn't support patch manager (OSS 3.7 or newer), - * define the following line. - */ -#undef AWE_NO_PATCHMGR - -/* if your system has an additional parameter (OSS 3.8b5 or newer), - * define this. - */ -#undef AWE_OSS38 - -/*---------------------------------------------------------------- - * AWE32 card configuration: - * uncomment the following lines only when auto detection doesn't - * work properly on your machine. - *----------------------------------------------------------------*/ - -/*#define AWE_DEFAULT_BASE_ADDR 0x620*/ /* base port address */ -/*#define AWE_DEFAULT_MEM_SIZE 512*/ /* kbytes */ - - -/*---------------------------------------------------------------- - * maximum size of soundfont list table: - * you usually don't need to touch this value. - *----------------------------------------------------------------*/ - -#define AWE_MAX_SF_LISTS 16 - - -/*---------------------------------------------------------------- - * chunk size of sample and voice tables: - * you usually don't need to touch these values. - *----------------------------------------------------------------*/ - -#define AWE_MAX_SAMPLES 400 -#define AWE_MAX_INFOS 800 - - -/*---------------------------------------------------------------- - * chorus & reverb effects send for FM chip: from 0 to 0xff - * larger numbers often cause weird sounds. - *----------------------------------------------------------------*/ - -#define DEF_FM_CHORUS_DEPTH 0x10 -#define DEF_FM_REVERB_DEPTH 0x10 - - -/*----------------------------------------------------------------* - * other compile conditions - *----------------------------------------------------------------*/ - -/* initialize FM passthrough even without extended RAM */ -#undef AWE_ALWAYS_INIT_FM - -/* debug on */ -#define AWE_DEBUG_ON - -/* GUS compatible mode */ -#define AWE_HAS_GUS_COMPATIBILITY - -/* accept all notes/sounds off controls */ -#define AWE_ACCEPT_ALL_SOUNDS_CONTROL - -/* add mixer control of emu8000 equalizer */ -#define CONFIG_AWE32_MIXER - -/* look up voices according to MIDI channel priority */ -#define AWE_LOOKUP_MIDI_PRIORITY - -/*----------------------------------------------------------------*/ - -/* reading configuration of sound driver */ - -#ifdef AWE_OBSOLETE_VOXWARE - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include -#else -# include "sound_config.h" -#endif - -#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32) -#define CONFIG_AWE32_SYNTH -#endif - -#else /* AWE_OBSOLETE_VOXWARE */ - -#ifdef HAS_LOWLEVEL_H -#include "lowlevel.h" -#endif - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include -# if defined(CONFIGURE_SOUNDCARD) && defined(CONFIG_AWE32) -# define CONFIG_AWE32_SYNTH -# endif -#else -# include "../sound_config.h" -#endif - - -#endif /* AWE_OBSOLETE_VOXWARE */ - - -#endif /* AWE_CONFIG_H_DEF */ diff --git a/sys/platform/pc32/gnu/isa/sound/awe_hw.h b/sys/platform/pc32/gnu/isa/sound/awe_hw.h deleted file mode 100644 index 7d0d88e77d..0000000000 --- a/sys/platform/pc32/gnu/isa/sound/awe_hw.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * sound/awe_hw.h - * - * Access routines and definitions for the low level driver for the - * AWE32/Sound Blaster 32 wave table synth. - * version 0.4.2; Sep. 15, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef AWE_HW_H_DEF -#define AWE_HW_H_DEF - -/* - * Emu-8000 control registers - * name(channel) reg, port - */ - -#define awe_cmd_idx(reg,ch) (((reg)<< 5) | (ch)) - -#define Data0 0x620 /* doubleword r/w */ -#define Data1 0xA20 /* doubleword r/w */ -#define Data2 0xA22 /* word r/w */ -#define Data3 0xE20 /* word r/w */ -#define Pointer 0xE22 /* register pointer r/w */ - -#define AWE_CPF(ch) awe_cmd_idx(0,ch), Data0 /* DW: current pitch and fractional address */ -#define AWE_PTRX(ch) awe_cmd_idx(1,ch), Data0 /* DW: pitch target and reverb send */ -#define AWE_CVCF(ch) awe_cmd_idx(2,ch), Data0 /* DW: current volume and filter cutoff */ -#define AWE_VTFT(ch) awe_cmd_idx(3,ch), Data0 /* DW: volume and filter cutoff targets */ -#define AWE_PSST(ch) awe_cmd_idx(6,ch), Data0 /* DW: pan send and loop start address */ -#define AWE_CSL(ch) awe_cmd_idx(7,ch), Data0 /* DW: chorus send and loop end address */ -#define AWE_CCCA(ch) awe_cmd_idx(0,ch), Data1 /* DW: Q, control bits, and current address */ -#define AWE_HWCF4 awe_cmd_idx(1,9), Data1 /* DW: config dw 4 */ -#define AWE_HWCF5 awe_cmd_idx(1,10), Data1 /* DW: config dw 5 */ -#define AWE_HWCF6 awe_cmd_idx(1,13), Data1 /* DW: config dw 6 */ -#define AWE_HWCF7 awe_cmd_idx(1,14), Data1 /* DW: config dw 7? (not documented) */ -#define AWE_SMALR awe_cmd_idx(1,20), Data1 /* DW: sound memory address for left read */ -#define AWE_SMARR awe_cmd_idx(1,21), Data1 /* DW: for right read */ -#define AWE_SMALW awe_cmd_idx(1,22), Data1 /* DW: sound memory address for left write */ -#define AWE_SMARW awe_cmd_idx(1,23), Data1 /* DW: for right write */ -#define AWE_SMLD awe_cmd_idx(1,26), Data1 /* W: sound memory left data */ -#define AWE_SMRD awe_cmd_idx(1,26), Data2 /* W: right data */ -#define AWE_WC awe_cmd_idx(1,27), Data2 /* W: sample counter */ -#define AWE_WC_Cmd awe_cmd_idx(1,27) -#define AWE_WC_Port Data2 -#define AWE_HWCF1 awe_cmd_idx(1,29), Data1 /* W: config w 1 */ -#define AWE_HWCF2 awe_cmd_idx(1,30), Data1 /* W: config w 2 */ -#define AWE_HWCF3 awe_cmd_idx(1,31), Data1 /* W: config w 3 */ -#define AWE_INIT1(ch) awe_cmd_idx(2,ch), Data1 /* W: init array 1 */ -#define AWE_INIT2(ch) awe_cmd_idx(2,ch), Data2 /* W: init array 2 */ -#define AWE_INIT3(ch) awe_cmd_idx(3,ch), Data1 /* W: init array 3 */ -#define AWE_INIT4(ch) awe_cmd_idx(3,ch), Data2 /* W: init array 4 */ -#define AWE_ENVVOL(ch) awe_cmd_idx(4,ch), Data1 /* W: volume envelope delay */ -#define AWE_DCYSUSV(ch) awe_cmd_idx(5,ch), Data1 /* W: volume envelope sustain and decay */ -#define AWE_ENVVAL(ch) awe_cmd_idx(6,ch), Data1 /* W: modulation envelope delay */ -#define AWE_DCYSUS(ch) awe_cmd_idx(7,ch), Data1 /* W: modulation envelope sustain and decay */ -#define AWE_ATKHLDV(ch) awe_cmd_idx(4,ch), Data2 /* W: volume envelope attack and hold */ -#define AWE_LFO1VAL(ch) awe_cmd_idx(5,ch), Data2 /* W: LFO#1 Delay */ -#define AWE_ATKHLD(ch) awe_cmd_idx(6,ch), Data2 /* W: modulation envelope attack and hold */ -#define AWE_LFO2VAL(ch) awe_cmd_idx(7,ch), Data2 /* W: LFO#2 Delay */ -#define AWE_IP(ch) awe_cmd_idx(0,ch), Data3 /* W: initial pitch */ -#define AWE_IFATN(ch) awe_cmd_idx(1,ch), Data3 /* W: initial filter cutoff and attenuation */ -#define AWE_PEFE(ch) awe_cmd_idx(2,ch), Data3 /* W: pitch and filter envelope heights */ -#define AWE_FMMOD(ch) awe_cmd_idx(3,ch), Data3 /* W: vibrato and filter modulation freq */ -#define AWE_TREMFRQ(ch) awe_cmd_idx(4,ch), Data3 /* W: LFO#1 tremolo amount and freq */ -#define AWE_FM2FRQ2(ch) awe_cmd_idx(5,ch), Data3 /* W: LFO#2 vibrato amount and freq */ - -/* used during detection (returns ROM version?; not documented in ADIP) */ -#define AWE_U1 0xE0, Data3 /* (R)(W) used in initialization */ -#define AWE_U2(ch) 0xC0+(ch), Data3 /* (W)(W) used in init envelope */ - - -#define AWE_MAX_VOICES 32 -#define AWE_NORMAL_VOICES 30 /*30&31 are reserved for DRAM refresh*/ - -#define AWE_MAX_CHANNELS 32 /* max midi channels (must >= voices) */ -#define AWE_MAX_LAYERS AWE_MAX_VOICES /* maximum number of multiple layers */ - -#define AWE_DRAM_OFFSET 0x200000 -#define AWE_MAX_DRAM_SIZE (28 * 1024) /* 28 MB is max onboard memory */ - -#define AWE_DEFAULT_ATTENUATION 32 /* 12dB below */ -#define AWE_DEFAULT_MOD_SENSE 18 - -#endif diff --git a/sys/platform/pc32/gnu/isa/sound/awe_version.h b/sys/platform/pc32/gnu/isa/sound/awe_version.h deleted file mode 100644 index 42013bbbf2..0000000000 --- a/sys/platform/pc32/gnu/isa/sound/awe_version.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * sound/awe_version.h - * - * Version defines for the AWE32/Sound Blaster 32 wave table synth driver. - * version 0.4.2c; Oct. 7, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* AWE32 driver version number */ - -#ifndef AWE_VERSION_H_DEF -#define AWE_VERSION_H_DEF - -#define AWE_VERSION_NUMBER 0x00040203 -#define AWEDRV_VERSION "0.4.2c" -#define AWE_MAJOR_VERSION(id) (((id) >> 16) & 0xff) -#define AWE_MINOR_VERSION(id) (((id) >> 8) & 0xff) -#define AWE_TINY_VERSION(id) ((id) & 0xff) - -#endif diff --git a/sys/platform/pc32/gnu/isa/sound/awe_voice.h b/sys/platform/pc32/gnu/isa/sound/awe_voice.h deleted file mode 100644 index aa13131314..0000000000 --- a/sys/platform/pc32/gnu/isa/sound/awe_voice.h +++ /dev/null @@ -1,490 +0,0 @@ -/* - * sound/awe_voice.h - * - * Voice information definitions for the low level driver for the - * AWE32/Sound Blaster 32 wave table synth. - * version 0.4.2c; Oct. 7, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef AWE_VOICE_H -#define AWE_VOICE_H - -#ifndef SAMPLE_TYPE_AWE32 -#define SAMPLE_TYPE_AWE32 0x20 -#endif - -#ifndef _PATCHKEY -#define _PATCHKEY(id) ((id<<8)|0xfd) -#endif - -/*---------------------------------------------------------------- - * patch information record - *----------------------------------------------------------------*/ - -/* patch interface header: 16 bytes */ -typedef struct awe_patch_info { - short key; /* use AWE_PATCH here */ -#define AWE_PATCH _PATCHKEY(0x07) - - short device_no; /* synthesizer number */ - unsigned short sf_id; /* file id (should be zero) */ - short optarg; /* optional argument */ - int len; /* data length (without this header) */ - - short type; /* patch operation type */ -#define AWE_LOAD_INFO 0 /* awe_voice_rec */ -#define AWE_LOAD_DATA 1 /* awe_sample_info */ -#define AWE_OPEN_PATCH 2 /* awe_open_parm */ -#define AWE_CLOSE_PATCH 3 /* none */ -#define AWE_UNLOAD_PATCH 4 /* none */ -#define AWE_REPLACE_DATA 5 /* awe_sample_info (optarg=#channels)*/ -#define AWE_MAP_PRESET 6 /* awe_voice_map */ -#define AWE_LOAD_CHORUS_FX 0x10 /* awe_chorus_fx_rec (optarg=mode) */ -#define AWE_LOAD_REVERB_FX 0x11 /* awe_reverb_fx_rec (optarg=mode) */ - - short reserved; /* word alignment data */ - - /* the actual patch data begins after this */ -#if defined(AWE_COMPAT_030) && AWE_COMPAT_030 - char data[0]; -#endif -} awe_patch_info; - -/*#define AWE_PATCH_INFO_SIZE 16*/ -#define AWE_PATCH_INFO_SIZE sizeof(awe_patch_info) - - -/*---------------------------------------------------------------- - * open patch - *----------------------------------------------------------------*/ - -#define AWE_PATCH_NAME_LEN 32 - -typedef struct _awe_open_parm { - unsigned short type; /* sample type */ -#define AWE_PAT_TYPE_MISC 0 -#define AWE_PAT_TYPE_GM 1 -#define AWE_PAT_TYPE_GS 2 -#define AWE_PAT_TYPE_MT32 3 -#define AWE_PAT_TYPE_XG 4 -#define AWE_PAT_TYPE_SFX 5 -#define AWE_PAT_TYPE_GUS 6 -#define AWE_PAT_TYPE_MAP 7 - -#define AWE_PAT_LOCKED 0x100 /* lock the samples */ - - short reserved; - char name[AWE_PATCH_NAME_LEN]; -} awe_open_parm; - -/*#define AWE_OPEN_PARM_SIZE 28*/ -#define AWE_OPEN_PARM_SIZE sizeof(awe_open_parm) - - -/*---------------------------------------------------------------- - * raw voice information record - *----------------------------------------------------------------*/ - -/* wave table envelope & effect parameters to control EMU8000 */ -typedef struct _awe_voice_parm { - unsigned short moddelay; /* modulation delay (0x8000) */ - unsigned short modatkhld; /* modulation attack & hold time (0x7f7f) */ - unsigned short moddcysus; /* modulation decay & sustain (0x7f7f) */ - unsigned short modrelease; /* modulation release time (0x807f) */ - short modkeyhold, modkeydecay; /* envelope change per key (not used) */ - unsigned short voldelay; /* volume delay (0x8000) */ - unsigned short volatkhld; /* volume attack & hold time (0x7f7f) */ - unsigned short voldcysus; /* volume decay & sustain (0x7f7f) */ - unsigned short volrelease; /* volume release time (0x807f) */ - short volkeyhold, volkeydecay; /* envelope change per key (not used) */ - unsigned short lfo1delay; /* LFO1 delay (0x8000) */ - unsigned short lfo2delay; /* LFO2 delay (0x8000) */ - unsigned short pefe; /* modulation pitch & cutoff (0x0000) */ - unsigned short fmmod; /* LFO1 pitch & cutoff (0x0000) */ - unsigned short tremfrq; /* LFO1 volume & freq (0x0000) */ - unsigned short fm2frq2; /* LFO2 pitch & freq (0x0000) */ - unsigned char cutoff; /* initial cutoff (0xff) */ - unsigned char filterQ; /* initial filter Q [0-15] (0x0) */ - unsigned char chorus; /* chorus send (0x00) */ - unsigned char reverb; /* reverb send (0x00) */ - unsigned short reserved[4]; /* not used */ -} awe_voice_parm; - -#define AWE_VOICE_PARM_SIZE 48 - - -/* wave table parameters: 92 bytes */ -typedef struct _awe_voice_info { - unsigned short sf_id; /* file id (should be zero) */ - unsigned short sample; /* sample id */ - int start, end; /* sample offset correction */ - int loopstart, loopend; /* loop offset correction */ - short rate_offset; /* sample rate pitch offset */ - unsigned short mode; /* sample mode */ -#define AWE_MODE_ROMSOUND 0x8000 -#define AWE_MODE_STEREO 1 -#define AWE_MODE_LOOPING 2 -#define AWE_MODE_NORELEASE 4 /* obsolete */ -#define AWE_MODE_INIT_PARM 8 - - short root; /* midi root key */ - short tune; /* pitch tuning (in cents) */ - char low, high; /* key note range */ - char vellow, velhigh; /* velocity range */ - char fixkey, fixvel; /* fixed key, velocity */ - char pan, fixpan; /* panning, fixed panning */ - short exclusiveClass; /* exclusive class (0 = none) */ - unsigned char amplitude; /* sample volume (127 max) */ - unsigned char attenuation; /* attenuation (0.375dB) */ - short scaleTuning; /* pitch scale tuning(%), normally 100 */ - awe_voice_parm parm; /* voice envelope parameters */ - short index; /* internal index (set by driver) */ -} awe_voice_info; - -/*#define AWE_VOICE_INFO_SIZE 92*/ -#define AWE_VOICE_INFO_SIZE sizeof(awe_voice_info) - -/*----------------------------------------------------------------*/ - -/* The info entry of awe_voice_rec is changed from 0 to 1 - * for some compilers refusing zero size array. - * Due to this change, sizeof(awe_voice_rec) becomes different - * from older versions. - * Use AWE_VOICE_REC_SIZE instead. - */ - -/* instrument info header: 4 bytes */ -typedef struct _awe_voice_rec_hdr { - unsigned char bank; /* midi bank number */ - unsigned char instr; /* midi preset number */ - char nvoices; /* number of voices */ - char write_mode; /* write mode; normally 0 */ -#define AWE_WR_APPEND 0 /* append anyway */ -#define AWE_WR_EXCLUSIVE 1 /* skip if already exists */ -#define AWE_WR_REPLACE 2 /* replace if already exists */ -} awe_voice_rec_hdr; - -/*#define AWE_VOICE_REC_SIZE 4*/ -#define AWE_VOICE_REC_SIZE sizeof(awe_voice_rec_hdr) - -/* the standard patch structure for one sample */ -typedef struct _awe_voice_rec_patch { - awe_patch_info patch; - awe_voice_rec_hdr hdr; - awe_voice_info info; -} awe_voice_rec_patch; - - -/* obsolete data type */ -#if defined(AWE_COMPAT_030) && AWE_COMPAT_030 -#define AWE_INFOARRAY_SIZE 0 -#else -#define AWE_INFOARRAY_SIZE 1 -#endif - -typedef struct _awe_voice_rec { - unsigned char bank; /* midi bank number */ - unsigned char instr; /* midi preset number */ - short nvoices; /* number of voices */ - /* voice information follows here */ - awe_voice_info info[AWE_INFOARRAY_SIZE]; -} awe_voice_rec; - - -/*---------------------------------------------------------------- - * sample wave information - *----------------------------------------------------------------*/ - -/* wave table sample header: 32 bytes */ -typedef struct awe_sample_info { - unsigned short sf_id; /* file id (should be zero) */ - unsigned short sample; /* sample id */ - int start, end; /* start & end offset */ - int loopstart, loopend; /* loop start & end offset */ - int size; /* size (0 = ROM) */ - short checksum_flag; /* use check sum = 1 */ - unsigned short mode_flags; /* mode flags */ -#define AWE_SAMPLE_8BITS 1 /* wave data is 8bits */ -#define AWE_SAMPLE_UNSIGNED 2 /* wave data is unsigned */ -#define AWE_SAMPLE_NO_BLANK 4 /* no blank loop is attached */ -#define AWE_SAMPLE_SINGLESHOT 8 /* single-shot w/o loop */ -#define AWE_SAMPLE_BIDIR_LOOP 16 /* bidirectional looping */ -#define AWE_SAMPLE_STEREO_LEFT 32 /* stereo left sound */ -#define AWE_SAMPLE_STEREO_RIGHT 64 /* stereo right sound */ -#define AWE_SAMPLE_REVERSE_LOOP 128 /* reverse looping */ - unsigned int checksum; /* check sum */ -#if defined(AWE_COMPAT_030) && AWE_COMPAT_030 - unsigned short data[0]; /* sample data follows here */ -#endif -} awe_sample_info; - -/*#define AWE_SAMPLE_INFO_SIZE 32*/ -#define AWE_SAMPLE_INFO_SIZE sizeof(awe_sample_info) - - -/*---------------------------------------------------------------- - * voice preset mapping - *----------------------------------------------------------------*/ - -typedef struct awe_voice_map { - int map_bank, map_instr, map_key; /* key = -1 means all keys */ - int src_bank, src_instr, src_key; -} awe_voice_map; - -#define AWE_VOICE_MAP_SIZE sizeof(awe_voice_map) - - -/*---------------------------------------------------------------- - * awe hardware controls - *----------------------------------------------------------------*/ - -#define _AWE_DEBUG_MODE 0x00 -#define _AWE_REVERB_MODE 0x01 -#define _AWE_CHORUS_MODE 0x02 -#define _AWE_REMOVE_LAST_SAMPLES 0x03 -#define _AWE_INITIALIZE_CHIP 0x04 -#define _AWE_SEND_EFFECT 0x05 -#define _AWE_TERMINATE_CHANNEL 0x06 -#define _AWE_TERMINATE_ALL 0x07 -#define _AWE_INITIAL_VOLUME 0x08 -#define _AWE_INITIAL_ATTEN _AWE_INITIAL_VOLUME -#define _AWE_RESET_CHANNEL 0x09 -#define _AWE_CHANNEL_MODE 0x0a -#define _AWE_DRUM_CHANNELS 0x0b -#define _AWE_MISC_MODE 0x0c -#define _AWE_RELEASE_ALL 0x0d -#define _AWE_NOTEOFF_ALL 0x0e -#define _AWE_CHN_PRESSURE 0x0f -/*#define _AWE_GET_CURRENT_MODE 0x10*/ -#define _AWE_EQUALIZER 0x11 -/*#define _AWE_GET_MISC_MODE 0x12*/ -/*#define _AWE_GET_FONTINFO 0x13*/ - -#define _AWE_MODE_FLAG 0x80 -#define _AWE_COOKED_FLAG 0x40 /* not supported */ -#define _AWE_MODE_VALUE_MASK 0x3F - -/*----------------------------------------------------------------*/ - -#define _AWE_SET_CMD(p,dev,voice,cmd,p1,p2) \ -{((char*)(p))[0] = SEQ_PRIVATE;\ - ((char*)(p))[1] = dev;\ - ((char*)(p))[2] = _AWE_MODE_FLAG|(cmd);\ - ((char*)(p))[3] = voice;\ - ((unsigned short*)(p))[2] = p1;\ - ((unsigned short*)(p))[3] = p2;} - -/* buffered access */ -#define _AWE_CMD(dev, voice, cmd, p1, p2) \ -{_SEQ_NEEDBUF(8);\ - _AWE_SET_CMD(_seqbuf + _seqbufptr, dev, voice, cmd, p1, p2);\ - _SEQ_ADVBUF(8);} - -/* direct access */ -#define _AWE_CMD_NOW(seqfd,dev,voice,cmd,p1,p2) \ -{struct seq_event_rec tmp;\ - _AWE_SET_CMD(&tmp, dev, voice, cmd, p1, p2);\ - ioctl(seqfd, SNDCTL_SEQ_OUTOFBAND, &tmp);} - -/*----------------------------------------------------------------*/ - -/* set debugging mode */ -#define AWE_DEBUG_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0) -/* set reverb mode; from 0 to 7 */ -#define AWE_REVERB_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0) -/* set chorus mode; from 0 to 7 */ -#define AWE_CHORUS_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0) - -/* reset channel */ -#define AWE_RESET_CHANNEL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 0, 0) -#define AWE_RESET_CONTROL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 1, 0) - -/* send an effect to all layers */ -#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value) -#define AWE_ADD_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x80),value) -#define AWE_UNSET_EFFECT(dev,voice,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x40),0) -/* send an effect to a layer */ -#define AWE_SEND_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)),value) -#define AWE_ADD_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x80),value) -#define AWE_UNSET_LAYER_EFFECT(dev,voice,layer,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x40),0) - -/* terminate sound on the channel/voice */ -#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0) -/* terminate all sounds */ -#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0) -/* release all sounds (w/o sustain effect) */ -#define AWE_RELEASE_ALL(dev) _AWE_CMD(dev, 0, _AWE_RELEASE_ALL, 0, 0) -/* note off all sounds (w sustain effect) */ -#define AWE_NOTEOFF_ALL(dev) _AWE_CMD(dev, 0, _AWE_NOTEOFF_ALL, 0, 0) - -/* set initial attenuation */ -#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0) -#define AWE_INITIAL_ATTEN AWE_INITIAL_VOLUME -/* relative attenuation */ -#define AWE_SET_ATTEN(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 1) - -/* set channel playing mode; mode=0/1/2 */ -#define AWE_SET_CHANNEL_MODE(dev,mode) _AWE_CMD(dev, 0, _AWE_CHANNEL_MODE, mode, 0) -#define AWE_PLAY_INDIRECT 0 /* indirect voice mode (default) */ -#define AWE_PLAY_MULTI 1 /* multi note voice mode */ -#define AWE_PLAY_DIRECT 2 /* direct single voice mode */ -#define AWE_PLAY_MULTI2 3 /* sequencer2 mode; used internally */ - -/* set drum channel mask; channels is 32bit long value */ -#define AWE_DRUM_CHANNELS(dev,channels) _AWE_CMD(dev, 0, _AWE_DRUM_CHANNELS, ((channels) & 0xffff), ((channels) >> 16)) - -/* set bass and treble control; values are from 0 to 11 */ -#define AWE_EQUALIZER(dev,bass,treble) _AWE_CMD(dev, 0, _AWE_EQUALIZER, bass, treble) - -/* remove last loaded samples */ -#define AWE_REMOVE_LAST_SAMPLES(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0) -/* initialize emu8000 chip */ -#define AWE_INITIALIZE_CHIP(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_INITIALIZE_CHIP, 0, 0) - -/* set miscellaneous modes; meta command */ -#define AWE_MISC_MODE(dev,mode,value) _AWE_CMD(dev, 0, _AWE_MISC_MODE, mode, value) -/* exclusive sound off; 1=off */ -#define AWE_EXCLUSIVE_SOUND(dev,mode) AWE_MISC_MODE(dev,AWE_MD_EXCLUSIVE_SOUND,mode) -/* default GUS bank number */ -#define AWE_SET_GUS_BANK(dev,bank) AWE_MISC_MODE(dev,AWE_MD_GUS_BANK,bank) -/* change panning position in realtime; 0=don't 1=do */ -#define AWE_REALTIME_PAN(dev,mode) AWE_MISC_MODE(dev,AWE_MD_REALTIME_PAN,mode) - -/* extended pressure controls; not portable with other sound drivers */ -#define AWE_KEY_PRESSURE(dev,ch,note,vel) SEQ_START_NOTE(dev,ch,(note)+128,vel) -#define AWE_CHN_PRESSURE(dev,ch,vel) _AWE_CMD(dev,ch,_AWE_CHN_PRESSURE,vel,0) - -/*----------------------------------------------------------------*/ - -/* reverb mode parameters */ -#define AWE_REVERB_ROOM1 0 -#define AWE_REVERB_ROOM2 1 -#define AWE_REVERB_ROOM3 2 -#define AWE_REVERB_HALL1 3 -#define AWE_REVERB_HALL2 4 -#define AWE_REVERB_PLATE 5 -#define AWE_REVERB_DELAY 6 -#define AWE_REVERB_PANNINGDELAY 7 -#define AWE_REVERB_PREDEFINED 8 -/* user can define reverb modes up to 32 */ -#define AWE_REVERB_NUMBERS 32 - -typedef struct awe_reverb_fx_rec { - unsigned short parms[28]; -} awe_reverb_fx_rec; - -/*----------------------------------------------------------------*/ - -/* chorus mode parameters */ -#define AWE_CHORUS_1 0 -#define AWE_CHORUS_2 1 -#define AWE_CHORUS_3 2 -#define AWE_CHORUS_4 3 -#define AWE_CHORUS_FEEDBACK 4 -#define AWE_CHORUS_FLANGER 5 -#define AWE_CHORUS_SHORTDELAY 6 -#define AWE_CHORUS_SHORTDELAY2 7 -#define AWE_CHORUS_PREDEFINED 8 -/* user can define chorus modes up to 32 */ -#define AWE_CHORUS_NUMBERS 32 - -typedef struct awe_chorus_fx_rec { - unsigned short feedback; /* feedback level (0xE600-0xE6FF) */ - unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */ - unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */ - unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */ - unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */ -} awe_chorus_fx_rec; - -/*----------------------------------------------------------------*/ - -/* misc mode types */ -enum { -/* 0*/ AWE_MD_EXCLUSIVE_OFF, /* obsolete */ -/* 1*/ AWE_MD_EXCLUSIVE_ON, /* obsolete */ -/* 2*/ AWE_MD_VERSION, /* read only */ -/* 3*/ AWE_MD_EXCLUSIVE_SOUND, /* ignored */ -/* 4*/ AWE_MD_REALTIME_PAN, /* 0/1: do realtime pan change (default=1) */ -/* 5*/ AWE_MD_GUS_BANK, /* bank number for GUS patches (default=0) */ -/* 6*/ AWE_MD_KEEP_EFFECT, /* 0/1: keep effect values, (default=0) */ -/* 7*/ AWE_MD_ZERO_ATTEN, /* attenuation of max volume (default=32) */ -/* 8*/ AWE_MD_CHN_PRIOR, /* 0/1: set MIDI channel priority mode (default=1) */ -/* 9*/ AWE_MD_MOD_SENSE, /* integer: modwheel sensitivity (def=18) */ -/*10*/ AWE_MD_DEF_PRESET, /* integer: default preset number (def=0) */ -/*11*/ AWE_MD_DEF_BANK, /* integer: default bank number (def=0) */ -/*12*/ AWE_MD_DEF_DRUM, /* integer: default drumset number (def=0) */ -/*13*/ AWE_MD_TOGGLE_DRUM_BANK, /* 0/1: toggle drum flag with bank# (def=0) */ - AWE_MD_END, -}; - -/*----------------------------------------------------------------*/ - -/* effect parameters */ -enum { - -/* modulation envelope parameters */ -/* 0*/ AWE_FX_ENV1_DELAY, /* WORD: ENVVAL */ -/* 1*/ AWE_FX_ENV1_ATTACK, /* BYTE: up ATKHLD */ -/* 2*/ AWE_FX_ENV1_HOLD, /* BYTE: lw ATKHLD */ -/* 3*/ AWE_FX_ENV1_DECAY, /* BYTE: lw DCYSUS */ -/* 4*/ AWE_FX_ENV1_RELEASE, /* BYTE: lw DCYSUS */ -/* 5*/ AWE_FX_ENV1_SUSTAIN, /* BYTE: up DCYSUS */ -/* 6*/ AWE_FX_ENV1_PITCH, /* BYTE: up PEFE */ -/* 7*/ AWE_FX_ENV1_CUTOFF, /* BYTE: lw PEFE */ - -/* volume envelope parameters */ -/* 8*/ AWE_FX_ENV2_DELAY, /* WORD: ENVVOL */ -/* 9*/ AWE_FX_ENV2_ATTACK, /* BYTE: up ATKHLDV */ -/*10*/ AWE_FX_ENV2_HOLD, /* BYTE: lw ATKHLDV */ -/*11*/ AWE_FX_ENV2_DECAY, /* BYTE: lw DCYSUSV */ -/*12*/ AWE_FX_ENV2_RELEASE, /* BYTE: lw DCYSUSV */ -/*13*/ AWE_FX_ENV2_SUSTAIN, /* BYTE: up DCYSUSV */ - -/* LFO1 (tremolo & vibrato) parameters */ -/*14*/ AWE_FX_LFO1_DELAY, /* WORD: LFO1VAL */ -/*15*/ AWE_FX_LFO1_FREQ, /* BYTE: lo TREMFRQ */ -/*16*/ AWE_FX_LFO1_VOLUME, /* BYTE: up TREMFRQ */ -/*17*/ AWE_FX_LFO1_PITCH, /* BYTE: up FMMOD */ -/*18*/ AWE_FX_LFO1_CUTOFF, /* BYTE: lo FMMOD */ - -/* LFO2 (vibrato) parameters */ -/*19*/ AWE_FX_LFO2_DELAY, /* WORD: LFO2VAL */ -/*20*/ AWE_FX_LFO2_FREQ, /* BYTE: lo FM2FRQ2 */ -/*21*/ AWE_FX_LFO2_PITCH, /* BYTE: up FM2FRQ2 */ - -/* Other overall effect parameters */ -/*22*/ AWE_FX_INIT_PITCH, /* SHORT: pitch offset */ -/*23*/ AWE_FX_CHORUS, /* BYTE: chorus effects send (0-255) */ -/*24*/ AWE_FX_REVERB, /* BYTE: reverb effects send (0-255) */ -/*25*/ AWE_FX_CUTOFF, /* BYTE: up IFATN */ -/*26*/ AWE_FX_FILTERQ, /* BYTE: up CCCA */ - -/* Sample / loop offset changes */ -/*27*/ AWE_FX_SAMPLE_START, /* SHORT: offset */ -/*28*/ AWE_FX_LOOP_START, /* SHORT: offset */ -/*29*/ AWE_FX_LOOP_END, /* SHORT: offset */ -/*30*/ AWE_FX_COARSE_SAMPLE_START, /* SHORT: upper word offset */ -/*31*/ AWE_FX_COARSE_LOOP_START, /* SHORT: upper word offset */ -/*32*/ AWE_FX_COARSE_LOOP_END, /* SHORT: upper word offset */ -/*33*/ AWE_FX_ATTEN, /* BYTE: lo IFATN */ - - AWE_FX_END, -}; - -#endif /* AWE_VOICE_H */ diff --git a/sys/platform/pc32/gnu/isa/sound/awe_wave.c b/sys/platform/pc32/gnu/isa/sound/awe_wave.c deleted file mode 100644 index 4bbaae14fa..0000000000 --- a/sys/platform/pc32/gnu/isa/sound/awe_wave.c +++ /dev/null @@ -1,4581 +0,0 @@ -/* - * sound/awe_wave.c - * - * The low level driver for the AWE32/Sound Blaster 32 wave table synth. - * version 0.4.2c; Oct. 7, 1997 - * - * Copyright (C) 1996,1997 Takashi Iwai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $DragonFly: src/sys/platform/pc32/gnu/isa/sound/Attic/awe_wave.c,v 1.4 2004/12/08 20:36:39 joerg Exp $ - */ - -#include "opt_depricated.h" -#ifndef I_WANT_DEPRICATED_STUFF -#error "Add options I_WANT_DEPRICATED_STUFF to your kernel config and send a mail to kernel@" -#endif - -#include - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include "awe_config.h" -#else -# include "awe_config.h" -#endif - -/*----------------------------------------------------------------*/ - -#ifdef CONFIG_AWE32_SYNTH - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include "awe_hw.h" -# include "awe_version.h" -# include "awe_voice.h" -#else -# include "awe_hw.h" -# include "awe_version.h" -# include "awe_voice.h" -#endif - -#ifdef AWE_HAS_GUS_COMPATIBILITY -/* include finetune table */ - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# ifdef AWE_OBSOLETE_VOXWARE -# define SEQUENCER_C -# endif -# include -#else -# ifdef AWE_OBSOLETE_VOXWARE -# include "tuning.h" -# else -# include "../tuning.h" -# endif -#endif - -#ifdef linux -# include -#elif defined(__DragonFly__) || defined(__FreeBSD__) -# include -#endif - -#endif /* AWE_HAS_GUS_COMPATIBILITY */ - - -/*---------------------------------------------------------------- - * debug message - *----------------------------------------------------------------*/ - -static int debug_mode = 0; -#ifdef AWE_DEBUG_ON -#define AWE_DEBUG(LVL,XXX) {if (debug_mode > LVL) { XXX; }} -#define ERRMSG(XXX) {if (debug_mode) { XXX; }} -#define FATALERR(XXX) XXX -#else -#define AWE_DEBUG(LVL,XXX) /**/ -#define ERRMSG(XXX) XXX -#define FATALERR(XXX) XXX -#endif - -/*---------------------------------------------------------------- - * bank and voice record - *----------------------------------------------------------------*/ - -/* soundfont record */ -typedef struct _sf_list { - unsigned short sf_id; - unsigned short type; - int num_info; /* current info table index */ - int num_sample; /* current sample table index */ - int mem_ptr; /* current word byte pointer */ - int infos; - int samples; - /*char name[AWE_PATCH_NAME_LEN];*/ -} sf_list; - -/* bank record */ -typedef struct _awe_voice_list { - int next; /* linked list with same sf_id */ - unsigned char bank, instr; /* preset number information */ - char type, disabled; /* type=normal/mapped, disabled=boolean */ - awe_voice_info v; /* voice information */ - int next_instr; /* preset table list */ - int next_bank; /* preset table list */ -} awe_voice_list; - -/* voice list type */ -#define V_ST_NORMAL 0 -#define V_ST_MAPPED 1 - -typedef struct _awe_sample_list { - int next; /* linked list with same sf_id */ - awe_sample_info v; /* sample information */ -} awe_sample_list; - -/* sample and information table */ -static int current_sf_id = 0; -static int locked_sf_id = 0; -static int max_sfs; -static sf_list *sflists = NULL; - -#define awe_free_mem_ptr() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].mem_ptr) -#define awe_free_info() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].num_info) -#define awe_free_sample() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].num_sample) - -static int max_samples; -static awe_sample_list *samples = NULL; - -static int max_infos; -static awe_voice_list *infos = NULL; - - -#define AWE_MAX_PRESETS 256 -#define AWE_DEFAULT_PRESET 0 -#define AWE_DEFAULT_BANK 0 -#define AWE_DEFAULT_DRUM 0 -#define AWE_DRUM_BANK 128 - -#define MAX_LAYERS AWE_MAX_VOICES - -/* preset table index */ -static int preset_table[AWE_MAX_PRESETS]; - -/*---------------------------------------------------------------- - * voice table - *----------------------------------------------------------------*/ - -/* effects table */ -typedef struct FX_Rec { /* channel effects */ - unsigned char flags[AWE_FX_END]; - short val[AWE_FX_END]; -} FX_Rec; - - -/* channel parameters */ -typedef struct _awe_chan_info { - int channel; /* channel number */ - int bank; /* current tone bank */ - int instr; /* current program */ - int bender; /* midi pitchbend (-8192 - 8192) */ - int bender_range; /* midi bender range (x100) */ - int panning; /* panning (0-127) */ - int main_vol; /* channel volume (0-127) */ - int expression_vol; /* midi expression (0-127) */ - int chan_press; /* channel pressure */ - int vrec; /* instrument list */ - int def_vrec; /* default instrument list */ - int sustained; /* sustain status in MIDI */ - FX_Rec fx; /* effects */ - FX_Rec fx_layer[MAX_LAYERS]; /* layer effects */ -} awe_chan_info; - -/* voice parameters */ -typedef struct _voice_info { - int state; -#define AWE_ST_OFF (1<<0) /* no sound */ -#define AWE_ST_ON (1<<1) /* playing */ -#define AWE_ST_STANDBY (1<<2) /* stand by for playing */ -#define AWE_ST_SUSTAINED (1<<3) /* sustained */ -#define AWE_ST_MARK (1<<4) /* marked for allocation */ -#define AWE_ST_DRAM (1<<5) /* DRAM read/write */ -#define AWE_ST_FM (1<<6) /* reserved for FM */ -#define AWE_ST_RELEASED (1<<7) /* released */ - - int ch; /* midi channel */ - int key; /* internal key for search */ - int layer; /* layer number (for channel mode only) */ - int time; /* allocated time */ - awe_chan_info *cinfo; /* channel info */ - - int note; /* midi key (0-127) */ - int velocity; /* midi velocity (0-127) */ - int sostenuto; /* sostenuto on/off */ - awe_voice_info *sample; /* assigned voice */ - - /* EMU8000 parameters */ - int apitch; /* pitch parameter */ - int avol; /* volume parameter */ - int apan; /* panning parameter */ -} voice_info; - -/* voice information */ -static voice_info *voices; - -#define IS_NO_SOUND(v) (voices[v].state & (AWE_ST_OFF|AWE_ST_RELEASED|AWE_ST_STANDBY|AWE_ST_SUSTAINED)) -#define IS_NO_EFFECT(v) (voices[v].state != AWE_ST_ON) -#define IS_PLAYING(v) (voices[v].state & (AWE_ST_ON|AWE_ST_SUSTAINED|AWE_ST_RELEASED)) -#define IS_EMPTY(v) (voices[v].state & (AWE_ST_OFF|AWE_ST_MARK|AWE_ST_DRAM|AWE_ST_FM)) - - -/* MIDI channel effects information (for hw control) */ -static awe_chan_info *channels; - - -/*---------------------------------------------------------------- - * global variables - *----------------------------------------------------------------*/ - -#ifndef AWE_DEFAULT_BASE_ADDR -#define AWE_DEFAULT_BASE_ADDR 0 /* autodetect */ -#endif - -#ifndef AWE_DEFAULT_MEM_SIZE -#define AWE_DEFAULT_MEM_SIZE 0 /* autodetect */ -#endif - -/* awe32 base address (overwritten at initialization) */ -static int awe_base = AWE_DEFAULT_BASE_ADDR; -/* memory byte size */ -static int awe_mem_size = AWE_DEFAULT_MEM_SIZE; -/* DRAM start offset */ -static int awe_mem_start = AWE_DRAM_OFFSET; - -/* maximum channels for playing */ -static int awe_max_voices = AWE_MAX_VOICES; - -static int patch_opened = 0; /* sample already loaded? */ - -static int reverb_mode = 4; /* reverb mode */ -static int chorus_mode = 2; /* chorus mode */ -static short init_atten = AWE_DEFAULT_ATTENUATION; /* 12dB below */ - -static int awe_present = FALSE; /* awe device present? */ -static int awe_busy = FALSE; /* awe device opened? */ - -#define DEFAULT_DRUM_FLAGS ((1 << 9) | (1 << 25)) -#define IS_DRUM_CHANNEL(c) (drum_flags & (1 << (c))) -#define DRUM_CHANNEL_ON(c) (drum_flags |= (1 << (c))) -#define DRUM_CHANNEL_OFF(c) (drum_flags &= ~(1 << (c))) -static unsigned int drum_flags = DEFAULT_DRUM_FLAGS; /* channel flags */ - -static int playing_mode = AWE_PLAY_INDIRECT; -#define SINGLE_LAYER_MODE() (playing_mode == AWE_PLAY_INDIRECT || playing_mode == AWE_PLAY_DIRECT) -#define MULTI_LAYER_MODE() (playing_mode == AWE_PLAY_MULTI || playing_mode == AWE_PLAY_MULTI2) - -static int current_alloc_time = 0; /* voice allocation index for channel mode */ - -static struct MiscModeDef { - int value; - int init_each_time; -} misc_modes_default[AWE_MD_END] = { - {0,0}, {0,0}, /* <-- not used */ - {AWE_VERSION_NUMBER, FALSE}, - {TRUE, TRUE}, /* exclusive */ - {TRUE, TRUE}, /* realpan */ - {AWE_DEFAULT_BANK, TRUE}, /* gusbank */ - {FALSE, TRUE}, /* keep effect */ - {AWE_DEFAULT_ATTENUATION, FALSE}, /* zero_atten */ - {FALSE, TRUE}, /* chn_prior */ - {AWE_DEFAULT_MOD_SENSE, TRUE}, /* modwheel sense */ - {AWE_DEFAULT_PRESET, TRUE}, /* def_preset */ - {AWE_DEFAULT_BANK, TRUE}, /* def_bank */ - {AWE_DEFAULT_DRUM, TRUE}, /* def_drum */ - {FALSE, TRUE}, /* toggle_drum_bank */ -}; - -static int misc_modes[AWE_MD_END]; - -static int awe_bass_level = 5; -static int awe_treble_level = 9; - - -static struct synth_info awe_info = { - "AWE32 Synth", /* name */ - 0, /* device */ - SYNTH_TYPE_SAMPLE, /* synth_type */ - SAMPLE_TYPE_AWE32, /* synth_subtype */ - 0, /* perc_mode (obsolete) */ - AWE_MAX_VOICES, /* nr_voices */ - 0, /* nr_drums (obsolete) */ - AWE_MAX_INFOS /* instr_bank_size */ -}; - - -static struct voice_alloc_info *voice_alloc; /* set at initialization */ - - -/*---------------------------------------------------------------- - * function prototypes - *----------------------------------------------------------------*/ - -#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE) -static int awe_check_port(void); -static void awe_request_region(void); -static void awe_release_region(void); -#endif - -static void awe_reset_samples(void); -/* emu8000 chip i/o access */ -static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data); -static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data); -static unsigned short awe_peek(unsigned short cmd, unsigned short port); -static unsigned int awe_peek_dw(unsigned short cmd, unsigned short port); -static void awe_wait(unsigned short delay); - -/* initialize emu8000 chip */ -static void awe_initialize(void); - -/* set voice parameters */ -static void awe_init_misc_modes(int init_all); -static void awe_init_voice_info(awe_voice_info *vp); -static void awe_init_voice_parm(awe_voice_parm *pp); -#ifdef AWE_HAS_GUS_COMPATIBILITY -static int freq_to_note(int freq); -static int calc_rate_offset(int Hz); -/*static int calc_parm_delay(int msec);*/ -static int calc_parm_hold(int msec); -static int calc_parm_attack(int msec); -static int calc_parm_decay(int msec); -static int calc_parm_search(int msec, short *table); -#endif - -/* turn on/off note */ -static void awe_note_on(int voice); -static void awe_note_off(int voice); -static void awe_terminate(int voice); -static void awe_exclusive_off(int voice); -static void awe_note_off_all(int do_sustain); - -/* calculate voice parameters */ -typedef void (*fx_affect_func)(int voice, int forced); -static void awe_set_pitch(int voice, int forced); -static void awe_set_voice_pitch(int voice, int forced); -static void awe_set_volume(int voice, int forced); -static void awe_set_voice_vol(int voice, int forced); -static void awe_set_pan(int voice, int forced); -static void awe_fx_fmmod(int voice, int forced); -static void awe_fx_tremfrq(int voice, int forced); -static void awe_fx_fm2frq2(int voice, int forced); -static void awe_fx_filterQ(int voice, int forced); -static void awe_calc_pitch(int voice); -#ifdef AWE_HAS_GUS_COMPATIBILITY -static void awe_calc_pitch_from_freq(int voice, int freq); -#endif -static void awe_calc_volume(int voice); -static void awe_voice_init(int voice, int init_all); -static void awe_channel_init(int ch, int init_all); -static void awe_fx_init(int ch); - -/* sequencer interface */ -static int awe_open(int dev, int mode); -static void awe_close(int dev); -static int awe_ioctl(int dev, unsigned int cmd, caddr_t arg); -static int awe_kill_note(int dev, int voice, int note, int velocity); -static int awe_start_note(int dev, int v, int note_num, int volume); -static int awe_set_instr(int dev, int voice, int instr_no); -static int awe_set_instr_2(int dev, int voice, int instr_no); -static void awe_reset(int dev); -static void awe_hw_control(int dev, unsigned char *event); -static int awe_load_patch(int dev, int format, const char *addr, - int offs, int count, int pmgr_flag); -static void awe_aftertouch(int dev, int voice, int pressure); -static void awe_controller(int dev, int voice, int ctrl_num, int value); -static void awe_panning(int dev, int voice, int value); -static void awe_volume_method(int dev, int mode); -#ifndef AWE_NO_PATCHMGR -static int awe_patchmgr(int dev, struct patmgr_info *rec); -#endif -static void awe_bender(int dev, int voice, int value); -static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc); -static void awe_setup_voice(int dev, int voice, int chn); - -/* hardware controls */ -#ifdef AWE_HAS_GUS_COMPATIBILITY -static void awe_hw_gus_control(int dev, int cmd, unsigned char *event); -#endif -static void awe_hw_awe_control(int dev, int cmd, unsigned char *event); -static void awe_voice_change(int voice, fx_affect_func func); -static void awe_sostenuto_on(int voice, int forced); -static void awe_sustain_off(int voice, int forced); -static void awe_terminate_and_init(int voice, int forced); - -/* voice search */ -static int awe_search_instr(int bank, int preset); -static int awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist); -static void awe_alloc_multi_voices(int ch, int note, int velocity, int key); -static void awe_alloc_one_voice(int voice, int note, int velocity); -static int awe_clear_voice(void); - -/* load / remove patches */ -static int awe_open_patch(awe_patch_info *patch, const char *addr, int count); -static int awe_close_patch(awe_patch_info *patch, const char *addr, int count); -static int awe_unload_patch(awe_patch_info *patch, const char *addr, int count); -static int awe_load_info(awe_patch_info *patch, const char *addr, int count); -static int awe_load_data(awe_patch_info *patch, const char *addr, int count); -static int awe_replace_data(awe_patch_info *patch, const char *addr, int count); -static int awe_load_map(awe_patch_info *patch, const char *addr, int count); -#ifdef AWE_HAS_GUS_COMPATIBILITY -static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag); -#endif -static int check_patch_opened(int type, char *name); -static int awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels); -static void add_sf_info(int rec); -static void add_sf_sample(int rec); -static void purge_old_list(int rec, int next); -static void add_info_list(int rec); -static void awe_remove_samples(int sf_id); -static void rebuild_preset_list(void); -static short awe_set_sample(awe_voice_info *vp); - -/* lowlevel functions */ -static void awe_init_audio(void); -static void awe_init_dma(void); -static void awe_init_array(void); -static void awe_send_array(unsigned short *data); -static void awe_tweak_voice(int voice); -static void awe_tweak(void); -static void awe_init_fm(void); -static int awe_open_dram_for_write(int offset, int channels); -static void awe_open_dram_for_check(void); -static void awe_close_dram(void); -static void awe_write_dram(unsigned short c); -static int awe_detect_base(int addr); -static int awe_detect(void); -static int awe_check_dram(void); -static int awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count); -static void awe_set_chorus_mode(int mode); -static int awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count); -static void awe_set_reverb_mode(int mode); -static void awe_equalizer(int bass, int treble); -#ifdef CONFIG_AWE32_MIXER -static int awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg); -#endif - -/* define macros for compatibility */ -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include "awe_compat.h" -#else -# include "awe_compat.h" -#endif - -/*---------------------------------------------------------------- - * synth operation table - *----------------------------------------------------------------*/ - -static struct synth_operations awe_operations = -{ -#ifdef AWE_OSS38 - "EMU8K", -#endif - &awe_info, - 0, - SYNTH_TYPE_SAMPLE, - SAMPLE_TYPE_AWE32, - awe_open, - awe_close, - awe_ioctl, - awe_kill_note, - awe_start_note, - awe_set_instr_2, - awe_reset, - awe_hw_control, - awe_load_patch, - awe_aftertouch, - awe_controller, - awe_panning, - awe_volume_method, -#ifndef AWE_NO_PATCHMGR - awe_patchmgr, -#endif - awe_bender, - awe_alloc, - awe_setup_voice -}; - -#ifdef CONFIG_AWE32_MIXER -static struct mixer_operations awe_mixer_operations = { -#if !defined(__DragonFly__) && !defined(__FreeBSD__) - "AWE32", -#endif - "AWE32 Equalizer", - awe_mixer_ioctl, -}; -#endif - - -/*================================================================ - * attach / unload interface - *================================================================*/ - -#ifdef AWE_OBSOLETE_VOXWARE -#define ATTACH_DECL static -#else -#define ATTACH_DECL /**/ -#endif - -#if (defined(__DragonFly__) || defined(__FreeBSD__)) && !defined(AWE_OBSOLETE_VOXWARE) -# define ATTACH_RET -void attach_awe(struct address_info *hw_config) -#else -# define ATTACH_RET ret -ATTACH_DECL -int attach_awe(void) -#endif -{ - int ret = 0; - - /* check presence of AWE32 card */ - if (! awe_detect()) { - printk("AWE32: not detected\n"); - return ATTACH_RET; - } - - /* check AWE32 ports are available */ - if (awe_check_port()) { - printk("AWE32: I/O area already used.\n"); - return ATTACH_RET; - } - - /* set buffers to NULL */ - voices = NULL; - channels = NULL; - sflists = NULL; - samples = NULL; - infos = NULL; - - /* voice & channel info */ - voices = (voice_info*)my_malloc(AWE_MAX_VOICES * sizeof(voice_info)); - channels = (awe_chan_info*)my_malloc(AWE_MAX_CHANNELS * sizeof(awe_chan_info)); - - if (voices == NULL || channels == NULL) { - my_free(voices); - my_free(channels); - printk("AWE32: can't allocate sample tables\n"); - return ATTACH_RET; - } - - /* allocate sample tables */ - INIT_TABLE(sflists, max_sfs, AWE_MAX_SF_LISTS, sf_list); - INIT_TABLE(samples, max_samples, AWE_MAX_SAMPLES, awe_sample_list); - INIT_TABLE(infos, max_infos, AWE_MAX_INFOS, awe_voice_list); - - if (num_synths >= MAX_SYNTH_DEV) - printk("AWE32 Error: too many synthesizers\n"); - else { - voice_alloc = &awe_operations.alloc; - voice_alloc->max_voice = awe_max_voices; - synth_devs[num_synths++] = &awe_operations; - } - -#ifdef CONFIG_AWE32_MIXER - if (num_mixers < MAX_MIXER_DEV) { - mixer_devs[num_mixers++] = &awe_mixer_operations; - } -#endif - - /* reserve I/O ports for awedrv */ - awe_request_region(); - - /* clear all samples */ - awe_reset_samples(); - - /* intialize AWE32 hardware */ - awe_initialize(); - - snprintf(awe_info.name, sizeof(awe_info.name), "AWE32-%s (RAM%dk)", - AWEDRV_VERSION, awe_mem_size/1024); -#if defined(__DragonFly__) || defined(__FreeBSD__) - printk("awe0: ", awe_mem_size/1024); -#elif defined(AWE_DEBUG_ON) - printk("%s\n", awe_info.name); -#endif - - /* set default values */ - awe_init_misc_modes(TRUE); - - /* set reverb & chorus modes */ - awe_set_reverb_mode(reverb_mode); - awe_set_chorus_mode(chorus_mode); - - awe_present = TRUE; - - ret = 1; - return ATTACH_RET; -} - - -#ifdef AWE_DYNAMIC_BUFFER -static void free_tables(void) -{ - my_free(sflists); - sflists = NULL; max_sfs = 0; - my_free(samples); - samples = NULL; max_samples = 0; - my_free(infos); - infos = NULL; max_infos = 0; -} -#else -#define free_buffers() /**/ -#endif - - -#ifdef linux -ATTACH_DECL -void unload_awe(void) -{ - if (awe_present) { - awe_reset_samples(); - awe_release_region(); - my_free(voices); - my_free(channels); - free_tables(); - awe_present = FALSE; - } -} -#endif - - -/*---------------------------------------------------------------- - * old type interface - *----------------------------------------------------------------*/ - -#ifdef AWE_OBSOLETE_VOXWARE - -#if defined(__DragonFly__) || defined(__FreeBSD__) -long attach_awe_obsolete(long mem_start, struct address_info *hw_config) -#else -int attach_awe_obsolete(int mem_start, struct address_info *hw_config) -#endif -{ - my_malloc_init(mem_start); - if (! attach_awe()) - return 0; - return my_malloc_memptr(); -} - -int probe_awe_obsolete(struct address_info *hw_config) -{ - return 1; - /*return awe_detect();*/ -} - -#else -#if defined(__DragonFly__) || defined(__FreeBSD__ ) -int probe_awe(struct address_info *hw_config) -{ - return 1; -} -#endif -#endif /* AWE_OBSOLETE_VOXWARE */ - - -/*================================================================ - * clear sample tables - *================================================================*/ - -static void -awe_reset_samples(void) -{ - int i; - - /* free all bank tables */ - for (i = 0; i < AWE_MAX_PRESETS; i++) - preset_table[i] = -1; - - free_tables(); - - current_sf_id = 0; - locked_sf_id = 0; - patch_opened = 0; -} - - -/*================================================================ - * EMU register access - *================================================================*/ - -/* select a given AWE32 pointer */ -static int awe_cur_cmd = -1; -#define awe_set_cmd(cmd) \ -if (awe_cur_cmd != cmd) { OUTW(cmd, awe_base + 0x802); awe_cur_cmd = cmd; } -#define awe_port(port) (awe_base - 0x620 + port) - -/* write 16bit data */ -INLINE static void -awe_poke(unsigned short cmd, unsigned short port, unsigned short data) -{ - awe_set_cmd(cmd); - OUTW(data, awe_port(port)); -} - -/* write 32bit data */ -INLINE static void -awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data) -{ - awe_set_cmd(cmd); - OUTW(data, awe_port(port)); /* write lower 16 bits */ - OUTW(data >> 16, awe_port(port)+2); /* write higher 16 bits */ -} - -/* read 16bit data */ -INLINE static unsigned short -awe_peek(unsigned short cmd, unsigned short port) -{ - unsigned short k; - awe_set_cmd(cmd); - k = inw(awe_port(port)); - return k; -} - -/* read 32bit data */ -INLINE static unsigned int -awe_peek_dw(unsigned short cmd, unsigned short port) -{ - unsigned int k1, k2; - awe_set_cmd(cmd); - k1 = inw(awe_port(port)); - k2 = inw(awe_port(port)+2); - k1 |= k2 << 16; - return k1; -} - -/* wait delay number of AWE32 44100Hz clocks */ -static void -awe_wait(unsigned short delay) -{ - unsigned short clock, target; - unsigned short port = awe_port(AWE_WC_Port); - int counter; - - /* sample counter */ - awe_set_cmd(AWE_WC_Cmd); - clock = (unsigned short)inw(port); - target = clock + delay; - counter = 0; - if (target < clock) { - for (; (unsigned short)inw(port) > target; counter++) - if (counter > 65536) - break; - } - for (; (unsigned short)inw(port) < target; counter++) - if (counter > 65536) - break; -} - -/* write a word data */ -INLINE static void -awe_write_dram(unsigned short c) -{ - awe_poke(AWE_SMLD, c); -} - - -#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE) - -/*================================================================ - * port check / request - * 0x620-622, 0xA20-A22, 0xE20-E22 - *================================================================*/ - -static int -awe_check_port(void) -{ - return (check_region(awe_port(Data0), 4) || - check_region(awe_port(Data1), 4) || - check_region(awe_port(Data3), 4)); -} - -static void -awe_request_region(void) -{ - request_region(awe_port(Data0), 4, "sound driver (AWE32)"); - request_region(awe_port(Data1), 4, "sound driver (AWE32)"); - request_region(awe_port(Data3), 4, "sound driver (AWE32)"); -} - -static void -awe_release_region(void) -{ - release_region(awe_port(Data0), 4); - release_region(awe_port(Data1), 4); - release_region(awe_port(Data3), 4); -} - -#endif /* !AWE_OBSOLETE_VOXWARE */ - - -/*================================================================ - * AWE32 initialization - *================================================================*/ -static void -awe_initialize(void) -{ - AWE_DEBUG(0,printk("AWE32: initializing..\n")); - - /* initialize hardware configuration */ - awe_poke(AWE_HWCF1, 0x0059); - awe_poke(AWE_HWCF2, 0x0020); - - /* disable audio; this seems to reduce a clicking noise a bit.. */ - awe_poke(AWE_HWCF3, 0); - - /* initialize audio channels */ - awe_init_audio(); - - /* initialize DMA */ - awe_init_dma(); - - /* initialize init array */ - awe_init_array(); - - /* check DRAM memory size */ - awe_mem_size = awe_check_dram(); - - /* initialize the FM section of the AWE32 */ - awe_init_fm(); - - /* set up voice envelopes */ - awe_tweak(); - - /* enable audio */ - awe_poke(AWE_HWCF3, 0x0004); - - /* set equalizer */ - awe_equalizer(5, 9); -} - - -/*================================================================ - * AWE32 voice parameters - *================================================================*/ - -/* initialize voice_info record */ -static void -awe_init_voice_info(awe_voice_info *vp) -{ - vp->sf_id = 0; /* normal mode */ - vp->sample = 0; - vp->rate_offset = 0; - - vp->start = 0; - vp->end = 0; - vp->loopstart = 0; - vp->loopend = 0; - vp->mode = 0; - vp->root = 60; - vp->tune = 0; - vp->low = 0; - vp->high = 127; - vp->vellow = 0; - vp->velhigh = 127; - - vp->fixkey = -1; - vp->fixvel = -1; - vp->fixpan = -1; - vp->pan = -1; - - vp->exclusiveClass = 0; - vp->amplitude = 127; - vp->attenuation = 0; - vp->scaleTuning = 100; - - awe_init_voice_parm(&vp->parm); -} - -/* initialize voice_parm record: - * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0. - * Vibrato and Tremolo effects are zero. - * Cutoff is maximum. - * Chorus and Reverb effects are zero. - */ -static void -awe_init_voice_parm(awe_voice_parm *pp) -{ - pp->moddelay = 0x8000; - pp->modatkhld = 0x7f7f; - pp->moddcysus = 0x7f7f; - pp->modrelease = 0x807f; - pp->modkeyhold = 0; - pp->modkeydecay = 0; - - pp->voldelay = 0x8000; - pp->volatkhld = 0x7f7f; - pp->voldcysus = 0x7f7f; - pp->volrelease = 0x807f; - pp->volkeyhold = 0; - pp->volkeydecay = 0; - - pp->lfo1delay = 0x8000; - pp->lfo2delay = 0x8000; - pp->pefe = 0; - - pp->fmmod = 0; - pp->tremfrq = 0; - pp->fm2frq2 = 0; - - pp->cutoff = 0xff; - pp->filterQ = 0; - - pp->chorus = 0; - pp->reverb = 0; -} - - -#ifdef AWE_HAS_GUS_COMPATIBILITY - -/* convert frequency mHz to abstract cents (= midi key * 100) */ -static int -freq_to_note(int mHz) -{ - /* abscents = log(mHz/8176) / log(2) * 1200 */ - unsigned int max_val = (unsigned int)0xffffffff / 10000; - int i, times; - unsigned int base; - unsigned int freq; - int note, tune; - - if (mHz == 0) - return 0; - if (mHz < 0) - return 12799; /* maximum */ - - freq = mHz; - note = 0; - for (base = 8176 * 2; freq >= base; base *= 2) { - note += 12; - if (note >= 128) /* over maximum */ - return 12799; - } - base /= 2; - - /* to avoid overflow... */ - times = 10000; - while (freq > max_val) { - max_val *= 10; - times /= 10; - base /= 10; - } - - freq = freq * times / base; - for (i = 0; i < 12; i++) { - if (freq < semitone_tuning[i+1]) - break; - note++; - } - - tune = 0; - freq = freq * 10000 / semitone_tuning[i]; - for (i = 0; i < 100; i++) { - if (freq < cent_tuning[i+1]) - break; - tune++; - } - - return note * 100 + tune; -} - - -/* convert Hz to AWE32 rate offset: - * sample pitch offset for the specified sample rate - * rate=44100 is no offset, each 4096 is 1 octave (twice). - * eg, when rate is 22050, this offset becomes -4096. - */ -static int -calc_rate_offset(int Hz) -{ - /* offset = log(Hz / 44100) / log(2) * 4096 */ - int freq, base, i; - - /* maybe smaller than max (44100Hz) */ - if (Hz <= 0 || Hz >= 44100) return 0; - - base = 0; - for (freq = Hz * 2; freq < 44100; freq *= 2) - base++; - base *= 1200; - - freq = 44100 * 10000 / (freq/2); - for (i = 0; i < 12; i++) { - if (freq < semitone_tuning[i+1]) - break; - base += 100; - } - freq = freq * 10000 / semitone_tuning[i]; - for (i = 0; i < 100; i++) { - if (freq < cent_tuning[i+1]) - break; - base++; - } - return -base * 4096 / 1200; -} - - -/*---------------------------------------------------------------- - * convert envelope time parameter to AWE32 raw parameter - *----------------------------------------------------------------*/ - -/* attack & decay/release time table (msec) */ -static short attack_time_tbl[128] = { -32767, 11878, 5939, 3959, 2969, 2375, 1979, 1696, 1484, 1319, 1187, 1079, 989, 913, 848, 791, 742, - 698, 659, 625, 593, 565, 539, 516, 494, 475, 456, 439, 424, 409, 395, 383, 371, - 359, 344, 330, 316, 302, 290, 277, 266, 255, 244, 233, 224, 214, 205, 196, 188, - 180, 173, 165, 158, 152, 145, 139, 133, 127, 122, 117, 112, 107, 103, 98, 94, - 90, 86, 83, 79, 76, 73, 69, 67, 64, 61, 58, 56, 54, 51, 49, 47, - 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 25, 24, 23, - 22, 21, 20, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11, - 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 0, -}; - -static short decay_time_tbl[128] = { -32767, 32766, 4589, 4400, 4219, 4045, 3879, 3719, 3566, 3419, 3279, 3144, 3014, 2890, 2771, 2657, - 2548, 2443, 2343, 2246, 2154, 2065, 1980, 1899, 1820, 1746, 1674, 1605, 1539, 1475, 1415, 1356, - 1301, 1247, 1196, 1146, 1099, 1054, 1011, 969, 929, 891, 854, 819, 785, 753, 722, 692, - 664, 636, 610, 585, 561, 538, 516, 494, 474, 455, 436, 418, 401, 384, 368, 353, - 339, 325, 311, 298, 286, 274, 263, 252, 242, 232, 222, 213, 204, 196, 188, 180, - 173, 166, 159, 152, 146, 140, 134, 129, 123, 118, 113, 109, 104, 100, 96, 92, - 88, 84, 81, 77, 74, 71, 68, 65, 63, 60, 58, 55, 53, 51, 49, 47, - 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 26, 25, 24, -}; - -/* -static int -calc_parm_delay(int msec) -{ - return (0x8000 - msec * 1000 / 725); -} -*/ - -/* delay time = 0x8000 - msec/92 */ -static int -calc_parm_hold(int msec) -{ - int val = (0x7f * 92 - msec) / 92; - if (val < 1) val = 1; - if (val > 127) val = 127; - return val; -} - -/* attack time: search from time table */ -static int -calc_parm_attack(int msec) -{ - return calc_parm_search(msec, attack_time_tbl); -} - -/* decay/release time: search from time table */ -static int -calc_parm_decay(int msec) -{ - return calc_parm_search(msec, decay_time_tbl); -} - -/* search an index for specified time from given time table */ -static int -calc_parm_search(int msec, short *table) -{ - int left = 1, right = 127, mid; - while (left < right) { - mid = (left + right) / 2; - if (msec < (int)table[mid]) - left = mid + 1; - else - right = mid; - } - return left; -} -#endif /* AWE_HAS_GUS_COMPATIBILITY */ - - -/*================================================================ - * effects table - *================================================================*/ - -/* set an effect value */ -#define FX_FLAG_OFF 0 -#define FX_FLAG_SET 1 -#define FX_FLAG_ADD 2 - -#define FX_SET(rec,type,value) \ - ((rec)->flags[type] = FX_FLAG_SET, (rec)->val[type] = (value)) -#define FX_ADD(rec,type,value) \ - ((rec)->flags[type] = FX_FLAG_ADD, (rec)->val[type] = (value)) -#define FX_UNSET(rec,type) \ - ((rec)->flags[type] = FX_FLAG_OFF, (rec)->val[type] = 0) - -/* check the effect value is set */ -#define FX_ON(rec,type) ((rec)->flags[type]) - -#define PARM_BYTE 0 -#define PARM_WORD 1 - -static struct PARM_DEFS { - int type; /* byte or word */ - int low, high; /* value range */ - fx_affect_func realtime; /* realtime paramater change */ -} parm_defs[] = { - {PARM_WORD, 0, 0x8000, NULL}, /* env1 delay */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env1 attack */ - {PARM_BYTE, 0, 0x7e, NULL}, /* env1 hold */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env1 decay */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env1 release */ - {PARM_BYTE, 0, 0x7f, NULL}, /* env1 sustain */ - {PARM_BYTE, 0, 0xff, NULL}, /* env1 pitch */ - {PARM_BYTE, 0, 0xff, NULL}, /* env1 cutoff */ - - {PARM_WORD, 0, 0x8000, NULL}, /* env2 delay */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env2 attack */ - {PARM_BYTE, 0, 0x7e, NULL}, /* env2 hold */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env2 decay */ - {PARM_BYTE, 1, 0x7f, NULL}, /* env2 release */ - {PARM_BYTE, 0, 0x7f, NULL}, /* env2 sustain */ - - {PARM_WORD, 0, 0x8000, NULL}, /* lfo1 delay */ - {PARM_BYTE, 0, 0xff, awe_fx_tremfrq}, /* lfo1 freq */ - {PARM_BYTE, 0, 0x7f, awe_fx_tremfrq}, /* lfo1 volume (positive only)*/ - {PARM_BYTE, 0, 0x7f, awe_fx_fmmod}, /* lfo1 pitch (positive only)*/ - {PARM_BYTE, 0, 0xff, awe_fx_fmmod}, /* lfo1 cutoff (positive only)*/ - - {PARM_WORD, 0, 0x8000, NULL}, /* lfo2 delay */ - {PARM_BYTE, 0, 0xff, awe_fx_fm2frq2}, /* lfo2 freq */ - {PARM_BYTE, 0, 0x7f, awe_fx_fm2frq2}, /* lfo2 pitch (positive only)*/ - - {PARM_WORD, 0, 0xffff, awe_set_voice_pitch}, /* initial pitch */ - {PARM_BYTE, 0, 0xff, NULL}, /* chorus */ - {PARM_BYTE, 0, 0xff, NULL}, /* reverb */ - {PARM_BYTE, 0, 0xff, awe_set_volume}, /* initial cutoff */ - {PARM_BYTE, 0, 15, awe_fx_filterQ}, /* initial resonance */ - - {PARM_WORD, 0, 0xffff, NULL}, /* sample start */ - {PARM_WORD, 0, 0xffff, NULL}, /* loop start */ - {PARM_WORD, 0, 0xffff, NULL}, /* loop end */ - {PARM_WORD, 0, 0xffff, NULL}, /* coarse sample start */ - {PARM_WORD, 0, 0xffff, NULL}, /* coarse loop start */ - {PARM_WORD, 0, 0xffff, NULL}, /* coarse loop end */ - {PARM_BYTE, 0, 0xff, awe_set_volume}, /* initial attenuation */ -}; - - -static unsigned char -FX_BYTE(FX_Rec *rec, FX_Rec *lay, int type, unsigned char value) -{ - int effect = 0; - int on = 0; - if (lay && (on = FX_ON(lay, type)) != 0) - effect = lay->val[type]; - if (!on && (on = FX_ON(rec, type)) != 0) - effect = rec->val[type]; - if (on == FX_FLAG_ADD) - effect += (int)value; - if (on) { - if (effect < parm_defs[type].low) - effect = parm_defs[type].low; - else if (effect > parm_defs[type].high) - effect = parm_defs[type].high; - return (unsigned char)effect; - } - return value; -} - -/* get word effect value */ -static unsigned short -FX_WORD(FX_Rec *rec, FX_Rec *lay, int type, unsigned short value) -{ - int effect = 0; - int on = 0; - if (lay && (on = FX_ON(lay, type)) != 0) - effect = lay->val[type]; - if (!on && (on = FX_ON(rec, type)) != 0) - effect = rec->val[type]; - if (on == FX_FLAG_ADD) - effect += (int)value; - if (on) { - if (effect < parm_defs[type].low) - effect = parm_defs[type].low; - else if (effect > parm_defs[type].high) - effect = parm_defs[type].high; - return (unsigned short)effect; - } - return value; -} - -/* get word (upper=type1/lower=type2) effect value */ -static unsigned short -FX_COMB(FX_Rec *rec, FX_Rec *lay, int type1, int type2, unsigned short value) -{ - unsigned short tmp; - tmp = FX_BYTE(rec, lay, type1, (unsigned char)(value >> 8)); - tmp <<= 8; - tmp |= FX_BYTE(rec, lay, type2, (unsigned char)(value & 0xff)); - return tmp; -} - -/* address offset */ -static int -FX_OFFSET(FX_Rec *rec, FX_Rec *lay, int lo, int hi, int mode) -{ - int addr = 0; - if (lay && FX_ON(lay, hi)) - addr = (short)lay->val[hi]; - else if (FX_ON(rec, hi)) - addr = (short)rec->val[hi]; - addr = addr << 15; - if (lay && FX_ON(lay, lo)) - addr += (short)lay->val[lo]; - else if (FX_ON(rec, lo)) - addr += (short)rec->val[lo]; - if (!(mode & AWE_SAMPLE_8BITS)) - addr /= 2; - return addr; -} - - -/*================================================================ - * turn on/off sample - *================================================================*/ - -static void -awe_note_on(int voice) -{ - unsigned int temp; - int addr; - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - /* A voice sample must assigned before calling */ - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - - /* channel to be silent and idle */ - awe_poke(AWE_DCYSUSV(voice), 0x0080); - awe_poke(AWE_VTFT(voice), 0); - awe_poke(AWE_CVCF(voice), 0); - awe_poke(AWE_PTRX(voice), 0); - awe_poke(AWE_CPF(voice), 0); - - /* modulation & volume envelope */ - awe_poke(AWE_ENVVAL(voice), - FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, vp->parm.moddelay)); - awe_poke(AWE_ATKHLD(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK, - vp->parm.modatkhld)); - awe_poke(AWE_DCYSUS(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY, - vp->parm.moddcysus)); - awe_poke(AWE_ENVVOL(voice), - FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay)); - awe_poke(AWE_ATKHLDV(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK, - vp->parm.volatkhld)); - /* decay/sustain parameter for volume envelope must be set at last */ - - /* pitch offset */ - awe_set_pitch(voice, TRUE); - - /* cutoff and volume */ - awe_set_volume(voice, TRUE); - - /* modulation envelope heights */ - awe_poke(AWE_PEFE(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF, - vp->parm.pefe)); - - /* lfo1/2 delay */ - awe_poke(AWE_LFO1VAL(voice), - FX_WORD(fx, fx_lay, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay)); - awe_poke(AWE_LFO2VAL(voice), - FX_WORD(fx, fx_lay, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay)); - - /* lfo1 pitch & cutoff shift */ - awe_fx_fmmod(voice, TRUE); - /* lfo1 volume & freq */ - awe_fx_tremfrq(voice, TRUE); - /* lfo2 pitch & freq */ - awe_fx_fm2frq2(voice, TRUE); - /* pan & loop start */ - awe_set_pan(voice, TRUE); - - /* chorus & loop end (chorus 8bit, MSB) */ - addr = vp->loopend - 1; - addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_END, - AWE_FX_COARSE_LOOP_END, vp->mode); - temp = FX_BYTE(fx, fx_lay, AWE_FX_CHORUS, vp->parm.chorus); - temp = (temp <<24) | (unsigned int)addr; - awe_poke_dw(AWE_CSL(voice), temp); - AWE_DEBUG(4,printk("AWE32: [-- loopend=%x/%x]\n", vp->loopend, addr)); - - /* Q & current address (Q 4bit value, MSB) */ - addr = vp->start - 1; - addr += FX_OFFSET(fx, fx_lay, AWE_FX_SAMPLE_START, - AWE_FX_COARSE_SAMPLE_START, vp->mode); - temp = FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ); - temp = (temp<<28) | (unsigned int)addr; - awe_poke_dw(AWE_CCCA(voice), temp); - AWE_DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n", vp->start, addr)); - - /* reset volume */ - awe_poke_dw(AWE_VTFT(voice), 0x0000FFFF); - awe_poke_dw(AWE_CVCF(voice), 0x0000FFFF); - - /* turn on envelope */ - awe_poke(AWE_DCYSUSV(voice), - FX_COMB(fx, fx_lay, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY, - vp->parm.voldcysus)); - /* set reverb */ - temp = FX_BYTE(fx, fx_lay, AWE_FX_REVERB, vp->parm.reverb); - temp = (awe_peek_dw(AWE_PTRX(voice)) & 0xffff0000) | (temp<<8); - awe_poke_dw(AWE_PTRX(voice), temp); - awe_poke_dw(AWE_CPF(voice), 0x40000000); - - voices[voice].state = AWE_ST_ON; - - /* clear voice position for the next note on this channel */ - if (SINGLE_LAYER_MODE()) { - FX_UNSET(fx, AWE_FX_SAMPLE_START); - FX_UNSET(fx, AWE_FX_COARSE_SAMPLE_START); - } -} - - -/* turn off the voice */ -static void -awe_note_off(int voice) -{ - awe_voice_info *vp; - unsigned short tmp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if ((vp = voices[voice].sample) == NULL) { - voices[voice].state = AWE_ST_OFF; - return; - } - - tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV1_RELEASE, - (unsigned char)vp->parm.modrelease); - awe_poke(AWE_DCYSUS(voice), tmp); - tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV2_RELEASE, - (unsigned char)vp->parm.volrelease); - awe_poke(AWE_DCYSUSV(voice), tmp); - voices[voice].state = AWE_ST_RELEASED; -} - -/* force to terminate the voice (no releasing echo) */ -static void -awe_terminate(int voice) -{ - awe_poke(AWE_DCYSUSV(voice), 0x807F); - awe_tweak_voice(voice); - voices[voice].state = AWE_ST_OFF; -} - -/* turn off other voices with the same exclusive class (for drums) */ -static void -awe_exclusive_off(int voice) -{ - int i, exclass; - - if (voices[voice].sample == NULL) - return; - if ((exclass = voices[voice].sample->exclusiveClass) == 0) - return; /* not exclusive */ - - /* turn off voices with the same class */ - for (i = 0; i < awe_max_voices; i++) { - if (i != voice && IS_PLAYING(i) && - voices[i].sample && voices[i].ch == voices[voice].ch && - voices[i].sample->exclusiveClass == exclass) { - AWE_DEBUG(4,printk("AWE32: [exoff(%d)]\n", i)); - awe_terminate(i); - awe_voice_init(i, TRUE); - } - } -} - - -/*================================================================ - * change the parameters of an audible voice - *================================================================*/ - -/* change pitch */ -static void -awe_set_pitch(int voice, int forced) -{ - if (IS_NO_EFFECT(voice) && !forced) return; - awe_poke(AWE_IP(voice), voices[voice].apitch); - AWE_DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch)); -} - -/* calculate & change pitch */ -static void -awe_set_voice_pitch(int voice, int forced) -{ - awe_calc_pitch(voice); - awe_set_pitch(voice, forced); -} - -/* change volume & cutoff */ -static void -awe_set_volume(int voice, int forced) -{ - awe_voice_info *vp; - unsigned short tmp2; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (!IS_PLAYING(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - - tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF, vp->parm.cutoff); - tmp2 = (tmp2 << 8); - tmp2 |= FX_BYTE(fx, fx_lay, AWE_FX_ATTEN, - (unsigned char)voices[voice].avol); - awe_poke(AWE_IFATN(voice), tmp2); -} - -/* calculate & change volume */ -static void -awe_set_voice_vol(int voice, int forced) -{ - if (IS_EMPTY(voice)) - return; - awe_calc_volume(voice); - awe_set_volume(voice, forced); -} - - -/* change pan; this could make a click noise.. */ -static void -awe_set_pan(int voice, int forced) -{ - unsigned int temp; - int addr; - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - - /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */ - if (vp->fixpan > 0) /* 0-127 */ - temp = 255 - (int)vp->fixpan * 2; - else { - int pos = 0; - if (vp->pan >= 0) /* 0-127 */ - pos = (int)vp->pan * 2 - 128; - pos += voices[voice].cinfo->panning; /* -128 - 127 */ - pos = 127 - pos; - if (pos < 0) - temp = 0; - else if (pos > 255) - temp = 255; - else - temp = pos; - } - if (forced || temp != voices[voice].apan) { - addr = vp->loopstart - 1; - addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_START, - AWE_FX_COARSE_LOOP_START, vp->mode); - temp = (temp<<24) | (unsigned int)addr; - awe_poke_dw(AWE_PSST(voice), temp); - voices[voice].apan = temp; - AWE_DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n", vp->loopstart, addr)); - } -} - -/* effects change during playing */ -static void -awe_fx_fmmod(int voice, int forced) -{ - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - awe_poke(AWE_FMMOD(voice), - FX_COMB(fx, fx_lay, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF, - vp->parm.fmmod)); -} - -/* set tremolo (lfo1) volume & frequency */ -static void -awe_fx_tremfrq(int voice, int forced) -{ - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - awe_poke(AWE_TREMFRQ(voice), - FX_COMB(fx, fx_lay, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ, - vp->parm.tremfrq)); -} - -/* set lfo2 pitch & frequency */ -static void -awe_fx_fm2frq2(int voice, int forced) -{ - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - awe_poke(AWE_FM2FRQ2(voice), - FX_COMB(fx, fx_lay, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ, - vp->parm.fm2frq2)); -} - - -/* Q & current address (Q 4bit value, MSB) */ -static void -awe_fx_filterQ(int voice, int forced) -{ - unsigned int addr; - awe_voice_info *vp; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - if (IS_NO_EFFECT(voice) && !forced) return; - if ((vp = voices[voice].sample) == NULL || vp->index < 0) - return; - - addr = awe_peek_dw(AWE_CCCA(voice)) & 0xffffff; - addr |= (FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ) << 28); - awe_poke_dw(AWE_CCCA(voice), addr); -} - -/*================================================================ - * calculate pitch offset - *---------------------------------------------------------------- - * 0xE000 is no pitch offset at 44100Hz sample. - * Every 4096 is one octave. - *================================================================*/ - -static void -awe_calc_pitch(int voice) -{ - voice_info *vp = &voices[voice]; - awe_voice_info *ap; - awe_chan_info *cp = voices[voice].cinfo; - int offset; - - /* search voice information */ - if ((ap = vp->sample) == NULL) - return; - if (ap->index < 0) { - AWE_DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); - if (awe_set_sample(ap) < 0) - return; - } - - /* calculate offset */ - if (ap->fixkey >= 0) { - AWE_DEBUG(3,printk("AWE32: p-> fixkey(%d) tune(%d)\n", ap->fixkey, ap->tune)); - offset = (ap->fixkey - ap->root) * 4096 / 12; - } else { - AWE_DEBUG(3,printk("AWE32: p(%d)-> root(%d) tune(%d)\n", vp->note, ap->root, ap->tune)); - offset = (vp->note - ap->root) * 4096 / 12; - AWE_DEBUG(4,printk("AWE32: p-> ofs=%d\n", offset)); - } - offset = (offset * ap->scaleTuning) / 100; - AWE_DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset)); - offset += ap->tune * 4096 / 1200; - AWE_DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset)); - if (cp->bender != 0) { - AWE_DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, cp->bender)); - /* (819200: 1 semitone) ==> (4096: 12 semitones) */ - offset += cp->bender * cp->bender_range / 2400; - } - - /* add initial pitch correction */ - if (FX_ON(&cp->fx_layer[vp->layer], AWE_FX_INIT_PITCH)) - offset += cp->fx_layer[vp->layer].val[AWE_FX_INIT_PITCH]; - else if (FX_ON(&cp->fx, AWE_FX_INIT_PITCH)) - offset += cp->fx.val[AWE_FX_INIT_PITCH]; - - /* 0xe000: root pitch */ - vp->apitch = 0xe000 + ap->rate_offset + offset; - AWE_DEBUG(4,printk("AWE32: p-> sum aofs=%x, rate_ofs=%d\n", vp->apitch, ap->rate_offset)); - if (vp->apitch > 0xffff) - vp->apitch = 0xffff; - if (vp->apitch < 0) - vp->apitch = 0; -} - - -#ifdef AWE_HAS_GUS_COMPATIBILITY -/* calculate MIDI key and semitone from the specified frequency */ -static void -awe_calc_pitch_from_freq(int voice, int freq) -{ - voice_info *vp = &voices[voice]; - awe_voice_info *ap; - FX_Rec *fx = &voices[voice].cinfo->fx; - FX_Rec *fx_lay = NULL; - int offset; - int note; - - if (voices[voice].layer < MAX_LAYERS) - fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; - - /* search voice information */ - if ((ap = vp->sample) == NULL) - return; - if (ap->index < 0) { - AWE_DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); - if (awe_set_sample(ap) < 0) - return; - } - note = freq_to_note(freq); - offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200; - offset = (offset * ap->scaleTuning) / 100; - if (fx_lay && FX_ON(fx_lay, AWE_FX_INIT_PITCH)) - offset += fx_lay->val[AWE_FX_INIT_PITCH]; - else if (FX_ON(fx, AWE_FX_INIT_PITCH)) - offset += fx->val[AWE_FX_INIT_PITCH]; - vp->apitch = 0xe000 + ap->rate_offset + offset; - if (vp->apitch > 0xffff) - vp->apitch = 0xffff; - if (vp->apitch < 0) - vp->apitch = 0; -} -#endif /* AWE_HAS_GUS_COMPATIBILITY */ - - -/*================================================================ - * calculate volume attenuation - *---------------------------------------------------------------- - * Voice volume is controlled by volume attenuation parameter. - * So volume becomes maximum when avol is 0 (no attenuation), and - * minimum when 255 (-96dB or silence). - *================================================================*/ - -static int vol_table[128] = { - 255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49, - 47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32, - 31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22, - 22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16, - 15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10, - 10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6, - 6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3, - 2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0, -}; - -static void -awe_calc_volume(int voice) -{ - voice_info *vp = &voices[voice]; - awe_voice_info *ap; - awe_chan_info *cp = voices[voice].cinfo; - int vol; - - /* search voice information */ - if ((ap = vp->sample) == NULL) - return; - - ap = vp->sample; - if (ap->index < 0) { - AWE_DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); - if (awe_set_sample(ap) < 0) - return; - } - - /* 0 - 127 */ - vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127); - vol = vol * ap->amplitude / 127; - - if (vol < 0) vol = 0; - if (vol > 127) vol = 127; - - /* calc to attenuation */ - vol = vol_table[vol]; - vol = vol + (int)ap->attenuation + init_atten; - if (vol > 255) vol = 255; - - vp->avol = vol; - AWE_DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol)); -} - - -/* set sostenuto on */ -static void awe_sostenuto_on(int voice, int forced) -{ - if (IS_NO_EFFECT(voice) && !forced) return; - voices[voice].sostenuto = 127; -} - - -/* drop sustain */ -static void awe_sustain_off(int voice, int forced) -{ - if (voices[voice].state == AWE_ST_SUSTAINED) { - awe_note_off(voice); - awe_fx_init(voices[voice].ch); - awe_voice_init(voice, FALSE); - } -} - - -/* terminate and initialize voice */ -static void awe_terminate_and_init(int voice, int forced) -{ - awe_terminate(voice); - awe_fx_init(voices[voice].ch); - awe_voice_init(voice, TRUE); -} - - -/*================================================================ - * synth operation routines - *================================================================*/ - -#define AWE_VOICE_KEY(v) (0x8000 | (v)) -#define AWE_CHAN_KEY(c,n) (((c) << 8) | ((n) + 1)) -#define KEY_CHAN_MATCH(key,c) (((key) >> 8) == (c)) - -/* initialize the voice */ -static void -awe_voice_init(int voice, int init_all) -{ - voice_info *vp = &voices[voice]; - - /* reset voice search key */ - if (playing_mode == AWE_PLAY_DIRECT) - vp->key = AWE_VOICE_KEY(voice); - else - vp->key = 0; - - /* clear voice mapping */ - voice_alloc->map[voice] = 0; - - /* touch the timing flag */ - vp->time = current_alloc_time; - - /* initialize other parameters if necessary */ - if (init_all) { - vp->note = -1; - vp->velocity = 0; - vp->sostenuto = 0; - - vp->sample = NULL; - vp->cinfo = &channels[voice]; - vp->ch = voice; - vp->state = AWE_ST_OFF; - - /* emu8000 parameters */ - vp->apitch = 0; - vp->avol = 255; - vp->apan = -1; - } -} - -/* clear effects */ -static void awe_fx_init(int ch) -{ - if (SINGLE_LAYER_MODE() && !misc_modes[AWE_MD_KEEP_EFFECT]) { - BZERO(&channels[ch].fx, sizeof(channels[ch].fx)); - BZERO(&channels[ch].fx_layer, sizeof(&channels[ch].fx_layer)); - } -} - -/* initialize channel info */ -static void awe_channel_init(int ch, int init_all) -{ - awe_chan_info *cp = &channels[ch]; - cp->channel = ch; - if (init_all) { - cp->panning = 0; /* zero center */ - cp->bender_range = 200; /* sense * 100 */ - cp->main_vol = 127; - if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) { - cp->instr = misc_modes[AWE_MD_DEF_DRUM]; - cp->bank = AWE_DRUM_BANK; - } else { - cp->instr = misc_modes[AWE_MD_DEF_PRESET]; - cp->bank = misc_modes[AWE_MD_DEF_BANK]; - } - cp->vrec = -1; - cp->def_vrec = -1; - } - - cp->bender = 0; /* zero tune skew */ - cp->expression_vol = 127; - cp->chan_press = 0; - cp->sustained = 0; - - if (! misc_modes[AWE_MD_KEEP_EFFECT]) { - BZERO(&cp->fx, sizeof(cp->fx)); - BZERO(&cp->fx_layer, sizeof(cp->fx_layer)); - } -} - - -/* change the voice parameters; voice = channel */ -static void awe_voice_change(int voice, fx_affect_func func) -{ - int i; - switch (playing_mode) { - case AWE_PLAY_DIRECT: - func(voice, FALSE); - break; - case AWE_PLAY_INDIRECT: - for (i = 0; i < awe_max_voices; i++) - if (voices[i].key == AWE_VOICE_KEY(voice)) - func(i, FALSE); - break; - default: - for (i = 0; i < awe_max_voices; i++) - if (KEY_CHAN_MATCH(voices[i].key, voice)) - func(i, FALSE); - break; - } -} - - -/*---------------------------------------------------------------- - * device open / close - *----------------------------------------------------------------*/ - -/* open device: - * reset status of all voices, and clear sample position flag - */ -static int -awe_open(int dev, int mode) -{ - if (awe_busy) - return RET_ERROR(EBUSY); - - awe_busy = TRUE; - - /* set default mode */ - awe_init_misc_modes(FALSE); - init_atten = misc_modes[AWE_MD_ZERO_ATTEN]; - drum_flags = DEFAULT_DRUM_FLAGS; - playing_mode = AWE_PLAY_INDIRECT; - - /* reset voices & channels */ - awe_reset(dev); - - patch_opened = 0; - - return 0; -} - - -/* close device: - * reset all voices again (terminate sounds) - */ -static void -awe_close(int dev) -{ - awe_reset(dev); - awe_busy = FALSE; -} - - -/* set miscellaneous mode parameters - */ -static void -awe_init_misc_modes(int init_all) -{ - int i; - for (i = 0; i < AWE_MD_END; i++) { - if (init_all || misc_modes_default[i].init_each_time) - misc_modes[i] = misc_modes_default[i].value; - } -} - - -/* sequencer I/O control: - */ -static int -awe_ioctl(int dev, unsigned int cmd, caddr_t arg) -{ - switch (cmd) { - case SNDCTL_SYNTH_INFO: - if (playing_mode == AWE_PLAY_DIRECT) - awe_info.nr_voices = awe_max_voices; - else - awe_info.nr_voices = AWE_MAX_CHANNELS; - IOCTL_TO_USER((char*)arg, 0, &awe_info, sizeof(awe_info)); - return 0; - break; - - case SNDCTL_SEQ_RESETSAMPLES: - awe_reset_samples(); - awe_reset(dev); - return 0; - break; - - case SNDCTL_SEQ_PERCMODE: - /* what's this? */ - return 0; - break; - - case SNDCTL_SYNTH_MEMAVL: - return awe_mem_size - awe_free_mem_ptr() * 2; - - default: - printk("AWE32: unsupported ioctl %d\n", cmd); - return RET_ERROR(EINVAL); - } -} - - -static int voice_in_range(int voice) -{ - if (playing_mode == AWE_PLAY_DIRECT) { - if (voice < 0 || voice >= awe_max_voices) - return FALSE; - } else { - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return FALSE; - } - return TRUE; -} - -static void release_voice(int voice, int do_sustain) -{ - if (IS_NO_SOUND(voice)) - return; - if (do_sustain && (voices[voice].cinfo->sustained == 127 || - voices[voice].sostenuto == 127)) - voices[voice].state = AWE_ST_SUSTAINED; - else { - awe_note_off(voice); - awe_fx_init(voices[voice].ch); - awe_voice_init(voice, FALSE); - } -} - -/* release all notes */ -static void awe_note_off_all(int do_sustain) -{ - int i; - for (i = 0; i < awe_max_voices; i++) - release_voice(i, do_sustain); -} - -/* kill a voice: - * not terminate, just release the voice. - */ -static int -awe_kill_note(int dev, int voice, int note, int velocity) -{ - int i, v2, key; - - AWE_DEBUG(2,printk("AWE32: [off(%d) nt=%d vl=%d]\n", voice, note, velocity)); - if (! voice_in_range(voice)) - return RET_ERROR(EINVAL); - - switch (playing_mode) { - case AWE_PLAY_DIRECT: - case AWE_PLAY_INDIRECT: - key = AWE_VOICE_KEY(voice); - break; - - case AWE_PLAY_MULTI2: - v2 = voice_alloc->map[voice] >> 8; - voice_alloc->map[voice] = 0; - voice = v2; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return RET_ERROR(EINVAL); - /* continue to below */ - default: - key = AWE_CHAN_KEY(voice, note); - break; - } - - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].key == key) - release_voice(i, TRUE); - } - return 0; -} - - -static void start_or_volume_change(int voice, int velocity) -{ - voices[voice].velocity = velocity; - awe_calc_volume(voice); - if (voices[voice].state == AWE_ST_STANDBY) - awe_note_on(voice); - else if (voices[voice].state == AWE_ST_ON) - awe_set_volume(voice, FALSE); -} - -static void set_and_start_voice(int voice, int state) -{ - /* calculate pitch & volume parameters */ - voices[voice].state = state; - awe_calc_pitch(voice); - awe_calc_volume(voice); - if (state == AWE_ST_ON) - awe_note_on(voice); -} - -/* start a voice: - * if note is 255, identical with aftertouch function. - * Otherwise, start a voice with specified not and volume. - */ -static int -awe_start_note(int dev, int voice, int note, int velocity) -{ - int i, key, state, volonly; - - AWE_DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", voice, note, velocity)); - if (! voice_in_range(voice)) - return RET_ERROR(EINVAL); - - if (velocity == 0) - state = AWE_ST_STANDBY; /* stand by for playing */ - else - state = AWE_ST_ON; /* really play */ - volonly = FALSE; - - switch (playing_mode) { - case AWE_PLAY_DIRECT: - case AWE_PLAY_INDIRECT: - key = AWE_VOICE_KEY(voice); - if (note == 255) - volonly = TRUE; - break; - - case AWE_PLAY_MULTI2: - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return RET_ERROR(EINVAL); - /* continue to below */ - default: - if (note >= 128) { /* key volume mode */ - note -= 128; - volonly = TRUE; - } - key = AWE_CHAN_KEY(voice, note); - break; - } - - /* dynamic volume change */ - if (volonly) { - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].key == key) - start_or_volume_change(i, velocity); - } - return 0; - } - - /* if the same note still playing, stop it */ - for (i = 0; i < awe_max_voices; i++) - if (voices[i].key == key) { - if (voices[i].state == AWE_ST_ON) { - awe_note_off(i); - awe_voice_init(i, FALSE); - } else if (voices[i].state == AWE_ST_STANDBY) - awe_voice_init(i, TRUE); - } - - /* allocate voices */ - if (playing_mode == AWE_PLAY_DIRECT) - awe_alloc_one_voice(voice, note, velocity); - else - awe_alloc_multi_voices(voice, note, velocity, key); - - /* turn off other voices exlusively (for drums) */ - for (i = 0; i < awe_max_voices; i++) - if (voices[i].key == key) - awe_exclusive_off(i); - - /* set up pitch and volume parameters */ - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].key == key && voices[i].state == AWE_ST_OFF) - set_and_start_voice(i, state); - } - - return 0; -} - - -/* search instrument from preset table with the specified bank */ -static int -awe_search_instr(int bank, int preset) -{ - int i; - - for (i = preset_table[preset]; i >= 0; i = infos[i].next_bank) { - if (infos[i].bank == bank) - return i; - } - return -1; -} - - -/* assign the instrument to a voice */ -static int -awe_set_instr_2(int dev, int voice, int instr_no) -{ - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return RET_ERROR(EINVAL); - } - return awe_set_instr(dev, voice, instr_no); -} - -/* assign the instrument to a channel; voice is the channel number */ -static int -awe_set_instr(int dev, int voice, int instr_no) -{ - awe_chan_info *cinfo; - int def_bank; - - if (! voice_in_range(voice)) - return RET_ERROR(EINVAL); - - if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS) - return RET_ERROR(EINVAL); - - cinfo = &channels[voice]; - - if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice)) - def_bank = AWE_DRUM_BANK; /* always search drumset */ - else - def_bank = cinfo->bank; - - cinfo->vrec = -1; - cinfo->def_vrec = -1; - cinfo->vrec = awe_search_instr(def_bank, instr_no); - if (def_bank == AWE_DRUM_BANK) /* search default drumset */ - cinfo->def_vrec = awe_search_instr(def_bank, misc_modes[AWE_MD_DEF_DRUM]); - else /* search default preset */ - cinfo->def_vrec = awe_search_instr(misc_modes[AWE_MD_DEF_BANK], instr_no); - - if (cinfo->vrec < 0 && cinfo->def_vrec < 0) { - AWE_DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no)); - } - - cinfo->instr = instr_no; - - return 0; -} - - -/* reset all voices; terminate sounds and initialize parameters */ -static void -awe_reset(int dev) -{ - int i; - current_alloc_time = 0; - /* don't turn off voice 31 and 32. they are used also for FM voices */ - for (i = 0; i < awe_max_voices; i++) { - awe_terminate(i); - awe_voice_init(i, TRUE); - } - for (i = 0; i < AWE_MAX_CHANNELS; i++) - awe_channel_init(i, TRUE); - for (i = 0; i < 16; i++) { - awe_operations.chn_info[i].controllers[CTL_MAIN_VOLUME] = 127; - awe_operations.chn_info[i].controllers[CTL_EXPRESSION] = 127; - } - awe_init_fm(); - awe_tweak(); -} - - -/* hardware specific control: - * GUS specific and AWE32 specific controls are available. - */ -static void -awe_hw_control(int dev, unsigned char *event) -{ - int cmd = event[2]; - if (cmd & _AWE_MODE_FLAG) - awe_hw_awe_control(dev, cmd & _AWE_MODE_VALUE_MASK, event); -#ifdef AWE_HAS_GUS_COMPATIBILITY - else - awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event); -#endif -} - - -#ifdef AWE_HAS_GUS_COMPATIBILITY - -/* GUS compatible controls */ -static void -awe_hw_gus_control(int dev, int cmd, unsigned char *event) -{ - int voice, i, key; - unsigned short p1; - short p2; - int plong; - - if (MULTI_LAYER_MODE()) - return; - if (cmd == _GUS_NUMVOICES) - return; - - voice = event[3]; - if (! voice_in_range(voice)) - return; - - p1 = *(unsigned short *) &event[4]; - p2 = *(short *) &event[6]; - plong = *(int*) &event[4]; - - switch (cmd) { - case _GUS_VOICESAMPLE: - awe_set_instr(dev, voice, p1); - return; - - case _GUS_VOICEBALA: - /* 0 to 15 --> -128 to 127 */ - awe_panning(dev, voice, ((int)p1 << 4) - 128); - return; - - case _GUS_VOICEVOL: - case _GUS_VOICEVOL2: - /* not supported yet */ - return; - - case _GUS_RAMPRANGE: - case _GUS_RAMPRATE: - case _GUS_RAMPMODE: - case _GUS_RAMPON: - case _GUS_RAMPOFF: - /* volume ramping not supported */ - return; - - case _GUS_VOLUME_SCALE: - return; - - case _GUS_VOICE_POS: - FX_SET(&channels[voice].fx, AWE_FX_SAMPLE_START, - (short)(plong & 0x7fff)); - FX_SET(&channels[voice].fx, AWE_FX_COARSE_SAMPLE_START, - (plong >> 15) & 0xffff); - return; - } - - key = AWE_VOICE_KEY(voice); - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].key == key) { - switch (cmd) { - case _GUS_VOICEON: - awe_note_on(i); - break; - - case _GUS_VOICEOFF: - awe_terminate(i); - awe_fx_init(voices[i].ch); - awe_voice_init(i, TRUE); - break; - - case _GUS_VOICEFADE: - awe_note_off(i); - awe_fx_init(voices[i].ch); - awe_voice_init(i, FALSE); - break; - - case _GUS_VOICEFREQ: - awe_calc_pitch_from_freq(i, plong); - break; - } - } - } -} - -#endif - - -/* AWE32 specific controls */ -static void -awe_hw_awe_control(int dev, int cmd, unsigned char *event) -{ - int voice; - unsigned short p1; - short p2; - awe_chan_info *cinfo; - FX_Rec *fx; - int i; - - voice = event[3]; - if (! voice_in_range(voice)) - return; - - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return; - } - - p1 = *(unsigned short *) &event[4]; - p2 = *(short *) &event[6]; - cinfo = &channels[voice]; - - switch (cmd) { - case _AWE_DEBUG_MODE: - debug_mode = p1; - printk("AWE32: debug mode = %d\n", debug_mode); - break; - case _AWE_REVERB_MODE: - awe_set_reverb_mode(p1); - break; - - case _AWE_CHORUS_MODE: - awe_set_chorus_mode(p1); - break; - - case _AWE_REMOVE_LAST_SAMPLES: - AWE_DEBUG(0,printk("AWE32: remove last samples\n")); - if (locked_sf_id > 0) - awe_remove_samples(locked_sf_id); - break; - - case _AWE_INITIALIZE_CHIP: - awe_initialize(); - break; - - case _AWE_SEND_EFFECT: - fx = &cinfo->fx; - i = FX_FLAG_SET; - if (p1 >= 0x100) { - int layer = (p1 >> 8); - if (layer >= 0 && layer < MAX_LAYERS) - fx = &cinfo->fx_layer[layer]; - p1 &= 0xff; - } - if (p1 & 0x40) i = FX_FLAG_OFF; - if (p1 & 0x80) i = FX_FLAG_ADD; - p1 &= 0x3f; - if (p1 < AWE_FX_END) { - AWE_DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, p2)); - if (i == FX_FLAG_SET) - FX_SET(fx, p1, p2); - else if (i == FX_FLAG_ADD) - FX_ADD(fx, p1, p2); - else - FX_UNSET(fx, p1); - if (i != FX_FLAG_OFF && parm_defs[p1].realtime) { - AWE_DEBUG(0,printk("AWE32: fx_realtime (%d)\n", voice)); - awe_voice_change(voice, parm_defs[p1].realtime); - } - } - break; - - case _AWE_RESET_CHANNEL: - awe_channel_init(voice, !p1); - break; - - case _AWE_TERMINATE_ALL: - awe_reset(0); - break; - - case _AWE_TERMINATE_CHANNEL: - awe_voice_change(voice, awe_terminate_and_init); - break; - - case _AWE_RELEASE_ALL: - awe_note_off_all(FALSE); - break; - case _AWE_NOTEOFF_ALL: - awe_note_off_all(TRUE); - break; - - case _AWE_INITIAL_VOLUME: - AWE_DEBUG(0,printk("AWE32: init attenuation %d\n", p1)); - if (p2 == 0) /* absolute value */ - init_atten = (short)p1; - else /* relative value */ - init_atten = misc_modes[AWE_MD_ZERO_ATTEN] + (short)p1; - if (init_atten < 0) init_atten = 0; - for (i = 0; i < awe_max_voices; i++) - awe_set_voice_vol(i, TRUE); - break; - - case _AWE_CHN_PRESSURE: - cinfo->chan_press = p1; - p1 = p1 * misc_modes[AWE_MD_MOD_SENSE] / 1200; - FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, p1); - awe_voice_change(voice, awe_fx_fmmod); - FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, p1); - awe_voice_change(voice, awe_fx_fm2frq2); - break; - - case _AWE_CHANNEL_MODE: - AWE_DEBUG(0,printk("AWE32: channel mode = %d\n", p1)); - playing_mode = p1; - awe_reset(0); - break; - - case _AWE_DRUM_CHANNELS: - AWE_DEBUG(0,printk("AWE32: drum flags = %x\n", p1)); - drum_flags = *(unsigned int*)&event[4]; - break; - - case _AWE_MISC_MODE: - AWE_DEBUG(0,printk("AWE32: misc mode = %d %d\n", p1, p2)); - if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END) - misc_modes[p1] = p2; - break; - - case _AWE_EQUALIZER: - awe_equalizer((int)p1, (int)p2); - break; - - default: - AWE_DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice)); - break; - } -} - - -/* voice pressure change */ -static void -awe_aftertouch(int dev, int voice, int pressure) -{ - int note; - - AWE_DEBUG(2,printk("AWE32: [after(%d) %d]\n", voice, pressure)); - if (! voice_in_range(voice)) - return; - - switch (playing_mode) { - case AWE_PLAY_DIRECT: - case AWE_PLAY_INDIRECT: - awe_start_note(dev, voice, 255, pressure); - break; - case AWE_PLAY_MULTI2: - note = (voice_alloc->map[voice] & 0xff) - 1; - awe_start_note(dev, voice, note + 0x80, pressure); - break; - } -} - - -/* voice control change */ -static void -awe_controller(int dev, int voice, int ctrl_num, int value) -{ - int i; - awe_chan_info *cinfo; - - if (! voice_in_range(voice)) - return; - - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return; - } - - cinfo = &channels[voice]; - - switch (ctrl_num) { - case CTL_BANK_SELECT: /* MIDI control #0 */ - AWE_DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value)); - if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice) && - !misc_modes[AWE_MD_TOGGLE_DRUM_BANK]) - break; - cinfo->bank = value; - if (cinfo->bank == AWE_DRUM_BANK) - DRUM_CHANNEL_ON(cinfo->channel); - else - DRUM_CHANNEL_OFF(cinfo->channel); - awe_set_instr(dev, voice, cinfo->instr); - break; - - case CTL_MODWHEEL: /* MIDI control #1 */ - AWE_DEBUG(2,printk("AWE32: [modwheel(%d) %d]\n", voice, value)); - i = value * misc_modes[AWE_MD_MOD_SENSE] / 1200; - FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i); - awe_voice_change(voice, awe_fx_fmmod); - FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i); - awe_voice_change(voice, awe_fx_fm2frq2); - break; - - case CTRL_PITCH_BENDER: /* SEQ1 V2 contorl */ - AWE_DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, value)); - /* zero centered */ - cinfo->bender = value; - awe_voice_change(voice, awe_set_voice_pitch); - break; - - case CTRL_PITCH_BENDER_RANGE: /* SEQ1 V2 control */ - AWE_DEBUG(2,printk("AWE32: [range(%d) %d]\n", voice, value)); - /* value = sense x 100 */ - cinfo->bender_range = value; - /* no audible pitch change yet.. */ - break; - - case CTL_EXPRESSION: /* MIDI control #11 */ - if (SINGLE_LAYER_MODE()) - value /= 128; - case CTRL_EXPRESSION: /* SEQ1 V2 control */ - AWE_DEBUG(2,printk("AWE32: [expr(%d) %d]\n", voice, value)); - /* 0 - 127 */ - cinfo->expression_vol = value; - awe_voice_change(voice, awe_set_voice_vol); - break; - - case CTL_PAN: /* MIDI control #10 */ - AWE_DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value)); - /* (0-127) -> signed 8bit */ - cinfo->panning = value * 2 - 128; - if (misc_modes[AWE_MD_REALTIME_PAN]) - awe_voice_change(voice, awe_set_pan); - break; - - case CTL_MAIN_VOLUME: /* MIDI control #7 */ - if (SINGLE_LAYER_MODE()) - value = (value * 100) / 16383; - case CTRL_MAIN_VOLUME: /* SEQ1 V2 control */ - AWE_DEBUG(2,printk("AWE32: [mainvol(%d) %d]\n", voice, value)); - /* 0 - 127 */ - cinfo->main_vol = value; - awe_voice_change(voice, awe_set_voice_vol); - break; - - case CTL_EXT_EFF_DEPTH: /* reverb effects: 0-127 */ - AWE_DEBUG(2,printk("AWE32: [reverb(%d) %d]\n", voice, value)); - FX_SET(&cinfo->fx, AWE_FX_REVERB, value * 2); - break; - - case CTL_CHORUS_DEPTH: /* chorus effects: 0-127 */ - AWE_DEBUG(2,printk("AWE32: [chorus(%d) %d]\n", voice, value)); - FX_SET(&cinfo->fx, AWE_FX_CHORUS, value * 2); - break; - -#ifdef AWE_ACCEPT_ALL_SOUNDS_CONTROLL - case 120: /* all sounds off */ - awe_note_off_all(FALSE); - break; - case 123: /* all notes off */ - awe_note_off_all(TRUE); - break; -#endif - - case CTL_SUSTAIN: /* MIDI control #64 */ - cinfo->sustained = value; - if (value != 127) - awe_voice_change(voice, awe_sustain_off); - break; - - case CTL_SOSTENUTO: /* MIDI control #66 */ - if (value == 127) - awe_voice_change(voice, awe_sostenuto_on); - else - awe_voice_change(voice, awe_sustain_off); - break; - - default: - AWE_DEBUG(0,printk("AWE32: [control(%d) ctrl=%d val=%d]\n", - voice, ctrl_num, value)); - break; - } -} - - -/* voice pan change (value = -128 - 127) */ -static void -awe_panning(int dev, int voice, int value) -{ - awe_chan_info *cinfo; - - if (! voice_in_range(voice)) - return; - - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return; - } - - cinfo = &channels[voice]; - cinfo->panning = value; - AWE_DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, cinfo->panning)); - if (misc_modes[AWE_MD_REALTIME_PAN]) - awe_voice_change(voice, awe_set_pan); -} - - -/* volume mode change */ -static void -awe_volume_method(int dev, int mode) -{ - /* not impremented */ - AWE_DEBUG(0,printk("AWE32: [volmethod mode=%d]\n", mode)); -} - - -#ifndef AWE_NO_PATCHMGR -/* patch manager */ -static int -awe_patchmgr(int dev, struct patmgr_info *rec) -{ - printk("AWE32 Warning: patch manager control not supported\n"); - return 0; -} -#endif - - -/* pitch wheel change: 0-16384 */ -static void -awe_bender(int dev, int voice, int value) -{ - awe_chan_info *cinfo; - - if (! voice_in_range(voice)) - return; - - if (playing_mode == AWE_PLAY_MULTI2) { - voice = voice_alloc->map[voice] >> 8; - if (voice < 0 || voice >= AWE_MAX_CHANNELS) - return; - } - - /* convert to zero centered value */ - cinfo = &channels[voice]; - cinfo->bender = value - 8192; - AWE_DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, cinfo->bender)); - awe_voice_change(voice, awe_set_voice_pitch); -} - - -/*---------------------------------------------------------------- - * load a sound patch: - * three types of patches are accepted: AWE, GUS, and SYSEX. - *----------------------------------------------------------------*/ - -static int -awe_load_patch(int dev, int format, const char *addr, - int offs, int count, int pmgr_flag) -{ - awe_patch_info patch; - int rc = 0; - -#ifdef AWE_HAS_GUS_COMPATIBILITY - if (format == GUS_PATCH) { - return awe_load_guspatch(addr, offs, count, pmgr_flag); - } else -#endif - if (format == SYSEX_PATCH) { - /* no system exclusive message supported yet */ - return 0; - } else if (format != AWE_PATCH) { - printk("AWE32 Error: Invalid patch format (key) 0x%x\n", format); - return RET_ERROR(EINVAL); - } - - if (count < AWE_PATCH_INFO_SIZE) { - printk("AWE32 Error: Patch header too short\n"); - return RET_ERROR(EINVAL); - } - COPY_FROM_USER(((char*)&patch) + offs, addr, offs, - AWE_PATCH_INFO_SIZE - offs); - - count -= AWE_PATCH_INFO_SIZE; - if (count < patch.len) { - printk("AWE32: sample: Patch record too short (%d<%d)\n", - count, patch.len); - return RET_ERROR(EINVAL); - } - - switch (patch.type) { - case AWE_LOAD_INFO: - rc = awe_load_info(&patch, addr, count); - break; - case AWE_LOAD_DATA: - rc = awe_load_data(&patch, addr, count); - break; - case AWE_OPEN_PATCH: - rc = awe_open_patch(&patch, addr, count); - break; - case AWE_CLOSE_PATCH: - rc = awe_close_patch(&patch, addr, count); - break; - case AWE_UNLOAD_PATCH: - rc = awe_unload_patch(&patch, addr, count); - break; - case AWE_REPLACE_DATA: - rc = awe_replace_data(&patch, addr, count); - break; - case AWE_MAP_PRESET: - rc = awe_load_map(&patch, addr, count); - break; - case AWE_LOAD_CHORUS_FX: - rc = awe_load_chorus_fx(&patch, addr, count); - break; - case AWE_LOAD_REVERB_FX: - rc = awe_load_reverb_fx(&patch, addr, count); - break; - - default: - printk("AWE32 Error: unknown patch format type %d\n", - patch.type); - rc = RET_ERROR(EINVAL); - } - - return rc; -} - - -/* create an sflist record */ -static int -awe_create_sf(int type, char *name) -{ - sf_list *rec; - - /* terminate sounds */ - awe_reset(0); - if (current_sf_id >= max_sfs) { - int newsize = max_sfs + AWE_MAX_SF_LISTS; - sf_list *newlist = my_realloc(sflists, sizeof(sf_list)*max_sfs, - sizeof(sf_list)*newsize); - if (newlist == NULL) - return 1; - sflists = newlist; - max_sfs = newsize; - } - rec = &sflists[current_sf_id]; - rec->sf_id = current_sf_id + 1; - rec->type = type; - if (current_sf_id == 0 || (type & AWE_PAT_LOCKED) != 0) - locked_sf_id = current_sf_id + 1; - /* - if (name) - MEMCPY(rec->name, name, AWE_PATCH_NAME_LEN); - else - BZERO(rec->name, AWE_PATCH_NAME_LEN); - */ - rec->num_info = awe_free_info(); - rec->num_sample = awe_free_sample(); - rec->mem_ptr = awe_free_mem_ptr(); - rec->infos = -1; - rec->samples = -1; - - current_sf_id++; - return 0; -} - - -/* open patch; create sf list and set opened flag */ -static int -awe_open_patch(awe_patch_info *patch, const char *addr, int count) -{ - awe_open_parm parm; - COPY_FROM_USER(&parm, addr, AWE_PATCH_INFO_SIZE, sizeof(parm)); - if (awe_create_sf(parm.type, parm.name)) { - printk("AWE32: can't open: failed to alloc new list\n"); - return RET_ERROR(ENOSPC); - } - patch_opened = TRUE; - return current_sf_id; -} - -/* check if the patch is already opened */ -static int -check_patch_opened(int type, char *name) -{ - if (! patch_opened) { - if (awe_create_sf(type, name)) { - printk("AWE32: failed to alloc new list\n"); - return RET_ERROR(ENOSPC); - } - patch_opened = TRUE; - return current_sf_id; - } - return current_sf_id; -} - -/* close the patch; if no voice is loaded, remove the patch */ -static int -awe_close_patch(awe_patch_info *patch, const char *addr, int count) -{ - if (patch_opened && current_sf_id > 0) { - /* if no voice is loaded, release the current patch */ - if (sflists[current_sf_id-1].infos == -1) - awe_remove_samples(current_sf_id - 1); - } - patch_opened = 0; - return 0; -} - - -/* remove the latest patch */ -static int -awe_unload_patch(awe_patch_info *patch, const char *addr, int count) -{ - if (current_sf_id > 0) - awe_remove_samples(current_sf_id - 1); - return 0; -} - -/* allocate voice info list records */ -static int alloc_new_info(int nvoices) -{ - int newsize, free_info; - awe_voice_list *newlist; - free_info = awe_free_info(); - if (free_info + nvoices >= max_infos) { - do { - newsize = max_infos + AWE_MAX_INFOS; - } while (free_info + nvoices >= newsize); - newlist = my_realloc(infos, sizeof(awe_voice_list)*max_infos, - sizeof(awe_voice_list)*newsize); - if (newlist == NULL) { - printk("AWE32: can't alloc info table\n"); - return RET_ERROR(ENOSPC); - } - infos = newlist; - max_infos = newsize; - } - return 0; -} - -/* allocate sample info list records */ -static int alloc_new_sample(void) -{ - int newsize, free_sample; - awe_sample_list *newlist; - free_sample = awe_free_sample(); - if (free_sample >= max_samples) { - newsize = max_samples + AWE_MAX_SAMPLES; - newlist = my_realloc(samples, - sizeof(awe_sample_list)*max_samples, - sizeof(awe_sample_list)*newsize); - if (newlist == NULL) { - printk("AWE32: can't alloc sample table\n"); - return RET_ERROR(ENOSPC); - } - samples = newlist; - max_samples = newsize; - } - return 0; -} - -/* load voice map */ -static int -awe_load_map(awe_patch_info *patch, const char *addr, int count) -{ - awe_voice_map map; - awe_voice_list *rec; - int free_info; - - if (check_patch_opened(AWE_PAT_TYPE_MAP, NULL) < 0) - return RET_ERROR(ENOSPC); - if (alloc_new_info(1) < 0) - return RET_ERROR(ENOSPC); - - COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map)); - - free_info = awe_free_info(); - rec = &infos[free_info]; - rec->bank = map.map_bank; - rec->instr = map.map_instr; - rec->type = V_ST_MAPPED; - rec->disabled = FALSE; - awe_init_voice_info(&rec->v); - if (map.map_key >= 0) { - rec->v.low = map.map_key; - rec->v.high = map.map_key; - } - rec->v.start = map.src_instr; - rec->v.end = map.src_bank; - rec->v.fixkey = map.src_key; - rec->v.sf_id = current_sf_id; - add_info_list(free_info); - add_sf_info(free_info); - - return 0; -} - -/* load voice information data */ -static int -awe_load_info(awe_patch_info *patch, const char *addr, int count) -{ - int offset; - awe_voice_rec_hdr hdr; - int i; - int total_size; - - if (count < AWE_VOICE_REC_SIZE) { - printk("AWE32 Error: invalid patch info length\n"); - return RET_ERROR(EINVAL); - } - - offset = AWE_PATCH_INFO_SIZE; - COPY_FROM_USER((char*)&hdr, addr, offset, AWE_VOICE_REC_SIZE); - offset += AWE_VOICE_REC_SIZE; - - if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { - printk("AWE32 Error: Illegal voice number %d\n", hdr.nvoices); - return RET_ERROR(EINVAL); - } - total_size = AWE_VOICE_REC_SIZE + AWE_VOICE_INFO_SIZE * hdr.nvoices; - if (count < total_size) { - printk("AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n", - count, hdr.nvoices); - return RET_ERROR(EINVAL); - } - - if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0) - return RET_ERROR(ENOSPC); - -#if 0 /* it looks like not so useful.. */ - /* check if the same preset already exists in the info list */ - for (i = sflists[current_sf_id-1].infos; i >= 0; i = infos[i].next) { - if (infos[i].disabled) continue; - if (infos[i].bank == hdr.bank && infos[i].instr == hdr.instr) { - /* in exclusive mode, do skip loading this */ - if (hdr.write_mode == AWE_WR_EXCLUSIVE) - return 0; - /* in replace mode, disable the old data */ - else if (hdr.write_mode == AWE_WR_REPLACE) - infos[i].disabled = TRUE; - } - } - if (hdr.write_mode == AWE_WR_REPLACE) - rebuild_preset_list(); -#endif - - if (alloc_new_info(hdr.nvoices) < 0) - return RET_ERROR(ENOSPC); - - for (i = 0; i < hdr.nvoices; i++) { - int rec = awe_free_info(); - - infos[rec].bank = hdr.bank; - infos[rec].instr = hdr.instr; - infos[rec].type = V_ST_NORMAL; - infos[rec].disabled = FALSE; - - /* copy awe_voice_info parameters */ - COPY_FROM_USER(&infos[rec].v, addr, offset, AWE_VOICE_INFO_SIZE); - offset += AWE_VOICE_INFO_SIZE; - infos[rec].v.sf_id = current_sf_id; - if (infos[rec].v.mode & AWE_MODE_INIT_PARM) - awe_init_voice_parm(&infos[rec].v.parm); - awe_set_sample(&infos[rec].v); - add_info_list(rec); - add_sf_info(rec); - } - - return 0; -} - -/* load wave sample data */ -static int -awe_load_data(awe_patch_info *patch, const char *addr, int count) -{ - int offset, size; - int rc, free_sample; - awe_sample_info *rec; - - if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0) - return RET_ERROR(ENOSPC); - - if (alloc_new_sample() < 0) - return RET_ERROR(ENOSPC); - - free_sample = awe_free_sample(); - rec = &samples[free_sample].v; - - size = (count - AWE_SAMPLE_INFO_SIZE) / 2; - offset = AWE_PATCH_INFO_SIZE; - COPY_FROM_USER(rec, addr, offset, AWE_SAMPLE_INFO_SIZE); - offset += AWE_SAMPLE_INFO_SIZE; - if (size != rec->size) { - printk("AWE32: load: sample size differed (%d != %d)\n", - rec->size, size); - return RET_ERROR(EINVAL); - } - if (rec->size > 0) - if ((rc = awe_write_wave_data(addr, offset, rec, -1)) != 0) - return rc; - - rec->sf_id = current_sf_id; - - add_sf_sample(free_sample); - - return 0; -} - - -/* replace wave sample data */ -static int -awe_replace_data(awe_patch_info *patch, const char *addr, int count) -{ - int offset; - int size; - int rc, i; - int channels; - awe_sample_info cursmp; - int save_mem_ptr; - - if (! patch_opened) { - printk("AWE32: replace: patch not opened\n"); - return RET_ERROR(EINVAL); - } - - size = (count - AWE_SAMPLE_INFO_SIZE) / 2; - offset = AWE_PATCH_INFO_SIZE; - COPY_FROM_USER(&cursmp, addr, offset, AWE_SAMPLE_INFO_SIZE); - offset += AWE_SAMPLE_INFO_SIZE; - if (cursmp.size == 0 || size != cursmp.size) { - printk("AWE32: replace: illegal sample size (%d!=%d)\n", - cursmp.size, size); - return RET_ERROR(EINVAL); - } - channels = patch->optarg; - if (channels <= 0 || channels > AWE_NORMAL_VOICES) { - printk("AWE32: replace: illegal channels %d\n", channels); - return RET_ERROR(EINVAL); - } - - for (i = sflists[current_sf_id-1].samples; - i >= 0; i = samples[i].next) { - if (samples[i].v.sample == cursmp.sample) - break; - } - if (i < 0) { - printk("AWE32: replace: cannot find existing sample data %d\n", - cursmp.sample); - return RET_ERROR(EINVAL); - } - - if (samples[i].v.size != cursmp.size) { - printk("AWE32: replace: exiting size differed (%d!=%d)\n", - samples[i].v.size, cursmp.size); - return RET_ERROR(EINVAL); - } - - save_mem_ptr = awe_free_mem_ptr(); - sflists[current_sf_id-1].mem_ptr = samples[i].v.start - awe_mem_start; - MEMCPY(&samples[i].v, &cursmp, sizeof(cursmp)); - if ((rc = awe_write_wave_data(addr, offset, &samples[i].v, channels)) != 0) - return rc; - sflists[current_sf_id-1].mem_ptr = save_mem_ptr; - samples[i].v.sf_id = current_sf_id; - - return 0; -} - - -/*----------------------------------------------------------------*/ - -static const char *readbuf_addr; -static int readbuf_offs; -static int readbuf_flags; -#if defined(__DragonFly__) || defined(__FreeBSD__) -static unsigned short *readbuf_loop; -static int readbuf_loopstart, readbuf_loopend; -#endif - -/* initialize read buffer */ -static int -readbuf_init(const char *addr, int offset, awe_sample_info *sp) -{ -#if defined(__DragonFly__) || defined(__FreeBSD__) - readbuf_loop = NULL; - readbuf_loopstart = sp->loopstart; - readbuf_loopend = sp->loopend; - if (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) { - int looplen = sp->loopend - sp->loopstart; - readbuf_loop = my_malloc(looplen * 2); - if (readbuf_loop == NULL) { - printk("AWE32: can't malloc temp buffer\n"); - return RET_ERROR(ENOSPC); - } - } -#endif - readbuf_addr = addr; - readbuf_offs = offset; - readbuf_flags = sp->mode_flags; - return 0; -} - -/* read directly from user buffer */ -static unsigned short -readbuf_word(int pos) -{ - unsigned short c; - /* read from user buffer */ - if (readbuf_flags & AWE_SAMPLE_8BITS) { - unsigned char cc; - GET_BYTE_FROM_USER(cc, readbuf_addr, readbuf_offs + pos); - c = cc << 8; /* convert 8bit -> 16bit */ - } else { - GET_SHORT_FROM_USER(c, readbuf_addr, readbuf_offs + pos * 2); - } - if (readbuf_flags & AWE_SAMPLE_UNSIGNED) - c ^= 0x8000; /* unsigned -> signed */ -#if defined(__DragonFly__) || defined(__FreeBSD__) - /* write on cache for reverse loop */ - if (readbuf_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) { - if (pos >= readbuf_loopstart && pos < readbuf_loopend) - readbuf_loop[pos - readbuf_loopstart] = c; - } -#endif - return c; -} - -#if defined(__DragonFly__) || defined(__FreeBSD__) -/* read from cache */ -static unsigned short -readbuf_word_cache(int pos) -{ - if (pos >= readbuf_loopstart && pos < readbuf_loopend) - return readbuf_loop[pos - readbuf_loopstart]; - return 0; -} - -static void -readbuf_end(void) -{ - if (readbuf_loop) { - my_free(readbuf_loop); - } - readbuf_loop = NULL; -} - -#else - -#define readbuf_word_cache readbuf_word -#define readbuf_end() /**/ - -#endif - -/*----------------------------------------------------------------*/ - -#define BLANK_LOOP_START 8 -#define BLANK_LOOP_END 40 -#define BLANK_LOOP_SIZE 48 - -/* loading onto memory */ -static int -awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels) -{ - int i, truesize, dram_offset; - int rc; - - /* be sure loop points start < end */ - if (sp->loopstart > sp->loopend) { - int tmp = sp->loopstart; - sp->loopstart = sp->loopend; - sp->loopend = tmp; - } - - /* compute true data size to be loaded */ - truesize = sp->size; - if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP) - truesize += sp->loopend - sp->loopstart; - if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) - truesize += BLANK_LOOP_SIZE; - if (awe_free_mem_ptr() + truesize >= awe_mem_size/2) { - printk("AWE32 Error: Sample memory full\n"); - return RET_ERROR(ENOSPC); - } - - /* recalculate address offset */ - sp->end -= sp->start; - sp->loopstart -= sp->start; - sp->loopend -= sp->start; - - dram_offset = awe_free_mem_ptr() + awe_mem_start; - sp->start = dram_offset; - sp->end += dram_offset; - sp->loopstart += dram_offset; - sp->loopend += dram_offset; - - /* set the total size (store onto obsolete checksum value) */ - if (sp->size == 0) - sp->checksum = 0; - else - sp->checksum = truesize; - - if ((rc = awe_open_dram_for_write(dram_offset, channels)) != 0) - return rc; - - if (readbuf_init(addr, offset, sp) < 0) - return RET_ERROR(ENOSPC); - - for (i = 0; i < sp->size; i++) { - unsigned short c; - c = readbuf_word(i); - awe_write_dram(c); - if (i == sp->loopend && - (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP))) { - int looplen = sp->loopend - sp->loopstart; - /* copy reverse loop */ - int k; - for (k = 1; k <= looplen; k++) { - c = readbuf_word_cache(i - k); - awe_write_dram(c); - } - if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP) { - sp->end += looplen; - } else { - sp->start += looplen; - sp->end += looplen; - } - } - } - readbuf_end(); - - /* if no blank loop is attached in the sample, add it */ - if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) { - for (i = 0; i < BLANK_LOOP_SIZE; i++) - awe_write_dram(0); - if (sp->mode_flags & AWE_SAMPLE_SINGLESHOT) { - sp->loopstart = sp->end + BLANK_LOOP_START; - sp->loopend = sp->end + BLANK_LOOP_END; - } - } - - sflists[current_sf_id-1].mem_ptr += truesize; - awe_close_dram(); - - /* initialize FM */ - awe_init_fm(); - - return 0; -} - - -/*----------------------------------------------------------------*/ - -#ifdef AWE_HAS_GUS_COMPATIBILITY - -/* calculate GUS envelope time: - * is this correct? i have no idea.. - */ -static int -calc_gus_envelope_time(int rate, int start, int end) -{ - int r, p, t; - r = (3 - ((rate >> 6) & 3)) * 3; - p = rate & 0x3f; - t = end - start; - if (t < 0) t = -t; - if (13 > r) - t = t << (13 - r); - else - t = t >> (r - 13); - return (t * 10) / (p * 441); -} - -#define calc_gus_sustain(val) (0x7f - vol_table[(val)/2]) -#define calc_gus_attenuation(val) vol_table[(val)/2] - -/* load GUS patch */ -static int -awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag) -{ - struct patch_info patch; - awe_voice_info *rec; - awe_sample_info *smp; - int sizeof_patch; - int note, free_sample, free_info; - int rc; - - sizeof_patch = offsetof(struct patch_info, data); /* header size */ - if (size < sizeof_patch) { - printk("AWE32 Error: Patch header too short\n"); - return RET_ERROR(EINVAL); - } - COPY_FROM_USER(((char*)&patch) + offs, addr, offs, sizeof_patch - offs); - size -= sizeof_patch; - if (size < patch.len) { - printk("AWE32 Warning: Patch record too short (%d<%ld)\n", - size, patch.len); - return RET_ERROR(EINVAL); - } - if (check_patch_opened(AWE_PAT_TYPE_GUS, NULL) < 0) - return RET_ERROR(ENOSPC); - if (alloc_new_sample() < 0) - return RET_ERROR(ENOSPC); - if (alloc_new_info(1)) - return RET_ERROR(ENOSPC); - - free_sample = awe_free_sample(); - smp = &samples[free_sample].v; - - smp->sample = free_sample; - smp->start = 0; - smp->end = patch.len; - smp->loopstart = patch.loop_start; - smp->loopend = patch.loop_end; - smp->size = patch.len; - - /* set up mode flags */ - smp->mode_flags = 0; - if (!(patch.mode & WAVE_16_BITS)) - smp->mode_flags |= AWE_SAMPLE_8BITS; - if (patch.mode & WAVE_UNSIGNED) - smp->mode_flags |= AWE_SAMPLE_UNSIGNED; - smp->mode_flags |= AWE_SAMPLE_NO_BLANK; - if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK))) - smp->mode_flags |= AWE_SAMPLE_SINGLESHOT; - if (patch.mode & WAVE_BIDIR_LOOP) - smp->mode_flags |= AWE_SAMPLE_BIDIR_LOOP; - if (patch.mode & WAVE_LOOP_BACK) - smp->mode_flags |= AWE_SAMPLE_REVERSE_LOOP; - - AWE_DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no, smp->mode_flags)); - if (patch.mode & WAVE_16_BITS) { - /* convert to word offsets */ - smp->size /= 2; - smp->end /= 2; - smp->loopstart /= 2; - smp->loopend /= 2; - } - smp->checksum_flag = 0; - smp->checksum = 0; - - if ((rc = awe_write_wave_data(addr, sizeof_patch, smp, -1)) != 0) - return rc; - - smp->sf_id = current_sf_id; - add_sf_sample(free_sample); - - /* set up voice info */ - free_info = awe_free_info(); - rec = &infos[free_info].v; - awe_init_voice_info(rec); - rec->sample = free_sample; /* the last sample */ - rec->rate_offset = calc_rate_offset(patch.base_freq); - note = freq_to_note(patch.base_note); - rec->root = note / 100; - rec->tune = -(note % 100); - rec->low = freq_to_note(patch.low_note) / 100; - rec->high = freq_to_note(patch.high_note) / 100; - AWE_DEBUG(1,printk("AWE32: [gus base offset=%d, note=%d, range=%d-%d(%lu-%lu)]\n", - rec->rate_offset, note, - rec->low, rec->high, - patch.low_note, patch.high_note)); - /* panning position; -128 - 127 => 0-127 */ - rec->pan = (patch.panning + 128) / 2; - - /* detuning is ignored */ - /* 6points volume envelope */ - if (patch.mode & WAVE_ENVELOPES) { - int attack, hold, decay, release; - attack = calc_gus_envelope_time - (patch.env_rate[0], 0, patch.env_offset[0]); - hold = calc_gus_envelope_time - (patch.env_rate[1], patch.env_offset[0], - patch.env_offset[1]); - decay = calc_gus_envelope_time - (patch.env_rate[2], patch.env_offset[1], - patch.env_offset[2]); - release = calc_gus_envelope_time - (patch.env_rate[3], patch.env_offset[1], - patch.env_offset[4]); - release += calc_gus_envelope_time - (patch.env_rate[4], patch.env_offset[3], - patch.env_offset[4]); - release += calc_gus_envelope_time - (patch.env_rate[5], patch.env_offset[4], - patch.env_offset[5]); - rec->parm.volatkhld = (calc_parm_attack(attack) << 8) | - calc_parm_hold(hold); - rec->parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) | - calc_parm_decay(decay); - rec->parm.volrelease = 0x8000 | calc_parm_decay(release); - AWE_DEBUG(2,printk("AWE32: [gusenv atk=%d, hld=%d, dcy=%d, rel=%d]\n", attack, hold, decay, release)); - rec->attenuation = calc_gus_attenuation(patch.env_offset[0]); - } - - /* tremolo effect */ - if (patch.mode & WAVE_TREMOLO) { - int rate = (patch.tremolo_rate * 1000 / 38) / 42; - rec->parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate; - AWE_DEBUG(2,printk("AWE32: [gusenv tremolo rate=%d, dep=%d, tremfrq=%x]\n", - patch.tremolo_rate, patch.tremolo_depth, - rec->parm.tremfrq)); - } - /* vibrato effect */ - if (patch.mode & WAVE_VIBRATO) { - int rate = (patch.vibrato_rate * 1000 / 38) / 42; - rec->parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate; - AWE_DEBUG(2,printk("AWE32: [gusenv vibrato rate=%d, dep=%d, tremfrq=%x]\n", - patch.tremolo_rate, patch.tremolo_depth, - rec->parm.tremfrq)); - } - - /* scale_freq, scale_factor, volume, and fractions not implemented */ - - /* append to the tail of the list */ - infos[free_info].bank = misc_modes[AWE_MD_GUS_BANK]; - infos[free_info].instr = patch.instr_no; - infos[free_info].disabled = FALSE; - infos[free_info].type = V_ST_NORMAL; - infos[free_info].v.sf_id = current_sf_id; - - add_info_list(free_info); - add_sf_info(free_info); - - /* set the voice index */ - awe_set_sample(rec); - - return 0; -} - -#endif /* AWE_HAS_GUS_COMPATIBILITY */ - -/*---------------------------------------------------------------- - * sample and voice list handlers - *----------------------------------------------------------------*/ - -/* append this to the sf list */ -static void add_sf_info(int rec) -{ - int sf_id = infos[rec].v.sf_id; - if (sf_id == 0) return; - sf_id--; - if (sflists[sf_id].infos < 0) - sflists[sf_id].infos = rec; - else { - int i, prev; - prev = sflists[sf_id].infos; - while ((i = infos[prev].next) >= 0) - prev = i; - infos[prev].next = rec; - } - infos[rec].next = -1; - sflists[sf_id].num_info++; -} - -/* prepend this sample to sf list */ -static void add_sf_sample(int rec) -{ - int sf_id = samples[rec].v.sf_id; - if (sf_id == 0) return; - sf_id--; - samples[rec].next = sflists[sf_id].samples; - sflists[sf_id].samples = rec; - sflists[sf_id].num_sample++; -} - -/* purge the old records which don't belong with the same file id */ -static void purge_old_list(int rec, int next) -{ - infos[rec].next_instr = next; - if (infos[rec].bank == AWE_DRUM_BANK) { - /* remove samples with the same note range */ - int cur, *prevp = &infos[rec].next_instr; - int low = infos[rec].v.low; - int high = infos[rec].v.high; - for (cur = next; cur >= 0; cur = infos[cur].next_instr) { - if (infos[cur].v.low == low && - infos[cur].v.high == high && - infos[cur].v.sf_id != infos[rec].v.sf_id) - *prevp = infos[cur].next_instr; - prevp = &infos[cur].next_instr; - } - } else { - if (infos[next].v.sf_id != infos[rec].v.sf_id) - infos[rec].next_instr = -1; - } -} - -/* prepend to top of the preset table */ -static void add_info_list(int rec) -{ - int *prevp, cur; - int instr = infos[rec].instr; - int bank = infos[rec].bank; - - if (infos[rec].disabled) - return; - - prevp = &preset_table[instr]; - cur = *prevp; - while (cur >= 0) { - /* search the first record with the same bank number */ - if (infos[cur].bank == bank) { - /* replace the list with the new record */ - infos[rec].next_bank = infos[cur].next_bank; - *prevp = rec; - purge_old_list(rec, cur); - return; - } - prevp = &infos[cur].next_bank; - cur = infos[cur].next_bank; - } - - /* this is the first bank record.. just add this */ - infos[rec].next_instr = -1; - infos[rec].next_bank = preset_table[instr]; - preset_table[instr] = rec; -} - -/* remove samples later than the specified sf_id */ -static void -awe_remove_samples(int sf_id) -{ - if (sf_id <= 0) { - awe_reset_samples(); - return; - } - /* already removed? */ - if (current_sf_id <= sf_id) - return; - - current_sf_id = sf_id; - if (locked_sf_id > sf_id) - locked_sf_id = sf_id; - - rebuild_preset_list(); -} - -/* rebuild preset search list */ -static void rebuild_preset_list(void) -{ - int i, j; - - for (i = 0; i < AWE_MAX_PRESETS; i++) - preset_table[i] = -1; - - for (i = 0; i < current_sf_id; i++) { - for (j = sflists[i].infos; j >= 0; j = infos[j].next) - add_info_list(j); - } -} - -/* search the specified sample */ -static short -awe_set_sample(awe_voice_info *vp) -{ - int i; - vp->index = -1; - for (i = sflists[vp->sf_id-1].samples; i >= 0; i = samples[i].next) { - if (samples[i].v.sample == vp->sample) { - /* set the actual sample offsets */ - vp->start += samples[i].v.start; - vp->end += samples[i].v.end; - vp->loopstart += samples[i].v.loopstart; - vp->loopend += samples[i].v.loopend; - /* copy mode flags */ - vp->mode = samples[i].v.mode_flags; - /* set index */ - vp->index = i; - return i; - } - } - return -1; -} - - -/*---------------------------------------------------------------- - * voice allocation - *----------------------------------------------------------------*/ - -/* look for all voices associated with the specified note & velocity */ -static int -awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist) -{ - int nvoices; - - nvoices = 0; - for (; rec >= 0; rec = infos[rec].next_instr) { - if (note >= infos[rec].v.low && - note <= infos[rec].v.high && - velocity >= infos[rec].v.vellow && - velocity <= infos[rec].v.velhigh) { - vlist[nvoices] = &infos[rec].v; - if (infos[rec].type == V_ST_MAPPED) /* mapper */ - return -1; - nvoices++; - if (nvoices >= AWE_MAX_VOICES) - break; - } - } - return nvoices; -} - -/* store the voice list from the specified note and velocity. - if the preset is mapped, seek for the destination preset, and rewrite - the note number if necessary. - */ -static int -really_alloc_voices(int vrec, int def_vrec, int *note, int velocity, awe_voice_info **vlist, int level) -{ - int nvoices; - - nvoices = awe_search_multi_voices(vrec, *note, velocity, vlist); - if (nvoices == 0) - nvoices = awe_search_multi_voices(def_vrec, *note, velocity, vlist); - if (nvoices < 0) { /* mapping */ - int preset = vlist[0]->start; - int bank = vlist[0]->end; - int key = vlist[0]->fixkey; - if (level > 5) { - printk("AWE32: too deep mapping level\n"); - return 0; - } - vrec = awe_search_instr(bank, preset); - if (bank == AWE_DRUM_BANK) - def_vrec = awe_search_instr(bank, 0); - else - def_vrec = awe_search_instr(0, preset); - if (key >= 0) - *note = key; - return really_alloc_voices(vrec, def_vrec, note, velocity, vlist, level+1); - } - - return nvoices; -} - -/* allocate voices corresponding note and velocity; supports multiple insts. */ -static void -awe_alloc_multi_voices(int ch, int note, int velocity, int key) -{ - int i, v, nvoices; - awe_voice_info *vlist[AWE_MAX_VOICES]; - - if (channels[ch].vrec < 0 && channels[ch].def_vrec < 0) - awe_set_instr(0, ch, channels[ch].instr); - - /* check the possible voices; note may be changeable if mapped */ - nvoices = really_alloc_voices(channels[ch].vrec, channels[ch].def_vrec, - ¬e, velocity, vlist, 0); - - /* set the voices */ - current_alloc_time++; - for (i = 0; i < nvoices; i++) { - v = awe_clear_voice(); - voices[v].key = key; - voices[v].ch = ch; - voices[v].note = note; - voices[v].velocity = velocity; - voices[v].time = current_alloc_time; - voices[v].cinfo = &channels[ch]; - voices[v].sample = vlist[i]; - voices[v].state = AWE_ST_MARK; - voices[v].layer = nvoices - i - 1; /* in reverse order */ - } - - /* clear the mark in allocated voices */ - for (i = 0; i < awe_max_voices; i++) { - if (voices[i].state == AWE_ST_MARK) - voices[i].state = AWE_ST_OFF; - - } -} - - -/* search the best voice from the specified status condition */ -static int -search_best_voice(int condition) -{ - int i, time, best; - best = -1; - time = current_alloc_time + 1; - for (i = 0; i < awe_max_voices; i++) { - if ((voices[i].state & condition) && - (best < 0 || voices[i].time < time)) { - best = i; - time = voices[i].time; - } - } - /* clear voice */ - if (best >= 0) { - if (voices[best].state != AWE_ST_OFF) - awe_terminate(best); - awe_voice_init(best, TRUE); - } - - return best; -} - -/* search an empty voice. - if no empty voice is found, at least terminate a voice - */ -static int -awe_clear_voice(void) -{ - int best; - - /* looking for the oldest empty voice */ - if ((best = search_best_voice(AWE_ST_OFF)) >= 0) - return best; - if ((best = search_best_voice(AWE_ST_RELEASED)) >= 0) - return best; - /* looking for the oldest sustained voice */ - if ((best = search_best_voice(AWE_ST_SUSTAINED)) >= 0) - return best; - -#ifdef AWE_LOOKUP_MIDI_PRIORITY - if (MULTI_LAYER_MODE() && misc_modes[AWE_MD_CHN_PRIOR]) { - int ch = -1; - int time = current_alloc_time + 1; - int i; - /* looking for the voices from high channel (except drum ch) */ - for (i = 0; i < awe_max_voices; i++) { - if (IS_DRUM_CHANNEL(voices[i].ch)) continue; - if (voices[i].ch < ch) continue; - if (voices[i].state != AWE_ST_MARK && - (voices[i].ch > ch || voices[i].time < time)) { - best = i; - time = voices[i].time; - ch = voices[i].ch; - } - } - } -#endif - if (best < 0) - best = search_best_voice(~AWE_ST_MARK); - - if (best >= 0) - return best; - - return 0; -} - - -/* search sample for the specified note & velocity and set it on the voice; - * note that voice is the voice index (not channel index) - */ -static void -awe_alloc_one_voice(int voice, int note, int velocity) -{ - int ch, nvoices; - awe_voice_info *vlist[AWE_MAX_VOICES]; - - ch = voices[voice].ch; - if (channels[ch].vrec < 0 && channels[ch].def_vrec < 0) - awe_set_instr(0, ch, channels[ch].instr); - - nvoices = really_alloc_voices(voices[voice].cinfo->vrec, - voices[voice].cinfo->def_vrec, - ¬e, velocity, vlist, 0); - if (nvoices > 0) { - voices[voice].time = ++current_alloc_time; - voices[voice].sample = vlist[0]; /* use the first one */ - voices[voice].layer = 0; - voices[voice].note = note; - voices[voice].velocity = velocity; - } -} - - -/*---------------------------------------------------------------- - * sequencer2 functions - *----------------------------------------------------------------*/ - -/* search an empty voice; used by sequencer2 */ -static int -awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc) -{ - playing_mode = AWE_PLAY_MULTI2; - awe_info.nr_voices = AWE_MAX_CHANNELS; - return awe_clear_voice(); -} - - -/* set up voice; used by sequencer2 */ -static void -awe_setup_voice(int dev, int voice, int chn) -{ - struct channel_info *info; - if (synth_devs[dev] == NULL || - (info = &synth_devs[dev]->chn_info[chn]) == NULL) - return; - - if (voice < 0 || voice >= awe_max_voices) - return; - - AWE_DEBUG(2,printk("AWE32: [setup(%d) ch=%d]\n", voice, chn)); - channels[chn].expression_vol = info->controllers[CTL_EXPRESSION]; - channels[chn].main_vol = info->controllers[CTL_MAIN_VOLUME]; - channels[chn].panning = - info->controllers[CTL_PAN] * 2 - 128; /* signed 8bit */ - channels[chn].bender = info->bender_value; /* zero center */ - channels[chn].bank = info->controllers[CTL_BANK_SELECT]; - channels[chn].sustained = info->controllers[CTL_SUSTAIN]; - if (info->controllers[CTL_EXT_EFF_DEPTH]) { - FX_SET(&channels[chn].fx, AWE_FX_REVERB, - info->controllers[CTL_EXT_EFF_DEPTH] * 2); - } - if (info->controllers[CTL_CHORUS_DEPTH]) { - FX_SET(&channels[chn].fx, AWE_FX_CHORUS, - info->controllers[CTL_CHORUS_DEPTH] * 2); - } - awe_set_instr(dev, chn, info->pgm_num); -} - - -#ifdef CONFIG_AWE32_MIXER -/*================================================================ - * AWE32 mixer device control - *================================================================*/ - -static int -awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) -{ - int i, level; - - if (((cmd >> 8) & 0xff) != 'M') - return RET_ERROR(EINVAL); - - level = (int)IOCTL_IN(arg); - level = ((level & 0xff) + (level >> 8)) / 2; - AWE_DEBUG(0,printk("AWEMix: cmd=%x val=%d\n", cmd & 0xff, level)); - - if (IO_WRITE_CHECK(cmd)) { - switch (cmd & 0xff) { - case SOUND_MIXER_BASS: - awe_bass_level = level * 12 / 100; - if (awe_bass_level >= 12) - awe_bass_level = 11; - awe_equalizer(awe_bass_level, awe_treble_level); - break; - case SOUND_MIXER_TREBLE: - awe_treble_level = level * 12 / 100; - if (awe_treble_level >= 12) - awe_treble_level = 11; - awe_equalizer(awe_bass_level, awe_treble_level); - break; - case SOUND_MIXER_VOLUME: - level = level * 127 / 100; - if (level >= 128) level = 127; - init_atten = vol_table[level]; - for (i = 0; i < awe_max_voices; i++) - awe_set_voice_vol(i, TRUE); - break; - } - } - switch (cmd & 0xff) { - case SOUND_MIXER_BASS: - level = awe_bass_level * 100 / 24; - level = (level << 8) | level; - break; - case SOUND_MIXER_TREBLE: - level = awe_treble_level * 100 / 24; - level = (level << 8) | level; - break; - case SOUND_MIXER_VOLUME: - for (i = 127; i > 0; i--) { - if (init_atten <= vol_table[i]) - break; - } - level = i * 100 / 127; - level = (level << 8) | level; - break; - case SOUND_MIXER_DEVMASK: - level = SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_VOLUME; - break; - default: - level = 0; - break; - } - return IOCTL_OUT(arg, level); -} -#endif /* CONFIG_AWE32_MIXER */ - - -/*================================================================ - * initialization of AWE32 - *================================================================*/ - -/* intiailize audio channels */ -static void -awe_init_audio(void) -{ - int ch; - - /* turn off envelope engines */ - for (ch = 0; ch < AWE_MAX_VOICES; ch++) { - awe_poke(AWE_DCYSUSV(ch), 0x80); - } - - /* reset all other parameters to zero */ - for (ch = 0; ch < AWE_MAX_VOICES; ch++) { - awe_poke(AWE_ENVVOL(ch), 0); - awe_poke(AWE_ENVVAL(ch), 0); - awe_poke(AWE_DCYSUS(ch), 0); - awe_poke(AWE_ATKHLDV(ch), 0); - awe_poke(AWE_LFO1VAL(ch), 0); - awe_poke(AWE_ATKHLD(ch), 0); - awe_poke(AWE_LFO2VAL(ch), 0); - awe_poke(AWE_IP(ch), 0); - awe_poke(AWE_IFATN(ch), 0); - awe_poke(AWE_PEFE(ch), 0); - awe_poke(AWE_FMMOD(ch), 0); - awe_poke(AWE_TREMFRQ(ch), 0); - awe_poke(AWE_FM2FRQ2(ch), 0); - awe_poke_dw(AWE_PTRX(ch), 0); - awe_poke_dw(AWE_VTFT(ch), 0); - awe_poke_dw(AWE_PSST(ch), 0); - awe_poke_dw(AWE_CSL(ch), 0); - awe_poke_dw(AWE_CCCA(ch), 0); - } - - for (ch = 0; ch < AWE_MAX_VOICES; ch++) { - awe_poke_dw(AWE_CPF(ch), 0); - awe_poke_dw(AWE_CVCF(ch), 0); - } -} - - -/* initialize DMA address */ -static void -awe_init_dma(void) -{ - awe_poke_dw(AWE_SMALR, 0); - awe_poke_dw(AWE_SMARR, 0); - awe_poke_dw(AWE_SMALW, 0); - awe_poke_dw(AWE_SMARW, 0); -} - - -/* initialization arrays; from ADIP */ - -static unsigned short init1[128] = { - 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330, - 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730, - 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30, - 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30, - - 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330, - 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730, - 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30, - 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30, - - 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330, - 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730, - 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30, - 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30, - - 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330, - 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730, - 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30, - 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30, -}; - -static unsigned short init2[128] = { - 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330, - 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730, - 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30, - 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30, - - 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330, - 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730, - 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30, - 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30, - - 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330, - 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730, - 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30, - 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30, - - 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330, - 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730, - 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30, - 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30, -}; - -static unsigned short init3[128] = { - 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, - 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254, - 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234, - 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224, - - 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254, - 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264, - 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294, - 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3, - - 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287, - 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7, - 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386, - 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55, - - 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308, - 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F, - 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319, - 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570, -}; - -static unsigned short init4[128] = { - 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, - 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254, - 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234, - 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224, - - 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254, - 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264, - 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294, - 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3, - - 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287, - 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7, - 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386, - 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55, - - 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308, - 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F, - 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319, - 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570, -}; - - -/* send initialization arrays to start up */ -static void -awe_init_array(void) -{ - awe_send_array(init1); - awe_wait(1024); - awe_send_array(init2); - awe_send_array(init3); - awe_poke_dw(AWE_HWCF4, 0); - awe_poke_dw(AWE_HWCF5, 0x83); - awe_poke_dw(AWE_HWCF6, 0x8000); - awe_send_array(init4); -} - -/* send an initialization array */ -static void -awe_send_array(unsigned short *data) -{ - int i; - unsigned short *p; - - p = data; - for (i = 0; i < AWE_MAX_VOICES; i++, p++) - awe_poke(AWE_INIT1(i), *p); - for (i = 0; i < AWE_MAX_VOICES; i++, p++) - awe_poke(AWE_INIT2(i), *p); - for (i = 0; i < AWE_MAX_VOICES; i++, p++) - awe_poke(AWE_INIT3(i), *p); - for (i = 0; i < AWE_MAX_VOICES; i++, p++) - awe_poke(AWE_INIT4(i), *p); -} - - -/* - * set up awe32 channels to some known state. - */ - -/* set the envelope & LFO parameters to the default values; see ADIP */ -static void -awe_tweak_voice(int i) -{ - /* set all mod/vol envelope shape to minimum */ - awe_poke(AWE_ENVVOL(i), 0x8000); - awe_poke(AWE_ENVVAL(i), 0x8000); - awe_poke(AWE_DCYSUS(i), 0x7F7F); - awe_poke(AWE_ATKHLDV(i), 0x7F7F); - awe_poke(AWE_ATKHLD(i), 0x7F7F); - awe_poke(AWE_PEFE(i), 0); /* mod envelope height to zero */ - awe_poke(AWE_LFO1VAL(i), 0x8000); /* no delay for LFO1 */ - awe_poke(AWE_LFO2VAL(i), 0x8000); - awe_poke(AWE_IP(i), 0xE000); /* no pitch shift */ - awe_poke(AWE_IFATN(i), 0xFF00); /* volume to minimum */ - awe_poke(AWE_FMMOD(i), 0); - awe_poke(AWE_TREMFRQ(i), 0); - awe_poke(AWE_FM2FRQ2(i), 0); -} - -static void -awe_tweak(void) -{ - int i; - /* reset all channels */ - for (i = 0; i < awe_max_voices; i++) - awe_tweak_voice(i); -} - - -/* - * initializes the FM section of AWE32; - * see Vince Vu's unofficial AWE32 programming guide - */ - -static void -awe_init_fm(void) -{ -#ifndef AWE_ALWAYS_INIT_FM - /* if no extended memory is on board.. */ - if (awe_mem_size <= 0) - return; -#endif - AWE_DEBUG(3,printk("AWE32: initializing FM\n")); - - /* Initialize the last two channels for DRAM refresh and producing - the reverb and chorus effects for Yamaha OPL-3 synthesizer */ - - /* 31: FM left channel, 0xffffe0-0xffffe8 */ - awe_poke(AWE_DCYSUSV(30), 0x80); - awe_poke_dw(AWE_PSST(30), 0xFFFFFFE0); /* full left */ - awe_poke_dw(AWE_CSL(30), 0x00FFFFE8 | - (DEF_FM_CHORUS_DEPTH << 24)); - awe_poke_dw(AWE_PTRX(30), (DEF_FM_REVERB_DEPTH << 8)); - awe_poke_dw(AWE_CPF(30), 0); - awe_poke_dw(AWE_CCCA(30), 0x00FFFFE3); - - /* 32: FM right channel, 0xfffff0-0xfffff8 */ - awe_poke(AWE_DCYSUSV(31), 0x80); - awe_poke_dw(AWE_PSST(31), 0x00FFFFF0); /* full right */ - awe_poke_dw(AWE_CSL(31), 0x00FFFFF8 | - (DEF_FM_CHORUS_DEPTH << 24)); - awe_poke_dw(AWE_PTRX(31), (DEF_FM_REVERB_DEPTH << 8)); - awe_poke_dw(AWE_CPF(31), 0x8000); - awe_poke_dw(AWE_CCCA(31), 0x00FFFFF3); - - /* skew volume & cutoff */ - awe_poke_dw(AWE_VTFT(30), 0x8000FFFF); - awe_poke_dw(AWE_VTFT(31), 0x8000FFFF); - - voices[30].state = AWE_ST_FM; - voices[31].state = AWE_ST_FM; - - /* change maximum channels to 30 */ - awe_max_voices = AWE_NORMAL_VOICES; - if (playing_mode == AWE_PLAY_DIRECT) - awe_info.nr_voices = awe_max_voices; - else - awe_info.nr_voices = AWE_MAX_CHANNELS; - voice_alloc->max_voice = awe_max_voices; -} - -/* - * AWE32 DRAM access routines - */ - -/* open DRAM write accessing mode */ -static int -awe_open_dram_for_write(int offset, int channels) -{ - int vidx[AWE_NORMAL_VOICES]; - int i; - - if (channels < 0 || channels >= AWE_NORMAL_VOICES) { - channels = AWE_NORMAL_VOICES; - for (i = 0; i < AWE_NORMAL_VOICES; i++) - vidx[i] = i; - } else { - for (i = 0; i < channels; i++) - vidx[i] = awe_clear_voice(); - } - - /* use all channels for DMA transfer */ - for (i = 0; i < channels; i++) { - if (vidx[i] < 0) continue; - awe_poke(AWE_DCYSUSV(vidx[i]), 0x80); - awe_poke_dw(AWE_VTFT(vidx[i]), 0); - awe_poke_dw(AWE_CVCF(vidx[i]), 0); - awe_poke_dw(AWE_PTRX(vidx[i]), 0x40000000); - awe_poke_dw(AWE_CPF(vidx[i]), 0x40000000); - awe_poke_dw(AWE_PSST(vidx[i]), 0); - awe_poke_dw(AWE_CSL(vidx[i]), 0); - awe_poke_dw(AWE_CCCA(vidx[i]), 0x06000000); - voices[vidx[i]].state = AWE_ST_DRAM; - } - /* point channels 31 & 32 to ROM samples for DRAM refresh */ - awe_poke_dw(AWE_VTFT(30), 0); - awe_poke_dw(AWE_PSST(30), 0x1d8); - awe_poke_dw(AWE_CSL(30), 0x1e0); - awe_poke_dw(AWE_CCCA(30), 0x1d8); - awe_poke_dw(AWE_VTFT(31), 0); - awe_poke_dw(AWE_PSST(31), 0x1d8); - awe_poke_dw(AWE_CSL(31), 0x1e0); - awe_poke_dw(AWE_CCCA(31), 0x1d8); - voices[30].state = AWE_ST_FM; - voices[31].state = AWE_ST_FM; - - /* if full bit is on, not ready to write on */ - if (awe_peek_dw(AWE_SMALW) & 0x80000000) { - for (i = 0; i < channels; i++) { - awe_poke_dw(AWE_CCCA(vidx[i]), 0); - voices[i].state = AWE_ST_OFF; - } - return RET_ERROR(ENOSPC); - } - - /* set address to write */ - awe_poke_dw(AWE_SMALW, offset); - - return 0; -} - -/* open DRAM for RAM size detection */ -static void -awe_open_dram_for_check(void) -{ - int i; - for (i = 0; i < AWE_NORMAL_VOICES; i++) { - awe_poke(AWE_DCYSUSV(i), 0x80); - awe_poke_dw(AWE_VTFT(i), 0); - awe_poke_dw(AWE_CVCF(i), 0); - awe_poke_dw(AWE_PTRX(i), 0x40000000); - awe_poke_dw(AWE_CPF(i), 0x40000000); - awe_poke_dw(AWE_PSST(i), 0); - awe_poke_dw(AWE_CSL(i), 0); - if (i & 1) /* DMA write */ - awe_poke_dw(AWE_CCCA(i), 0x06000000); - else /* DMA read */ - awe_poke_dw(AWE_CCCA(i), 0x04000000); - voices[i].state = AWE_ST_DRAM; - } -} - - -/* close dram access */ -static void -awe_close_dram(void) -{ - int i; - /* wait until FULL bit in SMAxW register be false */ - for (i = 0; i < 10000; i++) { - if (!(awe_peek_dw(AWE_SMALW) & 0x80000000)) - break; - awe_wait(10); - } - - for (i = 0; i < AWE_NORMAL_VOICES; i++) { - if (voices[i].state == AWE_ST_DRAM) { - awe_poke_dw(AWE_CCCA(i), 0); - awe_poke(AWE_DCYSUSV(i), 0x807F); - voices[i].state = AWE_ST_OFF; - } - } -} - - -/*================================================================ - * detect presence of AWE32 and check memory size - *================================================================*/ - -/* detect emu8000 chip on the specified address; from VV's guide */ - -static int -awe_detect_base(int addr) -{ - awe_base = addr; - if ((awe_peek(AWE_U1) & 0x000F) != 0x000C) - return 0; - if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058) - return 0; - if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003) - return 0; - AWE_DEBUG(0,printk("AWE32 found at %x\n", awe_base)); - return 1; -} - -static int -awe_detect(void) -{ - int base; - if (awe_base == 0) { - for (base = 0x620; base <= 0x680; base += 0x20) - if (awe_detect_base(base)) - return 1; - AWE_DEBUG(0,printk("AWE32 not found\n")); - return 0; - } - return 1; -} - - -/*================================================================ - * check dram size on AWE board - *================================================================*/ - -/* any three numbers you like */ -#define UNIQUE_ID1 0x1234 -#define UNIQUE_ID2 0x4321 -#define UNIQUE_ID3 0xFFFF - -static int -awe_check_dram(void) -{ - if (awe_mem_size > 0) { - awe_mem_size *= 1024; /* convert to Kbytes */ - return awe_mem_size; - } - - awe_open_dram_for_check(); - - awe_mem_size = 0; - - /* set up unique two id numbers */ - awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET); - awe_poke(AWE_SMLD, UNIQUE_ID1); - awe_poke(AWE_SMLD, UNIQUE_ID2); - - while (awe_mem_size < AWE_MAX_DRAM_SIZE) { - awe_wait(2); - /* read a data on the DRAM start address */ - awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET); - awe_peek(AWE_SMLD); /* discard stale data */ - if (awe_peek(AWE_SMLD) != UNIQUE_ID1) - break; - if (awe_peek(AWE_SMLD) != UNIQUE_ID2) - break; - awe_mem_size += 32; /* increment 32 Kbytes */ - /* Write a unique data on the test address; - * if the address is out of range, the data is written on - * 0x200000(=AWE_DRAM_OFFSET). Then the two id words are - * broken by this data. - */ - awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET + awe_mem_size*512L); - awe_poke(AWE_SMLD, UNIQUE_ID3); - awe_wait(2); - /* read a data on the just written DRAM address */ - awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET + awe_mem_size*512L); - awe_peek(AWE_SMLD); /* discard stale data */ - if (awe_peek(AWE_SMLD) != UNIQUE_ID3) - break; - } - awe_close_dram(); - - AWE_DEBUG(0,printk("AWE32: %d Kbytes memory detected\n", awe_mem_size)); - - /* convert to Kbytes */ - awe_mem_size *= 1024; - return awe_mem_size; -} - - -/*================================================================ - * chorus and reverb controls; from VV's guide - *================================================================*/ - -/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */ -static char chorus_defined[AWE_CHORUS_NUMBERS]; -static awe_chorus_fx_rec chorus_parm[AWE_CHORUS_NUMBERS] = { - {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */ - {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */ - {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */ - {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */ - {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */ - {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */ - {0xE600, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay */ - {0xE6C0, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay + feedback */ -}; - -static int -awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count) -{ - if (patch->optarg < AWE_CHORUS_PREDEFINED || patch->optarg >= AWE_CHORUS_NUMBERS) { - printk("AWE32 Error: illegal chorus mode %d for uploading\n", patch->optarg); - return RET_ERROR(EINVAL); - } - if (count < sizeof(awe_chorus_fx_rec)) { - printk("AWE32 Error: too short chorus fx parameters\n"); - return RET_ERROR(EINVAL); - } - COPY_FROM_USER(&chorus_parm[patch->optarg], addr, AWE_PATCH_INFO_SIZE, - sizeof(awe_chorus_fx_rec)); - chorus_defined[patch->optarg] = TRUE; - return 0; -} - -static void -awe_set_chorus_mode(int effect) -{ - if (effect < 0 || effect >= AWE_CHORUS_NUMBERS || - (effect >= AWE_CHORUS_PREDEFINED && !chorus_defined[effect])) - return; - awe_poke(AWE_INIT3(9), chorus_parm[effect].feedback); - awe_poke(AWE_INIT3(12), chorus_parm[effect].delay_offset); - awe_poke(AWE_INIT4(3), chorus_parm[effect].lfo_depth); - awe_poke_dw(AWE_HWCF4, chorus_parm[effect].delay); - awe_poke_dw(AWE_HWCF5, chorus_parm[effect].lfo_freq); - awe_poke_dw(AWE_HWCF6, 0x8000); - awe_poke_dw(AWE_HWCF7, 0x0000); - chorus_mode = effect; -} - -/*----------------------------------------------------------------*/ - -/* reverb mode settings; write the following 28 data of 16 bit length - * on the corresponding ports in the reverb_cmds array - */ -static char reverb_defined[AWE_CHORUS_NUMBERS]; -static awe_reverb_fx_rec reverb_parm[AWE_REVERB_NUMBERS] = { -{{ /* room 1 */ - 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4, - 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516, - 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* room 2 */ - 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* room 3 */ - 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516, - 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B, - 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A, -}}, -{{ /* hall 1 */ - 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284, - 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A, - 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529, -}}, -{{ /* hall 2 */ - 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254, - 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3, - 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* plate */ - 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234, - 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548, - 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, - 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, -}}, -{{ /* delay */ - 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204, - 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, - 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, - 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, -}}, -{{ /* panning delay */ - 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204, - 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, - 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, - 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, -}}, -}; - -static struct ReverbCmdPair { - unsigned short cmd, port; -} reverb_cmds[28] = { - {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)}, - {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)}, - {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)}, - {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)}, - {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)}, - {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)}, - {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)}, -}; - -static int -awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count) -{ - if (patch->optarg < AWE_REVERB_PREDEFINED || patch->optarg >= AWE_REVERB_NUMBERS) { - printk("AWE32 Error: illegal reverb mode %d for uploading\n", patch->optarg); - return RET_ERROR(EINVAL); - } - if (count < sizeof(awe_reverb_fx_rec)) { - printk("AWE32 Error: too short reverb fx parameters\n"); - return RET_ERROR(EINVAL); - } - COPY_FROM_USER(&reverb_parm[patch->optarg], addr, AWE_PATCH_INFO_SIZE, - sizeof(awe_reverb_fx_rec)); - reverb_defined[patch->optarg] = TRUE; - return 0; -} - -static void -awe_set_reverb_mode(int effect) -{ - int i; - if (effect < 0 || effect >= AWE_REVERB_NUMBERS || - (effect >= AWE_REVERB_PREDEFINED && !reverb_defined[effect])) - return; - for (i = 0; i < 28; i++) - awe_poke(reverb_cmds[i].cmd, reverb_cmds[i].port, - reverb_parm[effect].parms[i]); - reverb_mode = effect; -} - -/*================================================================ - * treble/bass equalizer control - *================================================================*/ - -static unsigned short bass_parm[12][3] = { - {0xD26A, 0xD36A, 0x0000}, /* -12 dB */ - {0xD25B, 0xD35B, 0x0000}, /* -8 */ - {0xD24C, 0xD34C, 0x0000}, /* -6 */ - {0xD23D, 0xD33D, 0x0000}, /* -4 */ - {0xD21F, 0xD31F, 0x0000}, /* -2 */ - {0xC208, 0xC308, 0x0001}, /* 0 (HW default) */ - {0xC219, 0xC319, 0x0001}, /* +2 */ - {0xC22A, 0xC32A, 0x0001}, /* +4 */ - {0xC24C, 0xC34C, 0x0001}, /* +6 */ - {0xC26E, 0xC36E, 0x0001}, /* +8 */ - {0xC248, 0xC348, 0x0002}, /* +10 */ - {0xC26A, 0xC36A, 0x0002}, /* +12 dB */ -}; - -static unsigned short treble_parm[12][9] = { - {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */ - {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002}, - {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */ - {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, - {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +12 dB */ -}; - - -/* - * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB] - */ -static void -awe_equalizer(int bass, int treble) -{ - unsigned short w; - - if (bass < 0 || bass > 11 || treble < 0 || treble > 11) - return; - awe_bass_level = bass; - awe_treble_level = treble; - awe_poke(AWE_INIT4(0x01), bass_parm[bass][0]); - awe_poke(AWE_INIT4(0x11), bass_parm[bass][1]); - awe_poke(AWE_INIT3(0x11), treble_parm[treble][0]); - awe_poke(AWE_INIT3(0x13), treble_parm[treble][1]); - awe_poke(AWE_INIT3(0x1B), treble_parm[treble][2]); - awe_poke(AWE_INIT4(0x07), treble_parm[treble][3]); - awe_poke(AWE_INIT4(0x0B), treble_parm[treble][4]); - awe_poke(AWE_INIT4(0x0D), treble_parm[treble][5]); - awe_poke(AWE_INIT4(0x17), treble_parm[treble][6]); - awe_poke(AWE_INIT4(0x19), treble_parm[treble][7]); - w = bass_parm[bass][2] + treble_parm[treble][8]; - awe_poke(AWE_INIT4(0x15), (unsigned short)(w + 0x0262)); - awe_poke(AWE_INIT4(0x1D), (unsigned short)(w + 0x8362)); -} - - -#endif /* CONFIG_AWE32_SYNTH */ diff --git a/sys/platform/pc32/i386/userconfig.c b/sys/platform/pc32/i386/userconfig.c index 3240724a74..7b42880f51 100644 --- a/sys/platform/pc32/i386/userconfig.c +++ b/sys/platform/pc32/i386/userconfig.c @@ -47,7 +47,7 @@ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ** $FreeBSD: src/sys/i386/i386/userconfig.c,v 1.175.2.10 2002/10/05 18:31:48 scottl Exp $ - ** $DragonFly: src/sys/platform/pc32/i386/userconfig.c,v 1.3 2003/08/07 21:17:22 dillon Exp $ + ** $DragonFly: src/sys/platform/pc32/i386/userconfig.c,v 1.4 2005/01/31 23:44:35 joerg Exp $ **/ /** @@ -390,7 +390,6 @@ static DEV_INFO device_info[] = { {"sb", "VOXWARE Soundblaster PCM (SB/Pro/16, ProAudio Spectrum)",0,CLS_MMEDIA}, {"sbxvi", "VOXWARE Soundblaster 16", 0, CLS_MMEDIA}, {"sbmidi", "VOXWARE Soundblaster MIDI interface", 0, CLS_MMEDIA}, -{"awe", "VOXWARE AWE32 MIDI", 0, CLS_MMEDIA}, {"pas", "VOXWARE ProAudio Spectrum PCM and MIDI", 0, CLS_MMEDIA}, {"gus", "VOXWARE Gravis Ultrasound, Ultrasound 16 and Ultrasound MAX",0,CLS_MMEDIA}, {"gusxvi", "VOXWARE Gravis Ultrasound 16-bit PCM", 0, CLS_MMEDIA}, diff --git a/sys/platform/pc32/isa/ic/i82365.h b/sys/platform/pc32/isa/ic/i82365.h deleted file mode 100644 index 88a71c24c4..0000000000 --- a/sys/platform/pc32/isa/ic/i82365.h +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef __83265_H__ -#define __83265_H__ - -/*********************************************************************** - * 82365.h -- information necessary for direct manipulation of PCMCIA - * cards and controllers - * - * Support is included for Intel 82365SL PCIC controllers and clones - * thereof. - * - * originally by Barry Jaspan; hacked over by Keith Moore - * - * $FreeBSD: src/sys/i386/isa/ic/i82365.h,v 1.2.16.1 2000/08/03 18:55:42 peter Exp $ - * $DragonFly: src/sys/platform/pc32/isa/ic/Attic/i82365.h,v 1.2 2003/06/17 04:28:37 dillon Exp $ - ***********************************************************************/ - -/* - * PCIC Registers - * Each register is given a name, and most of the bits are named too. - * I should really name them all. - * - * Finally, since the banks can be addressed with a regular syntax, - * some macros are provided for that purpose. - */ - -#define PCIC_BASE 0x03e0 /* base adddress of pcic register set */ - -/* First, all the registers */ -#define PCIC_ID_REV 0x00 /* Identification and Revision */ -#define PCIC_STATUS 0x01 /* Interface Status */ -#define PCIC_POWER 0x02 /* Power and RESETDRV control */ -#define PCIC_INT_GEN 0x03 /* Interrupt and General Control */ -#define PCIC_STAT_CHG 0x04 /* Card Status Change */ -#define PCIC_STAT_INT 0x05 /* Card Status Change Interrupt Config */ -#define PCIC_ADDRWINE 0x06 /* Address Window Enable */ -#define PCIC_IOCTL 0x07 /* I/O Control */ -#define PCIC_IO0_STL 0x08 /* I/O Address 0 Start Low Byte */ -#define PCIC_IO0_STH 0x09 /* I/O Address 0 Start High Byte */ -#define PCIC_IO0_SPL 0x0a /* I/O Address 0 Stop Low Byte */ -#define PCIC_IO0_SPH 0x0b /* I/O Address 0 Stop High Byte */ -#define PCIC_IO1_STL 0x0c /* I/O Address 1 Start Low Byte */ -#define PCIC_IO1_STH 0x0d /* I/O Address 1 Start High Byte */ -#define PCIC_IO1_SPL 0x0e /* I/O Address 1 Stop Low Byte */ -#define PCIC_IO1_SPH 0x0f /* I/O Address 1 Stop High Byte */ -#define PCIC_SM0_STL 0x10 /* System Memory Address 0 Mapping Start Low Byte */ -#define PCIC_SM0_STH 0x11 /* System Memory Address 0 Mapping Start High Byte */ -#define PCIC_SM0_SPL 0x12 /* System Memory Address 0 Mapping Stop Low Byte */ -#define PCIC_SM0_SPH 0x13 /* System Memory Address 0 Mapping Stop High Byte */ -#define PCIC_CM0_L 0x14 /* Card Memory Offset Address 0 Low Byte */ -#define PCIC_CM0_H 0x15 /* Card Memory Offset Address 0 High Byte */ -#define PCIC_CDGC 0x16 /* Card Detect and General Control */ -#define PCIC_RES17 0x17 /* Reserved */ -#define PCIC_SM1_STL 0x18 /* System Memory Address 1 Mapping Start Low Byte */ -#define PCIC_SM1_STH 0x19 /* System Memory Address 1 Mapping Start High Byte */ -#define PCIC_SM1_SPL 0x1a /* System Memory Address 1 Mapping Stop Low Byte */ -#define PCIC_SM1_SPH 0x1b /* System Memory Address 1 Mapping Stop High Byte */ -#define PCIC_CM1_L 0x1c /* Card Memory Offset Address 1 Low Byte */ -#define PCIC_CM1_H 0x1d /* Card Memory Offset Address 1 High Byte */ -#define PCIC_GLO_CTRL 0x1e /* Global Control Register */ -#define PCIC_RES1F 0x1f /* Reserved */ -#define PCIC_SM2_STL 0x20 /* System Memory Address 2 Mapping Start Low Byte */ -#define PCIC_SM2_STH 0x21 /* System Memory Address 2 Mapping Start High Byte */ -#define PCIC_SM2_SPL 0x22 /* System Memory Address 2 Mapping Stop Low Byte */ -#define PCIC_SM2_SPH 0x23 /* System Memory Address 2 Mapping Stop High Byte */ -#define PCIC_CM2_L 0x24 /* Card Memory Offset Address 2 Low Byte */ -#define PCIC_CM2_H 0x25 /* Card Memory Offset Address 2 High Byte */ -#define PCIC_RES26 0x26 /* Reserved */ -#define PCIC_RES27 0x27 /* Reserved */ -#define PCIC_SM3_STL 0x28 /* System Memory Address 3 Mapping Start Low Byte */ -#define PCIC_SM3_STH 0x29 /* System Memory Address 3 Mapping Start High Byte */ -#define PCIC_SM3_SPL 0x2a /* System Memory Address 3 Mapping Stop Low Byte */ -#define PCIC_SM3_SPH 0x2b /* System Memory Address 3 Mapping Stop High Byte */ -#define PCIC_CM3_L 0x2c /* Card Memory Offset Address 3 Low Byte */ -#define PCIC_CM3_H 0x2d /* Card Memory Offset Address 3 High Byte */ -#define PCIC_RES2E 0x2e /* Reserved */ -#define PCIC_RES2F 0x2f /* Reserved */ -#define PCIC_SM4_STL 0x30 /* System Memory Address 4 Mapping Start Low Byte */ -#define PCIC_SM4_STH 0x31 /* System Memory Address 4 Mapping Start High Byte */ -#define PCIC_SM4_SPL 0x32 /* System Memory Address 4 Mapping Stop Low Byte */ -#define PCIC_SM4_SPH 0x33 /* System Memory Address 4 Mapping Stop High Byte */ -#define PCIC_CM4_L 0x34 /* Card Memory Offset Address 4 Low Byte */ -#define PCIC_CM4_H 0x35 /* Card Memory Offset Address 4 High Byte */ -#define PCIC_RES36 0x36 /* Reserved */ -#define PCIC_RES37 0x37 /* Reserved */ -#define PCIC_RES38 0x38 /* Reserved */ -#define PCIC_RES39 0x39 /* Reserved */ -#define PCIC_RES3A 0x3a /* Reserved */ -#define PCIC_RES3B 0x3b /* Reserved */ -#define PCIC_RES3C 0x3c /* Reserved */ -#define PCIC_RES3D 0x3d /* Reserved */ -#define PCIC_RES3E 0x3e /* Reserved */ -#define PCIC_RES3F 0x3f /* Reserved */ - -/* Now register bits, ordered by reg # */ - -/* For Identification and Revision (PCIC_ID_REV) */ -#define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */ -#define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */ -#define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */ -#define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */ - -/* For Interface Status register (PCIC_STATUS) */ -#define PCIC_VPPV 0x80 /* Vpp_valid */ -#define PCIC_POW 0x40 /* PC Card power active */ -#define PCIC_READY 0x20 /* Ready/~Busy */ -#define PCIC_MWP 0x10 /* Memory Write Protect */ -#define PCIC_CD 0x0C /* Both card detect bits */ -#define PCIC_BVD 0x03 /* Both Battery Voltage Detect bits */ - -/* For the Power and RESETDRV register (PCIC_POWER) */ -#define PCIC_OUTENA 0x80 /* Output Enable */ -#define PCIC_DISRST 0x40 /* Disable RESETDRV */ -#define PCIC_APSENA 0x20 /* Auto Pwer Switch Enable */ -#define PCIC_PCPWRE 0x10 /* PC Card Power Enable */ - -/* For the Interrupt and General Control register (PCIC_INT_GEN) */ -#define PCIC_CARDTYPE 0x20 /* Card Type 0 = memory, 1 = I/O */ -#define PCIC_IOCARD 0x20 -#define PCIC_MEMCARD 0x00 -#define PCIC_CARDRESET 0x40 /* Card reset 0 = Reset, 1 = Normal */ - -/* For the Card Status Change register (PCIC_STAT_CHG) */ -#define PCIC_CDTCH 0x08 /* Card Detect Change */ -#define PCIC_RDYCH 0x04 /* Ready Change */ -#define PCIC_BATWRN 0x02 /* Battery Warning */ -#define PCIC_BATDED 0x01 /* Battery Dead */ - -/* For the Address Window Enable Register (PCIC_ADDRWINE) */ -#define PCIC_SM0_EN 0x01 /* Memory Window 0 Enable */ -#define PCIC_SM1_EN 0x02 /* Memory Window 1 Enable */ -#define PCIC_SM2_EN 0x04 /* Memory Window 2 Enable */ -#define PCIC_SM3_EN 0x08 /* Memory Window 3 Enable */ -#define PCIC_SM4_EN 0x10 /* Memory Window 4 Enable */ -#define PCIC_MEMCS16 0x20 /* ~MEMCS16 Decode A23-A12 */ -#define PCIC_IO0_EN 0x40 /* I/O Window 0 Enable */ -#define PCIC_IO1_EN 0x80 /* I/O Window 1 Enable */ - -/* For the I/O Control Register (PCIC_IOCTL) */ -#define PCIC_IO0_16BIT 0x01 /* I/O to this segment is 16 bit */ -#define PCIC_IO0_CS16 0x02 /* I/O cs16 source is the card */ -#define PCIC_IO0_0WS 0x04 /* zero wait states added on 8 bit cycles */ -#define PCIC_IO0_WS 0x08 /* Wait states added for 16 bit cycles */ -#define PCIC_IO1_16BIT 0x10 /* I/O to this segment is 16 bit */ -#define PCIC_IO1_CS16 0x20 /* I/O cs16 source is the card */ -#define PCIC_IO1_0WS 0x04 /* zero wait states added on 8 bit cycles */ -#define PCIC_IO1_WS 0x80 /* Wait states added for 16 bit cycles */ - -/* For the various I/O and Memory windows */ -#define PCIC_ADDR_LOW 0 -#define PCIC_ADDR_HIGH 1 -#define PCIC_START 0x00 /* Start of mapping region */ -#define PCIC_END 0x02 /* End of mapping region */ -#define PCIC_MOFF 0x04 /* Card Memory Mapping region offset */ -#define PCIC_IO0 0x08 /* I/O Address 0 */ -#define PCIC_IO1 0x0c /* I/O Address 1 */ -#define PCIC_SM0 0x10 /* System Memory Address 0 Mapping */ -#define PCIC_SM1 0x18 /* System Memory Address 1 Mapping */ -#define PCIC_SM2 0x20 /* System Memory Address 2 Mapping */ -#define PCIC_SM3 0x28 /* System Memory Address 3 Mapping */ -#define PCIC_SM4 0x30 /* System Memory Address 4 Mapping */ - -/* For System Memory Window start registers - (PCIC_SMx|PCIC_START|PCIC_ADDR_HIGH) */ -#define PCIC_ZEROWS 0x40 /* Zero wait states */ -#define PCIC_DATA16 0x80 /* Data width is 16 bits */ - -/* For System Memory Window stop registers - (PCIC_SMx|PCIC_END|PCIC_ADDR_HIGH) */ -#define PCIC_MW0 0x40 /* Wait state bit 0 */ -#define PCIC_MW1 0x80 /* Wait state bit 1 */ - -/* For System Memory Window offset registers - (PCIC_SMx|PCIC_MOFF|PCIC_ADDR_HIGH) */ -#define PCIC_REG 0x40 /* Attribute/Common select (why called Reg?) */ -#define PCIC_WP 0x80 /* Write-protect this window */ - -/* For Card Detect and General Control register (PCIC_CDGC) */ -#define PCIC_16_DL_INH 0x01 /* 16-bit memory delay inhibit */ -#define PCIC_CNFG_RST_EN 0x02 /* configuration reset enable */ -#define PCIC_GPI_EN 0x04 /* GPI Enable */ -#define PCIC_GPI_TRANS 0x08 /* GPI Transition Control */ -#define PCIC_CDRES_EN 0x10 /* card detect resume enable */ -#define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */ - -/* For Global Control register (PCIC_GLO_CTRL) */ -#define PCIC_PWR_DOWN 0x01 /* power down */ -#define PCIC_LVL_MODE 0x02 /* level mode interrupt enable */ -#define PCIC_WB_CSCINT 0x04 /* explicit write-back csc intr */ -#define PCIC_IRQ14_PULSE 0x08 /* irq 14 pulse mode enable */ - -/* DON'T ADD ANYTHING AFTER THIS #endif */ -#endif /* __83265_H__ */ diff --git a/sys/platform/pc32/isa/npx.c b/sys/platform/pc32/isa/npx.c index 239ac77f8f..2dca217da5 100644 --- a/sys/platform/pc32/isa/npx.c +++ b/sys/platform/pc32/isa/npx.c @@ -33,7 +33,7 @@ * * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 * $FreeBSD: src/sys/i386/isa/npx.c,v 1.80.2.3 2001/10/20 19:04:38 tegge Exp $ - * $DragonFly: src/sys/platform/pc32/isa/npx.c,v 1.21 2004/06/17 19:37:29 drhodus Exp $ + * $DragonFly: src/sys/platform/pc32/isa/npx.c,v 1.22 2005/01/31 23:44:35 joerg Exp $ */ #include "opt_cpu.h" @@ -440,7 +440,7 @@ npx_attach(device_t dev) if (npx_irq13) { device_printf(dev, "using IRQ 13 interface\n"); } else { -#if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) +#if defined(MATH_EMULATE) if (npx_ex16) { if (!(flags & NPX_PREFER_EMULATOR)) device_printf(dev, "INT 16 interface\n"); diff --git a/sys/platform/pc32/isa/sound/local.h b/sys/platform/pc32/isa/sound/local.h index 78749d38c4..aa5ebbbe9b 100644 --- a/sys/platform/pc32/isa/sound/local.h +++ b/sys/platform/pc32/isa/sound/local.h @@ -6,7 +6,7 @@ * will become more like that of standard bsd code. * lr 970714 * - * $DragonFly: src/sys/platform/pc32/isa/sound/Attic/local.h,v 1.2 2003/08/07 21:17:23 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/isa/sound/Attic/local.h,v 1.3 2005/01/31 23:44:35 joerg Exp $ */ /* build hex2hex /tmp/foo.x trix_boot.h trix_boot */ @@ -82,11 +82,6 @@ #define CONFIG_SB16MIDI #endif -#include "use_awe.h" -#if NAWE != 0 && !defined(CONFIG_AWE32) -#define CONFIG_AWE32 -#endif - #include "use_pas.h" #if NPAS != 0 && !defined(CONFIG_PAS) #define CONFIG_PAS -- 2.41.0