Commit a5596610 authored by Jeffrey Lee's avatar Jeffrey Lee
Browse files

Add VFPv2 support code

Detail:
  This update adds the support code necessary to allow the VFPv2 coprocessor in the Raspberry Pi to be used in its full IEEE-compliant mode, and to add support for the generation of errors on VFP match exceptions (division by zero, etc.)
  SoftFloat Release 2b (http://www.jhauser.us/arithmetic/SoftFloat.html) is used to perform the floating point calculations in software, ensuring their accuracy.
  As with FPEmulator, the support code will only be included on machines which require it; at the moment this decision is handled by the makefile, based around the target machine type.
  Note that the current version of the support code does not implement default NaN or flush-to-zero mode, so it is not a fully accurate emulation of the hardware.
  Also added a new SWI, VFPSupport_ExceptionDump, for creating and reading a VFP context exception dump, and a new reason code to VFPSupport_Features to query which exception enable bits are supported
  File changes:
  - Makefile - Rewritten to use the CModule fragment, and to add the necessary rules for (optionally) building the support code.
  - Licences - File summarising the different licences used by different portions of the code
  - Test/test2c,ffb, Test/test3,ffb, Test/test4,ffb, Test/test5,ffb, Test/test6src,ffb - Several test programs for validating behaviour of the support code, mainly focused around unusual causes of exceptions and validating instruction decoding and short vector support
  - actions/ARMv7_VFP, arctions/common, c/head, cache/classify - decgen files for building the instruction decoder. This decoder is only used for synchronous exceptions, to determine whether the instruction is or isn't a valid VFP instruction. Asynchronous exceptions utilise a simpler, hand-crafted decoder in the assembler sources.
  - h/classify - Header for the decgen decoder
  - hdr/shared - Header with some definitions shared between the C and assembler sources (will be Hdr2H'd to generate the C header)
  - hdr/VFPSupport - Updated with new error numbers, SWI definitions
  - s/CSupport - Math support functions from the C library sources, required by SoftFloat
  - s/Errors - Added new error definitions
  - s/GetAll - Include support code if necessary. Add debug switch, plus optimisation switch for machines with 16 D registers
  - s/Instructions - Core data processing instruction emulation code. This file is included twice, once for single precision and once for double precision. The code calls through to the SoftFloat routines to perform the calculations.
  - s/Module - Adjust handling of undefined instruction vector to allow the support code to be installed instead of OldHandler if necessary. Initialise the support code as necessary. Add new SWIs & reason codes.
  - s/SupportCode - Undefined instruction handler which controls the rest of the support code. Also raises RISC OS errors as necessary (division by zero, etc.)
  - softfloat/* - The SoftFloat library sources. It's been tweaked in a few places for integration with the assembler support code, but otherwise no changes to the core logic were necessary.
  - Resources/UK/Messages - Updated with new error text
Admin:
  Tested on Raspberry Pi & BB-xM
  Support code tested using the supplied test routines and the TestFloat tool (http://www.jhauser.us/arithmetic/TestFloat.html)


Version 0.06. Tagged as 'VFPSupport-0_06'
parent 04c27221
hdr/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
*,ffb gitlab-language=bbcbasic linguist-language=bbcbasic linguist-detectable=true
c/** gitlab-language=c linguist-language=c linguist-detectable=true
**/c/** gitlab-language=c linguist-language=c linguist-detectable=true
h/** gitlab-language=c linguist-language=c linguist-detectable=true
**/h/** gitlab-language=c linguist-language=c linguist-detectable=true
s/CSupport - Apache licence
softfloat/* - SoftFloat licence (see softfloat/ReadMe)
Everything else - ROOL BSD licence
Note that the CSupport and SoftFloat sources are only included in the build if SUPPORTCODE is enabled in the makefile.
......@@ -28,11 +28,70 @@
# Makefile for VFPSupport
#
# Use machine type to determine whether support code is needed
# Can also be overridden on command line by specifying SUPPORTCODE
DEFSUPPORTCODE = FALSE
ifneq (,$(findstring ${MACHINE},All All32 ARM11ZF))
DEFSUPPORTCODE = TRUE
endif
SUPPORTCODE ?= ${DEFSUPPORTCODE}
COMPONENT = VFPSupport
HEADER1 = VFPSupport
ROM_SOURCE = GetAll.s
ASMHDRS = VFPSupport
OBJS = GetAll
HDRS =
CMHGFILE =
ASMDEFINES += -PD "SupportCode SETL {${SUPPORTCODE}}"
RAMASMDEFINES += -PD "standalone SETL {TRUE}" -PD "MergedMsgs SETS \"${MERGEDMSGS}\""
ifeq (${SUPPORTCODE},TRUE)
OBJS += softfloat classify
VPATH = softfloat
endif
include CModule
# We don't want to link to CLib
CLIB =
ROMCSTUBS =
ABSSYM =
CFLAGS += -apcs /nofp
# Force -cpu 5 when building for 'all' to reduce assembler support code
# requirements. This shouldn't pose a problem since the C code will only get hit
# once we've verified VFP hardware is present (i.e. ARMv5+ CPU)
ifneq (,$(findstring ${MACHINE},All All32))
CFLAGS += -cpu 5
endif
# decgen rules
ACTIONS = actions/common \
actions/ARMv7_VFP
ENCODINGS = Build:decgen.encodings.ARMv7 \
Build:decgen.encodings.ARMv7_nASIMD \
Build:decgen.encodings.ARMv7_VFP
DECGEN = <Tools$Dir>.Misc.decgen.decgen
classify.c: $(ACTIONS) head.c $(ENCODINGS)
$(DECGEN) -bits=32 -e -DCDP= -DLDC_STC= -DMRC_MCR= -DVFP1=(cond:4) "-DVFP2={ne(cond,15)}" -DAS1(X)=1111001[X] -DAS2=11110100 $(ENCODINGS) -valid -a $(ACTIONS) -pre head.c -o classify.c -prefix=classify_ -name=classify -default=UNDEFINED -updatecache cache/classify -maxmaskbits=3
classify.o: classify.c shared.h
${CC} ${CFLAGS} -o $@ classify.c
classify.oz: classify.c shared.h
${CC} ${CFLAGS} ${C_MODULE} -o $@ classify.c
shared.h: hdr.shared
${PERL} Build:Hdr2H hdr.shared $@
softfloat.o: shared.h
include StdTools
include AAsmModule
clean::
${RM} c.classify
${RM} h.shared
# Dynamic dependencies:
#{DictTokens}
# Regular errors
E00:No VFP/NEON hardware present
E01:Unsupported VFP/NEON version
E02:A requested VFP/NEON feature is unavailable
E03:Bad VFP context
E04:Bad VFPSupport_Features reason code
E06:Only one instance of VFPSupport can be active at a time
E07:Invalid flags passed to VFPSupport SWI
# Serious errors from support code
S00:No VFP context active
S01:VFP coprocessor not enabled
S02:VFP coprocessor enable state mismatch
S03:Unexpected VFP instruction
S04:Divide by zero in VFP suppport code
S05:Unknown VFP exception requested
# Actual floating point exception errors
IO:Vector floating point exception: invalid operation
DZ:Vector floating point exception: division by zero
OF:Vector floating point exception: overflow
UF:Vector floating point exception: underflow
IX:Vector floating point exception: inexact operation
ID:Vector floating point exception: input subnormal
File added
File added
File added
File added
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "0.05"
Module_Version SETA 5
Module_MajorVersion SETS "0.06"
Module_Version SETA 6
Module_MinorVersion SETS ""
Module_Date SETS "19 Oct 2012"
Module_ApplicationDate SETS "19-Oct-12"
Module_Date SETS "08 Feb 2014"
Module_ApplicationDate SETS "08-Feb-14"
Module_ComponentName SETS "VFPSupport"
Module_ComponentPath SETS "bsd/RiscOS/Sources/HWSupport/VFPSupport"
Module_FullVersion SETS "0.05"
Module_HelpVersion SETS "0.05 (19 Oct 2012)"
Module_ComponentPath SETS "mixed/RiscOS/Sources/HWSupport/VFPSupport"
Module_FullVersion SETS "0.06"
Module_HelpVersion SETS "0.06 (08 Feb 2014)"
END
/* (0.05)
/* (0.06)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.05
#define Module_MajorVersion_CMHG 0.06
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 19 Oct 2012
#define Module_Date_CMHG 08 Feb 2014
#define Module_MajorVersion "0.05"
#define Module_Version 5
#define Module_MajorVersion "0.06"
#define Module_Version 6
#define Module_MinorVersion ""
#define Module_Date "19 Oct 2012"
#define Module_Date "08 Feb 2014"
#define Module_ApplicationDate "19-Oct-12"
#define Module_ApplicationDate "08-Feb-14"
#define Module_ComponentName "VFPSupport"
#define Module_ComponentPath "bsd/RiscOS/Sources/HWSupport/VFPSupport"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/VFPSupport"
#define Module_FullVersion "0.05"
#define Module_HelpVersion "0.05 (19 Oct 2012)"
#define Module_LibraryVersionInfo "0:5"
#define Module_FullVersion "0.06"
#define Module_HelpVersion "0.06 (08 Feb 2014)"
#define Module_LibraryVersionInfo "0:6"
#
# Copyright(c)2014, RISC OS Open Ltd
# Allrightsreserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of RISC OS Open Ltd nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
#
# These actions will fully classify VFP instructions, up to and including VFPv4
# Any unpredictable instructions will also be flagged (as CLASS_NOT_VFP), as we
# can't guarantee that attempting to re-execute them won't result in further
# synchronous exceptions (plus they might completely trash the system!)
VABS_A2(D,sz,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,M)
return class;
}
VADD_fp_A2(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VCMP_VCMPE_A1(D,sz,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,M)
return class;
}
VCMP_VCMPE_A2(D,sz,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
return class;
}
VCVT_VCVTR_fp_int_VFP_A1(D,opc2,sz,M,nonstandard)
{
COMMON_sz_nonstandard(0)
if(!(opc2 & 4))
{
/* Int to float */
D32_CHECK(sz,D);
}
else
{
/* Float to int */
D32_CHECK(sz,M);
}
return class;
}
VCVT_fp_fx_VFP_A1(D,sf,nonstandard)
{
COMMON_nonstandard(CLASS_VFP3)
if(sf)
class |= CLASS_D;
else
class |= CLASS_S;
D32_CHECK(sf,D)
return class;
}
VCVT_dp_sp_A1(D,sz,M,nonstandard)
{
COMMON_nonstandard(CLASS_S | CLASS_D);
D32_CHECK(sz,M)
D32_CHECK(!sz,D)
return class;
}
VCVTB_VCVTT_hp_sp_VFP_A1(nonstandard)
{
int class = CLASS_VFP3 | CLASS_HP;
if(nonstandard)
return CLASS_NOT_VFP;
return class;
}
VDIV_A1(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(CLASS_DIV)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VFMA_VFMS_A2(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(CLASS_VFP4)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VFNMA_VFNMS_A1(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(CLASS_VFP4)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VLDM_A1(D:Vd,W,Rn,imm8,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
uint32_t regs = imm8>>1;
_UNPREDICTABLE((Rn==15) && W);
_UNPREDICTABLE(!regs || (regs > 16) || ((D_Vd+regs) > 32));
if(imm8 & 1)
{
_UNPREDICTABLE(D_Vd+regs > 16);
}
if(D_Vd+regs > 16)
class |= CLASS_D32;
return class;
}
VLDM_A2(Vd:D,W,Rn,imm8,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
uint32_t regs = imm8;
_UNPREDICTABLE((Rn==15) && W);
_UNPREDICTABLE(!regs || ((Vd_D+regs) > 32));
return class;
}
VLDR_A1(D,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
if(D)
class |= CLASS_D32;
return class;
}
VLDR_A2(nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
return class;
}
VMLA_VMLS_fp_A2(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VMOV_imm_A2(D,sz,nonstandard)
{
COMMON_sz_nonstandard(CLASS_VFP3)
D32_CHECK(sz,D)
return class;
}
VMOV_reg_A2(D,sz,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,M)
return class;
}
VMOV_arm_A1(opc1,D,Rt,opc2,nonstandard)
{
int class = CLASS_NOT_CDP;
if(nonstandard || (opc1 & 2) || (opc2 & 3))
return CLASS_NOT_VFP;
if(D)
class |= CLASS_D32;
_UNPREDICTABLE(Rt==15);
return class;
}
VMOV_scalar_A1(U,opc1,N,Rt,opc2,nonstandard)
{
int class = CLASS_NOT_CDP;
if(nonstandard || U || (opc1 & 2) || (opc2 & 3))
return CLASS_NOT_VFP;
if(N)
class |= CLASS_D32;
_UNPREDICTABLE(Rt==15);
return class;
}
VMOV_1fp_A1(Rt,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
_UNPREDICTABLE(Rt==15);
return class;
}
VMOV_2fp_A1(op,Rt2,Rt,Vm:M,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
_UNPREDICTABLE((Rt==15) || (Rt2==15) || (Vm_M==31));
if(op)
{
_UNPREDICTABLE(Rt==Rt2);
}
return class;
}
VMOV_dbl_A1(op,Rt2,Rt,M,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
_UNPREDICTABLE((Rt==15) || (Rt2==15));
if(op)
{
_UNPREDICTABLE(Rt==Rt2);
}
if(M)
class |= CLASS_D32;
return class;
}
VMUL_fp_A2(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VNEG_A2(D,sz,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,M)
return class;
}
VNMLA_VNMLS_VNMUL_A1(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VNMLA_VNMLS_VNMUL_A2(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VPOP_A1(D:Vd,imm8,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
uint32_t regs = imm8>>1;
_UNPREDICTABLE(!regs || (regs > 16) || ((D_Vd+regs) > 32));
if(imm8 & 1)
{
_UNPREDICTABLE(D_Vd+regs > 16);
}
if(D_Vd+regs > 16)
class |= CLASS_D32;
return class;
}
VPOP_A2(Vd:D,imm8,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
uint32_t regs = imm8;
_UNPREDICTABLE(!regs || ((Vd_D+regs) > 32));
return class;
}
VPUSH_A1(D:Vd,imm8,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
uint32_t regs = imm8>>1;
_UNPREDICTABLE(!regs || (regs > 16) || ((D_Vd+regs) > 32));
if(imm8 & 1)
{
_UNPREDICTABLE(D_Vd+regs > 16);
}
if(D_Vd+regs > 16)
class |= CLASS_D32;
return class;
}
VPUSH_A2(Vd:D,imm8,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
uint32_t regs = imm8;
_UNPREDICTABLE(!regs || ((Vd_D+regs) > 32));
return class;
}
VSQRT_A1(D,sz,M,nonstandard)
{
COMMON_sz_nonstandard(CLASS_SQRT)
D32_CHECK(sz,D)
D32_CHECK(sz,M)
return class;
}
VSTM_A1(D:Vd,W,Rn,imm8,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
uint32_t regs = imm8>>1;
_UNPREDICTABLE((Rn==15) && W);
_UNPREDICTABLE(!regs || (regs > 16) || ((D_Vd+regs) > 32));
if(imm8 & 1)
{
_UNPREDICTABLE(D_Vd+regs > 16);
}
if(D_Vd+regs > 16)
class |= CLASS_D32;
return class;
}
VSTM_A2(Vd:D,W,Rn,imm8,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
uint32_t regs = imm8;
_UNPREDICTABLE((Rn==15) && W);
_UNPREDICTABLE(!regs || ((Vd_D+regs) > 32));
return class;
}
VSTR_A1(D,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
if(D)
class |= CLASS_D32;
return class;
}
VSTR_A2(nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
return class;
}
VSUB_fp_A2(D,sz,N,M,nonstandard)
{
COMMON_sz_nonstandard(0)
D32_CHECK(sz,D)
D32_CHECK(sz,N)
D32_CHECK(sz,M)
return class;
}
VMRS_A1(reg,Rt,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
_UNPREDICTABLE((Rt==15) && (reg != REG_FPSCR));
if(!(VMRS_MASK & (1<<reg)))
return CLASS_NOT_VFP;
/* Follow ARMv7 rules and limit user mode to only the FPSCR register */
if((reg != REG_FPSCR) && !privileged_mode())
return CLASS_NOT_VFP;
return class;
}
VMSR_A1(reg,nonstandard)
{
COMMON_nonstandard(CLASS_NOT_CDP)
if(!(VMSR_MASK & (1<<reg)))
return CLASS_NOT_VFP;
/* Follow ARMv7 rules and limit user mode to only the FPSCR register */
if((reg != REG_FPSCR) && !privileged_mode())
return CLASS_NOT_VFP;
return class;
}
#
# Copyright (c) 2014, RISC OS Open Ltd
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * 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.
# * Neither the name of RISC OS Open Ltd nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
#
# Common actions for ARM disassembly
UNDEFINED()
{
(void) OPCODE;
return CLASS_NOT_VFP;
}
UNPREDICTABLE()
{
(void) OPCODE;
return CLASS_NOT_VFP;
}
UNALLOCATED_HINT()
{
(void) OPCODE;
return CLASS_NOT_VFP;
}
PERMA_UNDEFINED()
{
(void) OPCODE;
return CLASS_NOT_VFP;
}
UNALLOCATED_MEM_HINT()
{
(void) OPCODE;
return CLASS_NOT_VFP;
}
/*
* Copyright (c) 2014, RISC OS Open Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: