diff --git a/AltairZ80/altairz80_sio.c b/AltairZ80/altairz80_sio.c index 0763f66b..9f4646ab 100644 --- a/AltairZ80/altairz80_sio.c +++ b/AltairZ80/altairz80_sio.c @@ -1771,12 +1771,12 @@ static int32 simh_out(const int32 port, const int32 data) { if (genInterruptPos == 0) { genInterruptVec = data; genInterruptPos = 1; - sim_printf("genInterruptVec=%d genInterruptPos=%d\n", genInterruptVec, genInterruptPos); + sim_printf("genInterruptVec=%d genInterruptPos=%d\n", genInterruptVec, genInterruptPos); } else { vectorInterrupt |= (1 << genInterruptVec); dataBus[genInterruptVec] = data; genInterruptPos = lastCommand = 0; - sim_printf("genInterruptVec=%d vectorInterrupt=%X dataBus=%02X genInterruptPos=%d\n", genInterruptVec, vectorInterrupt, data, genInterruptPos); + sim_printf("genInterruptVec=%d vectorInterrupt=%X dataBus=%02X genInterruptPos=%d\n", genInterruptVec, vectorInterrupt, data, genInterruptPos); } break; case setFCBAddressCmd: diff --git a/AltairZ80/m68k/example/softfloat/README.txt b/AltairZ80/m68k/example/softfloat/README.txt index 9500d25e..32d024c4 100644 --- a/AltairZ80/m68k/example/softfloat/README.txt +++ b/AltairZ80/m68k/example/softfloat/README.txt @@ -1,78 +1,78 @@ -MAME note: this package is derived from the following original SoftFloat -package and has been "re-packaged" to work with MAME's conventions and -build system. The source files come from bits64/ and bits64/templates -in the original distribution as MAME requires a compiler with a 64-bit -integer type. - - -Package Overview for SoftFloat Release 2b - -John R. Hauser -2002 May 27 - - ----------------------------------------------------------------------------- -Overview - -SoftFloat is a software implementation of floating-point that conforms to -the IEC/IEEE Standard for Binary Floating-Point Arithmetic. SoftFloat is -distributed in the form of C source code. Compiling the SoftFloat sources -generates two things: - --- A SoftFloat object file (typically `softfloat.o') containing the complete - set of IEC/IEEE floating-point routines. - --- A `timesoftfloat' program for evaluating the speed of the SoftFloat - routines. (The SoftFloat module is linked into this program.) - -The SoftFloat package is documented in four text files: - - SoftFloat.txt Documentation for using the SoftFloat functions. - SoftFloat-source.txt Documentation for compiling SoftFloat. - SoftFloat-history.txt History of major changes to SoftFloat. - timesoftfloat.txt Documentation for using `timesoftfloat'. - -Other files in the package comprise the source code for SoftFloat. - -Please be aware that some work is involved in porting this software to other -targets. It is not just a matter of getting `make' to complete without -error messages. I would have written the code that way if I could, but -there are fundamental differences between systems that can't be hidden. -You should not attempt to compile SoftFloat without first reading both -`SoftFloat.txt' and `SoftFloat-source.txt'. - - ----------------------------------------------------------------------------- -Legal Notice - -SoftFloat was written by me, John R. Hauser. This work was made possible in -part by the International Computer Science Institute, located at Suite 600, -1947 Center Street, Berkeley, California 94704. Funding was partially -provided by the National Science Foundation under grant MIP-9311980. The -original version of this code was written as part of a project to build -a fixed-point vector processor in collaboration with the University of -California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort -has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT -TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO -PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL -LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO -FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER -SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, -COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE -SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, provided -that the minimal documentation requirements stated in the source code are -satisfied. - - ----------------------------------------------------------------------------- -Contact Information - -At the time of this writing, the most up-to-date information about -SoftFloat and the latest release can be found at the Web page `http:// -www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html'. - - +MAME note: this package is derived from the following original SoftFloat +package and has been "re-packaged" to work with MAME's conventions and +build system. The source files come from bits64/ and bits64/templates +in the original distribution as MAME requires a compiler with a 64-bit +integer type. + + +Package Overview for SoftFloat Release 2b + +John R. Hauser +2002 May 27 + + +---------------------------------------------------------------------------- +Overview + +SoftFloat is a software implementation of floating-point that conforms to +the IEC/IEEE Standard for Binary Floating-Point Arithmetic. SoftFloat is +distributed in the form of C source code. Compiling the SoftFloat sources +generates two things: + +-- A SoftFloat object file (typically `softfloat.o') containing the complete + set of IEC/IEEE floating-point routines. + +-- A `timesoftfloat' program for evaluating the speed of the SoftFloat + routines. (The SoftFloat module is linked into this program.) + +The SoftFloat package is documented in four text files: + + SoftFloat.txt Documentation for using the SoftFloat functions. + SoftFloat-source.txt Documentation for compiling SoftFloat. + SoftFloat-history.txt History of major changes to SoftFloat. + timesoftfloat.txt Documentation for using `timesoftfloat'. + +Other files in the package comprise the source code for SoftFloat. + +Please be aware that some work is involved in porting this software to other +targets. It is not just a matter of getting `make' to complete without +error messages. I would have written the code that way if I could, but +there are fundamental differences between systems that can't be hidden. +You should not attempt to compile SoftFloat without first reading both +`SoftFloat.txt' and `SoftFloat-source.txt'. + + +---------------------------------------------------------------------------- +Legal Notice + +SoftFloat was written by me, John R. Hauser. This work was made possible in +part by the International Computer Science Institute, located at Suite 600, +1947 Center Street, Berkeley, California 94704. Funding was partially +provided by the National Science Foundation under grant MIP-9311980. The +original version of this code was written as part of a project to build +a fixed-point vector processor in collaboration with the University of +California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL +LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO +FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER +SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, +COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE +SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, provided +that the minimal documentation requirements stated in the source code are +satisfied. + + +---------------------------------------------------------------------------- +Contact Information + +At the time of this writing, the most up-to-date information about +SoftFloat and the latest release can be found at the Web page `http:// +www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html'. + + diff --git a/AltairZ80/m68k/example/softfloat/mamesf.h b/AltairZ80/m68k/example/softfloat/mamesf.h index c4195039..02f1055f 100644 --- a/AltairZ80/m68k/example/softfloat/mamesf.h +++ b/AltairZ80/m68k/example/softfloat/mamesf.h @@ -1,61 +1,61 @@ -/*---------------------------------------------------------------------------- -| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. -*----------------------------------------------------------------------------*/ -#ifdef LSB_FIRST -#define LITTLEENDIAN -#else -#define BIGENDIAN -#endif - -/*---------------------------------------------------------------------------- -| The macro `BITS64' can be defined to indicate that 64-bit integer types are -| supported by the compiler. -*----------------------------------------------------------------------------*/ -#define BITS64 - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines the most convenient type that holds -| integers of at least as many bits as specified. For example, `uint8' should -| be the most convenient type that can hold unsigned integers of as many as -| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most -| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed -| to the same as `int'. -*----------------------------------------------------------------------------*/ - -typedef sint8 flag; -typedef sint8 int8; -typedef sint16 int16; -typedef sint32 int32; -typedef sint64 int64; - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines a type that holds integers -| of _exactly_ the number of bits specified. For instance, for most -| implementation of C, `bits16' and `sbits16' should be `typedef'ed to -| `unsigned short int' and `signed short int' (or `short int'), respectively. -*----------------------------------------------------------------------------*/ -typedef uint8 bits8; -typedef sint8 sbits8; -typedef uint16 bits16; -typedef sint16 sbits16; -typedef uint32 bits32; -typedef sint32 sbits32; -typedef uint64 bits64; -typedef sint64 sbits64; - -/*---------------------------------------------------------------------------- -| The `LIT64' macro takes as its argument a textual integer literal and -| if necessary ``marks'' the literal as having a 64-bit integer type. -| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be -| appended with the letters `LL' standing for `long long', which is `gcc's -| name for the 64-bit integer type. Some compilers may allow `LIT64' to be -| defined as the identity macro: `#define LIT64( a ) a'. -*----------------------------------------------------------------------------*/ -#define LIT64( a ) a##ULL - -/*---------------------------------------------------------------------------- -| The macro `INLINE' can be used before functions that should be inlined. If -| a compiler does not support explicit inlining, this macro should be defined -| to be `static'. -*----------------------------------------------------------------------------*/ -// MAME defines INLINE +/*---------------------------------------------------------------------------- +| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. +*----------------------------------------------------------------------------*/ +#ifdef LSB_FIRST +#define LITTLEENDIAN +#else +#define BIGENDIAN +#endif + +/*---------------------------------------------------------------------------- +| The macro `BITS64' can be defined to indicate that 64-bit integer types are +| supported by the compiler. +*----------------------------------------------------------------------------*/ +#define BITS64 + +/*---------------------------------------------------------------------------- +| Each of the following `typedef's defines the most convenient type that holds +| integers of at least as many bits as specified. For example, `uint8' should +| be the most convenient type that can hold unsigned integers of as many as +| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most +| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed +| to the same as `int'. +*----------------------------------------------------------------------------*/ + +typedef sint8 flag; +typedef sint8 int8; +typedef sint16 int16; +typedef sint32 int32; +typedef sint64 int64; + +/*---------------------------------------------------------------------------- +| Each of the following `typedef's defines a type that holds integers +| of _exactly_ the number of bits specified. For instance, for most +| implementation of C, `bits16' and `sbits16' should be `typedef'ed to +| `unsigned short int' and `signed short int' (or `short int'), respectively. +*----------------------------------------------------------------------------*/ +typedef uint8 bits8; +typedef sint8 sbits8; +typedef uint16 bits16; +typedef sint16 sbits16; +typedef uint32 bits32; +typedef sint32 sbits32; +typedef uint64 bits64; +typedef sint64 sbits64; + +/*---------------------------------------------------------------------------- +| The `LIT64' macro takes as its argument a textual integer literal and +| if necessary ``marks'' the literal as having a 64-bit integer type. +| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be +| appended with the letters `LL' standing for `long long', which is `gcc's +| name for the 64-bit integer type. Some compilers may allow `LIT64' to be +| defined as the identity macro: `#define LIT64( a ) a'. +*----------------------------------------------------------------------------*/ +#define LIT64( a ) a##ULL + +/*---------------------------------------------------------------------------- +| The macro `INLINE' can be used before functions that should be inlined. If +| a compiler does not support explicit inlining, this macro should be defined +| to be `static'. +*----------------------------------------------------------------------------*/ +// MAME defines INLINE diff --git a/AltairZ80/m68k/example/softfloat/milieu.h b/AltairZ80/m68k/example/softfloat/milieu.h index 10687b75..f25f688e 100644 --- a/AltairZ80/m68k/example/softfloat/milieu.h +++ b/AltairZ80/m68k/example/softfloat/milieu.h @@ -1,42 +1,42 @@ - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Include common integer types and flags. -*----------------------------------------------------------------------------*/ -#include "mamesf.h" - -/*---------------------------------------------------------------------------- -| Symbolic Boolean literals. -*----------------------------------------------------------------------------*/ -#define FALSE 0 -#define TRUE 1 + +/*============================================================================ + +This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| Include common integer types and flags. +*----------------------------------------------------------------------------*/ +#include "mamesf.h" + +/*---------------------------------------------------------------------------- +| Symbolic Boolean literals. +*----------------------------------------------------------------------------*/ +#define FALSE 0 +#define TRUE 1 diff --git a/AltairZ80/m68k/example/softfloat/softfloat-macros b/AltairZ80/m68k/example/softfloat/softfloat-macros index 5de9031d..39ef1ba4 100644 --- a/AltairZ80/m68k/example/softfloat/softfloat-macros +++ b/AltairZ80/m68k/example/softfloat/softfloat-macros @@ -1,732 +1,732 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -static inline void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) -{ - bits32 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 32 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -static inline void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) -{ - bits64 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 64 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -static inline void - shift64ExtraRightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else { - z1 = ( ( a0 | a1 ) != 0 ); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - shift128Right( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ); - z0 = a0>>count; - } - else { - z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - shift128RightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ) | ( ( a1<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else if ( count < 128 ) { - z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); - z0 = a0>>count; - } - else { - if ( count == 64 ) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if ( count < 128 ) { - z2 = a0<>( count & 63 ); - } - else { - z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); - z1 = 0; - } - } - z0 = 0; - } - z2 |= ( a2 != 0 ); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' must be less than 64. The result is broken into two 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - shortShift128Left( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1<>( ( - count ) & 63 ) ); - -} - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left -| by the number of bits given in `count'. Any bits shifted off are lost. -| The value of `count' must be less than 64. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - shortShift192Left( - bits64 a0, - bits64 a1, - bits64 a2, - int16 count, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 negCount; - - z2 = a2<>negCount; - z0 |= a1>>negCount; - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - add128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z1; - - z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + ( z1 < a1 ); - -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - add192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - uint8 carry0, carry1; - - z2 = a2 + b2; - carry1 = ( z2 < a2 ); - z1 = a1 + b1; - carry0 = ( z1 < a1 ); - z0 = a0 + b0; - z1 += carry1; - z0 += ( z1 < carry1 ); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - sub128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - ( a1 < b1 ); - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - sub192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - uint8 borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = ( a2 < b2 ); - z1 = a1 - b1; - borrow0 = ( a1 < b1 ); - z0 = a0 - b0; - z0 -= ( z1 < borrow1 ); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits32 aHigh, aLow, bHigh, bLow; - bits64 z0, zMiddleA, zMiddleB, z1; - - aLow = a; - aHigh = a>>32; - bLow = b; - bHigh = b>>32; - z1 = ( (bits64) aLow ) * bLow; - zMiddleA = ( (bits64) aLow ) * bHigh; - zMiddleB = ( (bits64) aHigh ) * bLow; - z0 = ( (bits64) aHigh ) * bHigh; - zMiddleA += zMiddleB; - z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += ( z1 < zMiddleA ); - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - mul128By64To192( - bits64 a0, - bits64 a1, - bits64 b, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2, more1; - - mul64To128( a1, b, &z1, &z2 ); - mul64To128( a0, b, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - mul128To256( - bits64 a0, - bits64 a1, - bits64 b0, - bits64 b1, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr, - bits64 *z3Ptr - ) -{ - bits64 z0, z1, z2, z3; - bits64 more1, more2; - - mul64To128( a1, b1, &z2, &z3 ); - mul64To128( a1, b0, &z1, &more2 ); - add128( z1, more2, 0, z2, &z1, &z2 ); - mul64To128( a0, b0, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - mul64To128( a0, b1, &more1, &more2 ); - add128( more1, more2, 0, z2, &more1, &z2 ); - add128( z0, z1, 0, more1, &z0, &z1 ); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -static inline bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) -{ - bits64 b0, b1; - bits64 rem0, rem1, term0, term1; - bits64 z; - - if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); - b0 = b>>32; - z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; - mul64To128( b, z, &term0, &term1 ); - sub128( a0, a1, term0, term1, &rem0, &rem1 ); - while ( ( (sbits64) rem0 ) < 0 ) { - z -= LIT64( 0x100000000 ); - b1 = b<<32; - add128( rem0, rem1, b0, b1, &rem0, &rem1 ); - } - rem0 = ( rem0<<32 ) | ( rem1>>32 ); - z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -static inline bits32 estimateSqrt32( int16 aExp, bits32 a ) -{ - static const bits16 sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const bits16 sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - int8 index; - bits32 z; - - index = ( a>>27 ) & 15; - if ( aExp & 1 ) { - z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; - z = ( ( a / z )<<14 ) + ( z<<15 ); - a >>= 1; - } - else { - z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; - z = a / z + z; - z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); - if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); - } - return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros32( bits32 a ) -{ - static const int8 countLeadingZerosHigh[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - int8 shiftCount; - - shiftCount = 0; - if ( a < 0x10000 ) { - shiftCount += 16; - a <<= 16; - } - if ( a < 0x1000000 ) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZerosHigh[ a>>24 ]; - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros64( bits64 a ) -{ - int8 shiftCount; - - shiftCount = 0; - if ( a < ( (bits64) 1 )<<32 ) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32( a ); - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -static inline flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 == b0 ) && ( a1 == b1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -static inline flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -static inline flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is -| not equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -static inline flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 != b0 ) || ( a1 != b1 ); - -} - -/*----------------------------------------------------------------------------- -| Changes the sign of the extended double-precision floating-point value 'a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static inline floatx80 floatx80_chs(floatx80 reg) -{ - reg.high ^= 0x8000; - return reg; -} - + +/*============================================================================ + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count'. If any nonzero +| bits are shifted off, they are ``jammed'' into the least significant bit of +| the result by setting the least significant bit to 1. The value of `count' +| can be arbitrarily large; in particular, if `count' is greater than 32, the +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. +| The result is stored in the location pointed to by `zPtr'. +*----------------------------------------------------------------------------*/ + +static inline void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) +{ + bits32 z; + + if ( count == 0 ) { + z = a; + } + else if ( count < 32 ) { + z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); + } + else { + z = ( a != 0 ); + } + *zPtr = z; + +} + +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count'. If any nonzero +| bits are shifted off, they are ``jammed'' into the least significant bit of +| the result by setting the least significant bit to 1. The value of `count' +| can be arbitrarily large; in particular, if `count' is greater than 64, the +| result will be either 0 or 1, depending on whether `a' is zero or nonzero. +| The result is stored in the location pointed to by `zPtr'. +*----------------------------------------------------------------------------*/ + +static inline void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) +{ + bits64 z; + + if ( count == 0 ) { + z = a; + } + else if ( count < 64 ) { + z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); + } + else { + z = ( a != 0 ); + } + *zPtr = z; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 +| _plus_ the number of bits given in `count'. The shifted result is at most +| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The +| bits shifted off form a second 64-bit result as follows: The _last_ bit +| shifted off is the most-significant bit of the extra result, and the other +| 63 bits of the extra result are all zero if and only if _all_but_the_last_ +| bits shifted off were all zero. This extra result is stored in the location +| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. +| (This routine makes more sense if `a0' and `a1' are considered to form +| a fixed-point value with binary point between `a0' and `a1'. This fixed- +| point value is shifted right by the number of bits given in `count', and +| the integer part of the result is returned at the location pointed to by +| `z0Ptr'. The fractional part of the result may be slightly corrupted as +| described above, and is returned at the location pointed to by `z1Ptr'.) +*----------------------------------------------------------------------------*/ + +static inline void + shift64ExtraRightJamming( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z0, z1; + int8 negCount = ( - count ) & 63; + + if ( count == 0 ) { + z1 = a1; + z0 = a0; + } + else if ( count < 64 ) { + z1 = ( a0<>count; + } + else { + if ( count == 64 ) { + z1 = a0 | ( a1 != 0 ); + } + else { + z1 = ( ( a0 | a1 ) != 0 ); + } + z0 = 0; + } + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' can be arbitrarily large; in particular, if `count' is greater +| than 128, the result will be 0. The result is broken into two 64-bit pieces +| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + shift128Right( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z0, z1; + int8 negCount = ( - count ) & 63; + + if ( count == 0 ) { + z1 = a1; + z0 = a0; + } + else if ( count < 64 ) { + z1 = ( a0<>count ); + z0 = a0>>count; + } + else { + z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; + z0 = 0; + } + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the +| number of bits given in `count'. If any nonzero bits are shifted off, they +| are ``jammed'' into the least significant bit of the result by setting the +| least significant bit to 1. The value of `count' can be arbitrarily large; +| in particular, if `count' is greater than 128, the result will be either +| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or +| nonzero. The result is broken into two 64-bit pieces which are stored at +| the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + shift128RightJamming( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z0, z1; + int8 negCount = ( - count ) & 63; + + if ( count == 0 ) { + z1 = a1; + z0 = a0; + } + else if ( count < 64 ) { + z1 = ( a0<>count ) | ( ( a1<>count; + } + else { + if ( count == 64 ) { + z1 = a0 | ( a1 != 0 ); + } + else if ( count < 128 ) { + z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); + z0 = a0>>count; + } + else { + if ( count == 64 ) { + z2 = a1; + z1 = a0; + } + else { + a2 |= a1; + if ( count < 128 ) { + z2 = a0<>( count & 63 ); + } + else { + z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); + z1 = 0; + } + } + z0 = 0; + } + z2 |= ( a2 != 0 ); + } + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the +| number of bits given in `count'. Any bits shifted off are lost. The value +| of `count' must be less than 64. The result is broken into two 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + shortShift128Left( + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + + *z1Ptr = a1<>( ( - count ) & 63 ) ); + +} + +/*---------------------------------------------------------------------------- +| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left +| by the number of bits given in `count'. Any bits shifted off are lost. +| The value of `count' must be less than 64. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + shortShift192Left( + bits64 a0, + bits64 a1, + bits64 a2, + int16 count, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2; + int8 negCount; + + z2 = a2<>negCount; + z0 |= a1>>negCount; + } + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit +| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so +| any carry out is lost. The result is broken into two 64-bit pieces which +| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + add128( + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits64 z1; + + z1 = a1 + b1; + *z1Ptr = z1; + *z0Ptr = a0 + b0 + ( z1 < a1 ); + +} + +/*---------------------------------------------------------------------------- +| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the +| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is +| modulo 2^192, so any carry out is lost. The result is broken into three +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', +| `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + add192( + bits64 a0, + bits64 a1, + bits64 a2, + bits64 b0, + bits64 b1, + bits64 b2, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2; + uint8 carry0, carry1; + + z2 = a2 + b2; + carry1 = ( z2 < a2 ); + z1 = a1 + b1; + carry0 = ( z1 < a1 ); + z0 = a0 + b0; + z1 += carry1; + z0 += ( z1 < carry1 ); + z0 += carry0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the +| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo +| 2^128, so any borrow out (carry out) is lost. The result is broken into two +| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and +| `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + sub128( + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - ( a1 < b1 ); + +} + +/*---------------------------------------------------------------------------- +| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' +| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. +| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The +| result is broken into three 64-bit pieces which are stored at the locations +| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + sub192( + bits64 a0, + bits64 a1, + bits64 a2, + bits64 b0, + bits64 b1, + bits64 b2, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2; + uint8 borrow0, borrow1; + + z2 = a2 - b2; + borrow1 = ( a2 < b2 ); + z1 = a1 - b1; + borrow0 = ( a1 < b1 ); + z0 = a0 - b0; + z0 -= ( z1 < borrow1 ); + z1 -= borrow1; + z0 -= borrow0; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken +| into two 64-bit pieces which are stored at the locations pointed to by +| `z0Ptr' and `z1Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) +{ + bits32 aHigh, aLow, bHigh, bLow; + bits64 z0, zMiddleA, zMiddleB, z1; + + aLow = a; + aHigh = a>>32; + bLow = b; + bHigh = b>>32; + z1 = ( (bits64) aLow ) * bLow; + zMiddleA = ( (bits64) aLow ) * bHigh; + zMiddleB = ( (bits64) aHigh ) * bLow; + z0 = ( (bits64) aHigh ) * bHigh; + zMiddleA += zMiddleB; + z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); + zMiddleA <<= 32; + z1 += zMiddleA; + z0 += ( z1 < zMiddleA ); + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by +| `b' to obtain a 192-bit product. The product is broken into three 64-bit +| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and +| `z2Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + mul128By64To192( + bits64 a0, + bits64 a1, + bits64 b, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr + ) +{ + bits64 z0, z1, z2, more1; + + mul64To128( a1, b, &z1, &z2 ); + mul64To128( a0, b, &z0, &more1 ); + add128( z0, more1, 0, z1, &z0, &z1 ); + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the +| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit +| product. The product is broken into four 64-bit pieces which are stored at +| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. +*----------------------------------------------------------------------------*/ + +static inline void + mul128To256( + bits64 a0, + bits64 a1, + bits64 b0, + bits64 b1, + bits64 *z0Ptr, + bits64 *z1Ptr, + bits64 *z2Ptr, + bits64 *z3Ptr + ) +{ + bits64 z0, z1, z2, z3; + bits64 more1, more2; + + mul64To128( a1, b1, &z2, &z3 ); + mul64To128( a1, b0, &z1, &more2 ); + add128( z1, more2, 0, z2, &z1, &z2 ); + mul64To128( a0, b0, &z0, &more1 ); + add128( z0, more1, 0, z1, &z0, &z1 ); + mul64To128( a0, b1, &more1, &more2 ); + add128( more1, more2, 0, z2, &more1, &z2 ); + add128( z0, z1, 0, more1, &z0, &z1 ); + *z3Ptr = z3; + *z2Ptr = z2; + *z1Ptr = z1; + *z0Ptr = z0; + +} + +/*---------------------------------------------------------------------------- +| Returns an approximation to the 64-bit integer quotient obtained by dividing +| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The +| divisor `b' must be at least 2^63. If q is the exact quotient truncated +| toward zero, the approximation returned lies between q and q + 2 inclusive. +| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit +| unsigned integer is returned. +*----------------------------------------------------------------------------*/ + +static inline bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) +{ + bits64 b0, b1; + bits64 rem0, rem1, term0, term1; + bits64 z; + + if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); + b0 = b>>32; + z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; + mul64To128( b, z, &term0, &term1 ); + sub128( a0, a1, term0, term1, &rem0, &rem1 ); + while ( ( (sbits64) rem0 ) < 0 ) { + z -= LIT64( 0x100000000 ); + b1 = b<<32; + add128( rem0, rem1, b0, b1, &rem0, &rem1 ); + } + rem0 = ( rem0<<32 ) | ( rem1>>32 ); + z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns an approximation to the square root of the 32-bit significand given +| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of +| `aExp' (the least significant bit) is 1, the integer returned approximates +| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' +| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either +| case, the approximation returned lies strictly within +/-2 of the exact +| value. +*----------------------------------------------------------------------------*/ + +static inline bits32 estimateSqrt32( int16 aExp, bits32 a ) +{ + static const bits16 sqrtOddAdjustments[] = { + 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, + 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 + }; + static const bits16 sqrtEvenAdjustments[] = { + 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, + 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 + }; + int8 index; + bits32 z; + + index = ( a>>27 ) & 15; + if ( aExp & 1 ) { + z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; + z = ( ( a / z )<<14 ) + ( z<<15 ); + a >>= 1; + } + else { + z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; + z = a / z + z; + z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); + if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); + } + return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 32 is returned. +*----------------------------------------------------------------------------*/ + +static int8 countLeadingZeros32( bits32 a ) +{ + static const int8 countLeadingZerosHigh[] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + int8 shiftCount; + + shiftCount = 0; + if ( a < 0x10000 ) { + shiftCount += 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + shiftCount += 8; + a <<= 8; + } + shiftCount += countLeadingZerosHigh[ a>>24 ]; + return shiftCount; + +} + +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 64 is returned. +*----------------------------------------------------------------------------*/ + +static int8 countLeadingZeros64( bits64 a ) +{ + int8 shiftCount; + + shiftCount = 0; + if ( a < ( (bits64) 1 )<<32 ) { + shiftCount += 32; + } + else { + a >>= 32; + } + shiftCount += countLeadingZeros32( a ); + return shiftCount; + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' +| is equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +static inline flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 == b0 ) && ( a1 == b1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +static inline flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less +| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, +| returns 0. +*----------------------------------------------------------------------------*/ + +static inline flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is +| not equal to the 128-bit value formed by concatenating `b0' and `b1'. +| Otherwise, returns 0. +*----------------------------------------------------------------------------*/ + +static inline flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) +{ + + return ( a0 != b0 ) || ( a1 != b1 ); + +} + +/*----------------------------------------------------------------------------- +| Changes the sign of the extended double-precision floating-point value 'a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static inline floatx80 floatx80_chs(floatx80 reg) +{ + reg.high ^= 0x8000; + return reg; +} + diff --git a/AltairZ80/m68k/example/softfloat/softfloat-specialize b/AltairZ80/m68k/example/softfloat/softfloat-specialize index a3113bad..b1f9da49 100644 --- a/AltairZ80/m68k/example/softfloat/softfloat-specialize +++ b/AltairZ80/m68k/example/softfloat/softfloat-specialize @@ -1,476 +1,476 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -flag float32_is_nan( float32 a ); -flag float64_is_nan( float64 a ); -flag floatx80_is_nan( floatx80 a ); -floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ); -flag float128_is_nan( float128 a ); - -/*---------------------------------------------------------------------------- -| Underflow tininess-detection mode, statically initialized to default value. -| (The declaration in `softfloat.h' must match the `int8' type here.) -*----------------------------------------------------------------------------*/ -int8 float_detect_tininess = float_tininess_after_rounding; - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap to -| substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void float_raise( int8 flags ) -{ - - float_exception_flags |= flags; - -} - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -typedef struct { - flag sign; - bits64 high, low; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#define float32_default_nan 0xFFFFFFFF - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_nan( float32 a ) -{ - - return ( 0xFF000000 < (bits32) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_signaling_nan( float32 a ) -{ - - return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float32ToCommonNaN( float32 a ) -{ - commonNaNT z; - - if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>31; - z.low = 0; - z.high = ( (bits64) a )<<41; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float32 commonNaNToFloat32( commonNaNT a ) -{ - - return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32NaN( float32 a, float32 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float32_is_nan( a ); - aIsSignalingNaN = float32_is_signaling_nan( a ); - bIsNaN = float32_is_nan( b ); - bIsSignalingNaN = float32_is_signaling_nan( b ); - a |= 0x00400000; - b |= 0x00400000; - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_nan( float64 a ) -{ - - return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_signaling_nan( float64 a ) -{ - - return - ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) - && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float64ToCommonNaN( float64 a ) -{ - commonNaNT z; - - if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>63; - z.low = 0; - z.high = a<<12; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float64 commonNaNToFloat64( commonNaNT a ) -{ - - return - ( ( (bits64) a.sign )<<63 ) - | LIT64( 0x7FF8000000000000 ) - | ( a.high>>12 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64NaN( float64 a, float64 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float64_is_nan( a ); - aIsSignalingNaN = float64_is_signaling_nan( a ); - bIsNaN = float64_is_nan( b ); - bIsSignalingNaN = float64_is_signaling_nan( b ); - a |= LIT64( 0x0008000000000000 ); - b |= LIT64( 0x0008000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. The -| `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_high 0xFFFF -#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_nan( floatx80 a ) -{ - - return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_signaling_nan( floatx80 a ) -{ - bits64 aLow; - - aLow = a.low & ~ LIT64( 0x4000000000000000 ); - return - ( ( a.high & 0x7FFF ) == 0x7FFF ) - && (bits64) ( aLow<<1 ) - && ( a.low == aLow ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT floatx80ToCommonNaN( floatx80 a ) -{ - commonNaNT z; - - if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>15; - z.low = 0; - z.high = a.low<<1; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -static floatx80 commonNaNToFloatx80( commonNaNT a ) -{ - floatx80 z; - - z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); - z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = floatx80_is_nan( a ); - aIsSignalingNaN = floatx80_is_signaling_nan( a ); - bIsNaN = floatx80_is_nan( b ); - bIsSignalingNaN = floatx80_is_signaling_nan( b ); - a.low |= LIT64( 0xC000000000000000 ); - b.low |= LIT64( 0xC000000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -#define EXP_BIAS 0x3FFF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -static inline bits64 extractFloatx80Frac( floatx80 a ) -{ - - return a.low; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -static inline int32 extractFloatx80Exp( floatx80 a ) -{ - - return a.high & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloatx80Sign( floatx80 a ) -{ - - return a.high>>15; - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) -#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_nan( float128 a ) -{ - - return - ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) - && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_signaling_nan( float128 a ) -{ - - return - ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) - && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float128ToCommonNaN( float128 a ) -{ - commonNaNT z; - - if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>63; - shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float128 commonNaNToFloat128( commonNaNT a ) -{ - float128 z; - - shift128Right( a.high, a.low, 16, &z.high, &z.low ); - z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float128 propagateFloat128NaN( float128 a, float128 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float128_is_nan( a ); - aIsSignalingNaN = float128_is_signaling_nan( a ); - bIsNaN = float128_is_nan( b ); - bIsSignalingNaN = float128_is_signaling_nan( b ); - a.high |= LIT64( 0x0000800000000000 ); - b.high |= LIT64( 0x0000800000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -#endif - + +/*============================================================================ + +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +flag float32_is_nan( float32 a ); +flag float64_is_nan( float64 a ); +flag floatx80_is_nan( floatx80 a ); +floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ); +flag float128_is_nan( float128 a ); + +/*---------------------------------------------------------------------------- +| Underflow tininess-detection mode, statically initialized to default value. +| (The declaration in `softfloat.h' must match the `int8' type here.) +*----------------------------------------------------------------------------*/ +int8 float_detect_tininess = float_tininess_after_rounding; + +/*---------------------------------------------------------------------------- +| Raises the exceptions specified by `flags'. Floating-point traps can be +| defined here if desired. It is currently not possible for such a trap to +| substitute a result value. If traps are not implemented, this routine +| should be simply `float_exception_flags |= flags;'. +*----------------------------------------------------------------------------*/ + +void float_raise( int8 flags ) +{ + + float_exception_flags |= flags; + +} + +/*---------------------------------------------------------------------------- +| Internal canonical NaN format. +*----------------------------------------------------------------------------*/ +typedef struct { + flag sign; + bits64 high, low; +} commonNaNT; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +#define float32_default_nan 0xFFFFFFFF + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float32_is_nan( float32 a ) +{ + + return ( 0xFF000000 < (bits32) ( a<<1 ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float32_is_signaling_nan( float32 a ) +{ + + return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float32ToCommonNaN( float32 a ) +{ + commonNaNT z; + + if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a>>31; + z.low = 0; + z.high = ( (bits64) a )<<41; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the single- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float32 commonNaNToFloat32( commonNaNT a ) +{ + + return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); + +} + +/*---------------------------------------------------------------------------- +| Takes two single-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float32 propagateFloat32NaN( float32 a, float32 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float32_is_nan( a ); + aIsSignalingNaN = float32_is_signaling_nan( a ); + bIsNaN = float32_is_nan( b ); + bIsSignalingNaN = float32_is_signaling_nan( b ); + a |= 0x00400000; + b |= 0x00400000; + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsNaN ) { + return ( aIsSignalingNaN & bIsNaN ) ? b : a; + } + else { + return b; + } + +} + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float64_is_nan( float64 a ) +{ + + return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is a signaling +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float64_is_signaling_nan( float64 a ) +{ + + return + ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) + && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float64ToCommonNaN( float64 a ) +{ + commonNaNT z; + + if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a>>63; + z.low = 0; + z.high = a<<12; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the double- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float64 commonNaNToFloat64( commonNaNT a ) +{ + + return + ( ( (bits64) a.sign )<<63 ) + | LIT64( 0x7FF8000000000000 ) + | ( a.high>>12 ); + +} + +/*---------------------------------------------------------------------------- +| Takes two double-precision floating-point values `a' and `b', one of which +| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float64 propagateFloat64NaN( float64 a, float64 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float64_is_nan( a ); + aIsSignalingNaN = float64_is_signaling_nan( a ); + bIsNaN = float64_is_nan( b ); + bIsSignalingNaN = float64_is_signaling_nan( b ); + a |= LIT64( 0x0008000000000000 ); + b |= LIT64( 0x0008000000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsNaN ) { + return ( aIsSignalingNaN & bIsNaN ) ? b : a; + } + else { + return b; + } + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. The +| `high' and `low' values hold the most- and least-significant bits, +| respectively. +*----------------------------------------------------------------------------*/ +#define floatx80_default_nan_high 0xFFFF +#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is a +| NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag floatx80_is_nan( floatx80 a ) +{ + + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is a +| signaling NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag floatx80_is_signaling_nan( floatx80 a ) +{ + bits64 aLow; + + aLow = a.low & ~ LIT64( 0x4000000000000000 ); + return + ( ( a.high & 0x7FFF ) == 0x7FFF ) + && (bits64) ( aLow<<1 ) + && ( a.low == aLow ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT floatx80ToCommonNaN( floatx80 a ) +{ + commonNaNT z; + + if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a.high>>15; + z.low = 0; + z.high = a.low<<1; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the extended +| double-precision floating-point format. +*----------------------------------------------------------------------------*/ + +static floatx80 commonNaNToFloatx80( commonNaNT a ) +{ + floatx80 z; + + z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); + z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes two extended double-precision floating-point values `a' and `b', one +| of which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = floatx80_is_nan( a ); + aIsSignalingNaN = floatx80_is_signaling_nan( a ); + bIsNaN = floatx80_is_nan( b ); + bIsSignalingNaN = floatx80_is_signaling_nan( b ); + a.low |= LIT64( 0xC000000000000000 ); + b.low |= LIT64( 0xC000000000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsNaN ) { + return ( aIsSignalingNaN & bIsNaN ) ? b : a; + } + else { + return b; + } + +} + +#define EXP_BIAS 0x3FFF + +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the extended double-precision floating-point +| value `a'. +*----------------------------------------------------------------------------*/ + +static inline bits64 extractFloatx80Frac( floatx80 a ) +{ + + return a.low; + +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the extended double-precision floating-point +| value `a'. +*----------------------------------------------------------------------------*/ + +static inline int32 extractFloatx80Exp( floatx80 a ) +{ + + return a.high & 0x7FFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the extended double-precision floating-point value +| `a'. +*----------------------------------------------------------------------------*/ + +static inline flag extractFloatx80Sign( floatx80 a ) +{ + + return a.high>>15; + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| The pattern for a default generated quadruple-precision NaN. The `high' and +| `low' values hold the most- and least-significant bits, respectively. +*----------------------------------------------------------------------------*/ +#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) +#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; +| otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float128_is_nan( float128 a ) +{ + + return + ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) + && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is a +| signaling NaN; otherwise returns 0. +*----------------------------------------------------------------------------*/ + +flag float128_is_signaling_nan( float128 a ) +{ + + return + ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) + && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point NaN +| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ + +static commonNaNT float128ToCommonNaN( float128 a ) +{ + commonNaNT z; + + if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); + z.sign = a.high>>63; + shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the quadruple- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static float128 commonNaNToFloat128( commonNaNT a ) +{ + float128 z; + + shift128Right( a.high, a.low, 16, &z.high, &z.low ); + z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes two quadruple-precision floating-point values `a' and `b', one of +| which is a NaN, and returns the appropriate NaN result. If either `a' or +| `b' is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ + +static float128 propagateFloat128NaN( float128 a, float128 b ) +{ + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + + aIsNaN = float128_is_nan( a ); + aIsSignalingNaN = float128_is_signaling_nan( a ); + bIsNaN = float128_is_nan( b ); + bIsSignalingNaN = float128_is_signaling_nan( b ); + a.high |= LIT64( 0x0000800000000000 ); + b.high |= LIT64( 0x0000800000000000 ); + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); + if ( aIsNaN ) { + return ( aIsSignalingNaN & bIsNaN ) ? b : a; + } + else { + return b; + } + +} + +#endif + diff --git a/AltairZ80/m68k/example/softfloat/softfloat.c b/AltairZ80/m68k/example/softfloat/softfloat.c index 400fd593..75c0f20e 100644 --- a/AltairZ80/m68k/example/softfloat/softfloat.c +++ b/AltairZ80/m68k/example/softfloat/softfloat.c @@ -1,4940 +1,4940 @@ - -/*============================================================================ - -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "../m68kcpu.h" // which includes softfloat.h after defining the basic types - -/*---------------------------------------------------------------------------- -| Floating-point rounding mode, extended double-precision rounding precision, -| and exception flags. -*----------------------------------------------------------------------------*/ -int8 float_exception_flags = 0; -#ifdef FLOATX80 -int8 floatx80_rounding_precision = 80; -#endif - -int8 float_rounding_mode = float_round_nearest_even; - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) -{ - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int32 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - roundIncrement = 0x40; - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if ( zSign ) { - if ( roundingMode == float_round_up ) roundIncrement = 0; - } - else { - if ( roundingMode == float_round_down ) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = ( absZ + roundIncrement )>>7; - absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - z = absZ; - if ( zSign ) z = - z; - if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_raise( float_flag_invalid ); - return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( roundBits ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest positive or negative integer is -| returned. -*----------------------------------------------------------------------------*/ - -static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) -{ - int8 roundingMode; - flag roundNearestEven, increment; - int64 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) absZ1 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && absZ1; - } - else { - increment = ( roundingMode == float_round_up ) && absZ1; - } - } - } - if ( increment ) { - ++absZ0; - if ( absZ0 == 0 ) goto overflow; - absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); - } - z = absZ0; - if ( zSign ) z = - z; - if ( z && ( ( z < 0 ) ^ zSign ) ) { - overflow: - float_raise( float_flag_invalid ); - return - zSign ? (sbits64) LIT64( 0x8000000000000000 ) - : (sbits64) LIT64( 0x7FFFFFFFFFFFFFFF ); - } - if ( absZ1 ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline bits32 extractFloat32Frac( float32 a ) -{ - return a & 0x007FFFFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline int16 extractFloat32Exp( float32 a ) -{ - return ( a>>23 ) & 0xFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat32Sign( float32 a ) -{ - return a>>31; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( aSig ) - 8; - *zSigPtr = aSig<>7; - zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat64Sign( float64 a ) -{ - return a>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ) - 11; - *zSigPtr = aSig<>10; - zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>48 ) & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat128Sign( float128 a ) -{ - return a.high>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat128Subnormal( - bits64 aSig0, - bits64 aSig1, - int32 *zExpPtr, - bits64 *zSig0Ptr, - bits64 *zSig1Ptr - ) -{ - int8 shiftCount; - - if ( aSig0 == 0 ) { - shiftCount = countLeadingZeros64( aSig1 ) - 15; - if ( shiftCount < 0 ) { - *zSig0Ptr = aSig1>>( - shiftCount ); - *zSig1Ptr = aSig1<<( shiftCount & 63 ); - } - else { - *zSig0Ptr = aSig1<>( - shiftCount ); - if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64, aSigExtra; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = 0xBE - aExp; - if ( shiftCount < 0 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - if ( aExp ) aSig |= 0x00800000; - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); - return roundAndPackInt64( aSign, aSig64, aSigExtra ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64_round_to_zero( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64; - int64 z; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0xBE; - if ( 0 <= shiftCount ) { - if ( a != 0xDF000000 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>( - shiftCount ); - if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); - return packFloat64( aSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float32_to_floatx80( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - aSig |= 0x00800000; - return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float32_to_float128( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 lastBitMask, roundBitsMask; - int8 roundingMode; - float32 z; - - aExp = extractFloat32Exp( a ); - if ( 0x96 <= aExp ) { - if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { - return propagateFloat32NaN( a, a ); - } - return a; - } - if ( aExp <= 0x7E ) { - if ( (bits32) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat32Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { - return packFloat32( aSign, 0x7F, 0 ); - } - break; - case float_round_down: - return aSign ? 0xBF800000 : 0; - case float_round_up: - return aSign ? 0x80000000 : 0x3F800000; - } - return packFloat32( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - if ( 0 < expDiff ) { - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x20000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x20000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); - zSig = 0x40000000 + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= 0x20000000; - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits32) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign ^ 1, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x40000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x40000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return addFloat32Sigs( a, b, aSign ); - } - else { - return subFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return subFloat32Sigs( a, b, aSign ); - } - else { - return addFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig; - bits64 zSig64; - bits32 zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x7F; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); - zSig = zSig64; - if ( 0 <= (sbits32) ( zSig<<1 ) ) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat32( zSign, 0xFF, 0 ); - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x7D; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = ( ( (bits64) aSig )<<32 ) / bSig; - if ( ( zSig & 0x3F ) == 0 ) { - zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the single-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_rem( float32 a, float32 b ) -{ - flag aSign, zSign; - int16 aExp, bExp, expDiff; - bits32 aSig, bSig; - bits32 q; - bits64 aSig64, bSig64, q64; - bits32 alternateASig; - sbits32 sigMean; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); -// bSign = extractFloat32Sign( b ); - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig |= 0x00800000; - bSig |= 0x00800000; - if ( expDiff < 32 ) { - aSig <<= 8; - bSig <<= 8; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - if ( 0 < expDiff ) { - q = ( ( (bits64) aSig )<<32 ) / bSig; - q >>= 32 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - } - else { - if ( bSig <= aSig ) aSig -= bSig; - aSig64 = ( (bits64) aSig )<<40; - bSig64 = ( (bits64) bSig )<<40; - expDiff -= 64; - while ( 0 < expDiff ) { - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - aSig64 = - ( ( bSig * q64 )<<38 ); - expDiff -= 62; - } - expDiff += 64; - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - q = q64>>( 64 - expDiff ); - bSig <<= 6; - aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits32) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits32) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt( float32 a ) -{ - flag aSign; - int16 aExp, zExp; - bits32 aSig, zSig; - bits64 rem, term; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, 0 ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; - aSig = ( aSig | 0x00800000 )<<8; - zSig = estimateSqrt32( aExp, aSig ) + 2; - if ( ( zSig & 0x7F ) <= 5 ) { - if ( zSig < 2 ) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ( (bits64) zSig ) * zSig; - rem = ( ( (bits64) aSig )<<32 ) - term; - while ( (sbits64) rem < 0 ) { - --zSig; - rem += ( ( (bits64) zSig )<<1 ) | 1; - } - zSig |= ( rem != 0 ); - } - shift32RightJamming( zSig, 1, &zSig ); - roundAndPack: - return roundAndPackFloat32( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq( float32 a, float32 b ) -{ - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq_signaling( float32 a, float32 b ) -{ - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; -// int16 aExp, bExp; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x42C - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32_round_to_zero( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( 0x41E < aExp ) { - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - bits32 zSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 22, &aSig ); - zSig = aSig; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float64_to_floatx80( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - return - packFloatx80( - aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the quadruple-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float64_to_float128( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float64 z; - - aExp = extractFloat64Exp( a ); - if ( 0x433 <= aExp ) { - if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { - return propagateFloat64NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FF ) { - if ( (bits64) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat64Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { - return packFloat64( aSign, 0x3FF, 0 ); - } - break; - case float_round_down: - return aSign ? LIT64( 0xBFF0000000000000 ) : 0; - case float_round_up: - return - aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); - } - return packFloat64( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if ( 0 < expDiff ) { - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); - zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= LIT64( 0x2000000000000000 ); - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits64) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign ^ 1, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - bSig |= LIT64( 0x4000000000000000 ); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - aSig |= LIT64( 0x4000000000000000 ); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return addFloat64Sigs( a, b, aSign ); - } - else { - return subFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return subFloat64Sigs( a, b, aSign ); - } - else { - return addFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FF; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - zSig0 |= ( zSig1 != 0 ); - if ( 0 <= (sbits64) ( zSig0<<1 ) ) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64( zSign, zExp, zSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - bits64 rem0, rem1; - bits64 term0, term1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat64( zSign, 0x7FF, 0 ); - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FD; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64( aSig, 0, bSig ); - if ( ( zSig & 0x1FF ) <= 2 ) { - mul64To128( bSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig |= ( rem1 != 0 ); - } - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the double-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_rem( float64 a, float64 b ) -{ - flag aSign, zSign; - int16 aExp, bExp, expDiff; - bits64 aSig, bSig; - bits64 q, alternateASig; - sbits64 sigMean; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); -// bSign = extractFloat64Sign( b ); - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - aSig = - ( ( bSig>>2 ) * q ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits64) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits64) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt( float64 a ) -{ - flag aSign; - int16 aExp, zExp; - bits64 aSig, zSig, doubleZSig; - bits64 rem0, rem1, term0, term1; -// float64 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, a ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; - aSig |= LIT64( 0x0010000000000000 ); - zSig = estimateSqrt32( aExp, aSig>>21 ); - aSig <<= 9 - ( aExp & 1 ); - zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); - if ( ( zSig & 0x1FF ) <= 5 ) { - doubleZSig = zSig<<1; - mul64To128( zSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - doubleZSig -= 2; - add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); - } - zSig |= ( ( rem0 | rem1 ) != 0 ); - } - return roundAndPackFloat64( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq( float64 a, float64 b ) -{ - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The invalid exception is raised -| if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq_signaling( float64 a, float64 b ) -{ - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; -// int16 aExp, bExp; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic---which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN, the -| largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - shiftCount = 0x4037 - aExp; - if ( shiftCount <= 0 ) shiftCount = 1; - shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN, the largest positive integer is returned. -| Otherwise, if the conversion overflows, the largest integer with the same -| sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32_round_to_zero( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 33, &aSig ); - if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig, zSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shift64RightJamming( aSig, 1, &zSig ); - if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); - -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128( floatx80 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); - } - shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended quadruple-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - floatx80 z; - - aExp = extractFloatx80Exp( a ); - if ( 0x403E <= aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { - return propagateFloatx80NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FFF ) { - if ( ( aExp == 0 ) - && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { - return a; - } - float_exception_flags |= float_flag_inexact; - aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) - ) { - return - packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - break; - case float_round_down: - return - aSign ? - packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) - : packFloatx80( 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloatx80( 1, 0, 0 ) - : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - return packFloatx80( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.low += lastBitMask>>1; - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z.low += roundBitsMask; - } - } - z.low &= ~ roundBitsMask; - if ( z.low == 0 ) { - ++z.high; - z.low = LIT64( 0x8000000000000000 ); - } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if ( aExp == 0 ) { - normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ( (sbits64) zSig0 < 0 ) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); - ++zExp; - roundAndPack: - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - bBigger: - sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - aBigger: - sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); - } - else { - return subFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); - } - else { - return addFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) goto invalid; - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - if ( 0 < (sbits64) zSig0 ) { - shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); - --zExp; - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - bits64 rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - goto invalid; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if ( bSig <= aSig ) { - shift128Right( aSig, 0, 1, &aSig, &rem1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig, rem1, bSig ); - mul64To128( bSig, zSig0, &term0, &term1 ); - sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, bSig ); - if ( (bits64) ( zSig1<<1 ) <= 8 ) { - mul64To128( bSig, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); - } - zSig1 |= ( ( rem1 | rem2 ) != 0 ); - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_rem( floatx80 a, floatx80 b ) -{ - flag aSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig; - bits64 q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); -// bSign = extractFloatx80Sign( b ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( (bits64) ( aSig0<<1 ) == 0 ) return a; - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - bSig |= LIT64( 0x8000000000000000 ); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); - expDiff = 0; - } - q = ( bSig <= aSig0 ); - if ( q ) aSig0 -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - mul64To128( bSig, q, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); - while ( le128( term0, term1, aSig0, aSig1 ) ) { - ++q; - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - } - } - else { - term1 = 0; - term0 = bSig; - } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt( floatx80 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; - zSig0 = estimateSqrt32( aExp, aSig0>>32 ); - shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq( floatx80 a, floatx80 b ) -{ - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq_signaling( floatx80 a, floatx80 b ) -{ - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - aSig0 |= ( aSig1 != 0 ); - shiftCount = 0x4028 - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); - return roundAndPackInt32( aSign, aSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32_round_to_zero( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1, savedASig; - int32 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - aSig0 |= ( aSig1 != 0 ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = aSig0; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); - if ( (bits64) ( aSig1<>( - shiftCount ); - if ( aSig1 - || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - bits32 zSig; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - aSig0 |= ( aSig1 != 0 ); - shift64RightJamming( aSig0, 18, &aSig0 ); - zSig = aSig0; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - aSig0 |= ( aSig1 != 0 ); - if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); - aExp -= 0x3C01; - } - return roundAndPackFloat64( aSign, aExp, aSig0 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a ) ); - } - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); - return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, and -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float128 z; - - aExp = extractFloat128Exp( a ); - if ( 0x402F <= aExp ) { - if ( 0x406F <= aExp ) { - if ( ( aExp == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) - ) { - return propagateFloat128NaN( a, a ); - } - return a; - } - lastBitMask = 1; - lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else { - if ( (sbits64) z.low < 0 ) { - ++z.high; - if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; - } - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); - } - } - z.low &= ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat128Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.high += lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { - z.high &= ~ lastBitMask; - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - z.high |= ( a.low != 0 ); - z.high += roundBitsMask; - } - } - z.high &= ~ roundBitsMask; - } - if ( ( z.low != a.low ) || ( z.high != a.high ) ) { - float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32 expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32 expDiff; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs( a, b, aSign ); - } - else { - return subFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs( a, b, aSign ); - } - else { - return addFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the quadruple-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_rem( float128 a, float128 b ) -{ - flag aSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; - bits64 allZero, alternateASig0, alternateASig1, sigMean1; - sbits64 sigMean0; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); -// bSign = extractFloat128Sign( b ); - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return a; - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - expDiff = aExp - bExp; - if ( expDiff < -1 ) return a; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), - aSig1, - 15 - ( expDiff < 0 ), - &aSig0, - &aSig1 - ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - q = le128( bSig0, bSig1, aSig0, aSig1 ); - if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); - shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); - sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); - expDiff -= 61; - } - if ( -64 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - q >>= - expDiff; - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - expDiff += 52; - if ( expDiff < 0 ) { - shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - } - else { - shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); - } - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); - } - else { - shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - } - do { - alternateASig0 = aSig0; - alternateASig1 = aSig1; - ++q; - sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - } while ( 0 <= (sbits64) aSig0 ); - add128( - aSig0, aSig1, alternateASig0, alternateASig1, (bits64 *)&sigMean0, &sigMean1 ); - if ( ( sigMean0 < 0 ) - || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - } - zSign = ( (sbits64) aSig0 < 0 ); - if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); - return - normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt( float128 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); - zSig0 = estimateSqrt32( aExp, aSig0>>17 ); - shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & 0x1FFF ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq( float128 a, float128 b ) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq_signaling( float128 a, float128 b ) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif + +/*============================================================================ + +This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +#include "../m68kcpu.h" // which includes softfloat.h after defining the basic types + +/*---------------------------------------------------------------------------- +| Floating-point rounding mode, extended double-precision rounding precision, +| and exception flags. +*----------------------------------------------------------------------------*/ +int8 float_exception_flags = 0; +#ifdef FLOATX80 +int8 floatx80_rounding_precision = 80; +#endif + +int8 float_rounding_mode = float_round_nearest_even; + +/*---------------------------------------------------------------------------- +| Functions and definitions to determine: (1) whether tininess for underflow +| is detected before or after rounding by default, (2) what (if anything) +| happens when exceptions are raised, (3) how signaling NaNs are distinguished +| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs +| are propagated from function inputs to output. These details are target- +| specific. +*----------------------------------------------------------------------------*/ +#include "softfloat-specialize" + +/*---------------------------------------------------------------------------- +| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 +| and 7, and returns the properly rounded 32-bit integer corresponding to the +| input. If `zSign' is 1, the input is negated before being converted to an +| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input +| is simply rounded to an integer, with the inexact exception raised if the +| input cannot be represented exactly as an integer. However, if the fixed- +| point input is too large, the invalid exception is raised and the largest +| positive or negative integer is returned. +*----------------------------------------------------------------------------*/ + +static int32 roundAndPackInt32( flag zSign, bits64 absZ ) +{ + int8 roundingMode; + flag roundNearestEven; + int8 roundIncrement, roundBits; + int32 z; + + roundingMode = float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + roundIncrement = 0x40; + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + roundIncrement = 0; + } + else { + roundIncrement = 0x7F; + if ( zSign ) { + if ( roundingMode == float_round_up ) roundIncrement = 0; + } + else { + if ( roundingMode == float_round_down ) roundIncrement = 0; + } + } + } + roundBits = absZ & 0x7F; + absZ = ( absZ + roundIncrement )>>7; + absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + z = absZ; + if ( zSign ) z = - z; + if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { + float_raise( float_flag_invalid ); + return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( roundBits ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit integer corresponding to the input. +| If `zSign' is 1, the input is negated before being converted to an integer. +| Ordinarily, the fixed-point input is simply rounded to an integer, with +| the inexact exception raised if the input cannot be represented exactly as +| an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the largest positive or negative integer is +| returned. +*----------------------------------------------------------------------------*/ + +static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) +{ + int8 roundingMode; + flag roundNearestEven, increment; + int64 z; + + roundingMode = float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + increment = ( (sbits64) absZ1 < 0 ); + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + increment = 0; + } + else { + if ( zSign ) { + increment = ( roundingMode == float_round_down ) && absZ1; + } + else { + increment = ( roundingMode == float_round_up ) && absZ1; + } + } + } + if ( increment ) { + ++absZ0; + if ( absZ0 == 0 ) goto overflow; + absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); + } + z = absZ0; + if ( zSign ) z = - z; + if ( z && ( ( z < 0 ) ^ zSign ) ) { + overflow: + float_raise( float_flag_invalid ); + return + zSign ? (sbits64) LIT64( 0x8000000000000000 ) + : (sbits64) LIT64( 0x7FFFFFFFFFFFFFFF ); + } + if ( absZ1 ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline bits32 extractFloat32Frac( float32 a ) +{ + return a & 0x007FFFFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline int16 extractFloat32Exp( float32 a ) +{ + return ( a>>23 ) & 0xFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline flag extractFloat32Sign( float32 a ) +{ + return a>>31; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal single-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros32( aSig ) - 8; + *zSigPtr = aSig<>7; + zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + if ( zSig == 0 ) zExp = 0; + return packFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper single-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat32' except that `zSig' does not have to be normalized. +| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +static float32 + normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros32( zSig ) - 1; + return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline flag extractFloat64Sign( float64 a ) +{ + return a>>63; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal double-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64( aSig ) - 11; + *zSigPtr = aSig<>10; + zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); + if ( zSig == 0 ) zExp = 0; + return packFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper double-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat64' except that `zSig' does not have to be normalized. +| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +static float64 + normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64( zSig ) - 1; + return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>48 ) & 0x7FFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the quadruple-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline flag extractFloat128Sign( float128 a ) +{ + return a.high>>63; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal quadruple-precision floating-point value +| represented by the denormalized significand formed by the concatenation of +| `aSig0' and `aSig1'. The normalized exponent is stored at the location +| pointed to by `zExpPtr'. The most significant 49 bits of the normalized +| significand are stored at the location pointed to by `zSig0Ptr', and the +| least significant 64 bits of the normalized significand are stored at the +| location pointed to by `zSig1Ptr'. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat128Subnormal( + bits64 aSig0, + bits64 aSig1, + int32 *zExpPtr, + bits64 *zSig0Ptr, + bits64 *zSig1Ptr + ) +{ + int8 shiftCount; + + if ( aSig0 == 0 ) { + shiftCount = countLeadingZeros64( aSig1 ) - 15; + if ( shiftCount < 0 ) { + *zSig0Ptr = aSig1>>( - shiftCount ); + *zSig1Ptr = aSig1<<( shiftCount & 63 ); + } + else { + *zSig0Ptr = aSig1<>( - shiftCount ); + if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. Otherwise, if the conversion overflows, the +| largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int64 float32_to_int64( float32 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits32 aSig; + bits64 aSig64, aSigExtra; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + shiftCount = 0xBE - aExp; + if ( shiftCount < 0 ) { + float_raise( float_flag_invalid ); + if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + if ( aExp ) aSig |= 0x00800000; + aSig64 = aSig; + aSig64 <<= 40; + shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); + return roundAndPackInt64( aSign, aSig64, aSigExtra ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. If +| `a' is a NaN, the largest positive integer is returned. Otherwise, if the +| conversion overflows, the largest integer with the same sign as `a' is +| returned. +*----------------------------------------------------------------------------*/ + +int64 float32_to_int64_round_to_zero( float32 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits32 aSig; + bits64 aSig64; + int64 z; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + shiftCount = aExp - 0xBE; + if ( 0 <= shiftCount ) { + if ( a != 0xDF000000 ) { + float_raise( float_flag_invalid ); + if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + else if ( aExp <= 0x7E ) { + if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig64 = aSig | 0x00800000; + aSig64 <<= 40; + z = aSig64>>( - shiftCount ); + if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the double-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float32_to_float64( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); + return packFloat64( aSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the extended double-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float32_to_floatx80( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + aSig |= 0x00800000; + return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the double-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float32_to_float128( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); + return packFloat128( aSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the single-precision floating-point value `a' to an integer, and +| returns the result as a single-precision floating-point value. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_round_to_int( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 lastBitMask, roundBitsMask; + int8 roundingMode; + float32 z; + + aExp = extractFloat32Exp( a ); + if ( 0x96 <= aExp ) { + if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { + return propagateFloat32NaN( a, a ); + } + return a; + } + if ( aExp <= 0x7E ) { + if ( (bits32) ( a<<1 ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat32Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { + return packFloat32( aSign, 0x7F, 0 ); + } + break; + case float_round_down: + return aSign ? 0xBF800000 : 0; + case float_round_up: + return aSign ? 0x80000000 : 0x3F800000; + } + return packFloat32( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x96 - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z += lastBitMask>>1; + if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z += roundBitsMask; + } + } + z &= ~ roundBitsMask; + if ( z != a ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the single-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + expDiff = aExp - bExp; + aSig <<= 6; + bSig <<= 6; + if ( 0 < expDiff ) { + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= 0x20000000; + } + shift32RightJamming( bSig, expDiff, &bSig ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign, 0xFF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= 0x20000000; + } + shift32RightJamming( aSig, - expDiff, &aSig ); + zExp = bExp; + } + else { + if ( aExp == 0xFF ) { + if ( aSig | bSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); + zSig = 0x40000000 + aSig + bSig; + zExp = aExp; + goto roundAndPack; + } + aSig |= 0x20000000; + zSig = ( aSig + bSig )<<1; + --zExp; + if ( (sbits32) zSig < 0 ) { + zSig = aSig + bSig; + ++zExp; + } + roundAndPack: + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the single- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + expDiff = aExp - bExp; + aSig <<= 7; + bSig <<= 7; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0xFF ) { + if ( aSig | bSig ) return propagateFloat32NaN( a, b ); + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign ^ 1, 0xFF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= 0x40000000; + } + shift32RightJamming( aSig, - expDiff, &aSig ); + bSig |= 0x40000000; + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= 0x40000000; + } + shift32RightJamming( bSig, expDiff, &bSig ); + aSig |= 0x40000000; + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the single-precision floating-point values `a' +| and `b'. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_add( float32 a, float32 b ) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign == bSign ) { + return addFloat32Sigs( a, b, aSign ); + } + else { + return subFloat32Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_sub( float32 a, float32 b ) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign == bSign ) { + return subFloat32Sigs( a, b, aSign ); + } + else { + return addFloat32Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_mul( float32 a, float32 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits32 aSig, bSig; + bits64 zSig64; + bits32 zSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + bSign = extractFloat32Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0xFF ) { + if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { + return propagateFloat32NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x7F; + aSig = ( aSig | 0x00800000 )<<7; + bSig = ( bSig | 0x00800000 )<<8; + shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); + zSig = zSig64; + if ( 0 <= (sbits32) ( zSig<<1 ) ) { + zSig <<= 1; + --zExp; + } + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the single-precision floating-point value `a' +| by the corresponding value `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_div( float32 a, float32 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + bSign = extractFloat32Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + float_raise( float_flag_divbyzero ); + return packFloat32( zSign, 0xFF, 0 ); + } + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x7D; + aSig = ( aSig | 0x00800000 )<<7; + bSig = ( bSig | 0x00800000 )<<8; + if ( bSig <= ( aSig + aSig ) ) { + aSig >>= 1; + ++zExp; + } + zSig = ( ( (bits64) aSig )<<32 ) / bSig; + if ( ( zSig & 0x3F ) == 0 ) { + zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); + } + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the single-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_rem( float32 a, float32 b ) +{ + flag aSign, zSign; + int16 aExp, bExp, expDiff; + bits32 aSig, bSig; + bits32 q; + bits64 aSig64, bSig64, q64; + bits32 alternateASig; + sbits32 sigMean; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); +// bSign = extractFloat32Sign( b ); + if ( aExp == 0xFF ) { + if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { + return propagateFloat32NaN( a, b ); + } + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return a; + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + expDiff = aExp - bExp; + aSig |= 0x00800000; + bSig |= 0x00800000; + if ( expDiff < 32 ) { + aSig <<= 8; + bSig <<= 8; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + aSig >>= 1; + } + q = ( bSig <= aSig ); + if ( q ) aSig -= bSig; + if ( 0 < expDiff ) { + q = ( ( (bits64) aSig )<<32 ) / bSig; + q >>= 32 - expDiff; + bSig >>= 2; + aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; + } + else { + aSig >>= 2; + bSig >>= 2; + } + } + else { + if ( bSig <= aSig ) aSig -= bSig; + aSig64 = ( (bits64) aSig )<<40; + bSig64 = ( (bits64) bSig )<<40; + expDiff -= 64; + while ( 0 < expDiff ) { + q64 = estimateDiv128To64( aSig64, 0, bSig64 ); + q64 = ( 2 < q64 ) ? q64 - 2 : 0; + aSig64 = - ( ( bSig * q64 )<<38 ); + expDiff -= 62; + } + expDiff += 64; + q64 = estimateDiv128To64( aSig64, 0, bSig64 ); + q64 = ( 2 < q64 ) ? q64 - 2 : 0; + q = q64>>( 64 - expDiff ); + bSig <<= 6; + aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; + } + do { + alternateASig = aSig; + ++q; + aSig -= bSig; + } while ( 0 <= (sbits32) aSig ); + sigMean = aSig + alternateASig; + if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { + aSig = alternateASig; + } + zSign = ( (sbits32) aSig < 0 ); + if ( zSign ) aSig = - aSig; + return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the single-precision floating-point value `a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_sqrt( float32 a ) +{ + flag aSign; + int16 aExp, zExp; + bits32 aSig, zSig; + bits64 rem, term; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, 0 ); + if ( ! aSign ) return a; + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aSign ) { + if ( ( aExp | aSig ) == 0 ) return a; + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return 0; + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; + aSig = ( aSig | 0x00800000 )<<8; + zSig = estimateSqrt32( aExp, aSig ) + 2; + if ( ( zSig & 0x7F ) <= 5 ) { + if ( zSig < 2 ) { + zSig = 0x7FFFFFFF; + goto roundAndPack; + } + aSig >>= aExp & 1; + term = ( (bits64) zSig ) * zSig; + rem = ( ( (bits64) aSig )<<32 ) - term; + while ( (sbits64) rem < 0 ) { + --zSig; + rem += ( ( (bits64) zSig )<<1 ) | 1; + } + zSig |= ( rem != 0 ); + } + shift32RightJamming( zSig, 1, &zSig ); + roundAndPack: + return roundAndPackFloat32( 0, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_eq( float32 a, float32 b ) +{ + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. The comparison +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_le( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_lt( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_eq_signaling( float32 a, float32 b ) +{ + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_le_quiet( float32 a, float32 b ) +{ + flag aSign, bSign; +// int16 aExp, bExp; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_lt_quiet( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. Otherwise, if the conversion overflows, the +| largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 float64_to_int32( float64 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits64 aSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; + if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); + shiftCount = 0x42C - aExp; + if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); + return roundAndPackInt32( aSign, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. +| If `a' is a NaN, the largest positive integer is returned. Otherwise, if +| the conversion overflows, the largest integer with the same sign as `a' is +| returned. +*----------------------------------------------------------------------------*/ + +int32 float64_to_int32_round_to_zero( float64 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits64 aSig, savedASig; + int32 z; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( 0x41E < aExp ) { + if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FF ) { + if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig |= LIT64( 0x0010000000000000 ); + shiftCount = 0x433 - aExp; + savedASig = aSig; + aSig >>= shiftCount; + z = aSig; + if ( aSign ) z = - z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig<>( - shiftCount ); + if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the single-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float64_to_float32( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig; + bits32 zSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); + return packFloat32( aSign, 0xFF, 0 ); + } + shift64RightJamming( aSig, 22, &aSig ); + zSig = aSig; + if ( aExp || zSig ) { + zSig |= 0x40000000; + aExp -= 0x381; + } + return roundAndPackFloat32( aSign, aExp, zSig ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the extended double-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float64_to_floatx80( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + return + packFloatx80( + aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the quadruple-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float64_to_float128( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig, zSig0, zSig1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); + return packFloat128( aSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); + return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the double-precision floating-point value `a' to an integer, and +| returns the result as a double-precision floating-point value. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_round_to_int( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + float64 z; + + aExp = extractFloat64Exp( a ); + if ( 0x433 <= aExp ) { + if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { + return propagateFloat64NaN( a, a ); + } + return a; + } + if ( aExp < 0x3FF ) { + if ( (bits64) ( a<<1 ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat64Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { + return packFloat64( aSign, 0x3FF, 0 ); + } + break; + case float_round_down: + return aSign ? LIT64( 0xBFF0000000000000 ) : 0; + case float_round_up: + return + aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); + } + return packFloat64( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x433 - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z += lastBitMask>>1; + if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z += roundBitsMask; + } + } + z &= ~ roundBitsMask; + if ( z != a ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the double-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + expDiff = aExp - bExp; + aSig <<= 9; + bSig <<= 9; + if ( 0 < expDiff ) { + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= LIT64( 0x2000000000000000 ); + } + shift64RightJamming( bSig, expDiff, &bSig ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= LIT64( 0x2000000000000000 ); + } + shift64RightJamming( aSig, - expDiff, &aSig ); + zExp = bExp; + } + else { + if ( aExp == 0x7FF ) { + if ( aSig | bSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); + zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; + zExp = aExp; + goto roundAndPack; + } + aSig |= LIT64( 0x2000000000000000 ); + zSig = ( aSig + bSig )<<1; + --zExp; + if ( (sbits64) zSig < 0 ) { + zSig = aSig + bSig; + ++zExp; + } + roundAndPack: + return roundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the double- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + expDiff = aExp - bExp; + aSig <<= 10; + bSig <<= 10; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FF ) { + if ( aSig | bSig ) return propagateFloat64NaN( a, b ); + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign ^ 1, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= LIT64( 0x4000000000000000 ); + } + shift64RightJamming( aSig, - expDiff, &aSig ); + bSig |= LIT64( 0x4000000000000000 ); + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= LIT64( 0x4000000000000000 ); + } + shift64RightJamming( bSig, expDiff, &bSig ); + aSig |= LIT64( 0x4000000000000000 ); + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the double-precision floating-point values `a' +| and `b'. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_add( float64 a, float64 b ) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign == bSign ) { + return addFloat64Sigs( a, b, aSign ); + } + else { + return subFloat64Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_sub( float64 a, float64 b ) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign == bSign ) { + return subFloat64Sigs( a, b, aSign ); + } + else { + return addFloat64Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_mul( float64 a, float64 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + bSign = extractFloat64Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FF ) { + if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { + return propagateFloat64NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x3FF; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + mul64To128( aSig, bSig, &zSig0, &zSig1 ); + zSig0 |= ( zSig1 != 0 ); + if ( 0 <= (sbits64) ( zSig0<<1 ) ) { + zSig0 <<= 1; + --zExp; + } + return roundAndPackFloat64( zSign, zExp, zSig0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the double-precision floating-point value `a' +| by the corresponding value `b'. The operation is performed according to +| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_div( float64 a, float64 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + bits64 rem0, rem1; + bits64 term0, term1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + bSign = extractFloat64Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + float_raise( float_flag_divbyzero ); + return packFloat64( zSign, 0x7FF, 0 ); + } + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x3FD; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + if ( bSig <= ( aSig + aSig ) ) { + aSig >>= 1; + ++zExp; + } + zSig = estimateDiv128To64( aSig, 0, bSig ); + if ( ( zSig & 0x1FF ) <= 2 ) { + mul64To128( bSig, zSig, &term0, &term1 ); + sub128( aSig, 0, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig; + add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); + } + zSig |= ( rem1 != 0 ); + } + return roundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the double-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_rem( float64 a, float64 b ) +{ + flag aSign, zSign; + int16 aExp, bExp, expDiff; + bits64 aSig, bSig; + bits64 q, alternateASig; + sbits64 sigMean; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); +// bSign = extractFloat64Sign( b ); + if ( aExp == 0x7FF ) { + if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { + return propagateFloat64NaN( a, b ); + } + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return a; + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + expDiff = aExp - bExp; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + aSig >>= 1; + } + q = ( bSig <= aSig ); + if ( q ) aSig -= bSig; + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig, 0, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + aSig = - ( ( bSig>>2 ) * q ); + expDiff -= 62; + } + expDiff += 64; + if ( 0 < expDiff ) { + q = estimateDiv128To64( aSig, 0, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + q >>= 64 - expDiff; + bSig >>= 2; + aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; + } + else { + aSig >>= 2; + bSig >>= 2; + } + do { + alternateASig = aSig; + ++q; + aSig -= bSig; + } while ( 0 <= (sbits64) aSig ); + sigMean = aSig + alternateASig; + if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { + aSig = alternateASig; + } + zSign = ( (sbits64) aSig < 0 ); + if ( zSign ) aSig = - aSig; + return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the double-precision floating-point value `a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_sqrt( float64 a ) +{ + flag aSign; + int16 aExp, zExp; + bits64 aSig, zSig, doubleZSig; + bits64 rem0, rem1, term0, term1; +// float64 z; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, a ); + if ( ! aSign ) return a; + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aSign ) { + if ( ( aExp | aSig ) == 0 ) return a; + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return 0; + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; + aSig |= LIT64( 0x0010000000000000 ); + zSig = estimateSqrt32( aExp, aSig>>21 ); + aSig <<= 9 - ( aExp & 1 ); + zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); + if ( ( zSig & 0x1FF ) <= 5 ) { + doubleZSig = zSig<<1; + mul64To128( zSig, zSig, &term0, &term1 ); + sub128( aSig, 0, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig; + doubleZSig -= 2; + add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); + } + zSig |= ( ( rem0 | rem1 ) != 0 ); + } + return roundAndPackFloat64( 0, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is equal to the +| corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_eq( float64 a, float64 b ) +{ + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_le( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_lt( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is equal to the +| corresponding value `b', and 0 otherwise. The invalid exception is raised +| if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_eq_signaling( float64 a, float64 b ) +{ + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_le_quiet( float64 a, float64 b ) +{ + flag aSign, bSign; +// int16 aExp, bExp; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_lt_quiet( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the 32-bit two's complement integer format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic---which means in particular that the conversion +| is rounded according to the current rounding mode. If `a' is a NaN, the +| largest positive integer is returned. Otherwise, if the conversion +| overflows, the largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 floatx80_to_int32( floatx80 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; + shiftCount = 0x4037 - aExp; + if ( shiftCount <= 0 ) shiftCount = 1; + shift64RightJamming( aSig, shiftCount, &aSig ); + return roundAndPackInt32( aSign, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the 32-bit two's complement integer format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic, except that the conversion is always rounded +| toward zero. If `a' is a NaN, the largest positive integer is returned. +| Otherwise, if the conversion overflows, the largest integer with the same +| sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 floatx80_to_int32_round_to_zero( floatx80 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig, savedASig; + int32 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( 0x401E < aExp ) { + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FFF ) { + if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + shiftCount = 0x403E - aExp; + savedASig = aSig; + aSig >>= shiftCount; + z = aSig; + if ( aSign ) z = - z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig<>( - shiftCount ); + if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the single-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 floatx80_to_float32( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); + } + return packFloat32( aSign, 0xFF, 0 ); + } + shift64RightJamming( aSig, 33, &aSig ); + if ( aExp || aSig ) aExp -= 0x3F81; + return roundAndPackFloat32( aSign, aExp, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the double-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 floatx80_to_float64( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig, zSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); + } + return packFloat64( aSign, 0x7FF, 0 ); + } + shift64RightJamming( aSig, 1, &zSig ); + if ( aExp || aSig ) aExp -= 0x3C01; + return roundAndPackFloat64( aSign, aExp, zSig ); + +} + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the quadruple-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 floatx80_to_float128( floatx80 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig, zSig0, zSig1; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); + } + shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); + return packFloat128( aSign, aExp, zSig0, zSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the extended double-precision floating-point value `a' to an integer, +| and returns the result as an extended quadruple-precision floating-point +| value. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_round_to_int( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + floatx80 z; + + aExp = extractFloatx80Exp( a ); + if ( 0x403E <= aExp ) { + if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { + return propagateFloatx80NaN( a, a ); + } + return a; + } + if ( aExp < 0x3FFF ) { + if ( ( aExp == 0 ) + && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { + return a; + } + float_exception_flags |= float_flag_inexact; + aSign = extractFloatx80Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) + ) { + return + packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); + } + break; + case float_round_down: + return + aSign ? + packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) + : packFloatx80( 0, 0, 0 ); + case float_round_up: + return + aSign ? packFloatx80( 1, 0, 0 ) + : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); + } + return packFloatx80( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x403E - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z.low += lastBitMask>>1; + if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z.low += roundBitsMask; + } + } + z.low &= ~ roundBitsMask; + if ( z.low == 0 ) { + ++z.high; + z.low = LIT64( 0x8000000000000000 ); + } + if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the extended double- +| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is +| negated before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + int32 expDiff; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) { + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) --expDiff; + shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) ++expDiff; + shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); + zExp = bExp; + } + else { + if ( aExp == 0x7FFF ) { + if ( (bits64) ( ( aSig | bSig )<<1 ) ) { + return propagateFloatx80NaN( a, b ); + } + return a; + } + zSig1 = 0; + zSig0 = aSig + bSig; + if ( aExp == 0 ) { + normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); + goto roundAndPack; + } + zExp = aExp; + goto shiftRight1; + } + zSig0 = aSig + bSig; + if ( (sbits64) zSig0 < 0 ) goto roundAndPack; + shiftRight1: + shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); + zSig0 |= LIT64( 0x8000000000000000 ); + ++zExp; + roundAndPack: + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the extended +| double-precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + int32 expDiff; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( ( aSig | bSig )<<1 ) ) { + return propagateFloatx80NaN( a, b ); + } + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + zSig1 = 0; + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) ++expDiff; + shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); + bBigger: + sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) --expDiff; + shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); + aBigger: + sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); + zExp = aExp; + normalizeRoundAndPack: + return + normalizeRoundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the extended double-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_add( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign == bSign ) { + return addFloatx80Sigs( a, b, aSign ); + } + else { + return subFloatx80Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the extended double-precision floating- +| point values `a' and `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_sub( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign == bSign ) { + return subFloatx80Sigs( a, b, aSign ); + } + else { + return addFloatx80Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the extended double-precision floating- +| point values `a' and `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_mul( floatx80 a, floatx80 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + bSign = extractFloatx80Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) + || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { + return propagateFloatx80NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) goto invalid; + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x3FFE; + mul64To128( aSig, bSig, &zSig0, &zSig1 ); + if ( 0 < (sbits64) zSig0 ) { + shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); + --zExp; + } + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the extended double-precision floating-point +| value `a' by the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_div( floatx80 a, floatx80 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + bits64 rem0, rem1, rem2, term0, term1, term2; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + bSign = extractFloatx80Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + goto invalid; + } + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + float_raise( float_flag_divbyzero ); + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x3FFE; + rem1 = 0; + if ( bSig <= aSig ) { + shift128Right( aSig, 0, 1, &aSig, &rem1 ); + ++zExp; + } + zSig0 = estimateDiv128To64( aSig, rem1, bSig ); + mul64To128( bSig, zSig0, &term0, &term1 ); + sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, bSig ); + if ( (bits64) ( zSig1<<1 ) <= 8 ) { + mul64To128( bSig, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); + } + zSig1 |= ( ( rem1 | rem2 ) != 0 ); + } + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_rem( floatx80 a, floatx80 b ) +{ + flag aSign, zSign; + int32 aExp, bExp, expDiff; + bits64 aSig0, aSig1, bSig; + bits64 q, term0, term1, alternateASig0, alternateASig1; + floatx80 z; + + aSig0 = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); +// bSign = extractFloatx80Sign( b ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig0<<1 ) + || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { + return propagateFloatx80NaN( a, b ); + } + goto invalid; + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( (bits64) ( aSig0<<1 ) == 0 ) return a; + normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); + } + bSig |= LIT64( 0x8000000000000000 ); + zSign = aSign; + expDiff = aExp - bExp; + aSig1 = 0; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); + expDiff = 0; + } + q = ( bSig <= aSig0 ); + if ( q ) aSig0 -= bSig; + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + mul64To128( bSig, q, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); + expDiff -= 62; + } + expDiff += 64; + if ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + q >>= 64 - expDiff; + mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); + while ( le128( term0, term1, aSig0, aSig1 ) ) { + ++q; + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + } + } + else { + term1 = 0; + term0 = bSig; + } + sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); + if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) + || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) + && ( q & 1 ) ) + ) { + aSig0 = alternateASig0; + aSig1 = alternateASig1; + zSign = ! zSign; + } + return + normalizeRoundAndPackFloatx80( + 80, zSign, bExp + expDiff, aSig0, aSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the extended double-precision floating-point +| value `a'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_sqrt( floatx80 a ) +{ + flag aSign; + int32 aExp, zExp; + bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + floatx80 z; + + aSig0 = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); + if ( ! aSign ) return a; + goto invalid; + } + if ( aSign ) { + if ( ( aExp | aSig0 ) == 0 ) return a; + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + if ( aExp == 0 ) { + if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); + normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); + } + zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; + zSig0 = estimateSqrt32( aExp, aSig0>>32 ); + shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); + zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); + doubleZSig0 = zSig0<<1; + mul64To128( zSig0, zSig0, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + doubleZSig0 -= 2; + add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); + if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { + if ( zSig1 == 0 ) zSig1 = 1; + mul64To128( doubleZSig0, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + mul64To128( zSig1, zSig1, &term2, &term3 ); + sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + shortShift128Left( 0, zSig1, 1, &term2, &term3 ); + term3 |= 1; + term2 |= doubleZSig0; + add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); + zSig0 |= doubleZSig0; + return + roundAndPackFloatx80( + floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| equal to the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_eq( floatx80 a, floatx80 b ) +{ + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| less than or equal to the corresponding value `b', and 0 otherwise. The +| comparison is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_le( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| less than the corresponding value `b', and 0 otherwise. The comparison +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_lt( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is equal +| to the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_eq_signaling( floatx80 a, floatx80 b ) +{ + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is less +| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs +| do not cause an exception. Otherwise, the comparison is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_le_quiet( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is less +| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause +| an exception. Otherwise, the comparison is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_lt_quiet( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the 32-bit two's complement integer format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. Otherwise, if the conversion overflows, the +| largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 float128_to_int32( float128 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; + if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= ( aSig1 != 0 ); + shiftCount = 0x4028 - aExp; + if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); + return roundAndPackInt32( aSign, aSig0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the 32-bit two's complement integer format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. If +| `a' is a NaN, the largest positive integer is returned. Otherwise, if the +| conversion overflows, the largest integer with the same sign as `a' is +| returned. +*----------------------------------------------------------------------------*/ + +int32 float128_to_int32_round_to_zero( float128 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig0, aSig1, savedASig; + int32 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + aSig0 |= ( aSig1 != 0 ); + if ( 0x401E < aExp ) { + if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FFF ) { + if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig0 |= LIT64( 0x0001000000000000 ); + shiftCount = 0x402F - aExp; + savedASig = aSig0; + aSig0 >>= shiftCount; + z = aSig0; + if ( aSign ) z = - z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); + if ( (bits64) ( aSig1<>( - shiftCount ); + if ( aSig1 + || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { + float_exception_flags |= float_flag_inexact; + } + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the single-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float128_to_float32( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + bits32 zSig; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloat32( float128ToCommonNaN( a ) ); + } + return packFloat32( aSign, 0xFF, 0 ); + } + aSig0 |= ( aSig1 != 0 ); + shift64RightJamming( aSig0, 18, &aSig0 ); + zSig = aSig0; + if ( aExp || zSig ) { + zSig |= 0x40000000; + aExp -= 0x3F81; + } + return roundAndPackFloat32( aSign, aExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the double-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float128_to_float64( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloat64( float128ToCommonNaN( a ) ); + } + return packFloat64( aSign, 0x7FF, 0 ); + } + shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); + aSig0 |= ( aSig1 != 0 ); + if ( aExp || aSig0 ) { + aSig0 |= LIT64( 0x4000000000000000 ); + aExp -= 0x3C01; + } + return roundAndPackFloat64( aSign, aExp, aSig0 ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the extended double-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float128_to_floatx80( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloatx80( float128ToCommonNaN( a ) ); + } + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + else { + aSig0 |= LIT64( 0x0001000000000000 ); + } + shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); + return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the quadruple-precision floating-point value `a' to an integer, and +| returns the result as a quadruple-precision floating-point value. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_round_to_int( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + float128 z; + + aExp = extractFloat128Exp( a ); + if ( 0x402F <= aExp ) { + if ( 0x406F <= aExp ) { + if ( ( aExp == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) + ) { + return propagateFloat128NaN( a, a ); + } + return a; + } + lastBitMask = 1; + lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + if ( lastBitMask ) { + add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); + if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; + } + else { + if ( (sbits64) z.low < 0 ) { + ++z.high; + if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; + } + } + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat128Sign( z ) + ^ ( roundingMode == float_round_up ) ) { + add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); + } + } + z.low &= ~ roundBitsMask; + } + else { + if ( aExp < 0x3FFF ) { + if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat128Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FFE ) + && ( extractFloat128Frac0( a ) + | extractFloat128Frac1( a ) ) + ) { + return packFloat128( aSign, 0x3FFF, 0, 0 ); + } + break; + case float_round_down: + return + aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) + : packFloat128( 0, 0, 0, 0 ); + case float_round_up: + return + aSign ? packFloat128( 1, 0, 0, 0 ) + : packFloat128( 0, 0x3FFF, 0, 0 ); + } + return packFloat128( aSign, 0, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x402F - aExp; + roundBitsMask = lastBitMask - 1; + z.low = 0; + z.high = a.high; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z.high += lastBitMask>>1; + if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { + z.high &= ~ lastBitMask; + } + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat128Sign( z ) + ^ ( roundingMode == float_round_up ) ) { + z.high |= ( a.low != 0 ); + z.high += roundBitsMask; + } + } + z.high &= ~ roundBitsMask; + } + if ( ( z.low != a.low ) || ( z.high != a.high ) ) { + float_exception_flags |= float_flag_inexact; + } + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the quadruple-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + int32 expDiff; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) { + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig0 |= LIT64( 0x0001000000000000 ); + } + shift128ExtraRightJamming( + bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig0 |= LIT64( 0x0001000000000000 ); + } + shift128ExtraRightJamming( + aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); + zExp = bExp; + } + else { + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 | bSig0 | bSig1 ) { + return propagateFloat128NaN( a, b ); + } + return a; + } + add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); + zSig2 = 0; + zSig0 |= LIT64( 0x0002000000000000 ); + zExp = aExp; + goto shiftRight1; + } + aSig0 |= LIT64( 0x0001000000000000 ); + add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + --zExp; + if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; + ++zExp; + shiftRight1: + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); + roundAndPack: + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the quadruple- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; + int32 expDiff; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + expDiff = aExp - bExp; + shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); + shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 | bSig0 | bSig1 ) { + return propagateFloat128NaN( a, b ); + } + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig0 < aSig0 ) goto aBigger; + if ( aSig0 < bSig0 ) goto bBigger; + if ( bSig1 < aSig1 ) goto aBigger; + if ( aSig1 < bSig1 ) goto bBigger; + return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig0 |= LIT64( 0x4000000000000000 ); + } + shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); + bSig0 |= LIT64( 0x4000000000000000 ); + bBigger: + sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig0 |= LIT64( 0x4000000000000000 ); + } + shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); + aSig0 |= LIT64( 0x4000000000000000 ); + aBigger: + sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the quadruple-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_add( float128 a, float128 b ) +{ + flag aSign, bSign; + + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign == bSign ) { + return addFloat128Sigs( a, b, aSign ); + } + else { + return subFloat128Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the quadruple-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_sub( float128 a, float128 b ) +{ + flag aSign, bSign; + + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign == bSign ) { + return subFloat128Sigs( a, b, aSign ); + } + else { + return addFloat128Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the quadruple-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_mul( float128 a, float128 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + bSign = extractFloat128Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( ( aSig0 | aSig1 ) + || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { + return propagateFloat128NaN( a, b ); + } + if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + if ( ( aExp | aSig0 | aSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + zExp = aExp + bExp - 0x4000; + aSig0 |= LIT64( 0x0001000000000000 ); + shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); + mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); + add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); + zSig2 |= ( zSig3 != 0 ); + if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); + ++zExp; + } + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the quadruple-precision floating-point value +| `a' by the corresponding value `b'. The operation is performed according to +| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_div( float128 a, float128 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + bSign = extractFloat128Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + goto invalid; + } + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign, 0, 0, 0 ); + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) { + if ( ( aExp | aSig0 | aSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + float_raise( float_flag_divbyzero ); + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + zExp = aExp - bExp + 0x3FFD; + shortShift128Left( + aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); + shortShift128Left( + bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); + if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { + shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); + ++zExp; + } + zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); + mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); + sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); + } + zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); + if ( ( zSig1 & 0x3FFF ) <= 4 ) { + mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); + sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the quadruple-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_rem( float128 a, float128 b ) +{ + flag aSign, zSign; + int32 aExp, bExp, expDiff; + bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; + bits64 allZero, alternateASig0, alternateASig1, sigMean1; + sbits64 sigMean0; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); +// bSign = extractFloat128Sign( b ); + if ( aExp == 0x7FFF ) { + if ( ( aSig0 | aSig1 ) + || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { + return propagateFloat128NaN( a, b ); + } + goto invalid; + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return a; + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + expDiff = aExp - bExp; + if ( expDiff < -1 ) return a; + shortShift128Left( + aSig0 | LIT64( 0x0001000000000000 ), + aSig1, + 15 - ( expDiff < 0 ), + &aSig0, + &aSig1 + ); + shortShift128Left( + bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); + q = le128( bSig0, bSig1, aSig0, aSig1 ); + if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig0 ); + q = ( 4 < q ) ? q - 4 : 0; + mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); + shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); + shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); + sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); + expDiff -= 61; + } + if ( -64 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig0 ); + q = ( 4 < q ) ? q - 4 : 0; + q >>= - expDiff; + shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); + expDiff += 52; + if ( expDiff < 0 ) { + shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); + } + else { + shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); + } + mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); + sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); + } + else { + shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); + shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); + } + do { + alternateASig0 = aSig0; + alternateASig1 = aSig1; + ++q; + sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); + } while ( 0 <= (sbits64) aSig0 ); + add128( + aSig0, aSig1, alternateASig0, alternateASig1, (bits64 *)&sigMean0, &sigMean1 ); + if ( ( sigMean0 < 0 ) + || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { + aSig0 = alternateASig0; + aSig1 = alternateASig1; + } + zSign = ( (sbits64) aSig0 < 0 ); + if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); + return + normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the quadruple-precision floating-point value `a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_sqrt( float128 a ) +{ + flag aSign; + int32 aExp, zExp; + bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); + if ( ! aSign ) return a; + goto invalid; + } + if ( aSign ) { + if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; + aSig0 |= LIT64( 0x0001000000000000 ); + zSig0 = estimateSqrt32( aExp, aSig0>>17 ); + shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); + zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); + doubleZSig0 = zSig0<<1; + mul64To128( zSig0, zSig0, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + doubleZSig0 -= 2; + add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); + if ( ( zSig1 & 0x1FFF ) <= 5 ) { + if ( zSig1 == 0 ) zSig1 = 1; + mul64To128( doubleZSig0, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + mul64To128( zSig1, zSig1, &term2, &term3 ); + sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + shortShift128Left( 0, zSig1, 1, &term2, &term3 ); + term3 |= 1; + term2 |= doubleZSig0; + add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); + return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_eq( float128 a, float128 b ) +{ + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. The comparison +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_le( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_lt( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_eq_signaling( float128 a, float128 b ) +{ + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_le_quiet( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_lt_quiet( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +#endif diff --git a/AltairZ80/m68k/example/softfloat/softfloat.h b/AltairZ80/m68k/example/softfloat/softfloat.h index 92135e66..88b0c4fc 100644 --- a/AltairZ80/m68k/example/softfloat/softfloat.h +++ b/AltairZ80/m68k/example/softfloat/softfloat.h @@ -1,460 +1,460 @@ - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| The macro `FLOATX80' must be defined to enable the extended double-precision -| floating-point format `floatx80'. If this macro is not defined, the -| `floatx80' type will not be defined, and none of the functions that either -| input or output the `floatx80' type will be defined. The same applies to -| the `FLOAT128' macro and the quadruple-precision format `float128'. -*----------------------------------------------------------------------------*/ -#define FLOATX80 -#define FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -typedef bits32 float32; -typedef bits64 float64; -#ifdef FLOATX80 -typedef struct { - bits16 high; - bits64 low; -} floatx80; -#endif -#ifdef FLOAT128 -typedef struct { - bits64 high, low; -} float128; -#endif - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target if -| desired.) -*----------------------------------------------------------------------------*/ -#include "softfloat-macros" - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -extern int8 float_detect_tininess; -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -extern int8 float_rounding_mode; -enum { - float_round_nearest_even = 0, - float_round_to_zero = 1, - float_round_down = 2, - float_round_up = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -extern int8 float_exception_flags; -enum { - float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08, - float_flag_underflow = 0x10, float_flag_inexact = 0x20 -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ -void float_raise( int8 ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32( int32 ); -float64 int32_to_float64( int32 ); -#ifdef FLOATX80 -floatx80 int32_to_floatx80( int32 ); -#endif -#ifdef FLOAT128 -float128 int32_to_float128( int32 ); -#endif -float32 int64_to_float32( int64 ); -float64 int64_to_float64( int64 ); -#ifdef FLOATX80 -floatx80 int64_to_floatx80( int64 ); -#endif -#ifdef FLOAT128 -float128 int64_to_float128( int64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float32_to_int32( float32 ); -int32 float32_to_int32_round_to_zero( float32 ); -int64 float32_to_int64( float32 ); -int64 float32_to_int64_round_to_zero( float32 ); -float64 float32_to_float64( float32 ); -#ifdef FLOATX80 -floatx80 float32_to_floatx80( float32 ); -#endif -#ifdef FLOAT128 -float128 float32_to_float128( float32 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 ); -float32 float32_add( float32, float32 ); -float32 float32_sub( float32, float32 ); -float32 float32_mul( float32, float32 ); -float32 float32_div( float32, float32 ); -float32 float32_rem( float32, float32 ); -float32 float32_sqrt( float32 ); -flag float32_eq( float32, float32 ); -flag float32_le( float32, float32 ); -flag float32_lt( float32, float32 ); -flag float32_eq_signaling( float32, float32 ); -flag float32_le_quiet( float32, float32 ); -flag float32_lt_quiet( float32, float32 ); -flag float32_is_signaling_nan( float32 ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float64_to_int32( float64 ); -int32 float64_to_int32_round_to_zero( float64 ); -int64 float64_to_int64( float64 ); -int64 float64_to_int64_round_to_zero( float64 ); -float32 float64_to_float32( float64 ); -#ifdef FLOATX80 -floatx80 float64_to_floatx80( float64 ); -#endif -#ifdef FLOAT128 -float128 float64_to_float128( float64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int( float64 ); -float64 float64_add( float64, float64 ); -float64 float64_sub( float64, float64 ); -float64 float64_mul( float64, float64 ); -float64 float64_div( float64, float64 ); -float64 float64_rem( float64, float64 ); -float64 float64_sqrt( float64 ); -flag float64_eq( float64, float64 ); -flag float64_le( float64, float64 ); -flag float64_lt( float64, float64 ); -flag float64_eq_signaling( float64, float64 ); -flag float64_le_quiet( float64, float64 ); -flag float64_lt_quiet( float64, float64 ); -flag float64_is_signaling_nan( float64 ); - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 floatx80_to_int32( floatx80 ); -int32 floatx80_to_int32_round_to_zero( floatx80 ); -int64 floatx80_to_int64( floatx80 ); -int64 floatx80_to_int64_round_to_zero( floatx80 ); -float32 floatx80_to_float32( floatx80 ); -float64 floatx80_to_float64( floatx80 ); -#ifdef FLOAT128 -float128 floatx80_to_float128( floatx80 ); -#endif -floatx80 floatx80_scale(floatx80 a, floatx80 b); - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an -| extended double-precision floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -static inline floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) -{ - floatx80 z; - - z.low = zSig; - z.high = ( ( (bits16) zSign )<<15 ) + zExp; - return z; - -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision rounding precision. Valid -| values are 32, 64, and 80. -*----------------------------------------------------------------------------*/ -extern int8 floatx80_rounding_precision; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 ); -floatx80 floatx80_add( floatx80, floatx80 ); -floatx80 floatx80_sub( floatx80, floatx80 ); -floatx80 floatx80_mul( floatx80, floatx80 ); -floatx80 floatx80_div( floatx80, floatx80 ); -floatx80 floatx80_rem( floatx80, floatx80 ); -floatx80 floatx80_sqrt( floatx80 ); -flag floatx80_eq( floatx80, floatx80 ); -flag floatx80_le( floatx80, floatx80 ); -flag floatx80_lt( floatx80, floatx80 ); -flag floatx80_eq_signaling( floatx80, floatx80 ); -flag floatx80_le_quiet( floatx80, floatx80 ); -flag floatx80_lt_quiet( floatx80, floatx80 ); -flag floatx80_is_signaling_nan( floatx80 ); - -/* int floatx80_fsin(floatx80 &a); -int floatx80_fcos(floatx80 &a); -int floatx80_ftan(floatx80 &a); */ - -floatx80 floatx80_flognp1(floatx80 a); -floatx80 floatx80_flogn(floatx80 a); -floatx80 floatx80_flog2(floatx80 a); -floatx80 floatx80_flog10(floatx80 a); - -// roundAndPackFloatx80 used to be in softfloat-round-pack, is now in softfloat.c -floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1); - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float128_to_int32( float128 ); -int32 float128_to_int32_round_to_zero( float128 ); -int64 float128_to_int64( float128 ); -int64 float128_to_int64_round_to_zero( float128 ); -float32 float128_to_float32( float128 ); -float64 float128_to_float64( float128 ); -#ifdef FLOATX80 -floatx80 float128_to_floatx80( float128 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_round_to_int( float128 ); -float128 float128_add( float128, float128 ); -float128 float128_sub( float128, float128 ); -float128 float128_mul( float128, float128 ); -float128 float128_div( float128, float128 ); -float128 float128_rem( float128, float128 ); -float128 float128_sqrt( float128 ); -flag float128_eq( float128, float128 ); -flag float128_le( float128, float128 ); -flag float128_lt( float128, float128 ); -flag float128_eq_signaling( float128, float128 ); -flag float128_le_quiet( float128, float128 ); -flag float128_lt_quiet( float128, float128 ); -flag float128_is_signaling_nan( float128 ); - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', the exponent `zExp', and the significand formed -| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision -| floating-point value, returning the result. After being shifted into the -| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply -| added together to form the most significant 32 bits of the result. This -| means that any integer portion of `zSig0' will be added into the exponent. -| Since a properly normalized significand will have an integer portion equal -| to 1, the `zExp' input should be 1 less than the desired result exponent -| whenever `zSig0' and `zSig1' concatenated form a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -static inline float128 - packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) -{ - float128 z; - - z.low = zSig1; - z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static inline float128 - roundAndPackFloat128( - flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 ) -{ - int8 roundingMode; - flag roundNearestEven, increment, isTiny; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) zSig2 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && zSig2; - } - else { - increment = ( roundingMode == float_round_up ) && zSig2; - } - } - } - if ( 0x7FFD <= (bits32) zExp ) { - if ( ( 0x7FFD < zExp ) - || ( ( zExp == 0x7FFD ) - && eq128( - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ), - zSig0, - zSig1 - ) - && increment - ) - ) { - float_raise( float_flag_overflow | float_flag_inexact ); - if ( ( roundingMode == float_round_to_zero ) - || ( zSign && ( roundingMode == float_round_up ) ) - || ( ! zSign && ( roundingMode == float_round_down ) ) - ) { - return - packFloat128( - zSign, - 0x7FFE, - LIT64( 0x0000FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) - ); - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( zExp < 0 ) { - isTiny = - ( float_detect_tininess == float_tininess_before_rounding ) - || ( zExp < -1 ) - || ! increment - || lt128( - zSig0, - zSig1, - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) - ); - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); - zExp = 0; - if ( isTiny && zSig2 ) float_raise( float_flag_underflow ); - if ( roundNearestEven ) { - increment = ( (sbits64) zSig2 < 0 ); - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && zSig2; - } - else { - increment = ( roundingMode == float_round_up ) && zSig2; - } - } - } - } - if ( zSig2 ) float_exception_flags |= float_flag_inexact; - if ( increment ) { - add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); - zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); - } - else { - if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; - } - return packFloat128( zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -static inline float128 - normalizeRoundAndPackFloat128( - flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) -{ - int8 shiftCount; - bits64 zSig2; - - if ( zSig0 == 0 ) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - shiftCount = countLeadingZeros64( zSig0 ) - 15; - if ( 0 <= shiftCount ) { - zSig2 = 0; - shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); - } - else { - shift128ExtraRightJamming( - zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 ); - } - zExp -= shiftCount; - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} -#endif + +/*============================================================================ + +This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +| The macro `FLOATX80' must be defined to enable the extended double-precision +| floating-point format `floatx80'. If this macro is not defined, the +| `floatx80' type will not be defined, and none of the functions that either +| input or output the `floatx80' type will be defined. The same applies to +| the `FLOAT128' macro and the quadruple-precision format `float128'. +*----------------------------------------------------------------------------*/ +#define FLOATX80 +#define FLOAT128 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point types. +*----------------------------------------------------------------------------*/ +typedef bits32 float32; +typedef bits64 float64; +#ifdef FLOATX80 +typedef struct { + bits16 high; + bits64 low; +} floatx80; +#endif +#ifdef FLOAT128 +typedef struct { + bits64 high, low; +} float128; +#endif + +/*---------------------------------------------------------------------------- +| Primitive arithmetic functions, including multi-word arithmetic, and +| division and square root approximations. (Can be specialized to target if +| desired.) +*----------------------------------------------------------------------------*/ +#include "softfloat-macros" + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point underflow tininess-detection mode. +*----------------------------------------------------------------------------*/ +extern int8 float_detect_tininess; +enum { + float_tininess_after_rounding = 0, + float_tininess_before_rounding = 1 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point rounding mode. +*----------------------------------------------------------------------------*/ +extern int8 float_rounding_mode; +enum { + float_round_nearest_even = 0, + float_round_to_zero = 1, + float_round_down = 2, + float_round_up = 3 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point exception flags. +*----------------------------------------------------------------------------*/ +extern int8 float_exception_flags; +enum { + float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08, + float_flag_underflow = 0x10, float_flag_inexact = 0x20 +}; + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software IEC/IEEE floating-point +| exception flags. +*----------------------------------------------------------------------------*/ +void float_raise( int8 ); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float32 int32_to_float32( int32 ); +float64 int32_to_float64( int32 ); +#ifdef FLOATX80 +floatx80 int32_to_floatx80( int32 ); +#endif +#ifdef FLOAT128 +float128 int32_to_float128( int32 ); +#endif +float32 int64_to_float32( int64 ); +float64 int64_to_float64( int64 ); +#ifdef FLOATX80 +floatx80 int64_to_floatx80( int64 ); +#endif +#ifdef FLOAT128 +float128 int64_to_float128( int64 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE single-precision conversion routines. +*----------------------------------------------------------------------------*/ +int32 float32_to_int32( float32 ); +int32 float32_to_int32_round_to_zero( float32 ); +int64 float32_to_int64( float32 ); +int64 float32_to_int64_round_to_zero( float32 ); +float64 float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 float32_to_float128( float32 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE single-precision operations. +*----------------------------------------------------------------------------*/ +float32 float32_round_to_int( float32 ); +float32 float32_add( float32, float32 ); +float32 float32_sub( float32, float32 ); +float32 float32_mul( float32, float32 ); +float32 float32_div( float32, float32 ); +float32 float32_rem( float32, float32 ); +float32 float32_sqrt( float32 ); +flag float32_eq( float32, float32 ); +flag float32_le( float32, float32 ); +flag float32_lt( float32, float32 ); +flag float32_eq_signaling( float32, float32 ); +flag float32_le_quiet( float32, float32 ); +flag float32_lt_quiet( float32, float32 ); +flag float32_is_signaling_nan( float32 ); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE double-precision conversion routines. +*----------------------------------------------------------------------------*/ +int32 float64_to_int32( float64 ); +int32 float64_to_int32_round_to_zero( float64 ); +int64 float64_to_int64( float64 ); +int64 float64_to_int64_round_to_zero( float64 ); +float32 float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 float64_to_float128( float64 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE double-precision operations. +*----------------------------------------------------------------------------*/ +float64 float64_round_to_int( float64 ); +float64 float64_add( float64, float64 ); +float64 float64_sub( float64, float64 ); +float64 float64_mul( float64, float64 ); +float64 float64_div( float64, float64 ); +float64 float64_rem( float64, float64 ); +float64 float64_sqrt( float64 ); +flag float64_eq( float64, float64 ); +flag float64_le( float64, float64 ); +flag float64_lt( float64, float64 ); +flag float64_eq_signaling( float64, float64 ); +flag float64_le_quiet( float64, float64 ); +flag float64_lt_quiet( float64, float64 ); +flag float64_is_signaling_nan( float64 ); + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision conversion routines. +*----------------------------------------------------------------------------*/ +int32 floatx80_to_int32( floatx80 ); +int32 floatx80_to_int32_round_to_zero( floatx80 ); +int64 floatx80_to_int64( floatx80 ); +int64 floatx80_to_int64_round_to_zero( floatx80 ); +float32 floatx80_to_float32( floatx80 ); +float64 floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 floatx80_to_float128( floatx80 ); +#endif +floatx80 floatx80_scale(floatx80 a, floatx80 b); + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an +| extended double-precision floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +static inline floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) +{ + floatx80 z; + + z.low = zSig; + z.high = ( ( (bits16) zSign )<<15 ) + zExp; + return z; + +} + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision rounding precision. Valid +| values are 32, 64, and 80. +*----------------------------------------------------------------------------*/ +extern int8 floatx80_rounding_precision; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ +floatx80 floatx80_round_to_int( floatx80 ); +floatx80 floatx80_add( floatx80, floatx80 ); +floatx80 floatx80_sub( floatx80, floatx80 ); +floatx80 floatx80_mul( floatx80, floatx80 ); +floatx80 floatx80_div( floatx80, floatx80 ); +floatx80 floatx80_rem( floatx80, floatx80 ); +floatx80 floatx80_sqrt( floatx80 ); +flag floatx80_eq( floatx80, floatx80 ); +flag floatx80_le( floatx80, floatx80 ); +flag floatx80_lt( floatx80, floatx80 ); +flag floatx80_eq_signaling( floatx80, floatx80 ); +flag floatx80_le_quiet( floatx80, floatx80 ); +flag floatx80_lt_quiet( floatx80, floatx80 ); +flag floatx80_is_signaling_nan( floatx80 ); + +/* int floatx80_fsin(floatx80 &a); +int floatx80_fcos(floatx80 &a); +int floatx80_ftan(floatx80 &a); */ + +floatx80 floatx80_flognp1(floatx80 a); +floatx80 floatx80_flogn(floatx80 a); +floatx80 floatx80_flog2(floatx80 a); +floatx80 floatx80_flog10(floatx80 a); + +// roundAndPackFloatx80 used to be in softfloat-round-pack, is now in softfloat.c +floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1); + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE quadruple-precision conversion routines. +*----------------------------------------------------------------------------*/ +int32 float128_to_int32( float128 ); +int32 float128_to_int32_round_to_zero( float128 ); +int64 float128_to_int64( float128 ); +int64 float128_to_int64_round_to_zero( float128 ); +float32 float128_to_float32( float128 ); +float64 float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 float128_to_floatx80( float128 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE quadruple-precision operations. +*----------------------------------------------------------------------------*/ +float128 float128_round_to_int( float128 ); +float128 float128_add( float128, float128 ); +float128 float128_sub( float128, float128 ); +float128 float128_mul( float128, float128 ); +float128 float128_div( float128, float128 ); +float128 float128_rem( float128, float128 ); +float128 float128_sqrt( float128 ); +flag float128_eq( float128, float128 ); +flag float128_le( float128, float128 ); +flag float128_lt( float128, float128 ); +flag float128_eq_signaling( float128, float128 ); +flag float128_le_quiet( float128, float128 ); +flag float128_lt_quiet( float128, float128 ); +flag float128_is_signaling_nan( float128 ); + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', the exponent `zExp', and the significand formed +| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision +| floating-point value, returning the result. After being shifted into the +| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply +| added together to form the most significant 32 bits of the result. This +| means that any integer portion of `zSig0' will be added into the exponent. +| Since a properly normalized significand will have an integer portion equal +| to 1, the `zExp' input should be 1 less than the desired result exponent +| whenever `zSig0' and `zSig1' concatenated form a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static inline float128 + packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) +{ + float128 z; + + z.low = zSig1; + z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and extended significand formed by the concatenation of `zSig0', `zSig1', +| and `zSig2', and returns the proper quadruple-precision floating-point value +| corresponding to the abstract input. Ordinarily, the abstract value is +| simply rounded and packed into the quadruple-precision format, with the +| inexact exception raised if the abstract input cannot be represented +| exactly. However, if the abstract value is too large, the overflow and +| inexact exceptions are raised and an infinity or maximal finite value is +| returned. If the abstract value is too small, the input value is rounded to +| a subnormal number, and the underflow and inexact exceptions are raised if +| the abstract input cannot be represented exactly as a subnormal quadruple- +| precision floating-point number. +| The input significand must be normalized or smaller. If the input +| significand is not normalized, `zExp' must be 0; in that case, the result +| returned is a subnormal number, and it must not require rounding. In the +| usual case that the input significand is normalized, `zExp' must be 1 less +| than the ``true'' floating-point exponent. The handling of underflow and +| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static inline float128 + roundAndPackFloat128( + flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 ) +{ + int8 roundingMode; + flag roundNearestEven, increment, isTiny; + + roundingMode = float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + increment = ( (sbits64) zSig2 < 0 ); + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + increment = 0; + } + else { + if ( zSign ) { + increment = ( roundingMode == float_round_down ) && zSig2; + } + else { + increment = ( roundingMode == float_round_up ) && zSig2; + } + } + } + if ( 0x7FFD <= (bits32) zExp ) { + if ( ( 0x7FFD < zExp ) + || ( ( zExp == 0x7FFD ) + && eq128( + LIT64( 0x0001FFFFFFFFFFFF ), + LIT64( 0xFFFFFFFFFFFFFFFF ), + zSig0, + zSig1 + ) + && increment + ) + ) { + float_raise( float_flag_overflow | float_flag_inexact ); + if ( ( roundingMode == float_round_to_zero ) + || ( zSign && ( roundingMode == float_round_up ) ) + || ( ! zSign && ( roundingMode == float_round_down ) ) + ) { + return + packFloat128( + zSign, + 0x7FFE, + LIT64( 0x0000FFFFFFFFFFFF ), + LIT64( 0xFFFFFFFFFFFFFFFF ) + ); + } + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( zExp < 0 ) { + isTiny = + ( float_detect_tininess == float_tininess_before_rounding ) + || ( zExp < -1 ) + || ! increment + || lt128( + zSig0, + zSig1, + LIT64( 0x0001FFFFFFFFFFFF ), + LIT64( 0xFFFFFFFFFFFFFFFF ) + ); + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); + zExp = 0; + if ( isTiny && zSig2 ) float_raise( float_flag_underflow ); + if ( roundNearestEven ) { + increment = ( (sbits64) zSig2 < 0 ); + } + else { + if ( zSign ) { + increment = ( roundingMode == float_round_down ) && zSig2; + } + else { + increment = ( roundingMode == float_round_up ) && zSig2; + } + } + } + } + if ( zSig2 ) float_exception_flags |= float_flag_inexact; + if ( increment ) { + add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); + zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); + } + else { + if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; + } + return packFloat128( zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand formed by the concatenation of `zSig0' and `zSig1', and +| returns the proper quadruple-precision floating-point value corresponding +| to the abstract input. This routine is just like `roundAndPackFloat128' +| except that the input significand has fewer bits and does not have to be +| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- +| point exponent. +*----------------------------------------------------------------------------*/ + +static inline float128 + normalizeRoundAndPackFloat128( + flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) +{ + int8 shiftCount; + bits64 zSig2; + + if ( zSig0 == 0 ) { + zSig0 = zSig1; + zSig1 = 0; + zExp -= 64; + } + shiftCount = countLeadingZeros64( zSig0 ) - 15; + if ( 0 <= shiftCount ) { + zSig2 = 0; + shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); + } + else { + shift128ExtraRightJamming( + zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 ); + } + zExp -= shiftCount; + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} +#endif diff --git a/AltairZ80/m68k/m68k.h b/AltairZ80/m68k/m68k.h index 8654287a..d28a2893 100755 --- a/AltairZ80/m68k/m68k.h +++ b/AltairZ80/m68k/m68k.h @@ -93,62 +93,62 @@ extern "C" { /* CPU types for use in m68k_set_cpu_type() */ enum { - M68K_CPU_TYPE_INVALID, - M68K_CPU_TYPE_68000, - M68K_CPU_TYPE_68010, - M68K_CPU_TYPE_68EC020, - M68K_CPU_TYPE_68020, - M68K_CPU_TYPE_68EC030, - M68K_CPU_TYPE_68030, - M68K_CPU_TYPE_68EC040, - M68K_CPU_TYPE_68LC040, - M68K_CPU_TYPE_68040, - M68K_CPU_TYPE_SCC68070 + M68K_CPU_TYPE_INVALID, + M68K_CPU_TYPE_68000, + M68K_CPU_TYPE_68010, + M68K_CPU_TYPE_68EC020, + M68K_CPU_TYPE_68020, + M68K_CPU_TYPE_68EC030, + M68K_CPU_TYPE_68030, + M68K_CPU_TYPE_68EC040, + M68K_CPU_TYPE_68LC040, + M68K_CPU_TYPE_68040, + M68K_CPU_TYPE_SCC68070 }; /* Registers used by m68k_get_reg() and m68k_set_reg() */ typedef enum { - /* Real registers */ - M68K_REG_D0, /* Data registers */ - M68K_REG_D1, - M68K_REG_D2, - M68K_REG_D3, - M68K_REG_D4, - M68K_REG_D5, - M68K_REG_D6, - M68K_REG_D7, - M68K_REG_A0, /* Address registers */ - M68K_REG_A1, - M68K_REG_A2, - M68K_REG_A3, - M68K_REG_A4, - M68K_REG_A5, - M68K_REG_A6, - M68K_REG_A7, - M68K_REG_PC, /* Program Counter */ - M68K_REG_SR, /* Status Register */ - M68K_REG_SP, /* The current Stack Pointer (located in A7) */ - M68K_REG_USP, /* User Stack Pointer */ - M68K_REG_ISP, /* Interrupt Stack Pointer */ - M68K_REG_MSP, /* Master Stack Pointer */ - M68K_REG_SFC, /* Source Function Code */ - M68K_REG_DFC, /* Destination Function Code */ - M68K_REG_VBR, /* Vector Base Register */ - M68K_REG_CACR, /* Cache Control Register */ - M68K_REG_CAAR, /* Cache Address Register */ + /* Real registers */ + M68K_REG_D0, /* Data registers */ + M68K_REG_D1, + M68K_REG_D2, + M68K_REG_D3, + M68K_REG_D4, + M68K_REG_D5, + M68K_REG_D6, + M68K_REG_D7, + M68K_REG_A0, /* Address registers */ + M68K_REG_A1, + M68K_REG_A2, + M68K_REG_A3, + M68K_REG_A4, + M68K_REG_A5, + M68K_REG_A6, + M68K_REG_A7, + M68K_REG_PC, /* Program Counter */ + M68K_REG_SR, /* Status Register */ + M68K_REG_SP, /* The current Stack Pointer (located in A7) */ + M68K_REG_USP, /* User Stack Pointer */ + M68K_REG_ISP, /* Interrupt Stack Pointer */ + M68K_REG_MSP, /* Master Stack Pointer */ + M68K_REG_SFC, /* Source Function Code */ + M68K_REG_DFC, /* Destination Function Code */ + M68K_REG_VBR, /* Vector Base Register */ + M68K_REG_CACR, /* Cache Control Register */ + M68K_REG_CAAR, /* Cache Address Register */ - /* Assumed registers */ - /* These are cheat registers which emulate the 1-longword prefetch - * present in the 68000 and 68010. - */ - M68K_REG_PREF_ADDR, /* Last prefetch address */ - M68K_REG_PREF_DATA, /* Last prefetch data */ + /* Assumed registers */ + /* These are cheat registers which emulate the 1-longword prefetch + * present in the 68000 and 68010. + */ + M68K_REG_PREF_ADDR, /* Last prefetch address */ + M68K_REG_PREF_DATA, /* Last prefetch data */ - /* Convenience registers */ - M68K_REG_PPC, /* Previous value in the program counter */ - M68K_REG_IR, /* Instruction register */ - M68K_REG_CPU_TYPE /* Type of CPU being run */ + /* Convenience registers */ + M68K_REG_PPC, /* Previous value in the program counter */ + M68K_REG_IR, /* Instruction register */ + M68K_REG_CPU_TYPE /* Type of CPU being run */ } m68k_register_t; /* ======================================================================== */ diff --git a/AltairZ80/m68k/m68k_in.c b/AltairZ80/m68k/m68k_in.c index e5811b3b..53bfb72e 100644 --- a/AltairZ80/m68k/m68k_in.c +++ b/AltairZ80/m68k/m68k_in.c @@ -1,10653 +1,10653 @@ -/* -must fix: - callm - chk -*/ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 3.32 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* Special thanks to Bart Trzynadlowski for his insight into the - * undocumented features of this chip: - * - * http://dynarec.com/~bart/files/68knotes.txt - */ - - -/* Input file for m68kmake - * ----------------------- - * - * All sections begin with 80 X's in a row followed by an end-of-line - * sequence. - * After this, m68kmake will expect to find one of the following section - * identifiers: - * M68KMAKE_PROTOTYPE_HEADER - header for opcode handler prototypes - * M68KMAKE_PROTOTYPE_FOOTER - footer for opcode handler prototypes - * M68KMAKE_TABLE_HEADER - header for opcode handler jumptable - * M68KMAKE_TABLE_FOOTER - footer for opcode handler jumptable - * M68KMAKE_TABLE_BODY - the table itself - * M68KMAKE_OPCODE_HANDLER_HEADER - header for opcode handler implementation - * M68KMAKE_OPCODE_HANDLER_FOOTER - footer for opcode handler implementation - * M68KMAKE_OPCODE_HANDLER_BODY - body section for opcode handler implementation - * - * NOTE: M68KMAKE_OPCODE_HANDLER_BODY must be last in the file and - * M68KMAKE_TABLE_BODY must be second last in the file. - * - * The M68KMAKE_OPHANDLER_BODY section contains the opcode handler - * primitives themselves. Each opcode handler begins with: - * M68KMAKE_OP(A, B, C, D) - * - * where A is the opcode handler name, B is the size of the operation, - * C denotes any special processing mode, and D denotes a specific - * addressing mode. - * For C and D where nothing is specified, use "." - * - * Example: - * M68KMAKE_OP(abcd, 8, rr, .) abcd, size 8, register to register, default EA - * M68KMAKE_OP(abcd, 8, mm, ax7) abcd, size 8, memory to memory, register X is A7 - * M68KMAKE_OP(tst, 16, ., pcix) tst, size 16, PCIX addressing - * - * All opcode handler primitives end with a closing curly brace "}" at column 1 - * - * NOTE: Do not place a M68KMAKE_OP() directive inside the opcode handler, - * and do not put a closing curly brace at column 1 unless it is - * marking the end of the handler! - * - * Inside the handler, m68kmake will recognize M68KMAKE_GET_OPER_xx_xx, - * M68KMAKE_GET_EA_xx_xx, and M68KMAKE_CC directives, and create multiple - * opcode handlers to handle variations in the opcode handler. - * Note: M68KMAKE_CC will only be interpreted in condition code opcodes. - * As well, M68KMAKE_GET_EA_xx_xx and M68KMAKE_GET_OPER_xx_xx will only - * be interpreted on instructions where the corresponding table entry - * specifies multiple effective addressing modes. - * Example: - * clr 32 . . 0100001010...... A+-DXWL... U U U 12 6 4 - * - * This table entry says that the clr.l opcde has 7 variations (A+-DXWL). - * It is run in user or supervisor mode for all CPUs, and uses 12 cycles for - * 68000, 6 cycles for 68010, and 4 cycles for 68020. - */ - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_PROTOTYPE_HEADER - -#ifndef M68KOPS__HEADER -#define M68KOPS__HEADER - -/* ======================================================================== */ -/* ============================ OPCODE HANDLERS =========================== */ -/* ======================================================================== */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_PROTOTYPE_FOOTER - - -/* Build the opcode handler table */ -void m68ki_build_opcode_table(void); - -extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ -extern unsigned char m68ki_cycles[][0x10000]; - - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - -#endif /* M68KOPS__HEADER */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_TABLE_HEADER - -/* ======================================================================== */ -/* ========================= OPCODE TABLE BUILDER ========================= */ -/* ======================================================================== */ - -#include -#include "m68kops.h" - -#define NUM_CPU_TYPES 5 - -void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ -unsigned char m68ki_cycles[NUM_CPU_TYPES][0x10000]; /* Cycles used by CPU type */ - -/* This is used to generate the opcode handler jump table */ -typedef struct -{ - void (*opcode_handler)(void); /* handler function */ - unsigned int mask; /* mask on opcode */ - unsigned int match; /* what to match after masking */ - unsigned char cycles[NUM_CPU_TYPES]; /* cycles each cpu type takes */ -} opcode_handler_struct; - - -/* Opcode handler table */ -static const opcode_handler_struct m68k_opcode_handler_table[] = -{ -/* function mask match 000 010 020 040 */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_TABLE_FOOTER - - {0, 0, 0, {0, 0, 0, 0, 0}} -}; - - -/* Build the opcode handler jump table */ -void m68ki_build_opcode_table(void) -{ - const opcode_handler_struct *ostruct; - int cycle_cost; - int instr; - int i; - int j; - int k; - - for(i = 0; i < 0x10000; i++) - { - /* default to illegal */ - m68ki_instruction_jump_table[i] = m68k_op_illegal; - for(k=0;kmask != 0xff00) - { - for(i = 0;i < 0x10000;i++) - { - if((i & ostruct->mask) == ostruct->match) - { - m68ki_instruction_jump_table[i] = ostruct->opcode_handler; - for(k=0;kcycles[k]; - } - } - ostruct++; - } - while(ostruct->mask == 0xff00) - { - for(i = 0;i <= 0xff;i++) - { - m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; - for(k=0;kmatch | i] = ostruct->cycles[k]; - } - ostruct++; - } - while(ostruct->mask == 0xf1f8) - { - for(i = 0;i < 8;i++) - { - for(j = 0;j < 8;j++) - { - instr = ostruct->match | (i << 9) | j; - m68ki_instruction_jump_table[instr] = ostruct->opcode_handler; - for(k=0;kcycles[k]; - // For all shift operations with known shift distance (encoded in instruction word) - if((instr & 0xf000) == 0xe000 && (!(instr & 0x20))) - { - // On the 68000 and 68010 shift distance affect execution time. - // Add the cycle cost of shifting; 2 times the shift distance - cycle_cost = ((((i-1)&7)+1)<<1); - m68ki_cycles[0][instr] += cycle_cost; - m68ki_cycles[1][instr] += cycle_cost; - // On the 68020 shift distance does not affect execution time - m68ki_cycles[2][instr] += 0; - } - } - } - ostruct++; - } - while(ostruct->mask == 0xfff0) - { - for(i = 0;i <= 0x0f;i++) - { - m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; - for(k=0;kmatch | i] = ostruct->cycles[k]; - } - ostruct++; - } - while(ostruct->mask == 0xf1ff) - { - for(i = 0;i <= 0x07;i++) - { - m68ki_instruction_jump_table[ostruct->match | (i << 9)] = ostruct->opcode_handler; - for(k=0;kmatch | (i << 9)] = ostruct->cycles[k]; - } - ostruct++; - } - while(ostruct->mask == 0xfff8) - { - for(i = 0;i <= 0x07;i++) - { - m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; - for(k=0;kmatch | i] = ostruct->cycles[k]; - } - ostruct++; - } - while(ostruct->mask == 0xffff) - { - m68ki_instruction_jump_table[ostruct->match] = ostruct->opcode_handler; - for(k=0;kmatch] = ostruct->cycles[k]; - ostruct++; - } -} - - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_OPCODE_HANDLER_HEADER - -#include -#include "m68kcpu.h" -extern void m68040_fpu_op0(void); -extern void m68040_fpu_op1(void); -extern void m68881_mmu_ops(void); - -/* ======================================================================== */ -/* ========================= INSTRUCTION HANDLERS ========================= */ -/* ======================================================================== */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_OPCODE_HANDLER_FOOTER - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_TABLE_BODY - -The following table is arranged as follows: - -name: Opcode mnemonic - -size: Operation size - -spec proc: Special processing mode: - .: normal - s: static operand - r: register operand - rr: register to register - mm: memory to memory - er: effective address to register - re: register to effective address - dd: data register to data register - da: data register to address register - aa: address register to address register - cr: control register to register - rc: register to control register - toc: to condition code register - tos: to status register - tou: to user stack pointer - frc: from condition code register - frs: from status register - fru: from user stack pointer - * for move.x, the special processing mode is a specific - destination effective addressing mode. - -spec ea: Specific effective addressing mode: - .: normal - i: immediate - d: data register - a: address register - ai: address register indirect - pi: address register indirect with postincrement - pd: address register indirect with predecrement - di: address register indirect with displacement - ix: address register indirect with index - aw: absolute word address - al: absolute long address - pcdi: program counter relative with displacement - pcix: program counter relative with index - a7: register specified in instruction is A7 - ax7: register field X of instruction is A7 - ay7: register field Y of instruction is A7 - axy7: register fields X and Y of instruction are A7 - -bit pattern: Pattern to recognize this opcode. "." means don't care. - -allowed ea: List of allowed addressing modes: - .: not present - A: address register indirect - +: ARI (address register indirect) with postincrement - -: ARI with predecrement - D: ARI with displacement - X: ARI with index - W: absolute word address - L: absolute long address - d: program counter indirect with displacement - x: program counter indirect with index - I: immediate -mode: CPU operating mode for each cpu type. U = user or supervisor, - S = supervisor only, "." = opcode not present. - -cpu cycles: Base number of cycles required to execute this opcode on the - specified CPU type. - Use "." if CPU does not have this opcode. - - - - spec spec allowed ea mode cpu cycles -name size proc ea bit pattern A+-DXWLdxI 0 1 2 3 4 000 010 020 030 040 comments -====== ==== ==== ==== ================ ========== = = = = = === === === === === ============= -M68KMAKE_TABLE_START -1010 0 . . 1010............ .......... U U U U U 4 4 4 4 4 -1111 0 . . 1111............ .......... U U U U U 4 4 4 4 4 -040fpu0 32 . . 11110010........ .......... . . . . U . . . . 0 -040fpu1 32 . . 11110011........ .......... . . . . U . . . . 0 -abcd 8 rr . 1100...100000... .......... U U U U U 6 6 4 4 4 -abcd 8 mm ax7 1100111100001... .......... U U U U U 18 18 16 16 16 -abcd 8 mm ay7 1100...100001111 .......... U U U U U 18 18 16 16 16 -abcd 8 mm axy7 1100111100001111 .......... U U U U U 18 18 16 16 16 -abcd 8 mm . 1100...100001... .......... U U U U U 18 18 16 16 16 -add 8 er d 1101...000000... .......... U U U U U 4 4 2 2 2 -add 8 er . 1101...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -add 16 er d 1101...001000... .......... U U U U U 4 4 2 2 2 -add 16 er a 1101...001001... .......... U U U U U 4 4 2 2 2 -add 16 er . 1101...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -add 32 er d 1101...010000... .......... U U U U U 6 6 2 2 2 -add 32 er a 1101...010001... .......... U U U U U 6 6 2 2 2 -add 32 er . 1101...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -add 8 re . 1101...100...... A+-DXWL... U U U U U 8 8 4 4 4 -add 16 re . 1101...101...... A+-DXWL... U U U U U 8 8 4 4 4 -add 32 re . 1101...110...... A+-DXWL... U U U U U 12 12 4 4 4 -adda 16 . d 1101...011000... .......... U U U U U 8 8 2 2 2 -adda 16 . a 1101...011001... .......... U U U U U 8 8 2 2 2 -adda 16 . . 1101...011...... A+-DXWLdxI U U U U U 8 8 2 2 2 -adda 32 . d 1101...111000... .......... U U U U U 6 6 2 2 2 -adda 32 . a 1101...111001... .......... U U U U U 6 6 2 2 2 -adda 32 . . 1101...111...... A+-DXWLdxI U U U U U 6 6 2 2 2 -addi 8 . d 0000011000000... .......... U U U U U 8 8 2 2 2 -addi 8 . . 0000011000...... A+-DXWL... U U U U U 12 12 4 4 4 -addi 16 . d 0000011001000... .......... U U U U U 8 8 2 2 2 -addi 16 . . 0000011001...... A+-DXWL... U U U U U 12 12 4 4 4 -addi 32 . d 0000011010000... .......... U U U U U 16 14 2 2 2 -addi 32 . . 0000011010...... A+-DXWL... U U U U U 20 20 4 4 4 -addq 8 . d 0101...000000... .......... U U U U U 4 4 2 2 2 -addq 8 . . 0101...000...... A+-DXWL... U U U U U 8 8 4 4 4 -addq 16 . d 0101...001000... .......... U U U U U 4 4 2 2 2 -addq 16 . a 0101...001001... .......... U U U U U 4 4 2 2 2 -addq 16 . . 0101...001...... A+-DXWL... U U U U U 8 8 4 4 4 -addq 32 . d 0101...010000... .......... U U U U U 8 8 2 2 2 -addq 32 . a 0101...010001... .......... U U U U U 8 8 2 2 2 -addq 32 . . 0101...010...... A+-DXWL... U U U U U 12 12 4 4 4 -addx 8 rr . 1101...100000... .......... U U U U U 4 4 2 2 2 -addx 16 rr . 1101...101000... .......... U U U U U 4 4 2 2 2 -addx 32 rr . 1101...110000... .......... U U U U U 8 6 2 2 2 -addx 8 mm ax7 1101111100001... .......... U U U U U 18 18 12 12 12 -addx 8 mm ay7 1101...100001111 .......... U U U U U 18 18 12 12 12 -addx 8 mm axy7 1101111100001111 .......... U U U U U 18 18 12 12 12 -addx 8 mm . 1101...100001... .......... U U U U U 18 18 12 12 12 -addx 16 mm . 1101...101001... .......... U U U U U 18 18 12 12 12 -addx 32 mm . 1101...110001... .......... U U U U U 30 30 12 12 12 -and 8 er d 1100...000000... .......... U U U U U 4 4 2 2 2 -and 8 er . 1100...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -and 16 er d 1100...001000... .......... U U U U U 4 4 2 2 2 -and 16 er . 1100...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -and 32 er d 1100...010000... .......... U U U U U 6 6 2 2 2 -and 32 er . 1100...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -and 8 re . 1100...100...... A+-DXWL... U U U U U 8 8 4 4 4 -and 16 re . 1100...101...... A+-DXWL... U U U U U 8 8 4 4 4 -and 32 re . 1100...110...... A+-DXWL... U U U U U 12 12 4 4 4 -andi 16 toc . 0000001000111100 .......... U U U U U 20 16 12 12 12 -andi 16 tos . 0000001001111100 .......... S S S S S 20 16 12 12 12 -andi 8 . d 0000001000000... .......... U U U U U 8 8 2 2 2 -andi 8 . . 0000001000...... A+-DXWL... U U U U U 12 12 4 4 4 -andi 16 . d 0000001001000... .......... U U U U U 8 8 2 2 2 -andi 16 . . 0000001001...... A+-DXWL... U U U U U 12 12 4 4 4 -andi 32 . d 0000001010000... .......... U U U U U 14 14 2 2 2 -andi 32 . . 0000001010...... A+-DXWL... U U U U U 20 20 4 4 4 -asr 8 s . 1110...000000... .......... U U U U U 6 6 6 6 6 -asr 16 s . 1110...001000... .......... U U U U U 6 6 6 6 6 -asr 32 s . 1110...010000... .......... U U U U U 8 8 6 6 6 -asr 8 r . 1110...000100... .......... U U U U U 6 6 6 6 6 -asr 16 r . 1110...001100... .......... U U U U U 6 6 6 6 6 -asr 32 r . 1110...010100... .......... U U U U U 8 8 6 6 6 -asr 16 . . 1110000011...... A+-DXWL... U U U U U 8 8 5 5 5 -asl 8 s . 1110...100000... .......... U U U U U 6 6 8 8 8 -asl 16 s . 1110...101000... .......... U U U U U 6 6 8 8 8 -asl 32 s . 1110...110000... .......... U U U U U 8 8 8 8 8 -asl 8 r . 1110...100100... .......... U U U U U 6 6 8 8 8 -asl 16 r . 1110...101100... .......... U U U U U 6 6 8 8 8 -asl 32 r . 1110...110100... .......... U U U U U 8 8 8 8 8 -asl 16 . . 1110000111...... A+-DXWL... U U U U U 8 8 6 6 6 -bcc 8 . . 0110............ .......... U U U U U 10 10 6 6 6 -bcc 16 . . 0110....00000000 .......... U U U U U 10 10 6 6 6 -bcc 32 . . 0110....11111111 .......... U U U U U 10 10 6 6 6 -bchg 8 r . 0000...101...... A+-DXWL... U U U U U 8 8 4 4 4 -bchg 32 r d 0000...101000... .......... U U U U U 8 8 4 4 4 -bchg 8 s . 0000100001...... A+-DXWL... U U U U U 12 12 4 4 4 -bchg 32 s d 0000100001000... .......... U U U U U 12 12 4 4 4 -bclr 8 r . 0000...110...... A+-DXWL... U U U U U 8 10 4 4 4 -bclr 32 r d 0000...110000... .......... U U U U U 10 10 4 4 4 -bclr 8 s . 0000100010...... A+-DXWL... U U U U U 12 12 4 4 4 -bclr 32 s d 0000100010000... .......... U U U U U 14 14 4 4 4 -bfchg 32 . d 1110101011000... .......... . . U U U . . 12 12 12 timing not quite correct -bfchg 32 . . 1110101011...... A..DXWL... . . U U U . . 20 20 20 -bfclr 32 . d 1110110011000... .......... . . U U U . . 12 12 12 -bfclr 32 . . 1110110011...... A..DXWL... . . U U U . . 20 20 20 -bfexts 32 . d 1110101111000... .......... . . U U U . . 8 8 8 -bfexts 32 . . 1110101111...... A..DXWLdx. . . U U U . . 15 15 15 -bfextu 32 . d 1110100111000... .......... . . U U U . . 8 8 8 -bfextu 32 . . 1110100111...... A..DXWLdx. . . U U U . . 15 15 15 -bfffo 32 . d 1110110111000... .......... . . U U U . . 18 18 18 -bfffo 32 . . 1110110111...... A..DXWLdx. . . U U U . . 28 28 28 -bfins 32 . d 1110111111000... .......... . . U U U . . 10 10 10 -bfins 32 . . 1110111111...... A..DXWL... . . U U U . . 17 17 17 -bfset 32 . d 1110111011000... .......... . . U U U . . 12 12 12 -bfset 32 . . 1110111011...... A..DXWL... . . U U U . . 20 20 20 -bftst 32 . d 1110100011000... .......... . . U U U . . 6 6 6 -bftst 32 . . 1110100011...... A..DXWLdx. . . U U U . . 13 13 13 -bkpt 0 . . 0100100001001... .......... . U U U U . 10 10 10 10 -bra 8 . . 01100000........ .......... U U U U U 10 10 10 10 10 -bra 16 . . 0110000000000000 .......... U U U U U 10 10 10 10 10 -bra 32 . . 0110000011111111 .......... U U U U U 10 10 10 10 10 -bset 32 r d 0000...111000... .......... U U U U U 8 8 4 4 4 -bset 8 r . 0000...111...... A+-DXWL... U U U U U 8 8 4 4 4 -bset 8 s . 0000100011...... A+-DXWL... U U U U U 12 12 4 4 4 -bset 32 s d 0000100011000... .......... U U U U U 12 12 4 4 4 -bsr 8 . . 01100001........ .......... U U U U U 18 18 7 7 7 -bsr 16 . . 0110000100000000 .......... U U U U U 18 18 7 7 7 -bsr 32 . . 0110000111111111 .......... U U U U U 18 18 7 7 7 -btst 8 r . 0000...100...... A+-DXWLdxI U U U U U 4 4 4 4 4 -btst 32 r d 0000...100000... .......... U U U U U 6 6 4 4 4 -btst 8 s . 0000100000...... A+-DXWLdx. U U U U U 8 8 4 4 4 -btst 32 s d 0000100000000... .......... U U U U U 10 10 4 4 4 -callm 32 . . 0000011011...... A..DXWLdx. . . U U U . . 60 60 60 not properly emulated -cas 8 . . 0000101011...... A+-DXWL... . . U U U . . 12 12 12 -cas 16 . . 0000110011...... A+-DXWL... . . U U U . . 12 12 12 -cas 32 . . 0000111011...... A+-DXWL... . . U U U . . 12 12 12 -cas2 16 . . 0000110011111100 .......... . . U U U . . 12 12 12 -cas2 32 . . 0000111011111100 .......... . . U U U . . 12 12 12 -chk 16 . d 0100...110000... .......... U U U U U 10 8 8 8 8 -chk 16 . . 0100...110...... A+-DXWLdxI U U U U U 10 8 8 8 8 -chk 32 . d 0100...100000... .......... . . U U U . . 8 8 8 -chk 32 . . 0100...100...... A+-DXWLdxI . . U U U . . 8 8 8 -chk2cmp2 8 . pcdi 0000000011111010 .......... . . U U U . . 23 23 23 -chk2cmp2 8 . pcix 0000000011111011 .......... . . U U U . . 23 23 23 -chk2cmp2 8 . . 0000000011...... A..DXWL... . . U U U . . 18 18 18 -chk2cmp2 16 . pcdi 0000001011111010 .......... . . U U U . . 23 23 23 -chk2cmp2 16 . pcix 0000001011111011 .......... . . U U U . . 23 23 23 -chk2cmp2 16 . . 0000001011...... A..DXWL... . . U U U . . 18 18 18 -chk2cmp2 32 . pcdi 0000010011111010 .......... . . U U U . . 23 23 23 -chk2cmp2 32 . pcix 0000010011111011 .......... . . U U U . . 23 23 23 -chk2cmp2 32 . . 0000010011...... A..DXWL... . . U U U . . 18 18 18 -clr 8 . d 0100001000000... .......... U U U U U 4 4 2 2 2 -clr 8 . . 0100001000...... A+-DXWL... U U U U U 8 4 4 4 4 -clr 16 . d 0100001001000... .......... U U U U U 4 4 2 2 2 -clr 16 . . 0100001001...... A+-DXWL... U U U U U 8 4 4 4 4 -clr 32 . d 0100001010000... .......... U U U U U 6 6 2 2 2 -clr 32 . . 0100001010...... A+-DXWL... U U U U U 12 6 4 4 4 -cmp 8 . d 1011...000000... .......... U U U U U 4 4 2 2 2 -cmp 8 . . 1011...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -cmp 16 . d 1011...001000... .......... U U U U U 4 4 2 2 2 -cmp 16 . a 1011...001001... .......... U U U U U 4 4 2 2 2 -cmp 16 . . 1011...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -cmp 32 . d 1011...010000... .......... U U U U U 6 6 2 2 2 -cmp 32 . a 1011...010001... .......... U U U U U 6 6 2 2 2 -cmp 32 . . 1011...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -cmpa 16 . d 1011...011000... .......... U U U U U 6 6 4 4 4 -cmpa 16 . a 1011...011001... .......... U U U U U 6 6 4 4 4 -cmpa 16 . . 1011...011...... A+-DXWLdxI U U U U U 6 6 4 4 4 -cmpa 32 . d 1011...111000... .......... U U U U U 6 6 4 4 4 -cmpa 32 . a 1011...111001... .......... U U U U U 6 6 4 4 4 -cmpa 32 . . 1011...111...... A+-DXWLdxI U U U U U 6 6 4 4 4 -cmpi 8 . d 0000110000000... .......... U U U U U 8 8 2 2 2 -cmpi 8 . . 0000110000...... A+-DXWL... U U U U U 8 8 2 2 2 -cmpi 8 . pcdi 0000110000111010 .......... . . U U U . . 7 7 7 -cmpi 8 . pcix 0000110000111011 .......... . . U U U . . 9 9 9 -cmpi 16 . d 0000110001000... .......... U U U U U 8 8 2 2 2 -cmpi 16 . . 0000110001...... A+-DXWL... U U U U U 8 8 2 2 2 -cmpi 16 . pcdi 0000110001111010 .......... . . U U U . . 7 7 7 -cmpi 16 . pcix 0000110001111011 .......... . . U U U . . 9 9 9 -cmpi 32 . d 0000110010000... .......... U U U U U 14 12 2 2 2 -cmpi 32 . . 0000110010...... A+-DXWL... U U U U U 12 12 2 2 2 -cmpi 32 . pcdi 0000110010111010 .......... . . U U U . . 7 7 7 -cmpi 32 . pcix 0000110010111011 .......... . . U U U . . 9 9 9 -cmpm 8 . ax7 1011111100001... .......... U U U U U 12 12 9 9 9 -cmpm 8 . ay7 1011...100001111 .......... U U U U U 12 12 9 9 9 -cmpm 8 . axy7 1011111100001111 .......... U U U U U 12 12 9 9 9 -cmpm 8 . . 1011...100001... .......... U U U U U 12 12 9 9 9 -cmpm 16 . . 1011...101001... .......... U U U U U 12 12 9 9 9 -cmpm 32 . . 1011...110001... .......... U U U U U 20 20 9 9 9 -cpbcc 32 . . 1111...01....... .......... . . U U . . . 4 4 . unemulated -cpdbcc 32 . . 1111...001001... .......... . . U U . . . 4 4 . unemulated -cpgen 32 . . 1111...000...... .......... . . U U . . . 4 4 . unemulated -cpscc 32 . . 1111...001...... .......... . . U U . . . 4 4 . unemulated -cptrapcc 32 . . 1111...001111... .......... . . U U . . . 4 4 . unemulated -dbt 16 . . 0101000011001... .......... U U U U U 12 12 6 6 6 -dbf 16 . . 0101000111001... .......... U U U U U 12 12 6 6 6 -dbcc 16 . . 0101....11001... .......... U U U U U 12 12 6 6 6 -divs 16 . d 1000...111000... .......... U U U U U 158 122 56 56 56 -divs 16 . . 1000...111...... A+-DXWLdxI U U U U U 158 122 56 56 56 -divu 16 . d 1000...011000... .......... U U U U U 140 108 44 44 44 -divu 16 . . 1000...011...... A+-DXWLdxI U U U U U 140 108 44 44 44 -divl 32 . d 0100110001000... .......... . . U U U . . 84 84 84 -divl 32 . . 0100110001...... A+-DXWLdxI . . U U U . . 84 84 84 -eor 8 . d 1011...100000... .......... U U U U U 4 4 2 2 2 -eor 8 . . 1011...100...... A+-DXWL... U U U U U 8 8 4 4 4 -eor 16 . d 1011...101000... .......... U U U U U 4 4 2 2 2 -eor 16 . . 1011...101...... A+-DXWL... U U U U U 8 8 4 4 4 -eor 32 . d 1011...110000... .......... U U U U U 8 6 2 2 2 -eor 32 . . 1011...110...... A+-DXWL... U U U U U 12 12 4 4 4 -eori 16 toc . 0000101000111100 .......... U U U U U 20 16 12 12 12 -eori 16 tos . 0000101001111100 .......... S S S S S 20 16 12 12 12 -eori 8 . d 0000101000000... .......... U U U U U 8 8 2 2 2 -eori 8 . . 0000101000...... A+-DXWL... U U U U U 12 12 4 4 4 -eori 16 . d 0000101001000... .......... U U U U U 8 8 2 2 2 -eori 16 . . 0000101001...... A+-DXWL... U U U U U 12 12 4 4 4 -eori 32 . d 0000101010000... .......... U U U U U 16 14 2 2 2 -eori 32 . . 0000101010...... A+-DXWL... U U U U U 20 20 4 4 4 -exg 32 dd . 1100...101000... .......... U U U U U 6 6 2 2 2 -exg 32 aa . 1100...101001... .......... U U U U U 6 6 2 2 2 -exg 32 da . 1100...110001... .......... U U U U U 6 6 2 2 2 -ext 16 . . 0100100010000... .......... U U U U U 4 4 4 4 4 -ext 32 . . 0100100011000... .......... U U U U U 4 4 4 4 4 -extb 32 . . 0100100111000... .......... . . U U U . . 4 4 4 -illegal 0 . . 0100101011111100 .......... U U U U U 4 4 4 4 4 -jmp 32 . . 0100111011...... A..DXWLdx. U U U U U 4 4 0 0 0 -jsr 32 . . 0100111010...... A..DXWLdx. U U U U U 12 12 0 0 0 -lea 32 . . 0100...111...... A..DXWLdx. U U U U U 0 0 2 2 2 -link 16 . a7 0100111001010111 .......... U U U U U 16 16 5 5 5 -link 16 . . 0100111001010... .......... U U U U U 16 16 5 5 5 -link 32 . a7 0100100000001111 .......... . . U U U . . 6 6 6 -link 32 . . 0100100000001... .......... . . U U U . . 6 6 6 -lsr 8 s . 1110...000001... .......... U U U U U 6 6 4 4 4 -lsr 16 s . 1110...001001... .......... U U U U U 6 6 4 4 4 -lsr 32 s . 1110...010001... .......... U U U U U 8 8 4 4 4 -lsr 8 r . 1110...000101... .......... U U U U U 6 6 6 6 6 -lsr 16 r . 1110...001101... .......... U U U U U 6 6 6 6 6 -lsr 32 r . 1110...010101... .......... U U U U U 8 8 6 6 6 -lsr 16 . . 1110001011...... A+-DXWL... U U U U U 8 8 5 5 5 -lsl 8 s . 1110...100001... .......... U U U U U 6 6 4 4 4 -lsl 16 s . 1110...101001... .......... U U U U U 6 6 4 4 4 -lsl 32 s . 1110...110001... .......... U U U U U 8 8 4 4 4 -lsl 8 r . 1110...100101... .......... U U U U U 6 6 6 6 6 -lsl 16 r . 1110...101101... .......... U U U U U 6 6 6 6 6 -lsl 32 r . 1110...110101... .......... U U U U U 8 8 6 6 6 -lsl 16 . . 1110001111...... A+-DXWL... U U U U U 8 8 5 5 5 -move 8 d d 0001...000000... .......... U U U U U 4 4 2 2 2 -move 8 d . 0001...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -move 8 ai d 0001...010000... .......... U U U U U 8 8 4 4 4 -move 8 ai . 0001...010...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 8 pi d 0001...011000... .......... U U U U U 8 8 4 4 4 -move 8 pi . 0001...011...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 8 pi7 d 0001111011000... .......... U U U U U 8 8 4 4 4 -move 8 pi7 . 0001111011...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 8 pd d 0001...100000... .......... U U U U U 8 8 5 5 5 -move 8 pd . 0001...100...... A+-DXWLdxI U U U U U 8 8 5 5 5 -move 8 pd7 d 0001111100000... .......... U U U U U 8 8 5 5 5 -move 8 pd7 . 0001111100...... A+-DXWLdxI U U U U U 8 8 5 5 5 -move 8 di d 0001...101000... .......... U U U U U 12 12 5 5 5 -move 8 di . 0001...101...... A+-DXWLdxI U U U U U 12 12 5 5 5 -move 8 ix d 0001...110000... .......... U U U U U 14 14 7 7 7 -move 8 ix . 0001...110...... A+-DXWLdxI U U U U U 14 14 7 7 7 -move 8 aw d 0001000111000... .......... U U U U U 12 12 4 4 4 -move 8 aw . 0001000111...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 8 al d 0001001111000... .......... U U U U U 16 16 6 6 6 -move 8 al . 0001001111...... A+-DXWLdxI U U U U U 16 16 6 6 6 -move 16 d d 0011...000000... .......... U U U U U 4 4 2 2 2 -move 16 d a 0011...000001... .......... U U U U U 4 4 2 2 2 -move 16 d . 0011...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -move 16 ai d 0011...010000... .......... U U U U U 8 8 4 4 4 -move 16 ai a 0011...010001... .......... U U U U U 8 8 4 4 4 -move 16 ai . 0011...010...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 16 pi d 0011...011000... .......... U U U U U 8 8 4 4 4 -move 16 pi a 0011...011001... .......... U U U U U 8 8 4 4 4 -move 16 pi . 0011...011...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 16 pd d 0011...100000... .......... U U U U U 8 8 5 5 5 -move 16 pd a 0011...100001... .......... U U U U U 8 8 5 5 5 -move 16 pd . 0011...100...... A+-DXWLdxI U U U U U 8 8 5 5 5 -move 16 di d 0011...101000... .......... U U U U U 12 12 5 5 5 -move 16 di a 0011...101001... .......... U U U U U 12 12 5 5 5 -move 16 di . 0011...101...... A+-DXWLdxI U U U U U 12 12 5 5 5 -move 16 ix d 0011...110000... .......... U U U U U 14 14 7 7 7 -move 16 ix a 0011...110001... .......... U U U U U 14 14 7 7 7 -move 16 ix . 0011...110...... A+-DXWLdxI U U U U U 14 14 7 7 7 -move 16 aw d 0011000111000... .......... U U U U U 12 12 4 4 4 -move 16 aw a 0011000111001... .......... U U U U U 12 12 4 4 4 -move 16 aw . 0011000111...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 16 al d 0011001111000... .......... U U U U U 16 16 6 6 6 -move 16 al a 0011001111001... .......... U U U U U 16 16 6 6 6 -move 16 al . 0011001111...... A+-DXWLdxI U U U U U 16 16 6 6 6 -move 32 d d 0010...000000... .......... U U U U U 4 4 2 2 2 -move 32 d a 0010...000001... .......... U U U U U 4 4 2 2 2 -move 32 d . 0010...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -move 32 ai d 0010...010000... .......... U U U U U 12 12 4 4 4 -move 32 ai a 0010...010001... .......... U U U U U 12 12 4 4 4 -move 32 ai . 0010...010...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 32 pi d 0010...011000... .......... U U U U U 12 12 4 4 4 -move 32 pi a 0010...011001... .......... U U U U U 12 12 4 4 4 -move 32 pi . 0010...011...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 32 pd d 0010...100000... .......... U U U U U 12 14 5 5 5 -move 32 pd a 0010...100001... .......... U U U U U 12 14 5 5 5 -move 32 pd . 0010...100...... A+-DXWLdxI U U U U U 12 14 5 5 5 -move 32 di d 0010...101000... .......... U U U U U 16 16 5 5 5 -move 32 di a 0010...101001... .......... U U U U U 16 16 5 5 5 -move 32 di . 0010...101...... A+-DXWLdxI U U U U U 16 16 5 5 5 -move 32 ix d 0010...110000... .......... U U U U U 18 18 7 7 7 -move 32 ix a 0010...110001... .......... U U U U U 18 18 7 7 7 -move 32 ix . 0010...110...... A+-DXWLdxI U U U U U 18 18 7 7 7 -move 32 aw d 0010000111000... .......... U U U U U 16 16 4 4 4 -move 32 aw a 0010000111001... .......... U U U U U 16 16 4 4 4 -move 32 aw . 0010000111...... A+-DXWLdxI U U U U U 16 16 4 4 4 -move 32 al d 0010001111000... .......... U U U U U 20 20 6 6 6 -move 32 al a 0010001111001... .......... U U U U U 20 20 6 6 6 -move 32 al . 0010001111...... A+-DXWLdxI U U U U U 20 20 6 6 6 -movea 16 . d 0011...001000... .......... U U U U U 4 4 2 2 2 -movea 16 . a 0011...001001... .......... U U U U U 4 4 2 2 2 -movea 16 . . 0011...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -movea 32 . d 0010...001000... .......... U U U U U 4 4 2 2 2 -movea 32 . a 0010...001001... .......... U U U U U 4 4 2 2 2 -movea 32 . . 0010...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -move 16 frc d 0100001011000... .......... . U U U U . 4 4 4 4 -move 16 frc . 0100001011...... A+-DXWL... . U U U U . 8 4 4 4 -move 16 toc d 0100010011000... .......... U U U U U 12 12 4 4 4 -move 16 toc . 0100010011...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 16 frs d 0100000011000... .......... U S S S S 6 4 8 8 8 U only for 000 -move 16 frs . 0100000011...... A+-DXWL... U S S S S 8 8 8 8 8 U only for 000 -move 16 tos d 0100011011000... .......... S S S S S 12 12 8 8 8 -move 16 tos . 0100011011...... A+-DXWLdxI S S S S S 12 12 8 8 8 -move 32 fru . 0100111001101... .......... S S S S S 4 6 2 2 2 -move 32 tou . 0100111001100... .......... S S S S S 4 6 2 2 2 -movec 32 cr . 0100111001111010 .......... . S S S S . 12 6 6 6 -movec 32 rc . 0100111001111011 .......... . S S S S . 10 12 12 12 -movem 16 re pd 0100100010100... .......... U U U U U 8 8 4 4 4 -movem 16 re . 0100100010...... A..DXWL... U U U U U 8 8 4 4 4 -movem 32 re pd 0100100011100... .......... U U U U U 8 8 4 4 4 -movem 32 re . 0100100011...... A..DXWL... U U U U U 8 8 4 4 4 -movem 16 er pi 0100110010011... .......... U U U U U 12 12 8 8 8 -movem 16 er pcdi 0100110010111010 .......... U U U U U 16 16 9 9 9 -movem 16 er pcix 0100110010111011 .......... U U U U U 18 18 11 11 11 -movem 16 er . 0100110010...... A..DXWL... U U U U U 12 12 8 8 8 -movem 32 er pi 0100110011011... .......... U U U U U 12 12 8 8 8 -movem 32 er pcdi 0100110011111010 .......... U U U U U 16 16 9 9 9 -movem 32 er pcix 0100110011111011 .......... U U U U U 18 18 11 11 11 -movem 32 er . 0100110011...... A..DXWL... U U U U U 12 12 8 8 8 -movep 16 er . 0000...100001... .......... U U U U U 16 16 12 12 12 -movep 32 er . 0000...101001... .......... U U U U U 24 24 18 18 18 -movep 16 re . 0000...110001... .......... U U U U U 16 16 11 11 11 -movep 32 re . 0000...111001... .......... U U U U U 24 24 17 17 17 -moveq 32 . . 0111...0........ .......... U U U U U 4 4 2 2 2 -moves 8 . . 0000111000...... A+-DXWL... . S S S S . 14 5 5 5 -moves 16 . . 0000111001...... A+-DXWL... . S S S S . 14 5 5 5 -moves 32 . . 0000111010...... A+-DXWL... . S S S S . 16 5 5 5 -move16 32 . . 1111011000100... .......... . . . . U . . . . 4 TODO: correct timing -muls 16 . d 1100...111000... .......... U U U U U 54 32 27 27 27 -muls 16 . . 1100...111...... A+-DXWLdxI U U U U U 54 32 27 27 27 -mulu 16 . d 1100...011000... .......... U U U U U 54 30 27 27 27 -mulu 16 . . 1100...011...... A+-DXWLdxI U U U U U 54 30 27 27 27 -mull 32 . d 0100110000000... .......... . . U U U . . 43 43 43 -mull 32 . . 0100110000...... A+-DXWLdxI . . U U U . . 43 43 43 -nbcd 8 . d 0100100000000... .......... U U U U U 6 6 6 6 6 -nbcd 8 . . 0100100000...... A+-DXWL... U U U U U 8 8 6 6 6 -neg 8 . d 0100010000000... .......... U U U U U 4 4 2 2 2 -neg 8 . . 0100010000...... A+-DXWL... U U U U U 8 8 4 4 4 -neg 16 . d 0100010001000... .......... U U U U U 4 4 2 2 2 -neg 16 . . 0100010001...... A+-DXWL... U U U U U 8 8 4 4 4 -neg 32 . d 0100010010000... .......... U U U U U 6 6 2 2 2 -neg 32 . . 0100010010...... A+-DXWL... U U U U U 12 12 4 4 4 -negx 8 . d 0100000000000... .......... U U U U U 4 4 2 2 2 -negx 8 . . 0100000000...... A+-DXWL... U U U U U 8 8 4 4 4 -negx 16 . d 0100000001000... .......... U U U U U 4 4 2 2 2 -negx 16 . . 0100000001...... A+-DXWL... U U U U U 8 8 4 4 4 -negx 32 . d 0100000010000... .......... U U U U U 6 6 2 2 2 -negx 32 . . 0100000010...... A+-DXWL... U U U U U 12 12 4 4 4 -nop 0 . . 0100111001110001 .......... U U U U U 4 4 2 2 2 -not 8 . d 0100011000000... .......... U U U U U 4 4 2 2 2 -not 8 . . 0100011000...... A+-DXWL... U U U U U 8 8 4 4 4 -not 16 . d 0100011001000... .......... U U U U U 4 4 2 2 2 -not 16 . . 0100011001...... A+-DXWL... U U U U U 8 8 4 4 4 -not 32 . d 0100011010000... .......... U U U U U 6 6 2 2 2 -not 32 . . 0100011010...... A+-DXWL... U U U U U 12 12 4 4 4 -or 8 er d 1000...000000... .......... U U U U U 4 4 2 2 2 -or 8 er . 1000...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -or 16 er d 1000...001000... .......... U U U U U 4 4 2 2 2 -or 16 er . 1000...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -or 32 er d 1000...010000... .......... U U U U U 6 6 2 2 2 -or 32 er . 1000...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -or 8 re . 1000...100...... A+-DXWL... U U U U U 8 8 4 4 4 -or 16 re . 1000...101...... A+-DXWL... U U U U U 8 8 4 4 4 -or 32 re . 1000...110...... A+-DXWL... U U U U U 12 12 4 4 4 -ori 16 toc . 0000000000111100 .......... U U U U U 20 16 12 12 12 -ori 16 tos . 0000000001111100 .......... S S S S S 20 16 12 12 12 -ori 8 . d 0000000000000... .......... U U U U U 8 8 2 2 2 -ori 8 . . 0000000000...... A+-DXWL... U U U U U 12 12 4 4 4 -ori 16 . d 0000000001000... .......... U U U U U 8 8 2 2 2 -ori 16 . . 0000000001...... A+-DXWL... U U U U U 12 12 4 4 4 -ori 32 . d 0000000010000... .......... U U U U U 16 14 2 2 2 -ori 32 . . 0000000010...... A+-DXWL... U U U U U 20 20 4 4 4 -pack 16 rr . 1000...101000... .......... . . U U U . . 6 6 6 -pack 16 mm ax7 1000111101001... .......... . . U U U . . 13 13 13 -pack 16 mm ay7 1000...101001111 .......... . . U U U . . 13 13 13 -pack 16 mm axy7 1000111101001111 .......... . . U U U . . 13 13 13 -pack 16 mm . 1000...101001... .......... . . U U U . . 13 13 13 -pea 32 . . 0100100001...... A..DXWLdx. U U U U U 6 6 5 5 5 -pflush 32 . . 1111010100011000 .......... . . . . S . . . . 4 TODO: correct timing -pmmu 32 . . 1111000......... .......... . . S S S . . 8 8 8 -reset 0 . . 0100111001110000 .......... S S S S S 0 0 0 0 0 -ror 8 s . 1110...000011... .......... U U U U U 6 6 8 8 8 -ror 16 s . 1110...001011... .......... U U U U U 6 6 8 8 8 -ror 32 s . 1110...010011... .......... U U U U U 8 8 8 8 8 -ror 8 r . 1110...000111... .......... U U U U U 6 6 8 8 8 -ror 16 r . 1110...001111... .......... U U U U U 6 6 8 8 8 -ror 32 r . 1110...010111... .......... U U U U U 8 8 8 8 8 -ror 16 . . 1110011011...... A+-DXWL... U U U U U 8 8 7 7 7 -rol 8 s . 1110...100011... .......... U U U U U 6 6 8 8 8 -rol 16 s . 1110...101011... .......... U U U U U 6 6 8 8 8 -rol 32 s . 1110...110011... .......... U U U U U 8 8 8 8 8 -rol 8 r . 1110...100111... .......... U U U U U 6 6 8 8 8 -rol 16 r . 1110...101111... .......... U U U U U 6 6 8 8 8 -rol 32 r . 1110...110111... .......... U U U U U 8 8 8 8 8 -rol 16 . . 1110011111...... A+-DXWL... U U U U U 8 8 7 7 7 -roxr 8 s . 1110...000010... .......... U U U U U 6 6 12 12 12 -roxr 16 s . 1110...001010... .......... U U U U U 6 6 12 12 12 -roxr 32 s . 1110...010010... .......... U U U U U 8 8 12 12 12 -roxr 8 r . 1110...000110... .......... U U U U U 6 6 12 12 12 -roxr 16 r . 1110...001110... .......... U U U U U 6 6 12 12 12 -roxr 32 r . 1110...010110... .......... U U U U U 8 8 12 12 12 -roxr 16 . . 1110010011...... A+-DXWL... U U U U U 8 8 5 5 5 -roxl 8 s . 1110...100010... .......... U U U U U 6 6 12 12 12 -roxl 16 s . 1110...101010... .......... U U U U U 6 6 12 12 12 -roxl 32 s . 1110...110010... .......... U U U U U 8 8 12 12 12 -roxl 8 r . 1110...100110... .......... U U U U U 6 6 12 12 12 -roxl 16 r . 1110...101110... .......... U U U U U 6 6 12 12 12 -roxl 32 r . 1110...110110... .......... U U U U U 8 8 12 12 12 -roxl 16 . . 1110010111...... A+-DXWL... U U U U U 8 8 5 5 5 -rtd 32 . . 0100111001110100 .......... . U U U U . 16 10 10 10 -rte 32 . . 0100111001110011 .......... S S S S S 20 24 20 20 20 bus fault not emulated -rtm 32 . . 000001101100.... .......... . . U U U . . 19 19 19 not properly emulated -rtr 32 . . 0100111001110111 .......... U U U U U 20 20 14 14 14 -rts 32 . . 0100111001110101 .......... U U U U U 16 16 10 10 10 -sbcd 8 rr . 1000...100000... .......... U U U U U 6 6 4 4 4 -sbcd 8 mm ax7 1000111100001... .......... U U U U U 18 18 16 16 16 -sbcd 8 mm ay7 1000...100001111 .......... U U U U U 18 18 16 16 16 -sbcd 8 mm axy7 1000111100001111 .......... U U U U U 18 18 16 16 16 -sbcd 8 mm . 1000...100001... .......... U U U U U 18 18 16 16 16 -st 8 . d 0101000011000... .......... U U U U U 6 4 4 4 4 -st 8 . . 0101000011...... A+-DXWL... U U U U U 8 8 6 6 6 -sf 8 . d 0101000111000... .......... U U U U U 4 4 4 4 4 -sf 8 . . 0101000111...... A+-DXWL... U U U U U 8 8 6 6 6 -scc 8 . d 0101....11000... .......... U U U U U 4 4 4 4 4 -scc 8 . . 0101....11...... A+-DXWL... U U U U U 8 8 6 6 6 -stop 0 . . 0100111001110010 .......... S S S S S 4 4 8 8 8 -sub 8 er d 1001...000000... .......... U U U U U 4 4 2 2 2 -sub 8 er . 1001...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -sub 16 er d 1001...001000... .......... U U U U U 4 4 2 2 2 -sub 16 er a 1001...001001... .......... U U U U U 4 4 2 2 2 -sub 16 er . 1001...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -sub 32 er d 1001...010000... .......... U U U U U 6 6 2 2 2 -sub 32 er a 1001...010001... .......... U U U U U 6 6 2 2 2 -sub 32 er . 1001...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -sub 8 re . 1001...100...... A+-DXWL... U U U U U 8 8 4 4 4 -sub 16 re . 1001...101...... A+-DXWL... U U U U U 8 8 4 4 4 -sub 32 re . 1001...110...... A+-DXWL... U U U U U 12 12 4 4 4 -suba 16 . d 1001...011000... .......... U U U U U 8 8 2 2 2 -suba 16 . a 1001...011001... .......... U U U U U 8 8 2 2 2 -suba 16 . . 1001...011...... A+-DXWLdxI U U U U U 8 8 2 2 2 -suba 32 . d 1001...111000... .......... U U U U U 6 6 2 2 2 -suba 32 . a 1001...111001... .......... U U U U U 6 6 2 2 2 -suba 32 . . 1001...111...... A+-DXWLdxI U U U U U 6 6 2 2 2 -subi 8 . d 0000010000000... .......... U U U U U 8 8 2 2 2 -subi 8 . . 0000010000...... A+-DXWL... U U U U U 12 12 4 4 4 -subi 16 . d 0000010001000... .......... U U U U U 8 8 2 2 2 -subi 16 . . 0000010001...... A+-DXWL... U U U U U 12 12 4 4 4 -subi 32 . d 0000010010000... .......... U U U U U 16 14 2 2 2 -subi 32 . . 0000010010...... A+-DXWL... U U U U U 20 20 4 4 4 -subq 8 . d 0101...100000... .......... U U U U U 4 4 2 2 2 -subq 8 . . 0101...100...... A+-DXWL... U U U U U 8 8 4 4 4 -subq 16 . d 0101...101000... .......... U U U U U 4 4 2 2 2 -subq 16 . a 0101...101001... .......... U U U U U 8 4 2 2 2 -subq 16 . . 0101...101...... A+-DXWL... U U U U U 8 8 4 4 4 -subq 32 . d 0101...110000... .......... U U U U U 8 8 2 2 2 -subq 32 . a 0101...110001... .......... U U U U U 8 8 2 2 2 -subq 32 . . 0101...110...... A+-DXWL... U U U U U 12 12 4 4 4 -subx 8 rr . 1001...100000... .......... U U U U U 4 4 2 2 2 -subx 16 rr . 1001...101000... .......... U U U U U 4 4 2 2 2 -subx 32 rr . 1001...110000... .......... U U U U U 8 6 2 2 2 -subx 8 mm ax7 1001111100001... .......... U U U U U 18 18 12 12 12 -subx 8 mm ay7 1001...100001111 .......... U U U U U 18 18 12 12 12 -subx 8 mm axy7 1001111100001111 .......... U U U U U 18 18 12 12 12 -subx 8 mm . 1001...100001... .......... U U U U U 18 18 12 12 12 -subx 16 mm . 1001...101001... .......... U U U U U 18 18 12 12 12 -subx 32 mm . 1001...110001... .......... U U U U U 30 30 12 12 12 -swap 32 . . 0100100001000... .......... U U U U U 4 4 4 4 4 -tas 8 . d 0100101011000... .......... U U U U U 4 4 4 4 4 -tas 8 . . 0100101011...... A+-DXWL... U U U U U 14 14 12 12 12 -trap 0 . . 010011100100.... .......... U U U U U 4 4 4 4 4 -trapt 0 . . 0101000011111100 .......... . . U U U . . 4 4 4 -trapt 16 . . 0101000011111010 .......... . . U U U . . 6 6 6 -trapt 32 . . 0101000011111011 .......... . . U U U . . 8 8 8 -trapf 0 . . 0101000111111100 .......... . . U U U . . 4 4 4 -trapf 16 . . 0101000111111010 .......... . . U U U . . 6 6 6 -trapf 32 . . 0101000111111011 .......... . . U U U . . 8 8 8 -trapcc 0 . . 0101....11111100 .......... . . U U U . . 4 4 4 -trapcc 16 . . 0101....11111010 .......... . . U U U . . 6 6 6 -trapcc 32 . . 0101....11111011 .......... . . U U U . . 8 8 8 -trapv 0 . . 0100111001110110 .......... U U U U U 4 4 4 4 4 -tst 8 . d 0100101000000... .......... U U U U U 4 4 2 2 2 -tst 8 . . 0100101000...... A+-DXWL... U U U U U 4 4 2 2 2 -tst 8 . pcdi 0100101000111010 .......... . . U U U . . 7 7 7 -tst 8 . pcix 0100101000111011 .......... . . U U U . . 9 9 9 -tst 8 . i 0100101000111100 .......... . . U U U . . 6 6 6 -tst 16 . d 0100101001000... .......... U U U U U 4 4 2 2 2 -tst 16 . a 0100101001001... .......... . . U U U . . 2 2 2 -tst 16 . . 0100101001...... A+-DXWL... U U U U U 4 4 2 2 2 -tst 16 . pcdi 0100101001111010 .......... . . U U U . . 7 7 7 -tst 16 . pcix 0100101001111011 .......... . . U U U . . 9 9 9 -tst 16 . i 0100101001111100 .......... . . U U U . . 6 6 6 -tst 32 . d 0100101010000... .......... U U U U U 4 4 2 2 2 -tst 32 . a 0100101010001... .......... . . U U U . . 2 2 2 -tst 32 . . 0100101010...... A+-DXWL... U U U U U 4 4 2 2 2 -tst 32 . pcdi 0100101010111010 .......... . . U U U . . 7 7 7 -tst 32 . pcix 0100101010111011 .......... . . U U U . . 9 9 9 -tst 32 . i 0100101010111100 .......... . . U U U . . 6 6 6 -unlk 32 . a7 0100111001011111 .......... U U U U U 12 12 6 6 6 -unlk 32 . . 0100111001011... .......... U U U U U 12 12 6 6 6 -unpk 16 rr . 1000...110000... .......... . . U U U . . 8 8 8 -unpk 16 mm ax7 1000111110001... .......... . . U U U . . 13 13 13 -unpk 16 mm ay7 1000...110001111 .......... . . U U U . . 13 13 13 -unpk 16 mm axy7 1000111110001111 .......... . . U U U . . 13 13 13 -unpk 16 mm . 1000...110001... .......... . . U U U . . 13 13 13 - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_OPCODE_HANDLER_BODY - -M68KMAKE_OP(1010, 0, ., .) -{ - m68ki_exception_1010(); -} - - -M68KMAKE_OP(1111, 0, ., .) -{ - m68ki_exception_1111(); -} - - -M68KMAKE_OP(040fpu0, 32, ., .) -{ - if(CPU_TYPE_IS_030_PLUS(CPU_TYPE)) - { - m68040_fpu_op0(); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(040fpu1, 32, ., .) -{ - if(CPU_TYPE_IS_030_PLUS(CPU_TYPE)) - { - m68040_fpu_op1(); - return; - } - m68ki_exception_1111(); -} - - - -M68KMAKE_OP(abcd, 8, rr, .) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(abcd, 8, mm, ax7) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(abcd, 8, mm, ay7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(abcd, 8, mm, axy7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(abcd, 8, mm, .) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(add, 8, er, d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 8, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_8; - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 16, er, d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 16, er, a) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(AY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 16, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_16; - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 32, er, d) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(add, 32, er, a) -{ - uint* r_dst = &DX; - uint src = AY; - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(add, 32, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(add, 8, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = MASK_OUT_ABOVE_8(DX); - uint dst = m68ki_read_8(ea); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(add, 16, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = MASK_OUT_ABOVE_16(DX); - uint dst = m68ki_read_16(ea); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(add, 32, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint src = DX; - uint dst = m68ki_read_32(ea); - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(adda, 16, ., d) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(DY)); -} - - -M68KMAKE_OP(adda, 16, ., a) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(AY)); -} - - -M68KMAKE_OP(adda, 16, ., .) -{ - uint* r_dst = &AX; - uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + src); -} - - -M68KMAKE_OP(adda, 32, ., d) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + DY); -} - - -M68KMAKE_OP(adda, 32, ., a) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + AY); -} - - -M68KMAKE_OP(adda, 32, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_32; - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + src); -} - - -M68KMAKE_OP(addi, 8, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_8(); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(addi, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(addi, 16, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_16(); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(addi, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint dst = m68ki_read_16(ea); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(addi, 32, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_32(); - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(addi, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint dst = m68ki_read_32(ea); - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(addq, 8, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(addq, 8, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(addq, 16, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(addq, 16, ., a) -{ - uint* r_dst = &AY; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); -} - - -M68KMAKE_OP(addq, 16, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_16; - uint dst = m68ki_read_16(ea); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(addq, 32, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(addq, 32, ., a) -{ - uint* r_dst = &AY; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); -} - - -M68KMAKE_OP(addq, 32, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_32; - uint dst = m68ki_read_32(ea); - uint res = src + dst; - - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(addx, 8, rr, .) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(addx, 16, rr, .) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; -} - - -M68KMAKE_OP(addx, 32, rr, .) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - *r_dst = res; -} - - -M68KMAKE_OP(addx, 8, mm, ax7) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(addx, 8, mm, ay7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(addx, 8, mm, axy7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(addx, 8, mm, .) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(addx, 16, mm, .) -{ - uint src = OPER_AY_PD_16(); - uint ea = EA_AX_PD_16(); - uint dst = m68ki_read_16(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - m68ki_write_16(ea, res); -} - - -M68KMAKE_OP(addx, 32, mm, .) -{ - uint src = OPER_AY_PD_32(); - uint ea = EA_AX_PD_32(); - uint dst = m68ki_read_32(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(and, 8, er, d) -{ - FLAG_Z = MASK_OUT_ABOVE_8(DX &= (DY | 0xffffff00)); - - FLAG_N = NFLAG_8(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 8, er, .) -{ - FLAG_Z = MASK_OUT_ABOVE_8(DX &= (M68KMAKE_GET_OPER_AY_8 | 0xffffff00)); - - FLAG_N = NFLAG_8(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 16, er, d) -{ - FLAG_Z = MASK_OUT_ABOVE_16(DX &= (DY | 0xffff0000)); - - FLAG_N = NFLAG_16(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 16, er, .) -{ - FLAG_Z = MASK_OUT_ABOVE_16(DX &= (M68KMAKE_GET_OPER_AY_16 | 0xffff0000)); - - FLAG_N = NFLAG_16(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 32, er, d) -{ - FLAG_Z = DX &= DY; - - FLAG_N = NFLAG_32(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 32, er, .) -{ - FLAG_Z = DX &= M68KMAKE_GET_OPER_AY_32; - - FLAG_N = NFLAG_32(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 8, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = DX & m68ki_read_8(ea); - - FLAG_N = NFLAG_8(res); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(and, 16, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = DX & m68ki_read_16(ea); - - FLAG_N = NFLAG_16(res); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(and, 32, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = DX & m68ki_read_32(ea); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(andi, 8, ., d) -{ - FLAG_Z = MASK_OUT_ABOVE_8(DY &= (OPER_I_8() | 0xffffff00)); - - FLAG_N = NFLAG_8(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(andi, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = src & m68ki_read_8(ea); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(andi, 16, ., d) -{ - FLAG_Z = MASK_OUT_ABOVE_16(DY &= (OPER_I_16() | 0xffff0000)); - - FLAG_N = NFLAG_16(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(andi, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = src & m68ki_read_16(ea); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - - m68ki_write_16(ea, res); -} - - -M68KMAKE_OP(andi, 32, ., d) -{ - FLAG_Z = DY &= (OPER_I_32()); - - FLAG_N = NFLAG_32(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(andi, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = src & m68ki_read_32(ea); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(andi, 16, toc, .) -{ - m68ki_set_ccr(m68ki_get_ccr() & OPER_I_8()); -} - - -M68KMAKE_OP(andi, 16, tos, .) -{ - if(FLAG_S) - { - uint src = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_sr(m68ki_get_sr() & src); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(asr, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> (shift - 1))<<8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - if(GET_MSB_16(src)) - { - *r_dst |= 0xffff; - FLAG_C = CFLAG_SET; - FLAG_X = XFLAG_SET; - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst &= 0xffff0000; - FLAG_C = CFLAG_CLEAR; - FLAG_X = XFLAG_CLEAR; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(asr, 32, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = *r_dst; - uint res = src >> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> (shift - 1))<<8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - if(GET_MSB_32(src)) - { - *r_dst = 0xffffffff; - FLAG_C = CFLAG_SET; - FLAG_X = XFLAG_SET; - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst = 0; - FLAG_C = CFLAG_CLEAR; - FLAG_X = XFLAG_CLEAR; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(asr, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = src >> 1; - - if(GET_MSB_16(src)) - res |= 0x8000; - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = FLAG_X = src << 8; -} - - -M68KMAKE_OP(asl, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = MASK_OUT_ABOVE_8(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = MASK_OUT_ABOVE_16(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> (8-shift); - src &= m68ki_shift_16_table[shift + 1]; - FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; -} - - -M68KMAKE_OP(asl, 32, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> (24-shift); - src &= m68ki_shift_32_table[shift + 1]; - FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; -} - - -M68KMAKE_OP(asl, 8, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = MASK_OUT_ABOVE_8(src << shift); - - if(shift != 0) - { - USE_CYCLES(shift<> 8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - src &= m68ki_shift_16_table[shift + 1]; - FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; - return; - } - - *r_dst &= 0xffff0000; - FLAG_X = FLAG_C = ((shift == 16 ? src & 1 : 0))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = (!(src == 0))<<7; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(asl, 32, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32(src << shift); - - if(shift != 0) - { - USE_CYCLES(shift<> (32 - shift)) << 8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - src &= m68ki_shift_32_table[shift + 1]; - FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; - return; - } - - *r_dst = 0; - FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = (!(src == 0))<<7; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(asl, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = MASK_OUT_ABOVE_16(src << 1); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_X = FLAG_C = src >> 7; - src &= 0xc000; - FLAG_V = (!(src == 0 || src == 0xc000))<<7; -} - - -M68KMAKE_OP(bcc, 8, ., .) -{ - if(M68KMAKE_CC) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - return; - } - USE_CYCLES(CYC_BCC_NOTAKE_B); -} - - -M68KMAKE_OP(bcc, 16, ., .) -{ - if(M68KMAKE_CC) - { - uint offset = OPER_I_16(); - REG_PC -= 2; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset); - return; - } - REG_PC += 2; - USE_CYCLES(CYC_BCC_NOTAKE_W); -} - - -M68KMAKE_OP(bcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - if(M68KMAKE_CC) - { - uint offset = OPER_I_32(); - REG_PC -= 4; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_32(offset); - return; - } - REG_PC += 4; - return; - } - else - { - if(M68KMAKE_CC) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - return; - } - USE_CYCLES(CYC_BCC_NOTAKE_B); - } -} - - -M68KMAKE_OP(bchg, 32, r, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (DX & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst ^= mask; -} - - -M68KMAKE_OP(bchg, 8, r, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint mask = 1 << (DX & 7); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src ^ mask); -} - - -M68KMAKE_OP(bchg, 32, s, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (OPER_I_8() & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst ^= mask; -} - - -M68KMAKE_OP(bchg, 8, s, .) -{ - uint mask = 1 << (OPER_I_8() & 7); - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src ^ mask); -} - - -M68KMAKE_OP(bclr, 32, r, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (DX & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst &= ~mask; -} - - -M68KMAKE_OP(bclr, 8, r, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint mask = 1 << (DX & 7); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src & ~mask); -} - - -M68KMAKE_OP(bclr, 32, s, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (OPER_I_8() & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst &= ~mask; -} - - -M68KMAKE_OP(bclr, 8, s, .) -{ - uint mask = 1 << (OPER_I_8() & 7); - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src & ~mask); -} - - -M68KMAKE_OP(bfchg, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - offset &= 31; - width = ((width-1) & 31) + 1; - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - FLAG_N = NFLAG_32(*data<>6)&31; - uint width = word2; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_N = NFLAG_32(data_long << offset); - FLAG_Z = data_long & mask_long; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - m68ki_write_32(ea, data_long ^ mask_long); - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - m68ki_write_8(ea+4, data_byte ^ mask_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfclr, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - - offset &= 31; - width = ((width-1) & 31) + 1; - - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - FLAG_N = NFLAG_32(*data<>6)&31; - uint width = word2; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_N = NFLAG_32(data_long << offset); - FLAG_Z = data_long & mask_long; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - m68ki_write_32(ea, data_long & ~mask_long); - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - m68ki_write_8(ea+4, data_byte & ~mask_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfexts, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint64 data = DY; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - offset &= 31; - width = ((width-1) & 31) + 1; - - data = ROL_32(data, offset); - FLAG_N = NFLAG_32(data); - data = MAKE_INT_32(data) >> (32 - width); - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - REG_D[(word2>>12)&7] = data; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfexts, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint offset = (word2>>6)&31; - uint width = word2; - uint data; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - data = m68ki_read_32(ea); - - data = MASK_OUT_ABOVE_32(data< 32) - data |= (m68ki_read_8(ea+4) << offset) >> 8; - - FLAG_N = NFLAG_32(data); - data = MAKE_INT_32(data) >> (32 - width); - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - REG_D[(word2 >> 12) & 7] = data; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfextu, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint64 data = DY; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - offset &= 31; - width = ((width-1) & 31) + 1; - - data = ROL_32(data, offset); - FLAG_N = NFLAG_32(data); - data >>= 32 - width; - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - REG_D[(word2>>12)&7] = data; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfextu, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint offset = (word2>>6)&31; - uint width = word2; - uint data; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - data = m68ki_read_32(ea); - data = MASK_OUT_ABOVE_32(data< 32) - data |= (m68ki_read_8(ea+4) << offset) >> 8; - - FLAG_N = NFLAG_32(data); - data >>= (32 - width); - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - REG_D[(word2 >> 12) & 7] = data; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfffo, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint64 data = DY; - uint bit; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - offset &= 31; - width = ((width-1) & 31) + 1; - - data = ROL_32(data, offset); - FLAG_N = NFLAG_32(data); - data >>= 32 - width; - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) - offset++; - - REG_D[(word2>>12)&7] = offset; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfffo, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint offset = (word2>>6)&31; - sint local_offset; - uint width = word2; - uint data; - uint bit; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - local_offset = offset % 8; - if(local_offset < 0) - { - local_offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - data = m68ki_read_32(ea); - data = MASK_OUT_ABOVE_32(data< 32) - data |= (m68ki_read_8(ea+4) << local_offset) >> 8; - - FLAG_N = NFLAG_32(data); - data >>= (32 - width); - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) - offset++; - - REG_D[(word2>>12)&7] = offset; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfins, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - uint64 insert = REG_D[(word2>>12)&7]; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - - offset &= 31; - width = ((width-1) & 31) + 1; - - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - insert = MASK_OUT_ABOVE_32(insert << (32 - width)); - FLAG_N = NFLAG_32(insert); - FLAG_Z = insert; - insert = ROR_32(insert, offset); - - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - *data &= ~mask; - *data |= insert; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfins, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint offset = (word2>>6)&31; - uint width = word2; - uint insert_base = REG_D[(word2>>12)&7]; - uint insert_long; - uint insert_byte; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); - FLAG_N = NFLAG_32(insert_base); - FLAG_Z = insert_base; - insert_long = insert_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - insert_byte = MASK_OUT_ABOVE_8(insert_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfset, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - - offset &= 31; - width = ((width-1) & 31) + 1; - - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - FLAG_N = NFLAG_32(*data<>6)&31; - uint width = word2; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_N = NFLAG_32(data_long << offset); - FLAG_Z = data_long & mask_long; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - m68ki_write_32(ea, data_long | mask_long); - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - m68ki_write_8(ea+4, data_byte | mask_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bftst, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - - offset &= 31; - width = ((width-1) & 31) + 1; - - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - FLAG_N = NFLAG_32(*data<>6)&31; - uint width = word2; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_N = ((data_long & (0x80000000 >> offset))<>24; - FLAG_Z = data_long & mask_long; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bkpt, 0, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - m68ki_bkpt_ack(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE) ? REG_IR & 7 : 0); /* auto-disable (see m68kcpu.h) */ - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bra, 8, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); -} - - -M68KMAKE_OP(bra, 16, ., .) -{ - uint offset = OPER_I_16(); - REG_PC -= 2; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); -} - - -M68KMAKE_OP(bra, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint offset = OPER_I_32(); - REG_PC -= 4; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_32(offset); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); - return; - } - else - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); - } -} - - -M68KMAKE_OP(bset, 32, r, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (DX & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst |= mask; -} - - -M68KMAKE_OP(bset, 8, r, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint mask = 1 << (DX & 7); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src | mask); -} - - -M68KMAKE_OP(bset, 32, s, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (OPER_I_8() & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst |= mask; -} - - -M68KMAKE_OP(bset, 8, s, .) -{ - uint mask = 1 << (OPER_I_8() & 7); - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src | mask); -} - - -M68KMAKE_OP(bsr, 8, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); -} - - -M68KMAKE_OP(bsr, 16, ., .) -{ - uint offset = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - REG_PC -= 2; - m68ki_branch_16(offset); -} - - -M68KMAKE_OP(bsr, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint offset = OPER_I_32(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - REG_PC -= 4; - m68ki_branch_32(offset); - return; - } - else - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - } -} - - -M68KMAKE_OP(btst, 32, r, d) -{ - FLAG_Z = DY & (1 << (DX & 0x1f)); -} - - -M68KMAKE_OP(btst, 8, r, .) -{ - FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << (DX & 7)); -} - - -M68KMAKE_OP(btst, 32, s, d) -{ - FLAG_Z = DY & (1 << (OPER_I_8() & 0x1f)); -} - - -M68KMAKE_OP(btst, 8, s, .) -{ - uint bit = OPER_I_8() & 7; - - FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << bit); -} - - -M68KMAKE_OP(callm, 32, ., .) -{ - /* note: watch out for pcrelative modes */ - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - { - uint ea = M68KMAKE_GET_EA_AY_32; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - REG_PC += 2; -(void)ea; /* just to avoid an 'unused variable' warning */ - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas, 8, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint dest = m68ki_read_8(ea); - uint* compare = ®_D[word2 & 7]; - uint res = dest - MASK_OUT_ABOVE_8(*compare); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(*compare, dest, res); - FLAG_C = CFLAG_8(res); - - if(COND_NE()) - *compare = MASK_OUT_BELOW_8(*compare) | dest; - else - { - USE_CYCLES(3); - m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint dest = m68ki_read_16(ea); - uint* compare = ®_D[word2 & 7]; - uint res = dest - MASK_OUT_ABOVE_16(*compare); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(*compare, dest, res); - FLAG_C = CFLAG_16(res); - - if(COND_NE()) - *compare = MASK_OUT_BELOW_16(*compare) | dest; - else - { - USE_CYCLES(3); - m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint dest = m68ki_read_32(ea); - uint* compare = ®_D[word2 & 7]; - uint res = dest - *compare; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(*compare, dest, res); - FLAG_C = CFLAG_SUB_32(*compare, dest, res); - - if(COND_NE()) - *compare = dest; - else - { - USE_CYCLES(3); - m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas2, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_32(); - uint* compare1 = ®_D[(word2 >> 16) & 7]; - uint ea1 = REG_DA[(word2 >> 28) & 15]; - uint dest1 = m68ki_read_16(ea1); - uint res1 = dest1 - MASK_OUT_ABOVE_16(*compare1); - uint* compare2 = ®_D[word2 & 7]; - uint ea2 = REG_DA[(word2 >> 12) & 15]; - uint dest2 = m68ki_read_16(ea2); - uint res2; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_16(res1); - FLAG_Z = MASK_OUT_ABOVE_16(res1); - FLAG_V = VFLAG_SUB_16(*compare1, dest1, res1); - FLAG_C = CFLAG_16(res1); - - if(COND_EQ()) - { - res2 = dest2 - MASK_OUT_ABOVE_16(*compare2); - - FLAG_N = NFLAG_16(res2); - FLAG_Z = MASK_OUT_ABOVE_16(res2); - FLAG_V = VFLAG_SUB_16(*compare2, dest2, res2); - FLAG_C = CFLAG_16(res2); - - if(COND_EQ()) - { - USE_CYCLES(3); - m68ki_write_16(ea1, REG_D[(word2 >> 22) & 7]); - m68ki_write_16(ea2, REG_D[(word2 >> 6) & 7]); - return; - } - } - *compare1 = BIT_1F(word2) ? (uint)MAKE_INT_16(dest1) : MASK_OUT_BELOW_16(*compare1) | dest1; - *compare2 = BIT_F(word2) ? (uint)MAKE_INT_16(dest2) : MASK_OUT_BELOW_16(*compare2) | dest2; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas2, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_32(); - uint* compare1 = ®_D[(word2 >> 16) & 7]; - uint ea1 = REG_DA[(word2 >> 28) & 15]; - uint dest1 = m68ki_read_32(ea1); - uint res1 = dest1 - *compare1; - uint* compare2 = ®_D[word2 & 7]; - uint ea2 = REG_DA[(word2 >> 12) & 15]; - uint dest2 = m68ki_read_32(ea2); - uint res2; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_32(res1); - FLAG_Z = MASK_OUT_ABOVE_32(res1); - FLAG_V = VFLAG_SUB_32(*compare1, dest1, res1); - FLAG_C = CFLAG_SUB_32(*compare1, dest1, res1); - - if(COND_EQ()) - { - res2 = dest2 - *compare2; - - FLAG_N = NFLAG_32(res2); - FLAG_Z = MASK_OUT_ABOVE_32(res2); - FLAG_V = VFLAG_SUB_32(*compare2, dest2, res2); - FLAG_C = CFLAG_SUB_32(*compare2, dest2, res2); - - if(COND_EQ()) - { - USE_CYCLES(3); - m68ki_write_32(ea1, REG_D[(word2 >> 22) & 7]); - m68ki_write_32(ea2, REG_D[(word2 >> 6) & 7]); - return; - } - } - *compare1 = dest1; - *compare2 = dest2; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk, 16, ., d) -{ - sint src = MAKE_INT_16(DX); - sint bound = MAKE_INT_16(DY); - - FLAG_Z = ZFLAG_16(src); /* Undocumented */ - FLAG_V = VFLAG_CLEAR; /* Undocumented */ - FLAG_C = CFLAG_CLEAR; /* Undocumented */ - - if(src >= 0 && src <= bound) - { - return; - } - FLAG_N = (src < 0)<<7; - m68ki_exception_trap(EXCEPTION_CHK); -} - - -M68KMAKE_OP(chk, 16, ., .) -{ - sint src = MAKE_INT_16(DX); - sint bound = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - - FLAG_Z = ZFLAG_16(src); /* Undocumented */ - FLAG_V = VFLAG_CLEAR; /* Undocumented */ - FLAG_C = CFLAG_CLEAR; /* Undocumented */ - - if(src >= 0 && src <= bound) - { - return; - } - FLAG_N = (src < 0)<<7; - m68ki_exception_trap(EXCEPTION_CHK); -} - - -M68KMAKE_OP(chk, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - sint src = MAKE_INT_32(DX); - sint bound = MAKE_INT_32(DY); - - FLAG_Z = ZFLAG_32(src); /* Undocumented */ - FLAG_V = VFLAG_CLEAR; /* Undocumented */ - FLAG_C = CFLAG_CLEAR; /* Undocumented */ - - if(src >= 0 && src <= bound) - { - return; - } - FLAG_N = (src < 0)<<7; - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - sint src = MAKE_INT_32(DX); - sint bound = MAKE_INT_32(M68KMAKE_GET_OPER_AY_32); - - FLAG_Z = ZFLAG_32(src); /* Undocumented */ - FLAG_V = VFLAG_CLEAR; /* Undocumented */ - FLAG_C = CFLAG_CLEAR; /* Undocumented */ - - if(src >= 0 && src <= bound) - { - return; - } - FLAG_N = (src < 0)<<7; - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 8, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; - uint ea = EA_PCDI_8(); - sint lower_bound = m68ki_read_pcrel_8(ea); - sint upper_bound = m68ki_read_pcrel_8(ea + 1); - - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - - - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 8, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; - uint ea = EA_PCIX_8(); - sint lower_bound = m68ki_read_pcrel_8(ea); - sint upper_bound = m68ki_read_pcrel_8(ea + 1); - - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => ||, faster operation short circuits - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 8, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; - uint ea = M68KMAKE_GET_EA_AY_8; - sint lower_bound = (int8)m68ki_read_8(ea); - sint upper_bound = (int8)m68ki_read_8(ea + 1); - - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 16, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; - uint ea = EA_PCDI_16(); - sint lower_bound = (int16)m68ki_read_pcrel_16(ea); - sint upper_bound = (int16)m68ki_read_pcrel_16(ea + 2); - - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 16, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; - uint ea = EA_PCIX_16(); - sint lower_bound = (int16)m68ki_read_pcrel_16(ea); - sint upper_bound = (int16)m68ki_read_pcrel_16(ea + 2); - - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; - uint ea = M68KMAKE_GET_EA_AY_16; - sint lower_bound = (int16)m68ki_read_16(ea); - sint upper_bound = (int16)m68ki_read_16(ea + 2); - - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 32, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = EA_PCDI_32(); - sint lower_bound = m68ki_read_pcrel_32(ea); - sint upper_bound = m68ki_read_pcrel_32(ea + 4); - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 32, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = EA_PCIX_32(); - sint lower_bound = m68ki_read_32(ea); - sint upper_bound = m68ki_read_32(ea + 4); - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - // JFF changed the logic. chk2/cmp2 uses signed values, not unsigned - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = M68KMAKE_GET_EA_AY_32; - sint lower_bound = m68ki_read_32(ea); - sint upper_bound = m68ki_read_32(ea + 4); - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(clr, 8, ., d) -{ - DY &= 0xffffff00; - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 8, ., .) -{ - m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 16, ., d) -{ - DY &= 0xffff0000; - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 16, ., .) -{ - m68ki_write_16(M68KMAKE_GET_EA_AY_16, 0); - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 32, ., d) -{ - DY = 0; - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 32, ., .) -{ - m68ki_write_32(M68KMAKE_GET_EA_AY_32, 0); - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(cmp, 8, ., d) -{ - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(DX); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmp, 8, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_8; - uint dst = MASK_OUT_ABOVE_8(DX); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmp, 16, ., d) -{ - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(DX); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmp, 16, ., a) -{ - uint src = MASK_OUT_ABOVE_16(AY); - uint dst = MASK_OUT_ABOVE_16(DX); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmp, 16, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_16; - uint dst = MASK_OUT_ABOVE_16(DX); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmp, 32, ., d) -{ - uint src = DY; - uint dst = DX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmp, 32, ., a) -{ - uint src = AY; - uint dst = DX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmp, 32, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = DX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 16, ., d) -{ - uint src = MAKE_INT_16(DY); - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 16, ., a) -{ - uint src = MAKE_INT_16(AY); - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 16, ., .) -{ - uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 32, ., d) -{ - uint src = DY; - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 32, ., a) -{ - uint src = AY; - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 32, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpi, 8, ., d) -{ - uint src = OPER_I_8(); - uint dst = MASK_OUT_ABOVE_8(DY); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpi, 8, ., .) -{ - uint src = OPER_I_8(); - uint dst = M68KMAKE_GET_OPER_AY_8; - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpi, 8, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_8(); - uint dst = OPER_PCDI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 8, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_8(); - uint dst = OPER_PCIX_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 16, ., d) -{ - uint src = OPER_I_16(); - uint dst = MASK_OUT_ABOVE_16(DY); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmpi, 16, ., .) -{ - uint src = OPER_I_16(); - uint dst = M68KMAKE_GET_OPER_AY_16; - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmpi, 16, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_16(); - uint dst = OPER_PCDI_16(); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 16, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_16(); - uint dst = OPER_PCIX_16(); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 32, ., d) -{ - uint src = OPER_I_32(); - uint dst = DY; - uint res = dst - src; - - m68ki_cmpild_callback(src, REG_IR & 7); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpi, 32, ., .) -{ - uint src = OPER_I_32(); - uint dst = M68KMAKE_GET_OPER_AY_32; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpi, 32, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_32(); - uint dst = OPER_PCDI_32(); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 32, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_32(); - uint dst = OPER_PCIX_32(); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpm, 8, ., ax7) -{ - uint src = OPER_AY_PI_8(); - uint dst = OPER_A7_PI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpm, 8, ., ay7) -{ - uint src = OPER_A7_PI_8(); - uint dst = OPER_AX_PI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpm, 8, ., axy7) -{ - uint src = OPER_A7_PI_8(); - uint dst = OPER_A7_PI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpm, 8, ., .) -{ - uint src = OPER_AY_PI_8(); - uint dst = OPER_AX_PI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpm, 16, ., .) -{ - uint src = OPER_AY_PI_16(); - uint dst = OPER_AX_PI_16(); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmpm, 32, ., .) -{ - uint src = OPER_AY_PI_32(); - uint dst = OPER_AX_PI_32(); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cpbcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(cpdbcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(cpgen, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(cpscc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(cptrapcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - // JFF: unsupported, but at least if the trap doesn't occur, app should still work, so at least PC increase is correct - REG_PC += 4; - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(dbt, 16, ., .) -{ - REG_PC += 2; -} - - -M68KMAKE_OP(dbf, 16, ., .) -{ - uint* r_dst = &DY; - uint res = MASK_OUT_ABOVE_16(*r_dst - 1); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - if(res != 0xffff) - { - uint offset = OPER_I_16(); - REG_PC -= 2; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset); - USE_CYCLES(CYC_DBCC_F_NOEXP); - return; - } - REG_PC += 2; - USE_CYCLES(CYC_DBCC_F_EXP); -} - - -M68KMAKE_OP(dbcc, 16, ., .) -{ - if(M68KMAKE_NOT_CC) - { - uint* r_dst = &DY; - uint res = MASK_OUT_ABOVE_16(*r_dst - 1); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - if(res != 0xffff) - { - uint offset = OPER_I_16(); - REG_PC -= 2; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset); - USE_CYCLES(CYC_DBCC_F_NOEXP); - return; - } - REG_PC += 2; - USE_CYCLES(CYC_DBCC_F_EXP); - return; - } - REG_PC += 2; -} - - -M68KMAKE_OP(divs, 16, ., d) -{ - uint* r_dst = &DX; - sint src = MAKE_INT_16(DY); - sint quotient; - sint remainder; - - if(src != 0) - { - if((uint32)*r_dst == 0x80000000 && src == -1) - { - FLAG_Z = 0; - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = 0; - return; - } - - quotient = MAKE_INT_32(*r_dst) / src; - remainder = MAKE_INT_32(*r_dst) % src; - - if(quotient == MAKE_INT_16(quotient)) - { - FLAG_Z = quotient; - FLAG_N = NFLAG_16(quotient); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); - return; - } - FLAG_V = VFLAG_SET; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); -} - - -M68KMAKE_OP(divs, 16, ., .) -{ - uint* r_dst = &DX; - sint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - sint quotient; - sint remainder; - - if(src != 0) - { - if((uint32)*r_dst == 0x80000000 && src == -1) - { - FLAG_Z = 0; - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = 0; - return; - } - - quotient = MAKE_INT_32(*r_dst) / src; - remainder = MAKE_INT_32(*r_dst) % src; - - if(quotient == MAKE_INT_16(quotient)) - { - FLAG_Z = quotient; - FLAG_N = NFLAG_16(quotient); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); - return; - } - FLAG_V = VFLAG_SET; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); -} - - -M68KMAKE_OP(divu, 16, ., d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - - if(src != 0) - { - uint quotient = *r_dst / src; - uint remainder = *r_dst % src; - - if(quotient < 0x10000) - { - FLAG_Z = quotient; - FLAG_N = NFLAG_16(quotient); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); - return; - } - FLAG_V = VFLAG_SET; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); -} - - -M68KMAKE_OP(divu, 16, ., .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_16; - - if(src != 0) - { - uint quotient = *r_dst / src; - uint remainder = *r_dst % src; - - if(quotient < 0x10000) - { - FLAG_Z = quotient; - FLAG_N = NFLAG_16(quotient); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); - return; - } - FLAG_V = VFLAG_SET; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); -} - - -M68KMAKE_OP(divl, 32, ., d) -{ -#if M68K_USE_64_BIT - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint64 divisor = DY; - uint64 dividend = 0; - uint64 quotient = 0; - uint64 remainder = 0; - - if(divisor != 0) - { - if(BIT_A(word2)) /* 64 bit */ - { - dividend = REG_D[word2 & 7]; - dividend <<= 32; - dividend |= REG_D[(word2 >> 12) & 7]; - - if(BIT_B(word2)) /* signed */ - { - quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); - remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); - if((sint64)quotient != (sint64)((sint32)quotient)) - { - FLAG_V = VFLAG_SET; - return; - } - } - else /* unsigned */ - { - quotient = dividend / divisor; - if(quotient > 0xffffffff) - { - FLAG_V = VFLAG_SET; - return; - } - remainder = dividend % divisor; - } - } - else /* 32 bit */ - { - dividend = REG_D[(word2 >> 12) & 7]; - if(BIT_B(word2)) /* signed */ - { - quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); - remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); - } - else /* unsigned */ - { - quotient = dividend / divisor; - remainder = dividend % divisor; - } - } - - REG_D[word2 & 7] = remainder; - REG_D[(word2 >> 12) & 7] = quotient; - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); - return; - } - m68ki_exception_illegal(); - -#else - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint divisor = DY; - uint dividend_hi = REG_D[word2 & 7]; - uint dividend_lo = REG_D[(word2 >> 12) & 7]; - uint quotient = 0; - uint remainder = 0; - uint dividend_neg = 0; - uint divisor_neg = 0; - sint i; - uint overflow; - - if(divisor != 0) - { - /* quad / long : long quotient, long remainder */ - if(BIT_A(word2)) - { - if(BIT_B(word2)) /* signed */ - { - /* special case in signed divide */ - if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) - { - REG_D[word2 & 7] = 0; - REG_D[(word2 >> 12) & 7] = 0x80000000; - - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - if(GET_MSB_32(dividend_hi)) - { - dividend_neg = 1; - dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); - dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); - } - if(GET_MSB_32(divisor)) - { - divisor_neg = 1; - divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); - - } - } - - /* if the upper long is greater than the divisor, we're overflowing. */ - if(dividend_hi >= divisor) - { - FLAG_V = VFLAG_SET; - return; - } - - for(i = 31; i >= 0; i--) - { - quotient <<= 1; - remainder = (remainder << 1) + ((dividend_hi >> i) & 1); - if(remainder >= divisor) - { - remainder -= divisor; - quotient++; - } - } - for(i = 31; i >= 0; i--) - { - quotient <<= 1; - overflow = GET_MSB_32(remainder); - remainder = (remainder << 1) + ((dividend_lo >> i) & 1); - if(remainder >= divisor || overflow) - { - remainder -= divisor; - quotient++; - } - } - - if(BIT_B(word2)) /* signed */ - { - if(quotient > 0x7fffffff) - { - FLAG_V = VFLAG_SET; - return; - } - if(dividend_neg) - { - remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); - quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); - } - if(divisor_neg) - quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); - } - - REG_D[word2 & 7] = remainder; - REG_D[(word2 >> 12) & 7] = quotient; - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - - /* long / long: long quotient, maybe long remainder */ - if(BIT_B(word2)) /* signed */ - { - /* Special case in divide */ - if(dividend_lo == 0x80000000 && divisor == 0xffffffff) - { - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - REG_D[(word2 >> 12) & 7] = 0x80000000; - REG_D[word2 & 7] = 0; - return; - } - REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); - quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); - } - else - { - REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); - quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); - } - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); - return; - } - m68ki_exception_illegal(); - -#endif -} - - -M68KMAKE_OP(divl, 32, ., .) -{ -#if M68K_USE_64_BIT - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint64 divisor = M68KMAKE_GET_OPER_AY_32; - uint64 dividend = 0; - uint64 quotient = 0; - uint64 remainder = 0; - - if(divisor != 0) - { - if(BIT_A(word2)) /* 64 bit */ - { - dividend = REG_D[word2 & 7]; - dividend <<= 32; - dividend |= REG_D[(word2 >> 12) & 7]; - - if(BIT_B(word2)) /* signed */ - { - quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); - remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); - if((sint64)quotient != (sint64)((sint32)quotient)) - { - FLAG_V = VFLAG_SET; - return; - } - } - else /* unsigned */ - { - quotient = dividend / divisor; - if(quotient > 0xffffffff) - { - FLAG_V = VFLAG_SET; - return; - } - remainder = dividend % divisor; - } - } - else /* 32 bit */ - { - dividend = REG_D[(word2 >> 12) & 7]; - if(BIT_B(word2)) /* signed */ - { - quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); - remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); - } - else /* unsigned */ - { - quotient = dividend / divisor; - remainder = dividend % divisor; - } - } - - REG_D[word2 & 7] = remainder; - REG_D[(word2 >> 12) & 7] = quotient; - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); - return; - } - m68ki_exception_illegal(); - -#else - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint divisor = M68KMAKE_GET_OPER_AY_32; - uint dividend_hi = REG_D[word2 & 7]; - uint dividend_lo = REG_D[(word2 >> 12) & 7]; - uint quotient = 0; - uint remainder = 0; - uint dividend_neg = 0; - uint divisor_neg = 0; - sint i; - uint overflow; - - if(divisor != 0) - { - /* quad / long : long quotient, long remainder */ - if(BIT_A(word2)) - { - if(BIT_B(word2)) /* signed */ - { - /* special case in signed divide */ - if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) - { - REG_D[word2 & 7] = 0; - REG_D[(word2 >> 12) & 7] = 0x80000000; - - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - if(GET_MSB_32(dividend_hi)) - { - dividend_neg = 1; - dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); - dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); - } - if(GET_MSB_32(divisor)) - { - divisor_neg = 1; - divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); - - } - } - - /* if the upper long is greater than the divisor, we're overflowing. */ - if(dividend_hi >= divisor) - { - FLAG_V = VFLAG_SET; - return; - } - - for(i = 31; i >= 0; i--) - { - quotient <<= 1; - remainder = (remainder << 1) + ((dividend_hi >> i) & 1); - if(remainder >= divisor) - { - remainder -= divisor; - quotient++; - } - } - for(i = 31; i >= 0; i--) - { - quotient <<= 1; - overflow = GET_MSB_32(remainder); - remainder = (remainder << 1) + ((dividend_lo >> i) & 1); - if(remainder >= divisor || overflow) - { - remainder -= divisor; - quotient++; - } - } - - if(BIT_B(word2)) /* signed */ - { - if(quotient > 0x7fffffff) - { - FLAG_V = VFLAG_SET; - return; - } - if(dividend_neg) - { - remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); - quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); - } - if(divisor_neg) - quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); - } - - REG_D[word2 & 7] = remainder; - REG_D[(word2 >> 12) & 7] = quotient; - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - - /* long / long: long quotient, maybe long remainder */ - if(BIT_B(word2)) /* signed */ - { - /* Special case in divide */ - if(dividend_lo == 0x80000000 && divisor == 0xffffffff) - { - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - REG_D[(word2 >> 12) & 7] = 0x80000000; - REG_D[word2 & 7] = 0; - return; - } - REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); - quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); - } - else - { - REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); - quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); - } - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); - return; - } - m68ki_exception_illegal(); - -#endif -} - - -M68KMAKE_OP(eor, 8, ., d) -{ - uint res = MASK_OUT_ABOVE_8(DY ^= MASK_OUT_ABOVE_8(DX)); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 16, ., d) -{ - uint res = MASK_OUT_ABOVE_16(DY ^= MASK_OUT_ABOVE_16(DX)); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 32, ., d) -{ - uint res = DY ^= DX; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = DX ^ m68ki_read_32(ea); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 8, ., d) -{ - uint res = MASK_OUT_ABOVE_8(DY ^= OPER_I_8()); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = src ^ m68ki_read_8(ea); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 16, ., d) -{ - uint res = MASK_OUT_ABOVE_16(DY ^= OPER_I_16()); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = src ^ m68ki_read_16(ea); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 32, ., d) -{ - uint res = DY ^= OPER_I_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = src ^ m68ki_read_32(ea); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 16, toc, .) -{ - m68ki_set_ccr(m68ki_get_ccr() ^ OPER_I_8()); -} - - -M68KMAKE_OP(eori, 16, tos, .) -{ - if(FLAG_S) - { - uint src = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_sr(m68ki_get_sr() ^ src); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(exg, 32, dd, .) -{ - uint* reg_a = &DX; - uint* reg_b = &DY; - uint tmp = *reg_a; - *reg_a = *reg_b; - *reg_b = tmp; -} - - -M68KMAKE_OP(exg, 32, aa, .) -{ - uint* reg_a = &AX; - uint* reg_b = &AY; - uint tmp = *reg_a; - *reg_a = *reg_b; - *reg_b = tmp; -} - - -M68KMAKE_OP(exg, 32, da, .) -{ - uint* reg_a = &DX; - uint* reg_b = &AY; - uint tmp = *reg_a; - *reg_a = *reg_b; - *reg_b = tmp; -} - - -M68KMAKE_OP(ext, 16, ., .) -{ - uint* r_dst = &DY; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xff00 : 0); - - FLAG_N = NFLAG_16(*r_dst); - FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(ext, 32, ., .) -{ - uint* r_dst = &DY; - - *r_dst = MASK_OUT_ABOVE_16(*r_dst) | (GET_MSB_16(*r_dst) ? 0xffff0000 : 0); - - FLAG_N = NFLAG_32(*r_dst); - FLAG_Z = *r_dst; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(extb, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint* r_dst = &DY; - - *r_dst = MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xffffff00 : 0); - - FLAG_N = NFLAG_32(*r_dst); - FLAG_Z = *r_dst; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(illegal, 0, ., .) -{ - m68ki_exception_illegal(); -} - -M68KMAKE_OP(jmp, 32, ., .) -{ - m68ki_jump(M68KMAKE_GET_EA_AY_32); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); -} - - -M68KMAKE_OP(jsr, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - m68ki_jump(ea); -} - - -M68KMAKE_OP(lea, 32, ., .) -{ - AX = M68KMAKE_GET_EA_AY_32; -} - - -M68KMAKE_OP(link, 16, ., a7) -{ - REG_A[7] -= 4; - m68ki_write_32(REG_A[7], REG_A[7]); - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); -} - - -M68KMAKE_OP(link, 16, ., .) -{ - uint* r_dst = &AY; - - m68ki_push_32(*r_dst); - *r_dst = REG_A[7]; - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); -} - - -M68KMAKE_OP(link, 32, ., a7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_A[7] -= 4; - m68ki_write_32(REG_A[7], REG_A[7]); - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(link, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint* r_dst = &AY; - - m68ki_push_32(*r_dst); - *r_dst = REG_A[7]; - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(lsr, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> (shift - 1))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst &= 0xffff0000; - FLAG_X = XFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsr, 32, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = *r_dst; - uint res = src >> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> (shift - 1))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst = 0; - FLAG_X = FLAG_C = (shift == 32 ? GET_MSB_32(src)>>23 : 0); - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsr, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = src >> 1; - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_CLEAR; - FLAG_Z = res; - FLAG_C = FLAG_X = src << 8; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = MASK_OUT_ABOVE_8(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = MASK_OUT_ABOVE_16(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> (8-shift); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 32, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> (24-shift); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 8, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = MASK_OUT_ABOVE_8(src << shift); - - if(shift != 0) - { - USE_CYCLES(shift<> 8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst &= 0xffff0000; - FLAG_X = XFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 32, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32(src << shift); - - if(shift != 0) - { - USE_CYCLES(shift<> (32 - shift)) << 8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst = 0; - FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = MASK_OUT_ABOVE_16(src << 1); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_X = FLAG_C = src >> 7; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, d, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, d, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, ai, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_AI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, ai, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_AI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pi7, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_A7_PI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pi, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_PI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pi7, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_A7_PI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pi, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_PI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pd7, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_A7_PD_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pd, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_PD_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pd7, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_A7_PD_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pd, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_PD_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, di, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_DI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, di, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_DI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, ix, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_IX_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, ix, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_IX_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, aw, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AW_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, aw, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AW_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, al, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AL_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, al, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AL_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, d, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, d, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, d, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ai, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_AI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ai, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_AI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ai, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_AI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pi, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_PI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pi, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_PI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pi, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_PI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pd, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_PD_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pd, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_PD_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pd, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_PD_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, di, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_DI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, di, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_DI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, di, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_DI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ix, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_IX_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ix, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_IX_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ix, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_IX_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, aw, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AW_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, aw, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AW_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, aw, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AW_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, al, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AL_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, al, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AL_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, al, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AL_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, d, d) -{ - uint res = DY; - uint* r_dst = &DX; - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, d, a) -{ - uint res = AY; - uint* r_dst = &DX; - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, d, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint* r_dst = &DX; - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ai, d) -{ - uint res = DY; - uint ea = EA_AX_AI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ai, a) -{ - uint res = AY; - uint ea = EA_AX_AI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ai, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_AI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pi, d) -{ - uint res = DY; - uint ea = EA_AX_PI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pi, a) -{ - uint res = AY; - uint ea = EA_AX_PI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pi, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_PI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pd, d) -{ - uint res = DY; - uint ea = EA_AX_PD_32(); - - m68ki_write_16(ea+2, res & 0xFFFF ); - m68ki_write_16(ea, (res >> 16) & 0xFFFF ); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pd, a) -{ - uint res = AY; - uint ea = EA_AX_PD_32(); - - m68ki_write_16(ea+2, res & 0xFFFF ); - m68ki_write_16(ea, (res >> 16) & 0xFFFF ); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pd, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_PD_32(); - - m68ki_write_16(ea+2, res & 0xFFFF ); - m68ki_write_16(ea, (res >> 16) & 0xFFFF ); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, di, d) -{ - uint res = DY; - uint ea = EA_AX_DI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, di, a) -{ - uint res = AY; - uint ea = EA_AX_DI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, di, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_DI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ix, d) -{ - uint res = DY; - uint ea = EA_AX_IX_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ix, a) -{ - uint res = AY; - uint ea = EA_AX_IX_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ix, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_IX_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, aw, d) -{ - uint res = DY; - uint ea = EA_AW_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, aw, a) -{ - uint res = AY; - uint ea = EA_AW_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, aw, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AW_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, al, d) -{ - uint res = DY; - uint ea = EA_AL_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, al, a) -{ - uint res = AY; - uint ea = EA_AL_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, al, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AL_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(movea, 16, ., d) -{ - AX = MAKE_INT_16(DY); -} - - -M68KMAKE_OP(movea, 16, ., a) -{ - AX = MAKE_INT_16(AY); -} - - -M68KMAKE_OP(movea, 16, ., .) -{ - AX = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); -} - - -M68KMAKE_OP(movea, 32, ., d) -{ - AX = DY; -} - - -M68KMAKE_OP(movea, 32, ., a) -{ - AX = AY; -} - - -M68KMAKE_OP(movea, 32, ., .) -{ - AX = M68KMAKE_GET_OPER_AY_32; -} - - -M68KMAKE_OP(move, 16, frc, d) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - DY = MASK_OUT_BELOW_16(DY) | m68ki_get_ccr(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(move, 16, frc, .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - m68ki_write_16(M68KMAKE_GET_EA_AY_16, m68ki_get_ccr()); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(move, 16, toc, d) -{ - m68ki_set_ccr(DY); -} - - -M68KMAKE_OP(move, 16, toc, .) -{ - m68ki_set_ccr(M68KMAKE_GET_OPER_AY_16); -} - - -M68KMAKE_OP(move, 16, frs, d) -{ - if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ - { - DY = MASK_OUT_BELOW_16(DY) | m68ki_get_sr(); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 16, frs, .) -{ - if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ - { - uint ea = M68KMAKE_GET_EA_AY_16; - m68ki_write_16(ea, m68ki_get_sr()); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 16, tos, d) -{ - if(FLAG_S) - { - m68ki_set_sr(DY); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 16, tos, .) -{ - if(FLAG_S) - { - uint new_sr = M68KMAKE_GET_OPER_AY_16; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_sr(new_sr); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 32, fru, .) -{ - if(FLAG_S) - { - AY = REG_USP; - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 32, tou, .) -{ - if(FLAG_S) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - REG_USP = AY; - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(movec, 32, cr, .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - switch (word2 & 0xfff) - { - case 0x000: /* SFC */ - REG_DA[(word2 >> 12) & 15] = REG_SFC; - return; - case 0x001: /* DFC */ - REG_DA[(word2 >> 12) & 15] = REG_DFC; - return; - case 0x002: /* CACR */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_DA[(word2 >> 12) & 15] = REG_CACR; - return; - } - return; - case 0x800: /* USP */ - REG_DA[(word2 >> 12) & 15] = REG_USP; - return; - case 0x801: /* VBR */ - REG_DA[(word2 >> 12) & 15] = REG_VBR; - return; - case 0x802: /* CAAR */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_DA[(word2 >> 12) & 15] = REG_CAAR; - return; - } - m68ki_exception_illegal(); - break; - case 0x803: /* MSP */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_SP : REG_MSP; - return; - } - m68ki_exception_illegal(); - return; - case 0x804: /* ISP */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_ISP : REG_SP; - return; - } - m68ki_exception_illegal(); - return; - case 0x003: /* TC */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x004: /* ITT0 */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x005: /* ITT1 */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x006: /* DTT0 */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x007: /* DTT1 */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x805: /* MMUSR */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x806: /* URP */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x807: /* SRP */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - default: - m68ki_exception_illegal(); - return; - } - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(movec, 32, rc, .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - switch (word2 & 0xfff) - { - case 0x000: /* SFC */ - REG_SFC = REG_DA[(word2 >> 12) & 15] & 7; - return; - case 0x001: /* DFC */ - REG_DFC = REG_DA[(word2 >> 12) & 15] & 7; - return; - case 0x002: /* CACR */ - /* Only EC020 and later have CACR */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* 68030 can write all bits except 5-7, 040 can write all */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - REG_CACR = REG_DA[(word2 >> 12) & 15]; - } - else if (CPU_TYPE_IS_030_PLUS(CPU_TYPE)) - { - REG_CACR = REG_DA[(word2 >> 12) & 15] & 0xff1f; - } - else - { - REG_CACR = REG_DA[(word2 >> 12) & 15] & 0x0f; - } - return; - } - m68ki_exception_illegal(); - return; - case 0x800: /* USP */ - REG_USP = REG_DA[(word2 >> 12) & 15]; - return; - case 0x801: /* VBR */ - REG_VBR = REG_DA[(word2 >> 12) & 15]; - return; - case 0x802: /* CAAR */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_CAAR = REG_DA[(word2 >> 12) & 15]; - return; - } - m68ki_exception_illegal(); - return; - case 0x803: /* MSP */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* we are in supervisor mode so just check for M flag */ - if(!FLAG_M) - { - REG_MSP = REG_DA[(word2 >> 12) & 15]; - return; - } - REG_SP = REG_DA[(word2 >> 12) & 15]; - return; - } - m68ki_exception_illegal(); - return; - case 0x804: /* ISP */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - if(!FLAG_M) - { - REG_SP = REG_DA[(word2 >> 12) & 15]; - return; - } - REG_ISP = REG_DA[(word2 >> 12) & 15]; - return; - } - m68ki_exception_illegal(); - return; - case 0x003: /* TC */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x004: /* ITT0 */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x005: /* ITT1 */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x006: /* DTT0 */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x007: /* DTT1 */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x805: /* MMUSR */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x806: /* URP */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x807: /* SRP */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - default: - m68ki_exception_illegal(); - return; - } - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(movem, 16, re, pd) -{ - uint i = 0; - uint register_list = OPER_I_16(); - uint ea = AY; - uint count = 0; - - for(; i < 16; i++) - if(register_list & (1 << i)) - { - ea -= 2; - m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[15-i])); - count++; - } - AY = ea; - - USE_CYCLES(count<> 16) & 0xFFFF ); - count++; - } - AY = ea; - - USE_CYCLES(count<> 8)); - m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); -} - - -M68KMAKE_OP(movep, 32, re, .) -{ - uint ea = EA_AY_DI_32(); - uint src = DX; - - m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 24)); - m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 16)); - m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 8)); - m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); -} - - -M68KMAKE_OP(movep, 16, er, .) -{ - uint ea = EA_AY_DI_16(); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | ((m68ki_read_8(ea) << 8) + m68ki_read_8(ea + 2)); -} - - -M68KMAKE_OP(movep, 32, er, .) -{ - uint ea = EA_AY_DI_32(); - - DX = (m68ki_read_8(ea) << 24) + (m68ki_read_8(ea + 2) << 16) - + (m68ki_read_8(ea + 4) << 8) + m68ki_read_8(ea + 6); -} - - -M68KMAKE_OP(moves, 8, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_8; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(BIT_B(word2)) /* Register to memory */ - { - m68ki_write_8_fc(ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); - return; - } - if(BIT_F(word2)) /* Memory to address register */ - { - REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(ea, REG_SFC)); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - /* Memory to data register */ - REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(ea, REG_SFC); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(moves, 16, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(BIT_B(word2)) /* Register to memory */ - { - m68ki_write_16_fc(ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); - return; - } - if(BIT_F(word2)) /* Memory to address register */ - { - REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(ea, REG_SFC)); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - /* Memory to data register */ - REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(ea, REG_SFC); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(moves, 32, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_32; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(BIT_B(word2)) /* Register to memory */ - { - m68ki_write_32_fc(ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - /* Memory to register */ - REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(ea, REG_SFC); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(moveq, 32, ., .) -{ - uint res = DX = MAKE_INT_8(MASK_OUT_ABOVE_8(REG_IR)); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move16, 32, ., .) -{ - uint16 w2 = OPER_I_16(); - int ax = REG_IR & 7; - int ay = (w2 >> 12) & 7; - - m68ki_write_32(REG_A[ay], m68ki_read_32(REG_A[ax])); - m68ki_write_32(REG_A[ay]+4, m68ki_read_32(REG_A[ax]+4)); - m68ki_write_32(REG_A[ay]+8, m68ki_read_32(REG_A[ax]+8)); - m68ki_write_32(REG_A[ay]+12, m68ki_read_32(REG_A[ax]+12)); - - REG_A[ax] += 16; - REG_A[ay] += 16; -} - - -M68KMAKE_OP(muls, 16, ., d) -{ - uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); - - *r_dst = res; - - FLAG_Z = res; - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(muls, 16, ., .) -{ - uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(M68KMAKE_GET_OPER_AY_16) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); - - *r_dst = res; - - FLAG_Z = res; - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(mulu, 16, ., d) -{ - uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); - - *r_dst = res; - - FLAG_Z = res; - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(mulu, 16, ., .) -{ - uint* r_dst = &DX; - uint res = M68KMAKE_GET_OPER_AY_16 * MASK_OUT_ABOVE_16(*r_dst); - - *r_dst = res; - - FLAG_Z = res; - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(mull, 32, ., d) -{ -#if M68K_USE_64_BIT - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint64 src = DY; - uint64 dst = REG_D[(word2 >> 12) & 7]; - uint64 res; - - FLAG_C = CFLAG_CLEAR; - - if(BIT_B(word2)) /* signed */ - { - res = (sint64)((sint32)src) * (sint64)((sint32)dst); - if(!BIT_A(word2)) - { - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_N = NFLAG_32(res); - FLAG_V = ((sint64)res != (sint32)res)<<7; - REG_D[(word2 >> 12) & 7] = FLAG_Z; - return; - } - FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); - FLAG_N = NFLAG_64(res); - FLAG_V = VFLAG_CLEAR; - REG_D[word2 & 7] = (res >> 32); - REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); - return; - } - - res = src * dst; - if(!BIT_A(word2)) - { - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_N = NFLAG_32(res); - FLAG_V = (res > 0xffffffff)<<7; - REG_D[(word2 >> 12) & 7] = FLAG_Z; - return; - } - FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); - FLAG_N = NFLAG_64(res); - FLAG_V = VFLAG_CLEAR; - REG_D[word2 & 7] = (res >> 32); - REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); - return; - } - m68ki_exception_illegal(); - -#else - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint src = DY; - uint dst = REG_D[(word2 >> 12) & 7]; - uint neg = GET_MSB_32(src ^ dst); - uint src1; - uint src2; - uint dst1; - uint dst2; - uint r1; - uint r2; - uint r3; - uint r4; - uint lo; - uint hi; - - FLAG_C = CFLAG_CLEAR; - - if(BIT_B(word2)) /* signed */ - { - if(GET_MSB_32(src)) - src = (uint)MASK_OUT_ABOVE_32(-(sint)src); - if(GET_MSB_32(dst)) - dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); - } - - src1 = MASK_OUT_ABOVE_16(src); - src2 = src>>16; - dst1 = MASK_OUT_ABOVE_16(dst); - dst2 = dst>>16; - - - r1 = src1 * dst1; - r2 = src1 * dst2; - r3 = src2 * dst1; - r4 = src2 * dst2; - - lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); - hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); - - if(BIT_B(word2) && neg) - { - hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); - lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); - } - - if(BIT_A(word2)) - { - REG_D[word2 & 7] = hi; - REG_D[(word2 >> 12) & 7] = lo; - FLAG_N = NFLAG_32(hi); - FLAG_Z = hi | lo; - FLAG_V = VFLAG_CLEAR; - return; - } - - REG_D[(word2 >> 12) & 7] = lo; - FLAG_N = NFLAG_32(lo); - FLAG_Z = lo; - if(BIT_B(word2)) - FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; - else - FLAG_V = (hi != 0) << 7; - return; - } - m68ki_exception_illegal(); - -#endif -} - - -M68KMAKE_OP(mull, 32, ., .) -{ -#if M68K_USE_64_BIT - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint64 src = M68KMAKE_GET_OPER_AY_32; - uint64 dst = REG_D[(word2 >> 12) & 7]; - uint64 res; - - FLAG_C = CFLAG_CLEAR; - - if(BIT_B(word2)) /* signed */ - { - res = (sint64)((sint32)src) * (sint64)((sint32)dst); - if(!BIT_A(word2)) - { - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_N = NFLAG_32(res); - FLAG_V = ((sint64)res != (sint32)res)<<7; - REG_D[(word2 >> 12) & 7] = FLAG_Z; - return; - } - FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); - FLAG_N = NFLAG_64(res); - FLAG_V = VFLAG_CLEAR; - REG_D[word2 & 7] = (res >> 32); - REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); - return; - } - - res = src * dst; - if(!BIT_A(word2)) - { - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_N = NFLAG_32(res); - FLAG_V = (res > 0xffffffff)<<7; - REG_D[(word2 >> 12) & 7] = FLAG_Z; - return; - } - FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); - FLAG_N = NFLAG_64(res); - FLAG_V = VFLAG_CLEAR; - REG_D[word2 & 7] = (res >> 32); - REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); - return; - } - m68ki_exception_illegal(); - -#else - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = REG_D[(word2 >> 12) & 7]; - uint neg = GET_MSB_32(src ^ dst); - uint src1; - uint src2; - uint dst1; - uint dst2; - uint r1; - uint r2; - uint r3; - uint r4; - uint lo; - uint hi; - - FLAG_C = CFLAG_CLEAR; - - if(BIT_B(word2)) /* signed */ - { - if(GET_MSB_32(src)) - src = (uint)MASK_OUT_ABOVE_32(-(sint)src); - if(GET_MSB_32(dst)) - dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); - } - - src1 = MASK_OUT_ABOVE_16(src); - src2 = src>>16; - dst1 = MASK_OUT_ABOVE_16(dst); - dst2 = dst>>16; - - - r1 = src1 * dst1; - r2 = src1 * dst2; - r3 = src2 * dst1; - r4 = src2 * dst2; - - lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); - hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); - - if(BIT_B(word2) && neg) - { - hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); - lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); - } - - if(BIT_A(word2)) - { - REG_D[word2 & 7] = hi; - REG_D[(word2 >> 12) & 7] = lo; - FLAG_N = NFLAG_32(hi); - FLAG_Z = hi | lo; - FLAG_V = VFLAG_CLEAR; - return; - } - - REG_D[(word2 >> 12) & 7] = lo; - FLAG_N = NFLAG_32(lo); - FLAG_Z = lo; - if(BIT_B(word2)) - FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; - else - FLAG_V = (hi != 0) << 7; - return; - } - m68ki_exception_illegal(); - -#endif -} - - -M68KMAKE_OP(nbcd, 8, ., d) -{ - uint* r_dst = &DY; - uint dst = *r_dst; - uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); - - if(res != 0x9a) - { - FLAG_V = ~res; /* Undefined V behavior */ - - if((res & 0x0f) == 0xa) - res = (res & 0xf0) + 0x10; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; - - FLAG_Z |= res; - FLAG_C = CFLAG_SET; - FLAG_X = XFLAG_SET; - } - else - { - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_X = XFLAG_CLEAR; - } - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ -} - - -M68KMAKE_OP(nbcd, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); - - if(res != 0x9a) - { - FLAG_V = ~res; /* Undefined V behavior */ - - if((res & 0x0f) == 0xa) - res = (res & 0xf0) + 0x10; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - - m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); - - FLAG_Z |= res; - FLAG_C = CFLAG_SET; - FLAG_X = XFLAG_SET; - } - else - { - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_X = XFLAG_CLEAR; - } - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ -} - - -M68KMAKE_OP(neg, 8, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_8(*r_dst); - - FLAG_N = NFLAG_8(res); - FLAG_C = FLAG_X = CFLAG_8(res); - FLAG_V = *r_dst & res; - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(neg, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint res = 0 - src; - - FLAG_N = NFLAG_8(res); - FLAG_C = FLAG_X = CFLAG_8(res); - FLAG_V = src & res; - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(neg, 16, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_16(*r_dst); - - FLAG_N = NFLAG_16(res); - FLAG_C = FLAG_X = CFLAG_16(res); - FLAG_V = (*r_dst & res)>>8; - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(neg, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = 0 - src; - - FLAG_N = NFLAG_16(res); - FLAG_C = FLAG_X = CFLAG_16(res); - FLAG_V = (src & res)>>8; - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(neg, 32, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - *r_dst; - - FLAG_N = NFLAG_32(res); - FLAG_C = FLAG_X = CFLAG_SUB_32(*r_dst, 0, res); - FLAG_V = (*r_dst & res)>>24; - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(neg, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint src = m68ki_read_32(ea); - uint res = 0 - src; - - FLAG_N = NFLAG_32(res); - FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); - FLAG_V = (src & res)>>24; - FLAG_Z = MASK_OUT_ABOVE_32(res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(negx, 8, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_8(*r_dst) - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = *r_dst & res; - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(negx, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint res = 0 - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = src & res; - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(negx, 16, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_16(*r_dst) - XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = (*r_dst & res)>>8; - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; -} - - -M68KMAKE_OP(negx, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = (src & res)>>8; - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - m68ki_write_16(ea, res); -} - - -M68KMAKE_OP(negx, 32, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_32(*r_dst) - XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(*r_dst, 0, res); - FLAG_V = (*r_dst & res)>>24; - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - *r_dst = res; -} - - -M68KMAKE_OP(negx, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint src = m68ki_read_32(ea); - uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); - FLAG_V = (src & res)>>24; - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(nop, 0, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ -} - - -M68KMAKE_OP(not, 8, ., d) -{ - uint* r_dst = &DY; - uint res = MASK_OUT_ABOVE_8(~*r_dst); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 16, ., d) -{ - uint* r_dst = &DY; - uint res = MASK_OUT_ABOVE_16(~*r_dst); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 32, ., d) -{ - uint* r_dst = &DY; - uint res = *r_dst = MASK_OUT_ABOVE_32(~*r_dst); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 8, er, d) -{ - uint res = MASK_OUT_ABOVE_8((DX |= MASK_OUT_ABOVE_8(DY))); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 8, er, .) -{ - uint res = MASK_OUT_ABOVE_8((DX |= M68KMAKE_GET_OPER_AY_8)); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 16, er, d) -{ - uint res = MASK_OUT_ABOVE_16((DX |= MASK_OUT_ABOVE_16(DY))); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 16, er, .) -{ - uint res = MASK_OUT_ABOVE_16((DX |= M68KMAKE_GET_OPER_AY_16)); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 32, er, d) -{ - uint res = DX |= DY; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 32, er, .) -{ - uint res = DX |= M68KMAKE_GET_OPER_AY_32; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 8, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 16, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 32, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = DX | m68ki_read_32(ea); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 8, ., d) -{ - uint res = MASK_OUT_ABOVE_8((DY |= OPER_I_8())); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 16, ., d) -{ - uint res = MASK_OUT_ABOVE_16(DY |= OPER_I_16()); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 32, ., d) -{ - uint res = DY |= OPER_I_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = src | m68ki_read_32(ea); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 16, toc, .) -{ - m68ki_set_ccr(m68ki_get_ccr() | OPER_I_8()); -} - - -M68KMAKE_OP(ori, 16, tos, .) -{ - if(FLAG_S) - { - uint src = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_sr(m68ki_get_sr() | src); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(pack, 16, rr, .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: DX and DY are reversed in Motorola's docs */ - uint src = DY + OPER_I_16(); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | ((src >> 4) & 0x00f0) | (src & 0x000f); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pack, 16, mm, ax7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint ea_src = EA_AY_PD_8(); - uint src = m68ki_read_8(ea_src); - ea_src = EA_AY_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - - m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pack, 16, mm, ay7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint ea_src = EA_A7_PD_8(); - uint src = m68ki_read_8(ea_src); - ea_src = EA_A7_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - - m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pack, 16, mm, axy7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint ea_src = EA_A7_PD_8(); - uint src = m68ki_read_8(ea_src); - ea_src = EA_A7_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - - m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pack, 16, mm, .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint ea_src = EA_AY_PD_8(); - uint src = m68ki_read_8(ea_src); - ea_src = EA_AY_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - - m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pea, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - - m68ki_push_32(ea); -} - -M68KMAKE_OP(pflush, 32, ., .) -{ - if ((CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) && (HAS_PMMU)) - { - fprintf(stderr,"68040: unhandled PFLUSH\n"); - return; - } - m68ki_exception_1111(); -} - -M68KMAKE_OP(pmmu, 32, ., .) -{ - if ((CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) && (HAS_PMMU)) - { - m68881_mmu_ops(); - } - else - { - m68ki_exception_1111(); - } -} - -M68KMAKE_OP(reset, 0, ., .) -{ - if(FLAG_S) - { - m68ki_output_reset(); /* auto-disable (see m68kcpu.h) */ - USE_CYCLES(CYC_RESET); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(ror, 8, s, .) -{ - uint* r_dst = &DY; - uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint shift = orig_shift & 7; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROR_8(src, shift); - - if(orig_shift != 0) - USE_CYCLES(orig_shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = ROR_16(src, shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint64 src = *r_dst; - uint res = ROR_32(src, shift); - - if(shift != 0) - USE_CYCLES(shift<> ((shift - 1) & 15)) << 8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ror, 32, r, .) -{ - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift & 31; - uint64 src = *r_dst; - uint res = ROR_32(src, shift); - - if(orig_shift != 0) - { - USE_CYCLES(orig_shift<> ((shift - 1) & 31)) << 8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ror, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = ROR_16(src, 1); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = src << 8; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 8, s, .) -{ - uint* r_dst = &DY; - uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint shift = orig_shift & 7; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROL_8(src, shift); - - if(orig_shift != 0) - USE_CYCLES(orig_shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = ROL_16(src, shift); - - if(shift != 0) - USE_CYCLES(shift<> (8-shift); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 32, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint64 src = *r_dst; - uint res = ROL_32(src, shift); - - if(shift != 0) - USE_CYCLES(shift<> (24-shift); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 8, r, .) -{ - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift & 7; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROL_8(src, shift); - - if(orig_shift != 0) - { - USE_CYCLES(orig_shift<> 8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - FLAG_C = (src & 1)<<8; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 32, r, .) -{ - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift & 31; - uint64 src = *r_dst; - uint res = ROL_32(src, shift); - - if(orig_shift != 0) - { - USE_CYCLES(orig_shift<> ((32 - shift) & 0x1f)) << 8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = src >> 7; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxr, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROR_9(src | (XFLAG_AS_1() << 8), shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = ROR_17(src | (XFLAG_AS_1() << 16), shift); - - if(shift != 0) - USE_CYCLES(shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxr, 32, s, .) -{ -#if M68K_USE_64_BIT - - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint64 src = *r_dst; - uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); - - if(shift != 0) - USE_CYCLES(shift<> 24; - res = MASK_OUT_ABOVE_32(res); - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - -#else - - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); - uint new_x_flag = src & (1 << (shift - 1)); - - if(shift != 0) - USE_CYCLES(shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = FLAG_X; - FLAG_N = NFLAG_16(*r_dst); - FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxr, 32, r, .) -{ -#if M68K_USE_64_BIT - - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - - if(orig_shift != 0) - { - uint shift = orig_shift % 33; - uint64 src = *r_dst; - uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); - - res = ROR_33_64(res, shift); - - USE_CYCLES(orig_shift<> 24; - res = MASK_OUT_ABOVE_32(res); - - *r_dst = res; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = FLAG_X; - FLAG_N = NFLAG_32(*r_dst); - FLAG_Z = *r_dst; - FLAG_V = VFLAG_CLEAR; - -#else - - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift % 33; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); - uint new_x_flag = src & (1 << (shift - 1)); - - if(orig_shift != 0) - USE_CYCLES(orig_shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxl, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROL_9(src | (XFLAG_AS_1() << 8), shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = ROL_17(src | (XFLAG_AS_1() << 16), shift); - - if(shift != 0) - USE_CYCLES(shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxl, 32, s, .) -{ -#if M68K_USE_64_BIT - - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint64 src = *r_dst; - uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); - - if(shift != 0) - USE_CYCLES(shift<> 24; - res = MASK_OUT_ABOVE_32(res); - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - -#else - - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); - uint new_x_flag = src & (1 << (32 - shift)); - - if(shift != 0) - USE_CYCLES(shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = FLAG_X; - FLAG_N = NFLAG_16(*r_dst); - FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxl, 32, r, .) -{ -#if M68K_USE_64_BIT - - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - - if(orig_shift != 0) - { - uint shift = orig_shift % 33; - uint64 src = *r_dst; - uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); - - res = ROL_33_64(res, shift); - - USE_CYCLES(orig_shift<> 24; - res = MASK_OUT_ABOVE_32(res); - - *r_dst = res; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = FLAG_X; - FLAG_N = NFLAG_32(*r_dst); - FLAG_Z = *r_dst; - FLAG_V = VFLAG_CLEAR; - -#else - - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift % 33; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); - uint new_x_flag = src & (1 << (32 - shift)); - - if(orig_shift != 0) - USE_CYCLES(orig_shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rtd, 32, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - uint new_pc = m68ki_pull_32(); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); - m68ki_jump(new_pc); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(rte, 32, ., .) -{ - if(FLAG_S) - { - uint new_sr; - uint new_pc; - uint format_word; - - m68ki_rte_callback(); /* auto-disable (see m68kcpu.h) */ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - - return; - } - - if(CPU_TYPE_IS_010(CPU_TYPE)) - { - format_word = m68ki_read_16(REG_A[7]+6) >> 12; - if(format_word == 0) - { - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_fake_pull_16(); /* format word */ - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - return; - } else if (format_word == 8) { - /* Format 8 stack frame -- 68010 only. 29 word bus/address error */ - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_fake_pull_16(); /* format word */ - m68ki_fake_pull_16(); /* special status word */ - m68ki_fake_pull_32(); /* fault address */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* data output buffer */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* data input buffer */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* instruction input buffer */ - m68ki_fake_pull_32(); /* internal information, 16 words */ - m68ki_fake_pull_32(); /* (actually, we use 8 DWORDs) */ - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - return; - } - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - /* Not handling other exception types (9) */ - m68ki_exception_format_error(); - return; - } - - /* Otherwise it's 020 */ -rte_loop: - format_word = m68ki_read_16(REG_A[7]+6) >> 12; - switch(format_word) - { - case 0: /* Normal */ - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_fake_pull_16(); /* format word */ - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - return; - case 1: /* Throwaway */ - new_sr = m68ki_pull_16(); - m68ki_fake_pull_32(); /* program counter */ - m68ki_fake_pull_16(); /* format word */ - m68ki_set_sr_noint(new_sr); - goto rte_loop; - case 2: /* Trap */ - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_fake_pull_16(); /* format word */ - m68ki_fake_pull_32(); /* address */ - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - return; - } - /* Not handling long or short bus fault */ - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - m68ki_exception_format_error(); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(rtm, 32, ., .) -{ - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(rtr, 32, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_ccr(m68ki_pull_16()); - m68ki_jump(m68ki_pull_32()); -} - - -M68KMAKE_OP(rts, 32, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_jump(m68ki_pull_32()); -} - - -M68KMAKE_OP(sbcd, 8, rr, .) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(sbcd, 8, mm, ax7) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(sbcd, 8, mm, ay7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(sbcd, 8, mm, axy7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(sbcd, 8, mm, .) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(st, 8, ., d) -{ - DY |= 0xff; -} - - -M68KMAKE_OP(st, 8, ., .) -{ - m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0xff); -} - - -M68KMAKE_OP(sf, 8, ., d) -{ - DY &= 0xffffff00; -} - - -M68KMAKE_OP(sf, 8, ., .) -{ - m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); -} - - -M68KMAKE_OP(scc, 8, ., d) -{ - if(M68KMAKE_CC) - { - DY |= 0xff; - USE_CYCLES(CYC_SCC_R_TRUE); - return; - } - DY &= 0xffffff00; -} - - -M68KMAKE_OP(scc, 8, ., .) -{ - m68ki_write_8(M68KMAKE_GET_EA_AY_8, M68KMAKE_CC ? 0xff : 0); -} - - -M68KMAKE_OP(stop, 0, ., .) -{ - if(FLAG_S) - { - uint new_sr = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - CPU_STOPPED |= STOP_LEVEL_STOP; - m68ki_set_sr(new_sr); - if(m68ki_remaining_cycles >= CYC_INSTRUCTION[REG_IR]) - m68ki_remaining_cycles = CYC_INSTRUCTION[REG_IR]; - else - USE_ALL_CYCLES(); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(sub, 8, er, d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 8, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_8; - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 16, er, d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 16, er, a) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(AY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 16, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_16; - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 32, er, d) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(sub, 32, er, a) -{ - uint* r_dst = &DX; - uint src = AY; - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(sub, 32, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(sub, 8, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = MASK_OUT_ABOVE_8(DX); - uint dst = m68ki_read_8(ea); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(sub, 16, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = MASK_OUT_ABOVE_16(DX); - uint dst = m68ki_read_16(ea); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(sub, 32, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint src = DX; - uint dst = m68ki_read_32(ea); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(suba, 16, ., d) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(DY)); -} - - -M68KMAKE_OP(suba, 16, ., a) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(AY)); -} - - -M68KMAKE_OP(suba, 16, ., .) -{ - uint* r_dst = &AX; - uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - src); -} - - -M68KMAKE_OP(suba, 32, ., d) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - DY); -} - - -M68KMAKE_OP(suba, 32, ., a) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - AY); -} - - -M68KMAKE_OP(suba, 32, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_32; - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - src); -} - - -M68KMAKE_OP(subi, 8, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_8(); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(subi, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(subi, 16, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_16(); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(subi, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint dst = m68ki_read_16(ea); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(subi, 32, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_32(); - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(subi, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint dst = m68ki_read_32(ea); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(subq, 8, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(subq, 8, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(subq, 16, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(subq, 16, ., a) -{ - uint* r_dst = &AY; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); -} - - -M68KMAKE_OP(subq, 16, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_16; - uint dst = m68ki_read_16(ea); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(subq, 32, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(subq, 32, ., a) -{ - uint* r_dst = &AY; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); -} - - -M68KMAKE_OP(subq, 32, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_32; - uint dst = m68ki_read_32(ea); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(subx, 8, rr, .) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(subx, 16, rr, .) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; -} - - -M68KMAKE_OP(subx, 32, rr, .) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - *r_dst = res; -} - - -M68KMAKE_OP(subx, 8, mm, ax7) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(subx, 8, mm, ay7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(subx, 8, mm, axy7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(subx, 8, mm, .) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(subx, 16, mm, .) -{ - uint src = OPER_AY_PD_16(); - uint ea = EA_AX_PD_16(); - uint dst = m68ki_read_16(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - m68ki_write_16(ea, res); -} - - -M68KMAKE_OP(subx, 32, mm, .) -{ - uint src = OPER_AY_PD_32(); - uint ea = EA_AX_PD_32(); - uint dst = m68ki_read_32(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(swap, 32, ., .) -{ - uint* r_dst = &DY; - - FLAG_Z = MASK_OUT_ABOVE_32(*r_dst<<16); - *r_dst = (*r_dst>>16) | FLAG_Z; - - FLAG_Z = *r_dst; - FLAG_N = NFLAG_32(*r_dst); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(tas, 8, ., d) -{ - uint* r_dst = &DY; - - FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); - FLAG_N = NFLAG_8(*r_dst); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst |= 0x80; -} - - -M68KMAKE_OP(tas, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint allow_writeback; - - FLAG_Z = dst; - FLAG_N = NFLAG_8(dst); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - /* The Genesis/Megadrive games Gargoyles and Ex-Mutants need the TAS writeback - disabled in order to function properly. Some Amiga software may also rely - on this, but only when accessing specific addresses so additional functionality - will be needed. */ - allow_writeback = m68ki_tas_callback(); - - if (allow_writeback==1) m68ki_write_8(ea, dst | 0x80); -} - - -M68KMAKE_OP(trap, 0, ., .) -{ - /* Trap#n stacks exception frame type 0 */ - m68ki_exception_trapN(EXCEPTION_TRAP_BASE + (REG_IR & 0xf)); /* HJB 990403 */ -} - - -M68KMAKE_OP(trapt, 0, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapt, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 2; // JFF else stackframe & return addresses are incorrect - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapt, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 4; // JFF else stackframe & return addresses are incorrect - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapf, 0, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapf, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 2; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapf, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 4; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapcc, 0, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - if(M68KMAKE_CC) - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapcc, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 2; /* JFF increase before or 1) stackframe is incorrect 2) RTE address is wrong if trap is taken */ - if(M68KMAKE_CC) - { - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 4; /* JFF increase before or 1) stackframe is incorrect 2) RTE address is wrong if trap is taken */ - if(M68KMAKE_CC) - { - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapv, 0, ., .) -{ - if(COND_VC()) - { - return; - } - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ -} - - -M68KMAKE_OP(tst, 8, ., d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 8, ., .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 8, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCDI_8(); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 8, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCIX_8(); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 8, ., i) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_I_8(); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 16, ., d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 16, ., a) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = MAKE_INT_16(AY); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 16, ., .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 16, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCDI_16(); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 16, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCIX_16(); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 16, ., i) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_I_16(); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 32, ., d) -{ - uint res = DY; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 32, ., a) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = AY; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 32, ., .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 32, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCDI_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 32, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCIX_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 32, ., i) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_I_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unlk, 32, ., a7) -{ - REG_A[7] = m68ki_read_32(REG_A[7]); -} - - -M68KMAKE_OP(unlk, 32, ., .) -{ - uint* r_dst = &AY; - - REG_A[7] = *r_dst; - *r_dst = m68ki_pull_32(); -} - - -M68KMAKE_OP(unpk, 16, rr, .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: DX and DY are reversed in Motorola's docs */ - uint src = DY; - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | (((((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16()) & 0xffff); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unpk, 16, mm, ax7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint src = OPER_AY_PD_8(); - uint ea_dst; - - src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); - ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, src & 0xff); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unpk, 16, mm, ay7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint src = OPER_A7_PD_8(); - uint ea_dst; - - src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); - ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, src & 0xff); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unpk, 16, mm, axy7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_A7_PD_8(); - uint ea_dst; - - src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); - ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, src & 0xff); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unpk, 16, mm, .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint src = OPER_AY_PD_8(); - uint ea_dst; - - src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); - ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, src & 0xff); - return; - } - m68ki_exception_illegal(); -} - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_END +/* +must fix: + callm + chk +*/ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 3.32 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright Karl Stenerud. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* Special thanks to Bart Trzynadlowski for his insight into the + * undocumented features of this chip: + * + * http://dynarec.com/~bart/files/68knotes.txt + */ + + +/* Input file for m68kmake + * ----------------------- + * + * All sections begin with 80 X's in a row followed by an end-of-line + * sequence. + * After this, m68kmake will expect to find one of the following section + * identifiers: + * M68KMAKE_PROTOTYPE_HEADER - header for opcode handler prototypes + * M68KMAKE_PROTOTYPE_FOOTER - footer for opcode handler prototypes + * M68KMAKE_TABLE_HEADER - header for opcode handler jumptable + * M68KMAKE_TABLE_FOOTER - footer for opcode handler jumptable + * M68KMAKE_TABLE_BODY - the table itself + * M68KMAKE_OPCODE_HANDLER_HEADER - header for opcode handler implementation + * M68KMAKE_OPCODE_HANDLER_FOOTER - footer for opcode handler implementation + * M68KMAKE_OPCODE_HANDLER_BODY - body section for opcode handler implementation + * + * NOTE: M68KMAKE_OPCODE_HANDLER_BODY must be last in the file and + * M68KMAKE_TABLE_BODY must be second last in the file. + * + * The M68KMAKE_OPHANDLER_BODY section contains the opcode handler + * primitives themselves. Each opcode handler begins with: + * M68KMAKE_OP(A, B, C, D) + * + * where A is the opcode handler name, B is the size of the operation, + * C denotes any special processing mode, and D denotes a specific + * addressing mode. + * For C and D where nothing is specified, use "." + * + * Example: + * M68KMAKE_OP(abcd, 8, rr, .) abcd, size 8, register to register, default EA + * M68KMAKE_OP(abcd, 8, mm, ax7) abcd, size 8, memory to memory, register X is A7 + * M68KMAKE_OP(tst, 16, ., pcix) tst, size 16, PCIX addressing + * + * All opcode handler primitives end with a closing curly brace "}" at column 1 + * + * NOTE: Do not place a M68KMAKE_OP() directive inside the opcode handler, + * and do not put a closing curly brace at column 1 unless it is + * marking the end of the handler! + * + * Inside the handler, m68kmake will recognize M68KMAKE_GET_OPER_xx_xx, + * M68KMAKE_GET_EA_xx_xx, and M68KMAKE_CC directives, and create multiple + * opcode handlers to handle variations in the opcode handler. + * Note: M68KMAKE_CC will only be interpreted in condition code opcodes. + * As well, M68KMAKE_GET_EA_xx_xx and M68KMAKE_GET_OPER_xx_xx will only + * be interpreted on instructions where the corresponding table entry + * specifies multiple effective addressing modes. + * Example: + * clr 32 . . 0100001010...... A+-DXWL... U U U 12 6 4 + * + * This table entry says that the clr.l opcde has 7 variations (A+-DXWL). + * It is run in user or supervisor mode for all CPUs, and uses 12 cycles for + * 68000, 6 cycles for 68010, and 4 cycles for 68020. + */ + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_PROTOTYPE_HEADER + +#ifndef M68KOPS__HEADER +#define M68KOPS__HEADER + +/* ======================================================================== */ +/* ============================ OPCODE HANDLERS =========================== */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_PROTOTYPE_FOOTER + + +/* Build the opcode handler table */ +void m68ki_build_opcode_table(void); + +extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ +extern unsigned char m68ki_cycles[][0x10000]; + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + +#endif /* M68KOPS__HEADER */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_HEADER + +/* ======================================================================== */ +/* ========================= OPCODE TABLE BUILDER ========================= */ +/* ======================================================================== */ + +#include +#include "m68kops.h" + +#define NUM_CPU_TYPES 5 + +void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ +unsigned char m68ki_cycles[NUM_CPU_TYPES][0x10000]; /* Cycles used by CPU type */ + +/* This is used to generate the opcode handler jump table */ +typedef struct +{ + void (*opcode_handler)(void); /* handler function */ + unsigned int mask; /* mask on opcode */ + unsigned int match; /* what to match after masking */ + unsigned char cycles[NUM_CPU_TYPES]; /* cycles each cpu type takes */ +} opcode_handler_struct; + + +/* Opcode handler table */ +static const opcode_handler_struct m68k_opcode_handler_table[] = +{ +/* function mask match 000 010 020 040 */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_FOOTER + + {0, 0, 0, {0, 0, 0, 0, 0}} +}; + + +/* Build the opcode handler jump table */ +void m68ki_build_opcode_table(void) +{ + const opcode_handler_struct *ostruct; + int cycle_cost; + int instr; + int i; + int j; + int k; + + for(i = 0; i < 0x10000; i++) + { + /* default to illegal */ + m68ki_instruction_jump_table[i] = m68k_op_illegal; + for(k=0;kmask != 0xff00) + { + for(i = 0;i < 0x10000;i++) + { + if((i & ostruct->mask) == ostruct->match) + { + m68ki_instruction_jump_table[i] = ostruct->opcode_handler; + for(k=0;kcycles[k]; + } + } + ostruct++; + } + while(ostruct->mask == 0xff00) + { + for(i = 0;i <= 0xff;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;kmatch | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xf1f8) + { + for(i = 0;i < 8;i++) + { + for(j = 0;j < 8;j++) + { + instr = ostruct->match | (i << 9) | j; + m68ki_instruction_jump_table[instr] = ostruct->opcode_handler; + for(k=0;kcycles[k]; + // For all shift operations with known shift distance (encoded in instruction word) + if((instr & 0xf000) == 0xe000 && (!(instr & 0x20))) + { + // On the 68000 and 68010 shift distance affect execution time. + // Add the cycle cost of shifting; 2 times the shift distance + cycle_cost = ((((i-1)&7)+1)<<1); + m68ki_cycles[0][instr] += cycle_cost; + m68ki_cycles[1][instr] += cycle_cost; + // On the 68020 shift distance does not affect execution time + m68ki_cycles[2][instr] += 0; + } + } + } + ostruct++; + } + while(ostruct->mask == 0xfff0) + { + for(i = 0;i <= 0x0f;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;kmatch | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xf1ff) + { + for(i = 0;i <= 0x07;i++) + { + m68ki_instruction_jump_table[ostruct->match | (i << 9)] = ostruct->opcode_handler; + for(k=0;kmatch | (i << 9)] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xfff8) + { + for(i = 0;i <= 0x07;i++) + { + m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; + for(k=0;kmatch | i] = ostruct->cycles[k]; + } + ostruct++; + } + while(ostruct->mask == 0xffff) + { + m68ki_instruction_jump_table[ostruct->match] = ostruct->opcode_handler; + for(k=0;kmatch] = ostruct->cycles[k]; + ostruct++; + } +} + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_HEADER + +#include +#include "m68kcpu.h" +extern void m68040_fpu_op0(void); +extern void m68040_fpu_op1(void); +extern void m68881_mmu_ops(void); + +/* ======================================================================== */ +/* ========================= INSTRUCTION HANDLERS ========================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_FOOTER + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_TABLE_BODY + +The following table is arranged as follows: + +name: Opcode mnemonic + +size: Operation size + +spec proc: Special processing mode: + .: normal + s: static operand + r: register operand + rr: register to register + mm: memory to memory + er: effective address to register + re: register to effective address + dd: data register to data register + da: data register to address register + aa: address register to address register + cr: control register to register + rc: register to control register + toc: to condition code register + tos: to status register + tou: to user stack pointer + frc: from condition code register + frs: from status register + fru: from user stack pointer + * for move.x, the special processing mode is a specific + destination effective addressing mode. + +spec ea: Specific effective addressing mode: + .: normal + i: immediate + d: data register + a: address register + ai: address register indirect + pi: address register indirect with postincrement + pd: address register indirect with predecrement + di: address register indirect with displacement + ix: address register indirect with index + aw: absolute word address + al: absolute long address + pcdi: program counter relative with displacement + pcix: program counter relative with index + a7: register specified in instruction is A7 + ax7: register field X of instruction is A7 + ay7: register field Y of instruction is A7 + axy7: register fields X and Y of instruction are A7 + +bit pattern: Pattern to recognize this opcode. "." means don't care. + +allowed ea: List of allowed addressing modes: + .: not present + A: address register indirect + +: ARI (address register indirect) with postincrement + -: ARI with predecrement + D: ARI with displacement + X: ARI with index + W: absolute word address + L: absolute long address + d: program counter indirect with displacement + x: program counter indirect with index + I: immediate +mode: CPU operating mode for each cpu type. U = user or supervisor, + S = supervisor only, "." = opcode not present. + +cpu cycles: Base number of cycles required to execute this opcode on the + specified CPU type. + Use "." if CPU does not have this opcode. + + + + spec spec allowed ea mode cpu cycles +name size proc ea bit pattern A+-DXWLdxI 0 1 2 3 4 000 010 020 030 040 comments +====== ==== ==== ==== ================ ========== = = = = = === === === === === ============= +M68KMAKE_TABLE_START +1010 0 . . 1010............ .......... U U U U U 4 4 4 4 4 +1111 0 . . 1111............ .......... U U U U U 4 4 4 4 4 +040fpu0 32 . . 11110010........ .......... . . . . U . . . . 0 +040fpu1 32 . . 11110011........ .......... . . . . U . . . . 0 +abcd 8 rr . 1100...100000... .......... U U U U U 6 6 4 4 4 +abcd 8 mm ax7 1100111100001... .......... U U U U U 18 18 16 16 16 +abcd 8 mm ay7 1100...100001111 .......... U U U U U 18 18 16 16 16 +abcd 8 mm axy7 1100111100001111 .......... U U U U U 18 18 16 16 16 +abcd 8 mm . 1100...100001... .......... U U U U U 18 18 16 16 16 +add 8 er d 1101...000000... .......... U U U U U 4 4 2 2 2 +add 8 er . 1101...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 +add 16 er d 1101...001000... .......... U U U U U 4 4 2 2 2 +add 16 er a 1101...001001... .......... U U U U U 4 4 2 2 2 +add 16 er . 1101...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 +add 32 er d 1101...010000... .......... U U U U U 6 6 2 2 2 +add 32 er a 1101...010001... .......... U U U U U 6 6 2 2 2 +add 32 er . 1101...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 +add 8 re . 1101...100...... A+-DXWL... U U U U U 8 8 4 4 4 +add 16 re . 1101...101...... A+-DXWL... U U U U U 8 8 4 4 4 +add 32 re . 1101...110...... A+-DXWL... U U U U U 12 12 4 4 4 +adda 16 . d 1101...011000... .......... U U U U U 8 8 2 2 2 +adda 16 . a 1101...011001... .......... U U U U U 8 8 2 2 2 +adda 16 . . 1101...011...... A+-DXWLdxI U U U U U 8 8 2 2 2 +adda 32 . d 1101...111000... .......... U U U U U 6 6 2 2 2 +adda 32 . a 1101...111001... .......... U U U U U 6 6 2 2 2 +adda 32 . . 1101...111...... A+-DXWLdxI U U U U U 6 6 2 2 2 +addi 8 . d 0000011000000... .......... U U U U U 8 8 2 2 2 +addi 8 . . 0000011000...... A+-DXWL... U U U U U 12 12 4 4 4 +addi 16 . d 0000011001000... .......... U U U U U 8 8 2 2 2 +addi 16 . . 0000011001...... A+-DXWL... U U U U U 12 12 4 4 4 +addi 32 . d 0000011010000... .......... U U U U U 16 14 2 2 2 +addi 32 . . 0000011010...... A+-DXWL... U U U U U 20 20 4 4 4 +addq 8 . d 0101...000000... .......... U U U U U 4 4 2 2 2 +addq 8 . . 0101...000...... A+-DXWL... U U U U U 8 8 4 4 4 +addq 16 . d 0101...001000... .......... U U U U U 4 4 2 2 2 +addq 16 . a 0101...001001... .......... U U U U U 4 4 2 2 2 +addq 16 . . 0101...001...... A+-DXWL... U U U U U 8 8 4 4 4 +addq 32 . d 0101...010000... .......... U U U U U 8 8 2 2 2 +addq 32 . a 0101...010001... .......... U U U U U 8 8 2 2 2 +addq 32 . . 0101...010...... A+-DXWL... U U U U U 12 12 4 4 4 +addx 8 rr . 1101...100000... .......... U U U U U 4 4 2 2 2 +addx 16 rr . 1101...101000... .......... U U U U U 4 4 2 2 2 +addx 32 rr . 1101...110000... .......... U U U U U 8 6 2 2 2 +addx 8 mm ax7 1101111100001... .......... U U U U U 18 18 12 12 12 +addx 8 mm ay7 1101...100001111 .......... U U U U U 18 18 12 12 12 +addx 8 mm axy7 1101111100001111 .......... U U U U U 18 18 12 12 12 +addx 8 mm . 1101...100001... .......... U U U U U 18 18 12 12 12 +addx 16 mm . 1101...101001... .......... U U U U U 18 18 12 12 12 +addx 32 mm . 1101...110001... .......... U U U U U 30 30 12 12 12 +and 8 er d 1100...000000... .......... U U U U U 4 4 2 2 2 +and 8 er . 1100...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 +and 16 er d 1100...001000... .......... U U U U U 4 4 2 2 2 +and 16 er . 1100...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 +and 32 er d 1100...010000... .......... U U U U U 6 6 2 2 2 +and 32 er . 1100...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 +and 8 re . 1100...100...... A+-DXWL... U U U U U 8 8 4 4 4 +and 16 re . 1100...101...... A+-DXWL... U U U U U 8 8 4 4 4 +and 32 re . 1100...110...... A+-DXWL... U U U U U 12 12 4 4 4 +andi 16 toc . 0000001000111100 .......... U U U U U 20 16 12 12 12 +andi 16 tos . 0000001001111100 .......... S S S S S 20 16 12 12 12 +andi 8 . d 0000001000000... .......... U U U U U 8 8 2 2 2 +andi 8 . . 0000001000...... A+-DXWL... U U U U U 12 12 4 4 4 +andi 16 . d 0000001001000... .......... U U U U U 8 8 2 2 2 +andi 16 . . 0000001001...... A+-DXWL... U U U U U 12 12 4 4 4 +andi 32 . d 0000001010000... .......... U U U U U 14 14 2 2 2 +andi 32 . . 0000001010...... A+-DXWL... U U U U U 20 20 4 4 4 +asr 8 s . 1110...000000... .......... U U U U U 6 6 6 6 6 +asr 16 s . 1110...001000... .......... U U U U U 6 6 6 6 6 +asr 32 s . 1110...010000... .......... U U U U U 8 8 6 6 6 +asr 8 r . 1110...000100... .......... U U U U U 6 6 6 6 6 +asr 16 r . 1110...001100... .......... U U U U U 6 6 6 6 6 +asr 32 r . 1110...010100... .......... U U U U U 8 8 6 6 6 +asr 16 . . 1110000011...... A+-DXWL... U U U U U 8 8 5 5 5 +asl 8 s . 1110...100000... .......... U U U U U 6 6 8 8 8 +asl 16 s . 1110...101000... .......... U U U U U 6 6 8 8 8 +asl 32 s . 1110...110000... .......... U U U U U 8 8 8 8 8 +asl 8 r . 1110...100100... .......... U U U U U 6 6 8 8 8 +asl 16 r . 1110...101100... .......... U U U U U 6 6 8 8 8 +asl 32 r . 1110...110100... .......... U U U U U 8 8 8 8 8 +asl 16 . . 1110000111...... A+-DXWL... U U U U U 8 8 6 6 6 +bcc 8 . . 0110............ .......... U U U U U 10 10 6 6 6 +bcc 16 . . 0110....00000000 .......... U U U U U 10 10 6 6 6 +bcc 32 . . 0110....11111111 .......... U U U U U 10 10 6 6 6 +bchg 8 r . 0000...101...... A+-DXWL... U U U U U 8 8 4 4 4 +bchg 32 r d 0000...101000... .......... U U U U U 8 8 4 4 4 +bchg 8 s . 0000100001...... A+-DXWL... U U U U U 12 12 4 4 4 +bchg 32 s d 0000100001000... .......... U U U U U 12 12 4 4 4 +bclr 8 r . 0000...110...... A+-DXWL... U U U U U 8 10 4 4 4 +bclr 32 r d 0000...110000... .......... U U U U U 10 10 4 4 4 +bclr 8 s . 0000100010...... A+-DXWL... U U U U U 12 12 4 4 4 +bclr 32 s d 0000100010000... .......... U U U U U 14 14 4 4 4 +bfchg 32 . d 1110101011000... .......... . . U U U . . 12 12 12 timing not quite correct +bfchg 32 . . 1110101011...... A..DXWL... . . U U U . . 20 20 20 +bfclr 32 . d 1110110011000... .......... . . U U U . . 12 12 12 +bfclr 32 . . 1110110011...... A..DXWL... . . U U U . . 20 20 20 +bfexts 32 . d 1110101111000... .......... . . U U U . . 8 8 8 +bfexts 32 . . 1110101111...... A..DXWLdx. . . U U U . . 15 15 15 +bfextu 32 . d 1110100111000... .......... . . U U U . . 8 8 8 +bfextu 32 . . 1110100111...... A..DXWLdx. . . U U U . . 15 15 15 +bfffo 32 . d 1110110111000... .......... . . U U U . . 18 18 18 +bfffo 32 . . 1110110111...... A..DXWLdx. . . U U U . . 28 28 28 +bfins 32 . d 1110111111000... .......... . . U U U . . 10 10 10 +bfins 32 . . 1110111111...... A..DXWL... . . U U U . . 17 17 17 +bfset 32 . d 1110111011000... .......... . . U U U . . 12 12 12 +bfset 32 . . 1110111011...... A..DXWL... . . U U U . . 20 20 20 +bftst 32 . d 1110100011000... .......... . . U U U . . 6 6 6 +bftst 32 . . 1110100011...... A..DXWLdx. . . U U U . . 13 13 13 +bkpt 0 . . 0100100001001... .......... . U U U U . 10 10 10 10 +bra 8 . . 01100000........ .......... U U U U U 10 10 10 10 10 +bra 16 . . 0110000000000000 .......... U U U U U 10 10 10 10 10 +bra 32 . . 0110000011111111 .......... U U U U U 10 10 10 10 10 +bset 32 r d 0000...111000... .......... U U U U U 8 8 4 4 4 +bset 8 r . 0000...111...... A+-DXWL... U U U U U 8 8 4 4 4 +bset 8 s . 0000100011...... A+-DXWL... U U U U U 12 12 4 4 4 +bset 32 s d 0000100011000... .......... U U U U U 12 12 4 4 4 +bsr 8 . . 01100001........ .......... U U U U U 18 18 7 7 7 +bsr 16 . . 0110000100000000 .......... U U U U U 18 18 7 7 7 +bsr 32 . . 0110000111111111 .......... U U U U U 18 18 7 7 7 +btst 8 r . 0000...100...... A+-DXWLdxI U U U U U 4 4 4 4 4 +btst 32 r d 0000...100000... .......... U U U U U 6 6 4 4 4 +btst 8 s . 0000100000...... A+-DXWLdx. U U U U U 8 8 4 4 4 +btst 32 s d 0000100000000... .......... U U U U U 10 10 4 4 4 +callm 32 . . 0000011011...... A..DXWLdx. . . U U U . . 60 60 60 not properly emulated +cas 8 . . 0000101011...... A+-DXWL... . . U U U . . 12 12 12 +cas 16 . . 0000110011...... A+-DXWL... . . U U U . . 12 12 12 +cas 32 . . 0000111011...... A+-DXWL... . . U U U . . 12 12 12 +cas2 16 . . 0000110011111100 .......... . . U U U . . 12 12 12 +cas2 32 . . 0000111011111100 .......... . . U U U . . 12 12 12 +chk 16 . d 0100...110000... .......... U U U U U 10 8 8 8 8 +chk 16 . . 0100...110...... A+-DXWLdxI U U U U U 10 8 8 8 8 +chk 32 . d 0100...100000... .......... . . U U U . . 8 8 8 +chk 32 . . 0100...100...... A+-DXWLdxI . . U U U . . 8 8 8 +chk2cmp2 8 . pcdi 0000000011111010 .......... . . U U U . . 23 23 23 +chk2cmp2 8 . pcix 0000000011111011 .......... . . U U U . . 23 23 23 +chk2cmp2 8 . . 0000000011...... A..DXWL... . . U U U . . 18 18 18 +chk2cmp2 16 . pcdi 0000001011111010 .......... . . U U U . . 23 23 23 +chk2cmp2 16 . pcix 0000001011111011 .......... . . U U U . . 23 23 23 +chk2cmp2 16 . . 0000001011...... A..DXWL... . . U U U . . 18 18 18 +chk2cmp2 32 . pcdi 0000010011111010 .......... . . U U U . . 23 23 23 +chk2cmp2 32 . pcix 0000010011111011 .......... . . U U U . . 23 23 23 +chk2cmp2 32 . . 0000010011...... A..DXWL... . . U U U . . 18 18 18 +clr 8 . d 0100001000000... .......... U U U U U 4 4 2 2 2 +clr 8 . . 0100001000...... A+-DXWL... U U U U U 8 4 4 4 4 +clr 16 . d 0100001001000... .......... U U U U U 4 4 2 2 2 +clr 16 . . 0100001001...... A+-DXWL... U U U U U 8 4 4 4 4 +clr 32 . d 0100001010000... .......... U U U U U 6 6 2 2 2 +clr 32 . . 0100001010...... A+-DXWL... U U U U U 12 6 4 4 4 +cmp 8 . d 1011...000000... .......... U U U U U 4 4 2 2 2 +cmp 8 . . 1011...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 +cmp 16 . d 1011...001000... .......... U U U U U 4 4 2 2 2 +cmp 16 . a 1011...001001... .......... U U U U U 4 4 2 2 2 +cmp 16 . . 1011...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 +cmp 32 . d 1011...010000... .......... U U U U U 6 6 2 2 2 +cmp 32 . a 1011...010001... .......... U U U U U 6 6 2 2 2 +cmp 32 . . 1011...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 +cmpa 16 . d 1011...011000... .......... U U U U U 6 6 4 4 4 +cmpa 16 . a 1011...011001... .......... U U U U U 6 6 4 4 4 +cmpa 16 . . 1011...011...... A+-DXWLdxI U U U U U 6 6 4 4 4 +cmpa 32 . d 1011...111000... .......... U U U U U 6 6 4 4 4 +cmpa 32 . a 1011...111001... .......... U U U U U 6 6 4 4 4 +cmpa 32 . . 1011...111...... A+-DXWLdxI U U U U U 6 6 4 4 4 +cmpi 8 . d 0000110000000... .......... U U U U U 8 8 2 2 2 +cmpi 8 . . 0000110000...... A+-DXWL... U U U U U 8 8 2 2 2 +cmpi 8 . pcdi 0000110000111010 .......... . . U U U . . 7 7 7 +cmpi 8 . pcix 0000110000111011 .......... . . U U U . . 9 9 9 +cmpi 16 . d 0000110001000... .......... U U U U U 8 8 2 2 2 +cmpi 16 . . 0000110001...... A+-DXWL... U U U U U 8 8 2 2 2 +cmpi 16 . pcdi 0000110001111010 .......... . . U U U . . 7 7 7 +cmpi 16 . pcix 0000110001111011 .......... . . U U U . . 9 9 9 +cmpi 32 . d 0000110010000... .......... U U U U U 14 12 2 2 2 +cmpi 32 . . 0000110010...... A+-DXWL... U U U U U 12 12 2 2 2 +cmpi 32 . pcdi 0000110010111010 .......... . . U U U . . 7 7 7 +cmpi 32 . pcix 0000110010111011 .......... . . U U U . . 9 9 9 +cmpm 8 . ax7 1011111100001... .......... U U U U U 12 12 9 9 9 +cmpm 8 . ay7 1011...100001111 .......... U U U U U 12 12 9 9 9 +cmpm 8 . axy7 1011111100001111 .......... U U U U U 12 12 9 9 9 +cmpm 8 . . 1011...100001... .......... U U U U U 12 12 9 9 9 +cmpm 16 . . 1011...101001... .......... U U U U U 12 12 9 9 9 +cmpm 32 . . 1011...110001... .......... U U U U U 20 20 9 9 9 +cpbcc 32 . . 1111...01....... .......... . . U U . . . 4 4 . unemulated +cpdbcc 32 . . 1111...001001... .......... . . U U . . . 4 4 . unemulated +cpgen 32 . . 1111...000...... .......... . . U U . . . 4 4 . unemulated +cpscc 32 . . 1111...001...... .......... . . U U . . . 4 4 . unemulated +cptrapcc 32 . . 1111...001111... .......... . . U U . . . 4 4 . unemulated +dbt 16 . . 0101000011001... .......... U U U U U 12 12 6 6 6 +dbf 16 . . 0101000111001... .......... U U U U U 12 12 6 6 6 +dbcc 16 . . 0101....11001... .......... U U U U U 12 12 6 6 6 +divs 16 . d 1000...111000... .......... U U U U U 158 122 56 56 56 +divs 16 . . 1000...111...... A+-DXWLdxI U U U U U 158 122 56 56 56 +divu 16 . d 1000...011000... .......... U U U U U 140 108 44 44 44 +divu 16 . . 1000...011...... A+-DXWLdxI U U U U U 140 108 44 44 44 +divl 32 . d 0100110001000... .......... . . U U U . . 84 84 84 +divl 32 . . 0100110001...... A+-DXWLdxI . . U U U . . 84 84 84 +eor 8 . d 1011...100000... .......... U U U U U 4 4 2 2 2 +eor 8 . . 1011...100...... A+-DXWL... U U U U U 8 8 4 4 4 +eor 16 . d 1011...101000... .......... U U U U U 4 4 2 2 2 +eor 16 . . 1011...101...... A+-DXWL... U U U U U 8 8 4 4 4 +eor 32 . d 1011...110000... .......... U U U U U 8 6 2 2 2 +eor 32 . . 1011...110...... A+-DXWL... U U U U U 12 12 4 4 4 +eori 16 toc . 0000101000111100 .......... U U U U U 20 16 12 12 12 +eori 16 tos . 0000101001111100 .......... S S S S S 20 16 12 12 12 +eori 8 . d 0000101000000... .......... U U U U U 8 8 2 2 2 +eori 8 . . 0000101000...... A+-DXWL... U U U U U 12 12 4 4 4 +eori 16 . d 0000101001000... .......... U U U U U 8 8 2 2 2 +eori 16 . . 0000101001...... A+-DXWL... U U U U U 12 12 4 4 4 +eori 32 . d 0000101010000... .......... U U U U U 16 14 2 2 2 +eori 32 . . 0000101010...... A+-DXWL... U U U U U 20 20 4 4 4 +exg 32 dd . 1100...101000... .......... U U U U U 6 6 2 2 2 +exg 32 aa . 1100...101001... .......... U U U U U 6 6 2 2 2 +exg 32 da . 1100...110001... .......... U U U U U 6 6 2 2 2 +ext 16 . . 0100100010000... .......... U U U U U 4 4 4 4 4 +ext 32 . . 0100100011000... .......... U U U U U 4 4 4 4 4 +extb 32 . . 0100100111000... .......... . . U U U . . 4 4 4 +illegal 0 . . 0100101011111100 .......... U U U U U 4 4 4 4 4 +jmp 32 . . 0100111011...... A..DXWLdx. U U U U U 4 4 0 0 0 +jsr 32 . . 0100111010...... A..DXWLdx. U U U U U 12 12 0 0 0 +lea 32 . . 0100...111...... A..DXWLdx. U U U U U 0 0 2 2 2 +link 16 . a7 0100111001010111 .......... U U U U U 16 16 5 5 5 +link 16 . . 0100111001010... .......... U U U U U 16 16 5 5 5 +link 32 . a7 0100100000001111 .......... . . U U U . . 6 6 6 +link 32 . . 0100100000001... .......... . . U U U . . 6 6 6 +lsr 8 s . 1110...000001... .......... U U U U U 6 6 4 4 4 +lsr 16 s . 1110...001001... .......... U U U U U 6 6 4 4 4 +lsr 32 s . 1110...010001... .......... U U U U U 8 8 4 4 4 +lsr 8 r . 1110...000101... .......... U U U U U 6 6 6 6 6 +lsr 16 r . 1110...001101... .......... U U U U U 6 6 6 6 6 +lsr 32 r . 1110...010101... .......... U U U U U 8 8 6 6 6 +lsr 16 . . 1110001011...... A+-DXWL... U U U U U 8 8 5 5 5 +lsl 8 s . 1110...100001... .......... U U U U U 6 6 4 4 4 +lsl 16 s . 1110...101001... .......... U U U U U 6 6 4 4 4 +lsl 32 s . 1110...110001... .......... U U U U U 8 8 4 4 4 +lsl 8 r . 1110...100101... .......... U U U U U 6 6 6 6 6 +lsl 16 r . 1110...101101... .......... U U U U U 6 6 6 6 6 +lsl 32 r . 1110...110101... .......... U U U U U 8 8 6 6 6 +lsl 16 . . 1110001111...... A+-DXWL... U U U U U 8 8 5 5 5 +move 8 d d 0001...000000... .......... U U U U U 4 4 2 2 2 +move 8 d . 0001...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 +move 8 ai d 0001...010000... .......... U U U U U 8 8 4 4 4 +move 8 ai . 0001...010...... A+-DXWLdxI U U U U U 8 8 4 4 4 +move 8 pi d 0001...011000... .......... U U U U U 8 8 4 4 4 +move 8 pi . 0001...011...... A+-DXWLdxI U U U U U 8 8 4 4 4 +move 8 pi7 d 0001111011000... .......... U U U U U 8 8 4 4 4 +move 8 pi7 . 0001111011...... A+-DXWLdxI U U U U U 8 8 4 4 4 +move 8 pd d 0001...100000... .......... U U U U U 8 8 5 5 5 +move 8 pd . 0001...100...... A+-DXWLdxI U U U U U 8 8 5 5 5 +move 8 pd7 d 0001111100000... .......... U U U U U 8 8 5 5 5 +move 8 pd7 . 0001111100...... A+-DXWLdxI U U U U U 8 8 5 5 5 +move 8 di d 0001...101000... .......... U U U U U 12 12 5 5 5 +move 8 di . 0001...101...... A+-DXWLdxI U U U U U 12 12 5 5 5 +move 8 ix d 0001...110000... .......... U U U U U 14 14 7 7 7 +move 8 ix . 0001...110...... A+-DXWLdxI U U U U U 14 14 7 7 7 +move 8 aw d 0001000111000... .......... U U U U U 12 12 4 4 4 +move 8 aw . 0001000111...... A+-DXWLdxI U U U U U 12 12 4 4 4 +move 8 al d 0001001111000... .......... U U U U U 16 16 6 6 6 +move 8 al . 0001001111...... A+-DXWLdxI U U U U U 16 16 6 6 6 +move 16 d d 0011...000000... .......... U U U U U 4 4 2 2 2 +move 16 d a 0011...000001... .......... U U U U U 4 4 2 2 2 +move 16 d . 0011...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 +move 16 ai d 0011...010000... .......... U U U U U 8 8 4 4 4 +move 16 ai a 0011...010001... .......... U U U U U 8 8 4 4 4 +move 16 ai . 0011...010...... A+-DXWLdxI U U U U U 8 8 4 4 4 +move 16 pi d 0011...011000... .......... U U U U U 8 8 4 4 4 +move 16 pi a 0011...011001... .......... U U U U U 8 8 4 4 4 +move 16 pi . 0011...011...... A+-DXWLdxI U U U U U 8 8 4 4 4 +move 16 pd d 0011...100000... .......... U U U U U 8 8 5 5 5 +move 16 pd a 0011...100001... .......... U U U U U 8 8 5 5 5 +move 16 pd . 0011...100...... A+-DXWLdxI U U U U U 8 8 5 5 5 +move 16 di d 0011...101000... .......... U U U U U 12 12 5 5 5 +move 16 di a 0011...101001... .......... U U U U U 12 12 5 5 5 +move 16 di . 0011...101...... A+-DXWLdxI U U U U U 12 12 5 5 5 +move 16 ix d 0011...110000... .......... U U U U U 14 14 7 7 7 +move 16 ix a 0011...110001... .......... U U U U U 14 14 7 7 7 +move 16 ix . 0011...110...... A+-DXWLdxI U U U U U 14 14 7 7 7 +move 16 aw d 0011000111000... .......... U U U U U 12 12 4 4 4 +move 16 aw a 0011000111001... .......... U U U U U 12 12 4 4 4 +move 16 aw . 0011000111...... A+-DXWLdxI U U U U U 12 12 4 4 4 +move 16 al d 0011001111000... .......... U U U U U 16 16 6 6 6 +move 16 al a 0011001111001... .......... U U U U U 16 16 6 6 6 +move 16 al . 0011001111...... A+-DXWLdxI U U U U U 16 16 6 6 6 +move 32 d d 0010...000000... .......... U U U U U 4 4 2 2 2 +move 32 d a 0010...000001... .......... U U U U U 4 4 2 2 2 +move 32 d . 0010...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 +move 32 ai d 0010...010000... .......... U U U U U 12 12 4 4 4 +move 32 ai a 0010...010001... .......... U U U U U 12 12 4 4 4 +move 32 ai . 0010...010...... A+-DXWLdxI U U U U U 12 12 4 4 4 +move 32 pi d 0010...011000... .......... U U U U U 12 12 4 4 4 +move 32 pi a 0010...011001... .......... U U U U U 12 12 4 4 4 +move 32 pi . 0010...011...... A+-DXWLdxI U U U U U 12 12 4 4 4 +move 32 pd d 0010...100000... .......... U U U U U 12 14 5 5 5 +move 32 pd a 0010...100001... .......... U U U U U 12 14 5 5 5 +move 32 pd . 0010...100...... A+-DXWLdxI U U U U U 12 14 5 5 5 +move 32 di d 0010...101000... .......... U U U U U 16 16 5 5 5 +move 32 di a 0010...101001... .......... U U U U U 16 16 5 5 5 +move 32 di . 0010...101...... A+-DXWLdxI U U U U U 16 16 5 5 5 +move 32 ix d 0010...110000... .......... U U U U U 18 18 7 7 7 +move 32 ix a 0010...110001... .......... U U U U U 18 18 7 7 7 +move 32 ix . 0010...110...... A+-DXWLdxI U U U U U 18 18 7 7 7 +move 32 aw d 0010000111000... .......... U U U U U 16 16 4 4 4 +move 32 aw a 0010000111001... .......... U U U U U 16 16 4 4 4 +move 32 aw . 0010000111...... A+-DXWLdxI U U U U U 16 16 4 4 4 +move 32 al d 0010001111000... .......... U U U U U 20 20 6 6 6 +move 32 al a 0010001111001... .......... U U U U U 20 20 6 6 6 +move 32 al . 0010001111...... A+-DXWLdxI U U U U U 20 20 6 6 6 +movea 16 . d 0011...001000... .......... U U U U U 4 4 2 2 2 +movea 16 . a 0011...001001... .......... U U U U U 4 4 2 2 2 +movea 16 . . 0011...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 +movea 32 . d 0010...001000... .......... U U U U U 4 4 2 2 2 +movea 32 . a 0010...001001... .......... U U U U U 4 4 2 2 2 +movea 32 . . 0010...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 +move 16 frc d 0100001011000... .......... . U U U U . 4 4 4 4 +move 16 frc . 0100001011...... A+-DXWL... . U U U U . 8 4 4 4 +move 16 toc d 0100010011000... .......... U U U U U 12 12 4 4 4 +move 16 toc . 0100010011...... A+-DXWLdxI U U U U U 12 12 4 4 4 +move 16 frs d 0100000011000... .......... U S S S S 6 4 8 8 8 U only for 000 +move 16 frs . 0100000011...... A+-DXWL... U S S S S 8 8 8 8 8 U only for 000 +move 16 tos d 0100011011000... .......... S S S S S 12 12 8 8 8 +move 16 tos . 0100011011...... A+-DXWLdxI S S S S S 12 12 8 8 8 +move 32 fru . 0100111001101... .......... S S S S S 4 6 2 2 2 +move 32 tou . 0100111001100... .......... S S S S S 4 6 2 2 2 +movec 32 cr . 0100111001111010 .......... . S S S S . 12 6 6 6 +movec 32 rc . 0100111001111011 .......... . S S S S . 10 12 12 12 +movem 16 re pd 0100100010100... .......... U U U U U 8 8 4 4 4 +movem 16 re . 0100100010...... A..DXWL... U U U U U 8 8 4 4 4 +movem 32 re pd 0100100011100... .......... U U U U U 8 8 4 4 4 +movem 32 re . 0100100011...... A..DXWL... U U U U U 8 8 4 4 4 +movem 16 er pi 0100110010011... .......... U U U U U 12 12 8 8 8 +movem 16 er pcdi 0100110010111010 .......... U U U U U 16 16 9 9 9 +movem 16 er pcix 0100110010111011 .......... U U U U U 18 18 11 11 11 +movem 16 er . 0100110010...... A..DXWL... U U U U U 12 12 8 8 8 +movem 32 er pi 0100110011011... .......... U U U U U 12 12 8 8 8 +movem 32 er pcdi 0100110011111010 .......... U U U U U 16 16 9 9 9 +movem 32 er pcix 0100110011111011 .......... U U U U U 18 18 11 11 11 +movem 32 er . 0100110011...... A..DXWL... U U U U U 12 12 8 8 8 +movep 16 er . 0000...100001... .......... U U U U U 16 16 12 12 12 +movep 32 er . 0000...101001... .......... U U U U U 24 24 18 18 18 +movep 16 re . 0000...110001... .......... U U U U U 16 16 11 11 11 +movep 32 re . 0000...111001... .......... U U U U U 24 24 17 17 17 +moveq 32 . . 0111...0........ .......... U U U U U 4 4 2 2 2 +moves 8 . . 0000111000...... A+-DXWL... . S S S S . 14 5 5 5 +moves 16 . . 0000111001...... A+-DXWL... . S S S S . 14 5 5 5 +moves 32 . . 0000111010...... A+-DXWL... . S S S S . 16 5 5 5 +move16 32 . . 1111011000100... .......... . . . . U . . . . 4 TODO: correct timing +muls 16 . d 1100...111000... .......... U U U U U 54 32 27 27 27 +muls 16 . . 1100...111...... A+-DXWLdxI U U U U U 54 32 27 27 27 +mulu 16 . d 1100...011000... .......... U U U U U 54 30 27 27 27 +mulu 16 . . 1100...011...... A+-DXWLdxI U U U U U 54 30 27 27 27 +mull 32 . d 0100110000000... .......... . . U U U . . 43 43 43 +mull 32 . . 0100110000...... A+-DXWLdxI . . U U U . . 43 43 43 +nbcd 8 . d 0100100000000... .......... U U U U U 6 6 6 6 6 +nbcd 8 . . 0100100000...... A+-DXWL... U U U U U 8 8 6 6 6 +neg 8 . d 0100010000000... .......... U U U U U 4 4 2 2 2 +neg 8 . . 0100010000...... A+-DXWL... U U U U U 8 8 4 4 4 +neg 16 . d 0100010001000... .......... U U U U U 4 4 2 2 2 +neg 16 . . 0100010001...... A+-DXWL... U U U U U 8 8 4 4 4 +neg 32 . d 0100010010000... .......... U U U U U 6 6 2 2 2 +neg 32 . . 0100010010...... A+-DXWL... U U U U U 12 12 4 4 4 +negx 8 . d 0100000000000... .......... U U U U U 4 4 2 2 2 +negx 8 . . 0100000000...... A+-DXWL... U U U U U 8 8 4 4 4 +negx 16 . d 0100000001000... .......... U U U U U 4 4 2 2 2 +negx 16 . . 0100000001...... A+-DXWL... U U U U U 8 8 4 4 4 +negx 32 . d 0100000010000... .......... U U U U U 6 6 2 2 2 +negx 32 . . 0100000010...... A+-DXWL... U U U U U 12 12 4 4 4 +nop 0 . . 0100111001110001 .......... U U U U U 4 4 2 2 2 +not 8 . d 0100011000000... .......... U U U U U 4 4 2 2 2 +not 8 . . 0100011000...... A+-DXWL... U U U U U 8 8 4 4 4 +not 16 . d 0100011001000... .......... U U U U U 4 4 2 2 2 +not 16 . . 0100011001...... A+-DXWL... U U U U U 8 8 4 4 4 +not 32 . d 0100011010000... .......... U U U U U 6 6 2 2 2 +not 32 . . 0100011010...... A+-DXWL... U U U U U 12 12 4 4 4 +or 8 er d 1000...000000... .......... U U U U U 4 4 2 2 2 +or 8 er . 1000...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 +or 16 er d 1000...001000... .......... U U U U U 4 4 2 2 2 +or 16 er . 1000...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 +or 32 er d 1000...010000... .......... U U U U U 6 6 2 2 2 +or 32 er . 1000...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 +or 8 re . 1000...100...... A+-DXWL... U U U U U 8 8 4 4 4 +or 16 re . 1000...101...... A+-DXWL... U U U U U 8 8 4 4 4 +or 32 re . 1000...110...... A+-DXWL... U U U U U 12 12 4 4 4 +ori 16 toc . 0000000000111100 .......... U U U U U 20 16 12 12 12 +ori 16 tos . 0000000001111100 .......... S S S S S 20 16 12 12 12 +ori 8 . d 0000000000000... .......... U U U U U 8 8 2 2 2 +ori 8 . . 0000000000...... A+-DXWL... U U U U U 12 12 4 4 4 +ori 16 . d 0000000001000... .......... U U U U U 8 8 2 2 2 +ori 16 . . 0000000001...... A+-DXWL... U U U U U 12 12 4 4 4 +ori 32 . d 0000000010000... .......... U U U U U 16 14 2 2 2 +ori 32 . . 0000000010...... A+-DXWL... U U U U U 20 20 4 4 4 +pack 16 rr . 1000...101000... .......... . . U U U . . 6 6 6 +pack 16 mm ax7 1000111101001... .......... . . U U U . . 13 13 13 +pack 16 mm ay7 1000...101001111 .......... . . U U U . . 13 13 13 +pack 16 mm axy7 1000111101001111 .......... . . U U U . . 13 13 13 +pack 16 mm . 1000...101001... .......... . . U U U . . 13 13 13 +pea 32 . . 0100100001...... A..DXWLdx. U U U U U 6 6 5 5 5 +pflush 32 . . 1111010100011000 .......... . . . . S . . . . 4 TODO: correct timing +pmmu 32 . . 1111000......... .......... . . S S S . . 8 8 8 +reset 0 . . 0100111001110000 .......... S S S S S 0 0 0 0 0 +ror 8 s . 1110...000011... .......... U U U U U 6 6 8 8 8 +ror 16 s . 1110...001011... .......... U U U U U 6 6 8 8 8 +ror 32 s . 1110...010011... .......... U U U U U 8 8 8 8 8 +ror 8 r . 1110...000111... .......... U U U U U 6 6 8 8 8 +ror 16 r . 1110...001111... .......... U U U U U 6 6 8 8 8 +ror 32 r . 1110...010111... .......... U U U U U 8 8 8 8 8 +ror 16 . . 1110011011...... A+-DXWL... U U U U U 8 8 7 7 7 +rol 8 s . 1110...100011... .......... U U U U U 6 6 8 8 8 +rol 16 s . 1110...101011... .......... U U U U U 6 6 8 8 8 +rol 32 s . 1110...110011... .......... U U U U U 8 8 8 8 8 +rol 8 r . 1110...100111... .......... U U U U U 6 6 8 8 8 +rol 16 r . 1110...101111... .......... U U U U U 6 6 8 8 8 +rol 32 r . 1110...110111... .......... U U U U U 8 8 8 8 8 +rol 16 . . 1110011111...... A+-DXWL... U U U U U 8 8 7 7 7 +roxr 8 s . 1110...000010... .......... U U U U U 6 6 12 12 12 +roxr 16 s . 1110...001010... .......... U U U U U 6 6 12 12 12 +roxr 32 s . 1110...010010... .......... U U U U U 8 8 12 12 12 +roxr 8 r . 1110...000110... .......... U U U U U 6 6 12 12 12 +roxr 16 r . 1110...001110... .......... U U U U U 6 6 12 12 12 +roxr 32 r . 1110...010110... .......... U U U U U 8 8 12 12 12 +roxr 16 . . 1110010011...... A+-DXWL... U U U U U 8 8 5 5 5 +roxl 8 s . 1110...100010... .......... U U U U U 6 6 12 12 12 +roxl 16 s . 1110...101010... .......... U U U U U 6 6 12 12 12 +roxl 32 s . 1110...110010... .......... U U U U U 8 8 12 12 12 +roxl 8 r . 1110...100110... .......... U U U U U 6 6 12 12 12 +roxl 16 r . 1110...101110... .......... U U U U U 6 6 12 12 12 +roxl 32 r . 1110...110110... .......... U U U U U 8 8 12 12 12 +roxl 16 . . 1110010111...... A+-DXWL... U U U U U 8 8 5 5 5 +rtd 32 . . 0100111001110100 .......... . U U U U . 16 10 10 10 +rte 32 . . 0100111001110011 .......... S S S S S 20 24 20 20 20 bus fault not emulated +rtm 32 . . 000001101100.... .......... . . U U U . . 19 19 19 not properly emulated +rtr 32 . . 0100111001110111 .......... U U U U U 20 20 14 14 14 +rts 32 . . 0100111001110101 .......... U U U U U 16 16 10 10 10 +sbcd 8 rr . 1000...100000... .......... U U U U U 6 6 4 4 4 +sbcd 8 mm ax7 1000111100001... .......... U U U U U 18 18 16 16 16 +sbcd 8 mm ay7 1000...100001111 .......... U U U U U 18 18 16 16 16 +sbcd 8 mm axy7 1000111100001111 .......... U U U U U 18 18 16 16 16 +sbcd 8 mm . 1000...100001... .......... U U U U U 18 18 16 16 16 +st 8 . d 0101000011000... .......... U U U U U 6 4 4 4 4 +st 8 . . 0101000011...... A+-DXWL... U U U U U 8 8 6 6 6 +sf 8 . d 0101000111000... .......... U U U U U 4 4 4 4 4 +sf 8 . . 0101000111...... A+-DXWL... U U U U U 8 8 6 6 6 +scc 8 . d 0101....11000... .......... U U U U U 4 4 4 4 4 +scc 8 . . 0101....11...... A+-DXWL... U U U U U 8 8 6 6 6 +stop 0 . . 0100111001110010 .......... S S S S S 4 4 8 8 8 +sub 8 er d 1001...000000... .......... U U U U U 4 4 2 2 2 +sub 8 er . 1001...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 +sub 16 er d 1001...001000... .......... U U U U U 4 4 2 2 2 +sub 16 er a 1001...001001... .......... U U U U U 4 4 2 2 2 +sub 16 er . 1001...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 +sub 32 er d 1001...010000... .......... U U U U U 6 6 2 2 2 +sub 32 er a 1001...010001... .......... U U U U U 6 6 2 2 2 +sub 32 er . 1001...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 +sub 8 re . 1001...100...... A+-DXWL... U U U U U 8 8 4 4 4 +sub 16 re . 1001...101...... A+-DXWL... U U U U U 8 8 4 4 4 +sub 32 re . 1001...110...... A+-DXWL... U U U U U 12 12 4 4 4 +suba 16 . d 1001...011000... .......... U U U U U 8 8 2 2 2 +suba 16 . a 1001...011001... .......... U U U U U 8 8 2 2 2 +suba 16 . . 1001...011...... A+-DXWLdxI U U U U U 8 8 2 2 2 +suba 32 . d 1001...111000... .......... U U U U U 6 6 2 2 2 +suba 32 . a 1001...111001... .......... U U U U U 6 6 2 2 2 +suba 32 . . 1001...111...... A+-DXWLdxI U U U U U 6 6 2 2 2 +subi 8 . d 0000010000000... .......... U U U U U 8 8 2 2 2 +subi 8 . . 0000010000...... A+-DXWL... U U U U U 12 12 4 4 4 +subi 16 . d 0000010001000... .......... U U U U U 8 8 2 2 2 +subi 16 . . 0000010001...... A+-DXWL... U U U U U 12 12 4 4 4 +subi 32 . d 0000010010000... .......... U U U U U 16 14 2 2 2 +subi 32 . . 0000010010...... A+-DXWL... U U U U U 20 20 4 4 4 +subq 8 . d 0101...100000... .......... U U U U U 4 4 2 2 2 +subq 8 . . 0101...100...... A+-DXWL... U U U U U 8 8 4 4 4 +subq 16 . d 0101...101000... .......... U U U U U 4 4 2 2 2 +subq 16 . a 0101...101001... .......... U U U U U 8 4 2 2 2 +subq 16 . . 0101...101...... A+-DXWL... U U U U U 8 8 4 4 4 +subq 32 . d 0101...110000... .......... U U U U U 8 8 2 2 2 +subq 32 . a 0101...110001... .......... U U U U U 8 8 2 2 2 +subq 32 . . 0101...110...... A+-DXWL... U U U U U 12 12 4 4 4 +subx 8 rr . 1001...100000... .......... U U U U U 4 4 2 2 2 +subx 16 rr . 1001...101000... .......... U U U U U 4 4 2 2 2 +subx 32 rr . 1001...110000... .......... U U U U U 8 6 2 2 2 +subx 8 mm ax7 1001111100001... .......... U U U U U 18 18 12 12 12 +subx 8 mm ay7 1001...100001111 .......... U U U U U 18 18 12 12 12 +subx 8 mm axy7 1001111100001111 .......... U U U U U 18 18 12 12 12 +subx 8 mm . 1001...100001... .......... U U U U U 18 18 12 12 12 +subx 16 mm . 1001...101001... .......... U U U U U 18 18 12 12 12 +subx 32 mm . 1001...110001... .......... U U U U U 30 30 12 12 12 +swap 32 . . 0100100001000... .......... U U U U U 4 4 4 4 4 +tas 8 . d 0100101011000... .......... U U U U U 4 4 4 4 4 +tas 8 . . 0100101011...... A+-DXWL... U U U U U 14 14 12 12 12 +trap 0 . . 010011100100.... .......... U U U U U 4 4 4 4 4 +trapt 0 . . 0101000011111100 .......... . . U U U . . 4 4 4 +trapt 16 . . 0101000011111010 .......... . . U U U . . 6 6 6 +trapt 32 . . 0101000011111011 .......... . . U U U . . 8 8 8 +trapf 0 . . 0101000111111100 .......... . . U U U . . 4 4 4 +trapf 16 . . 0101000111111010 .......... . . U U U . . 6 6 6 +trapf 32 . . 0101000111111011 .......... . . U U U . . 8 8 8 +trapcc 0 . . 0101....11111100 .......... . . U U U . . 4 4 4 +trapcc 16 . . 0101....11111010 .......... . . U U U . . 6 6 6 +trapcc 32 . . 0101....11111011 .......... . . U U U . . 8 8 8 +trapv 0 . . 0100111001110110 .......... U U U U U 4 4 4 4 4 +tst 8 . d 0100101000000... .......... U U U U U 4 4 2 2 2 +tst 8 . . 0100101000...... A+-DXWL... U U U U U 4 4 2 2 2 +tst 8 . pcdi 0100101000111010 .......... . . U U U . . 7 7 7 +tst 8 . pcix 0100101000111011 .......... . . U U U . . 9 9 9 +tst 8 . i 0100101000111100 .......... . . U U U . . 6 6 6 +tst 16 . d 0100101001000... .......... U U U U U 4 4 2 2 2 +tst 16 . a 0100101001001... .......... . . U U U . . 2 2 2 +tst 16 . . 0100101001...... A+-DXWL... U U U U U 4 4 2 2 2 +tst 16 . pcdi 0100101001111010 .......... . . U U U . . 7 7 7 +tst 16 . pcix 0100101001111011 .......... . . U U U . . 9 9 9 +tst 16 . i 0100101001111100 .......... . . U U U . . 6 6 6 +tst 32 . d 0100101010000... .......... U U U U U 4 4 2 2 2 +tst 32 . a 0100101010001... .......... . . U U U . . 2 2 2 +tst 32 . . 0100101010...... A+-DXWL... U U U U U 4 4 2 2 2 +tst 32 . pcdi 0100101010111010 .......... . . U U U . . 7 7 7 +tst 32 . pcix 0100101010111011 .......... . . U U U . . 9 9 9 +tst 32 . i 0100101010111100 .......... . . U U U . . 6 6 6 +unlk 32 . a7 0100111001011111 .......... U U U U U 12 12 6 6 6 +unlk 32 . . 0100111001011... .......... U U U U U 12 12 6 6 6 +unpk 16 rr . 1000...110000... .......... . . U U U . . 8 8 8 +unpk 16 mm ax7 1000111110001... .......... . . U U U . . 13 13 13 +unpk 16 mm ay7 1000...110001111 .......... . . U U U . . 13 13 13 +unpk 16 mm axy7 1000111110001111 .......... . . U U U . . 13 13 13 +unpk 16 mm . 1000...110001... .......... . . U U U . . 13 13 13 + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_OPCODE_HANDLER_BODY + +M68KMAKE_OP(1010, 0, ., .) +{ + m68ki_exception_1010(); +} + + +M68KMAKE_OP(1111, 0, ., .) +{ + m68ki_exception_1111(); +} + + +M68KMAKE_OP(040fpu0, 32, ., .) +{ + if(CPU_TYPE_IS_030_PLUS(CPU_TYPE)) + { + m68040_fpu_op0(); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(040fpu1, 32, ., .) +{ + if(CPU_TYPE_IS_030_PLUS(CPU_TYPE)) + { + m68040_fpu_op1(); + return; + } + m68ki_exception_1111(); +} + + + +M68KMAKE_OP(abcd, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(abcd, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(abcd, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res += 6; + res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res -= 0xa0; + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(add, 8, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 8, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, a) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 16, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, d) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, a) +{ + uint* r_dst = &DX; + uint src = AY; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 32, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(add, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(add, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(add, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(adda, 16, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(DY)); +} + + +M68KMAKE_OP(adda, 16, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(AY)); +} + + +M68KMAKE_OP(adda, 16, ., .) +{ + uint* r_dst = &AX; + uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + src); +} + + +M68KMAKE_OP(adda, 32, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + DY); +} + + +M68KMAKE_OP(adda, 32, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + AY); +} + + +M68KMAKE_OP(adda, 32, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_32; + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + src); +} + + +M68KMAKE_OP(addi, 8, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(addi, 16, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(addi, 32, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(addi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 8, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addq, 8, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = src + dst; + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 16, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(addq, 16, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); +} + + +M68KMAKE_OP(addq, 16, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = src + dst; + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(addq, 32, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = *r_dst; + uint res = src + dst; + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(addq, 32, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); +} + + +M68KMAKE_OP(addq, 32, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = src + dst; + + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(addx, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(addx, 16, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(addx, 32, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(addx, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_V = VFLAG_ADD_8(src, dst, res); + FLAG_X = FLAG_C = CFLAG_8(res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(addx, 16, mm, .) +{ + uint src = OPER_AY_PD_16(); + uint ea = EA_AX_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_V = VFLAG_ADD_16(src, dst, res); + FLAG_X = FLAG_C = CFLAG_16(res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(addx, 32, mm, .) +{ + uint src = OPER_AY_PD_32(); + uint ea = EA_AX_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = src + dst + XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_ADD_32(src, dst, res); + FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(and, 8, er, d) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (DY | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 8, er, .) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DX &= (M68KMAKE_GET_OPER_AY_8 | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 16, er, d) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (DY | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 16, er, .) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DX &= (M68KMAKE_GET_OPER_AY_16 | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 32, er, d) +{ + FLAG_Z = DX &= DY; + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 32, er, .) +{ + FLAG_Z = DX &= M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(and, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = DX & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(and, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = DX & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(and, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(andi, 8, ., d) +{ + FLAG_Z = MASK_OUT_ABOVE_8(DY &= (OPER_I_8() | 0xffffff00)); + + FLAG_N = NFLAG_8(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = src & m68ki_read_8(ea); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(andi, 16, ., d) +{ + FLAG_Z = MASK_OUT_ABOVE_16(DY &= (OPER_I_16() | 0xffff0000)); + + FLAG_N = NFLAG_16(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = src & m68ki_read_16(ea); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(andi, 32, ., d) +{ + FLAG_Z = DY &= (OPER_I_32()); + + FLAG_N = NFLAG_32(FLAG_Z); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(andi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src & m68ki_read_32(ea); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(andi, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() & OPER_I_8()); +} + + +M68KMAKE_OP(andi, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() & src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(asr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> (shift - 1))<<8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_16(src)) + { + *r_dst |= 0xffff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asr, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> (shift - 1))<<8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + if(GET_MSB_32(src)) + { + *r_dst = 0xffffffff; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asr, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + if(GET_MSB_16(src)) + res |= 0x8000; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = FLAG_X = src << 8; +} + + +M68KMAKE_OP(asl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> (8-shift); + src &= m68ki_shift_16_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; +} + + +M68KMAKE_OP(asl, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> (24-shift); + src &= m68ki_shift_32_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; +} + + +M68KMAKE_OP(asl, 8, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + src &= m68ki_shift_16_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = FLAG_C = ((shift == 16 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asl, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + src &= m68ki_shift_32_table[shift + 1]; + FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = (!(src == 0))<<7; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(asl, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + src &= 0xc000; + FLAG_V = (!(src == 0 || src == 0xc000))<<7; +} + + +M68KMAKE_OP(bcc, 8, ., .) +{ + if(M68KMAKE_CC) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); +} + + +M68KMAKE_OP(bcc, 16, ., .) +{ + if(M68KMAKE_CC) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_BCC_NOTAKE_W); +} + + +M68KMAKE_OP(bcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(offset); + return; + } + REG_PC += 4; + return; + } + else + { + if(M68KMAKE_CC) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + return; + } + USE_CYCLES(CYC_BCC_NOTAKE_B); + } +} + + +M68KMAKE_OP(bchg, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst ^= mask; +} + + +M68KMAKE_OP(bchg, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +M68KMAKE_OP(bchg, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst ^= mask; +} + + +M68KMAKE_OP(bchg, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src ^ mask); +} + + +M68KMAKE_OP(bclr, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst &= ~mask; +} + + +M68KMAKE_OP(bclr, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +M68KMAKE_OP(bclr, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst &= ~mask; +} + + +M68KMAKE_OP(bclr, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src & ~mask); +} + + +M68KMAKE_OP(bfchg, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long ^ mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte ^ mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfclr, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long & ~mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte & ~mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfexts, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2>>12)&7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfexts, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + + data = MASK_OUT_ABOVE_32(data< 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data = MAKE_INT_32(data) >> (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfextu, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data >>= 32 - width; + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2>>12)&7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfextu, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint data; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data< 32) + data |= (m68ki_read_8(ea+4) << offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + REG_D[(word2 >> 12) & 7] = data; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfffo, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint64 data = DY; + uint bit; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + offset &= 31; + width = ((width-1) & 31) + 1; + + data = ROL_32(data, offset); + FLAG_N = NFLAG_32(data); + data >>= 32 - width; + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfffo, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + sint local_offset; + uint width = word2; + uint data; + uint bit; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + local_offset = offset % 8; + if(local_offset < 0) + { + local_offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + data = m68ki_read_32(ea); + data = MASK_OUT_ABOVE_32(data< 32) + data |= (m68ki_read_8(ea+4) << local_offset) >> 8; + + FLAG_N = NFLAG_32(data); + data >>= (32 - width); + + FLAG_Z = data; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) + offset++; + + REG_D[(word2>>12)&7] = offset; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfins, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + uint64 insert = REG_D[(word2>>12)&7]; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + insert = MASK_OUT_ABOVE_32(insert << (32 - width)); + FLAG_N = NFLAG_32(insert); + FLAG_Z = insert; + insert = ROR_32(insert, offset); + + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + *data &= ~mask; + *data |= insert; + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfins, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint offset = (word2>>6)&31; + uint width = word2; + uint insert_base = REG_D[(word2>>12)&7]; + uint insert_long; + uint insert_byte; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); + FLAG_N = NFLAG_32(insert_base); + FLAG_Z = insert_base; + insert_long = insert_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + insert_byte = MASK_OUT_ABOVE_8(insert_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bfset, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = NFLAG_32(data_long << offset); + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + m68ki_write_32(ea, data_long | mask_long); + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + m68ki_write_8(ea+4, data_byte | mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bftst, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint offset = (word2>>6)&31; + uint width = word2; + uint* data = &DY; + uint64 mask; + + + if(BIT_B(word2)) + offset = REG_D[offset&7]; + if(BIT_5(word2)) + width = REG_D[width&7]; + + + offset &= 31; + width = ((width-1) & 31) + 1; + + + mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask = ROR_32(mask, offset); + + FLAG_N = NFLAG_32(*data<>6)&31; + uint width = word2; + uint mask_base; + uint data_long; + uint mask_long; + uint data_byte = 0; + uint mask_byte = 0; + uint ea = M68KMAKE_GET_EA_AY_8; + + if(BIT_B(word2)) + offset = MAKE_INT_32(REG_D[offset&7]); + if(BIT_5(word2)) + width = REG_D[width&7]; + + /* Offset is signed so we have to use ugly math =( */ + ea += offset / 8; + offset %= 8; + if(offset < 0) + { + offset += 8; + ea--; + } + width = ((width-1) & 31) + 1; + + + mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); + mask_long = mask_base >> offset; + + data_long = m68ki_read_32(ea); + FLAG_N = ((data_long & (0x80000000 >> offset))<>24; + FLAG_Z = data_long & mask_long; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + if((width + offset) > 32) + { + mask_byte = MASK_OUT_ABOVE_8(mask_base); + data_byte = m68ki_read_8(ea+4); + FLAG_Z |= (data_byte & mask_byte); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bkpt, 0, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_bkpt_ack(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE) ? REG_IR & 7 : 0); /* auto-disable (see m68kcpu.h) */ + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(bra, 8, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(bra, 16, ., .) +{ + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(bra, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint offset = OPER_I_32(); + REG_PC -= 4; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(offset); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); + return; + } + else + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); + } +} + + +M68KMAKE_OP(bset, 32, r, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (DX & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst |= mask; +} + + +M68KMAKE_OP(bset, 8, r, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint mask = 1 << (DX & 7); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +M68KMAKE_OP(bset, 32, s, d) +{ + uint* r_dst = &DY; + uint mask = 1 << (OPER_I_8() & 0x1f); + + FLAG_Z = *r_dst & mask; + *r_dst |= mask; +} + + +M68KMAKE_OP(bset, 8, s, .) +{ + uint mask = 1 << (OPER_I_8() & 7); + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + + FLAG_Z = src & mask; + m68ki_write_8(ea, src | mask); +} + + +M68KMAKE_OP(bsr, 8, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); +} + + +M68KMAKE_OP(bsr, 16, ., .) +{ + uint offset = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + REG_PC -= 2; + m68ki_branch_16(offset); +} + + +M68KMAKE_OP(bsr, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint offset = OPER_I_32(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + REG_PC -= 4; + m68ki_branch_32(offset); + return; + } + else + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); + } +} + + +M68KMAKE_OP(btst, 32, r, d) +{ + FLAG_Z = DY & (1 << (DX & 0x1f)); +} + + +M68KMAKE_OP(btst, 8, r, .) +{ + FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << (DX & 7)); +} + + +M68KMAKE_OP(btst, 32, s, d) +{ + FLAG_Z = DY & (1 << (OPER_I_8() & 0x1f)); +} + + +M68KMAKE_OP(btst, 8, s, .) +{ + uint bit = OPER_I_8() & 7; + + FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << bit); +} + + +M68KMAKE_OP(callm, 32, ., .) +{ + /* note: watch out for pcrelative modes */ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_PC += 2; +(void)ea; /* just to avoid an 'unused variable' warning */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 8, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dest = m68ki_read_8(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_8(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(*compare, dest, res); + FLAG_C = CFLAG_8(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_8(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dest = m68ki_read_16(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - MASK_OUT_ABOVE_16(*compare); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(*compare, dest, res); + FLAG_C = CFLAG_16(res); + + if(COND_NE()) + *compare = MASK_OUT_BELOW_16(*compare) | dest; + else + { + USE_CYCLES(3); + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dest = m68ki_read_32(ea); + uint* compare = ®_D[word2 & 7]; + uint res = dest - *compare; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(*compare, dest, res); + FLAG_C = CFLAG_SUB_32(*compare, dest, res); + + if(COND_NE()) + *compare = dest; + else + { + USE_CYCLES(3); + m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas2, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_32(); + uint* compare1 = ®_D[(word2 >> 16) & 7]; + uint ea1 = REG_DA[(word2 >> 28) & 15]; + uint dest1 = m68ki_read_16(ea1); + uint res1 = dest1 - MASK_OUT_ABOVE_16(*compare1); + uint* compare2 = ®_D[word2 & 7]; + uint ea2 = REG_DA[(word2 >> 12) & 15]; + uint dest2 = m68ki_read_16(ea2); + uint res2; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_16(res1); + FLAG_Z = MASK_OUT_ABOVE_16(res1); + FLAG_V = VFLAG_SUB_16(*compare1, dest1, res1); + FLAG_C = CFLAG_16(res1); + + if(COND_EQ()) + { + res2 = dest2 - MASK_OUT_ABOVE_16(*compare2); + + FLAG_N = NFLAG_16(res2); + FLAG_Z = MASK_OUT_ABOVE_16(res2); + FLAG_V = VFLAG_SUB_16(*compare2, dest2, res2); + FLAG_C = CFLAG_16(res2); + + if(COND_EQ()) + { + USE_CYCLES(3); + m68ki_write_16(ea1, REG_D[(word2 >> 22) & 7]); + m68ki_write_16(ea2, REG_D[(word2 >> 6) & 7]); + return; + } + } + *compare1 = BIT_1F(word2) ? (uint)MAKE_INT_16(dest1) : MASK_OUT_BELOW_16(*compare1) | dest1; + *compare2 = BIT_F(word2) ? (uint)MAKE_INT_16(dest2) : MASK_OUT_BELOW_16(*compare2) | dest2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cas2, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_32(); + uint* compare1 = ®_D[(word2 >> 16) & 7]; + uint ea1 = REG_DA[(word2 >> 28) & 15]; + uint dest1 = m68ki_read_32(ea1); + uint res1 = dest1 - *compare1; + uint* compare2 = ®_D[word2 & 7]; + uint ea2 = REG_DA[(word2 >> 12) & 15]; + uint dest2 = m68ki_read_32(ea2); + uint res2; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res1); + FLAG_Z = MASK_OUT_ABOVE_32(res1); + FLAG_V = VFLAG_SUB_32(*compare1, dest1, res1); + FLAG_C = CFLAG_SUB_32(*compare1, dest1, res1); + + if(COND_EQ()) + { + res2 = dest2 - *compare2; + + FLAG_N = NFLAG_32(res2); + FLAG_Z = MASK_OUT_ABOVE_32(res2); + FLAG_V = VFLAG_SUB_32(*compare2, dest2, res2); + FLAG_C = CFLAG_SUB_32(*compare2, dest2, res2); + + if(COND_EQ()) + { + USE_CYCLES(3); + m68ki_write_32(ea1, REG_D[(word2 >> 22) & 7]); + m68ki_write_32(ea2, REG_D[(word2 >> 6) & 7]); + return; + } + } + *compare1 = dest1; + *compare2 = dest2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk, 16, ., d) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(DY); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); +} + + +M68KMAKE_OP(chk, 16, ., .) +{ + sint src = MAKE_INT_16(DX); + sint bound = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + + FLAG_Z = ZFLAG_16(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); +} + + +M68KMAKE_OP(chk, 32, ., d) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(DY); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + sint src = MAKE_INT_32(DX); + sint bound = MAKE_INT_32(M68KMAKE_GET_OPER_AY_32); + + FLAG_Z = ZFLAG_32(src); /* Undocumented */ + FLAG_V = VFLAG_CLEAR; /* Undocumented */ + FLAG_C = CFLAG_CLEAR; /* Undocumented */ + + if(src >= 0 && src <= bound) + { + return; + } + FLAG_N = (src < 0)<<7; + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_PCDI_8(); + sint lower_bound = m68ki_read_pcrel_8(ea); + sint upper_bound = m68ki_read_pcrel_8(ea + 1); + + if(!BIT_F(word2)) + compare = (int32)(int8)compare; + + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + + + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = EA_PCIX_8(); + sint lower_bound = m68ki_read_pcrel_8(ea); + sint upper_bound = m68ki_read_pcrel_8(ea + 1); + + if(!BIT_F(word2)) + compare = (int32)(int8)compare; + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => ||, faster operation short circuits + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 8, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint compare = REG_DA[(word2 >> 12) & 15]&0xff; + uint ea = M68KMAKE_GET_EA_AY_8; + sint lower_bound = (int8)m68ki_read_8(ea); + sint upper_bound = (int8)m68ki_read_8(ea + 1); + + if(!BIT_F(word2)) + compare = (int32)(int8)compare; + + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_PCDI_16(); + sint lower_bound = (int16)m68ki_read_pcrel_16(ea); + sint upper_bound = (int16)m68ki_read_pcrel_16(ea + 2); + + if(!BIT_F(word2)) + compare = (int32)(int16)compare; + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = EA_PCIX_16(); + sint lower_bound = (int16)m68ki_read_pcrel_16(ea); + sint upper_bound = (int16)m68ki_read_pcrel_16(ea + 2); + + if(!BIT_F(word2)) + compare = (int32)(int16)compare; + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; + uint ea = M68KMAKE_GET_EA_AY_16; + sint lower_bound = (int16)m68ki_read_16(ea); + sint upper_bound = (int16)m68ki_read_16(ea + 2); + + if(!BIT_F(word2)) + compare = (int32)(int16)compare; + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_PCDI_32(); + sint lower_bound = m68ki_read_pcrel_32(ea); + sint upper_bound = m68ki_read_pcrel_32(ea + 4); + + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + sint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = EA_PCIX_32(); + sint lower_bound = m68ki_read_32(ea); + sint upper_bound = m68ki_read_32(ea + 4); + + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(chk2cmp2, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + // JFF changed the logic. chk2/cmp2 uses signed values, not unsigned + sint compare = REG_DA[(word2 >> 12) & 15]; + uint ea = M68KMAKE_GET_EA_AY_32; + sint lower_bound = m68ki_read_32(ea); + sint upper_bound = m68ki_read_32(ea + 4); + + FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || + + FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; + + if(COND_CS() && BIT_B(word2)) + m68ki_exception_trap(EXCEPTION_CHK); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(clr, 8, ., d) +{ + DY &= 0xffffff00; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 16, ., d) +{ + DY &= 0xffff0000; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 16, ., .) +{ + m68ki_write_16(M68KMAKE_GET_EA_AY_16, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 32, ., d) +{ + DY = 0; + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(clr, 32, ., .) +{ + m68ki_write_32(M68KMAKE_GET_EA_AY_32, 0); + + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; +} + + +M68KMAKE_OP(cmp, 8, ., d) +{ + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmp, 8, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(DX); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmp, 16, ., d) +{ + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 16, ., a) +{ + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 16, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(DX); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmp, 32, ., d) +{ + uint src = DY; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmp, 32, ., a) +{ + uint src = AY; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmp, 32, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = DX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., d) +{ + uint src = MAKE_INT_16(DY); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., a) +{ + uint src = MAKE_INT_16(AY); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 16, ., .) +{ + uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., d) +{ + uint src = DY; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., a) +{ + uint src = AY; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpa, 32, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = AX; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 8, ., d) +{ + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(DY); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpi, 8, ., .) +{ + uint src = OPER_I_8(); + uint dst = M68KMAKE_GET_OPER_AY_8; + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpi, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_8(); + uint dst = OPER_PCDI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_8(); + uint dst = OPER_PCIX_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 16, ., d) +{ + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(DY); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpi, 16, ., .) +{ + uint src = OPER_I_16(); + uint dst = M68KMAKE_GET_OPER_AY_16; + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpi, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_16(); + uint dst = OPER_PCDI_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_16(); + uint dst = OPER_PCIX_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 32, ., d) +{ + uint src = OPER_I_32(); + uint dst = DY; + uint res = dst - src; + + m68ki_cmpild_callback(src, REG_IR & 7); /* auto-disable (see m68kcpu.h) */ + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 32, ., .) +{ + uint src = OPER_I_32(); + uint dst = M68KMAKE_GET_OPER_AY_32; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cmpi, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_32(); + uint dst = OPER_PCDI_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpi, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_I_32(); + uint dst = OPER_PCIX_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(cmpm, 8, ., ax7) +{ + uint src = OPER_AY_PI_8(); + uint dst = OPER_A7_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., ay7) +{ + uint src = OPER_A7_PI_8(); + uint dst = OPER_AX_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., axy7) +{ + uint src = OPER_A7_PI_8(); + uint dst = OPER_A7_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 8, ., .) +{ + uint src = OPER_AY_PI_8(); + uint dst = OPER_AX_PI_8(); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_C = CFLAG_8(res); +} + + +M68KMAKE_OP(cmpm, 16, ., .) +{ + uint src = OPER_AY_PI_16(); + uint dst = OPER_AX_PI_16(); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_C = CFLAG_16(res); +} + + +M68KMAKE_OP(cmpm, 32, ., .) +{ + uint src = OPER_AY_PI_32(); + uint dst = OPER_AX_PI_32(); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_C = CFLAG_SUB_32(src, dst, res); +} + + +M68KMAKE_OP(cpbcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpdbcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpgen, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cpscc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(cptrapcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + // JFF: unsupported, but at least if the trap doesn't occur, app should still work, so at least PC increase is correct + REG_PC += 4; + return; + } + m68ki_exception_1111(); +} + + +M68KMAKE_OP(dbt, 16, ., .) +{ + REG_PC += 2; +} + + +M68KMAKE_OP(dbf, 16, ., .) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); +} + + +M68KMAKE_OP(dbcc, 16, ., .) +{ + if(M68KMAKE_NOT_CC) + { + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(*r_dst - 1); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + if(res != 0xffff) + { + uint offset = OPER_I_16(); + REG_PC -= 2; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset); + USE_CYCLES(CYC_DBCC_F_NOEXP); + return; + } + REG_PC += 2; + USE_CYCLES(CYC_DBCC_F_EXP); + return; + } + REG_PC += 2; +} + + +M68KMAKE_OP(divs, 16, ., d) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(DY); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divs, 16, ., .) +{ + uint* r_dst = &DX; + sint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + sint quotient; + sint remainder; + + if(src != 0) + { + if((uint32)*r_dst == 0x80000000 && src == -1) + { + FLAG_Z = 0; + FLAG_N = NFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = 0; + return; + } + + quotient = MAKE_INT_32(*r_dst) / src; + remainder = MAKE_INT_32(*r_dst) % src; + + if(quotient == MAKE_INT_16(quotient)) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divu, 16, ., d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divu, 16, ., .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + + if(src != 0) + { + uint quotient = *r_dst / src; + uint remainder = *r_dst % src; + + if(quotient < 0x10000) + { + FLAG_Z = quotient; + FLAG_N = NFLAG_16(quotient); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); + return; + } + FLAG_V = VFLAG_SET; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); +} + + +M68KMAKE_OP(divl, 32, ., d) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = DY; + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = DY; + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(divl, 32, ., .) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 divisor = M68KMAKE_GET_OPER_AY_32; + uint64 dividend = 0; + uint64 quotient = 0; + uint64 remainder = 0; + + if(divisor != 0) + { + if(BIT_A(word2)) /* 64 bit */ + { + dividend = REG_D[word2 & 7]; + dividend <<= 32; + dividend |= REG_D[(word2 >> 12) & 7]; + + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); + if((sint64)quotient != (sint64)((sint32)quotient)) + { + FLAG_V = VFLAG_SET; + return; + } + } + else /* unsigned */ + { + quotient = dividend / divisor; + if(quotient > 0xffffffff) + { + FLAG_V = VFLAG_SET; + return; + } + remainder = dividend % divisor; + } + } + else /* 32 bit */ + { + dividend = REG_D[(word2 >> 12) & 7]; + if(BIT_B(word2)) /* signed */ + { + quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); + remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); + } + else /* unsigned */ + { + quotient = dividend / divisor; + remainder = dividend % divisor; + } + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint divisor = M68KMAKE_GET_OPER_AY_32; + uint dividend_hi = REG_D[word2 & 7]; + uint dividend_lo = REG_D[(word2 >> 12) & 7]; + uint quotient = 0; + uint remainder = 0; + uint dividend_neg = 0; + uint divisor_neg = 0; + sint i; + uint overflow; + + if(divisor != 0) + { + /* quad / long : long quotient, long remainder */ + if(BIT_A(word2)) + { + if(BIT_B(word2)) /* signed */ + { + /* special case in signed divide */ + if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + REG_D[word2 & 7] = 0; + REG_D[(word2 >> 12) & 7] = 0x80000000; + + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + if(GET_MSB_32(dividend_hi)) + { + dividend_neg = 1; + dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); + dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); + } + if(GET_MSB_32(divisor)) + { + divisor_neg = 1; + divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); + + } + } + + /* if the upper long is greater than the divisor, we're overflowing. */ + if(dividend_hi >= divisor) + { + FLAG_V = VFLAG_SET; + return; + } + + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + remainder = (remainder << 1) + ((dividend_hi >> i) & 1); + if(remainder >= divisor) + { + remainder -= divisor; + quotient++; + } + } + for(i = 31; i >= 0; i--) + { + quotient <<= 1; + overflow = GET_MSB_32(remainder); + remainder = (remainder << 1) + ((dividend_lo >> i) & 1); + if(remainder >= divisor || overflow) + { + remainder -= divisor; + quotient++; + } + } + + if(BIT_B(word2)) /* signed */ + { + if(quotient > 0x7fffffff) + { + FLAG_V = VFLAG_SET; + return; + } + if(dividend_neg) + { + remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + if(divisor_neg) + quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); + } + + REG_D[word2 & 7] = remainder; + REG_D[(word2 >> 12) & 7] = quotient; + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + + /* long / long: long quotient, maybe long remainder */ + if(BIT_B(word2)) /* signed */ + { + /* Special case in divide */ + if(dividend_lo == 0x80000000 && divisor == 0xffffffff) + { + FLAG_N = NFLAG_SET; + FLAG_Z = ZFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + REG_D[(word2 >> 12) & 7] = 0x80000000; + REG_D[word2 & 7] = 0; + return; + } + REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); + } + else + { + REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); + quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); + } + + FLAG_N = NFLAG_32(quotient); + FLAG_Z = quotient; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(eor, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY ^= MASK_OUT_ABOVE_8(DX)); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY ^= MASK_OUT_ABOVE_16(DX)); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 32, ., d) +{ + uint res = DY ^= DX; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eor, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY ^= OPER_I_8()); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = src ^ m68ki_read_8(ea); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY ^= OPER_I_16()); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = src ^ m68ki_read_16(ea); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 32, ., d) +{ + uint res = DY ^= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src ^ m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(eori, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() ^ OPER_I_8()); +} + + +M68KMAKE_OP(eori, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() ^ src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(exg, 32, dd, .) +{ + uint* reg_a = &DX; + uint* reg_b = &DY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(exg, 32, aa, .) +{ + uint* reg_a = &AX; + uint* reg_b = &AY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(exg, 32, da, .) +{ + uint* reg_a = &DX; + uint* reg_b = &AY; + uint tmp = *reg_a; + *reg_a = *reg_b; + *reg_b = tmp; +} + + +M68KMAKE_OP(ext, 16, ., .) +{ + uint* r_dst = &DY; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xff00 : 0); + + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(ext, 32, ., .) +{ + uint* r_dst = &DY; + + *r_dst = MASK_OUT_ABOVE_16(*r_dst) | (GET_MSB_16(*r_dst) ? 0xffff0000 : 0); + + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(extb, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint* r_dst = &DY; + + *r_dst = MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xffffff00 : 0); + + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(illegal, 0, ., .) +{ + m68ki_exception_illegal(); +} + +M68KMAKE_OP(jmp, 32, ., .) +{ + m68ki_jump(M68KMAKE_GET_EA_AY_32); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(REG_PC == REG_PPC) + USE_ALL_CYCLES(); +} + + +M68KMAKE_OP(jsr, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_push_32(REG_PC); + m68ki_jump(ea); +} + + +M68KMAKE_OP(lea, 32, ., .) +{ + AX = M68KMAKE_GET_EA_AY_32; +} + + +M68KMAKE_OP(link, 16, ., a7) +{ + REG_A[7] -= 4; + m68ki_write_32(REG_A[7], REG_A[7]); + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); +} + + +M68KMAKE_OP(link, 16, ., .) +{ + uint* r_dst = &AY; + + m68ki_push_32(*r_dst); + *r_dst = REG_A[7]; + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); +} + + +M68KMAKE_OP(link, 32, ., a7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_A[7] -= 4; + m68ki_write_32(REG_A[7], REG_A[7]); + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(link, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint* r_dst = &AY; + + m68ki_push_32(*r_dst); + *r_dst = REG_A[7]; + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(lsr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + USE_CYCLES(shift<> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> (shift - 1))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = src >> shift; + + if(shift != 0) + { + USE_CYCLES(shift<> (shift - 1))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = (shift == 32 ? GET_MSB_32(src)>>23 : 0); + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsr, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = src >> 1; + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_CLEAR; + FLAG_Z = res; + FLAG_C = FLAG_X = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = MASK_OUT_ABOVE_16(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> (8-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + USE_CYCLES(shift<> (24-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 8, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = MASK_OUT_ABOVE_8(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst &= 0xffff0000; + FLAG_X = XFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 32, r, .) +{ + uint* r_dst = &DY; + uint shift = DX & 0x3f; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32(src << shift); + + if(shift != 0) + { + USE_CYCLES(shift<> (32 - shift)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + *r_dst = 0; + FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; + FLAG_N = NFLAG_CLEAR; + FLAG_Z = ZFLAG_SET; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(lsl, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(src << 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_X = FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, d, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ai, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_AI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi7, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi7, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_A7_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_PI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd7, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd7, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_A7_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_PD_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, di, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_DI_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ix, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AX_IX_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, aw, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AW_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, al, d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 8, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + uint ea = EA_AL_8(); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_AI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_PI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_PD_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_DI_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AX_IX_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AW_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, a) +{ + uint res = MASK_OUT_ABOVE_16(AY); + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 16, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + uint ea = EA_AL_16(); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, d) +{ + uint res = DY; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, a) +{ + uint res = AY; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, d, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint* r_dst = &DX; + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, d) +{ + uint res = DY; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, a) +{ + uint res = AY; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ai, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_AI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, d) +{ + uint res = DY; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, a) +{ + uint res = AY; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pi, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_PI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, d) +{ + uint res = DY; + uint ea = EA_AX_PD_32(); + + m68ki_write_16(ea+2, res & 0xFFFF ); + m68ki_write_16(ea, (res >> 16) & 0xFFFF ); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, a) +{ + uint res = AY; + uint ea = EA_AX_PD_32(); + + m68ki_write_16(ea+2, res & 0xFFFF ); + m68ki_write_16(ea, (res >> 16) & 0xFFFF ); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, pd, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_PD_32(); + + m68ki_write_16(ea+2, res & 0xFFFF ); + m68ki_write_16(ea, (res >> 16) & 0xFFFF ); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, d) +{ + uint res = DY; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, a) +{ + uint res = AY; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, di, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_DI_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, d) +{ + uint res = DY; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, a) +{ + uint res = AY; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, ix, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AX_IX_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, d) +{ + uint res = DY; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, a) +{ + uint res = AY; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, aw, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AW_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, d) +{ + uint res = DY; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, a) +{ + uint res = AY; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move, 32, al, .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + uint ea = EA_AL_32(); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(movea, 16, ., d) +{ + AX = MAKE_INT_16(DY); +} + + +M68KMAKE_OP(movea, 16, ., a) +{ + AX = MAKE_INT_16(AY); +} + + +M68KMAKE_OP(movea, 16, ., .) +{ + AX = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); +} + + +M68KMAKE_OP(movea, 32, ., d) +{ + AX = DY; +} + + +M68KMAKE_OP(movea, 32, ., a) +{ + AX = AY; +} + + +M68KMAKE_OP(movea, 32, ., .) +{ + AX = M68KMAKE_GET_OPER_AY_32; +} + + +M68KMAKE_OP(move, 16, frc, d) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + DY = MASK_OUT_BELOW_16(DY) | m68ki_get_ccr(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(move, 16, frc, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + m68ki_write_16(M68KMAKE_GET_EA_AY_16, m68ki_get_ccr()); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(move, 16, toc, d) +{ + m68ki_set_ccr(DY); +} + + +M68KMAKE_OP(move, 16, toc, .) +{ + m68ki_set_ccr(M68KMAKE_GET_OPER_AY_16); +} + + +M68KMAKE_OP(move, 16, frs, d) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + DY = MASK_OUT_BELOW_16(DY) | m68ki_get_sr(); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, frs, .) +{ + if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ + { + uint ea = M68KMAKE_GET_EA_AY_16; + m68ki_write_16(ea, m68ki_get_sr()); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, tos, d) +{ + if(FLAG_S) + { + m68ki_set_sr(DY); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 16, tos, .) +{ + if(FLAG_S) + { + uint new_sr = M68KMAKE_GET_OPER_AY_16; + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(new_sr); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 32, fru, .) +{ + if(FLAG_S) + { + AY = REG_USP; + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(move, 32, tou, .) +{ + if(FLAG_S) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_USP = AY; + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(movec, 32, cr, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + switch (word2 & 0xfff) + { + case 0x000: /* SFC */ + REG_DA[(word2 >> 12) & 15] = REG_SFC; + return; + case 0x001: /* DFC */ + REG_DA[(word2 >> 12) & 15] = REG_DFC; + return; + case 0x002: /* CACR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = REG_CACR; + return; + } + return; + case 0x800: /* USP */ + REG_DA[(word2 >> 12) & 15] = REG_USP; + return; + case 0x801: /* VBR */ + REG_DA[(word2 >> 12) & 15] = REG_VBR; + return; + case 0x802: /* CAAR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = REG_CAAR; + return; + } + m68ki_exception_illegal(); + break; + case 0x803: /* MSP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_SP : REG_MSP; + return; + } + m68ki_exception_illegal(); + return; + case 0x804: /* ISP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_ISP : REG_SP; + return; + } + m68ki_exception_illegal(); + return; + case 0x003: /* TC */ + if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x004: /* ITT0 */ + if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x005: /* ITT1 */ + if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x006: /* DTT0 */ + if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x007: /* DTT1 */ + if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x805: /* MMUSR */ + if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x806: /* URP */ + if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x807: /* SRP */ + if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + default: + m68ki_exception_illegal(); + return; + } + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(movec, 32, rc, .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + switch (word2 & 0xfff) + { + case 0x000: /* SFC */ + REG_SFC = REG_DA[(word2 >> 12) & 15] & 7; + return; + case 0x001: /* DFC */ + REG_DFC = REG_DA[(word2 >> 12) & 15] & 7; + return; + case 0x002: /* CACR */ + /* Only EC020 and later have CACR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* 68030 can write all bits except 5-7, 040 can write all */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + REG_CACR = REG_DA[(word2 >> 12) & 15]; + } + else if (CPU_TYPE_IS_030_PLUS(CPU_TYPE)) + { + REG_CACR = REG_DA[(word2 >> 12) & 15] & 0xff1f; + } + else + { + REG_CACR = REG_DA[(word2 >> 12) & 15] & 0x0f; + } + return; + } + m68ki_exception_illegal(); + return; + case 0x800: /* USP */ + REG_USP = REG_DA[(word2 >> 12) & 15]; + return; + case 0x801: /* VBR */ + REG_VBR = REG_DA[(word2 >> 12) & 15]; + return; + case 0x802: /* CAAR */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_CAAR = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x803: /* MSP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* we are in supervisor mode so just check for M flag */ + if(!FLAG_M) + { + REG_MSP = REG_DA[(word2 >> 12) & 15]; + return; + } + REG_SP = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x804: /* ISP */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(!FLAG_M) + { + REG_SP = REG_DA[(word2 >> 12) & 15]; + return; + } + REG_ISP = REG_DA[(word2 >> 12) & 15]; + return; + } + m68ki_exception_illegal(); + return; + case 0x003: /* TC */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x004: /* ITT0 */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x005: /* ITT1 */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x006: /* DTT0 */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x007: /* DTT1 */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x805: /* MMUSR */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x806: /* URP */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + case 0x807: /* SRP */ + if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) + { + /* TODO */ + return; + } + m68ki_exception_illegal(); + return; + default: + m68ki_exception_illegal(); + return; + } + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(movem, 16, re, pd) +{ + uint i = 0; + uint register_list = OPER_I_16(); + uint ea = AY; + uint count = 0; + + for(; i < 16; i++) + if(register_list & (1 << i)) + { + ea -= 2; + m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[15-i])); + count++; + } + AY = ea; + + USE_CYCLES(count<> 16) & 0xFFFF ); + count++; + } + AY = ea; + + USE_CYCLES(count<> 8)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); +} + + +M68KMAKE_OP(movep, 32, re, .) +{ + uint ea = EA_AY_DI_32(); + uint src = DX; + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 24)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 16)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 8)); + m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); +} + + +M68KMAKE_OP(movep, 16, er, .) +{ + uint ea = EA_AY_DI_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | ((m68ki_read_8(ea) << 8) + m68ki_read_8(ea + 2)); +} + + +M68KMAKE_OP(movep, 32, er, .) +{ + uint ea = EA_AY_DI_32(); + + DX = (m68ki_read_8(ea) << 24) + (m68ki_read_8(ea + 2) << 16) + + (m68ki_read_8(ea + 4) << 8) + m68ki_read_8(ea + 6); +} + + +M68KMAKE_OP(moves, 8, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_8; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_8_fc(ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moves, 16, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_16_fc(ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); + return; + } + if(BIT_F(word2)) /* Memory to address register */ + { + REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(ea, REG_SFC)); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to data register */ + REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moves, 32, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + if(FLAG_S) + { + uint word2 = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + if(BIT_B(word2)) /* Register to memory */ + { + m68ki_write_32_fc(ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + /* Memory to register */ + REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(ea, REG_SFC); + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + USE_CYCLES(2); + return; + } + m68ki_exception_privilege_violation(); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(moveq, 32, ., .) +{ + uint res = DX = MAKE_INT_8(MASK_OUT_ABOVE_8(REG_IR)); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(move16, 32, ., .) +{ + uint16 w2 = OPER_I_16(); + int ax = REG_IR & 7; + int ay = (w2 >> 12) & 7; + + m68ki_write_32(REG_A[ay], m68ki_read_32(REG_A[ax])); + m68ki_write_32(REG_A[ay]+4, m68ki_read_32(REG_A[ax]+4)); + m68ki_write_32(REG_A[ay]+8, m68ki_read_32(REG_A[ax]+8)); + m68ki_write_32(REG_A[ay]+12, m68ki_read_32(REG_A[ax]+12)); + + REG_A[ax] += 16; + REG_A[ay] += 16; +} + + +M68KMAKE_OP(muls, 16, ., d) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(muls, 16, ., .) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(M68KMAKE_GET_OPER_AY_16) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mulu, 16, ., d) +{ + uint* r_dst = &DX; + uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mulu, 16, ., .) +{ + uint* r_dst = &DX; + uint res = M68KMAKE_GET_OPER_AY_16 * MASK_OUT_ABOVE_16(*r_dst); + + *r_dst = res; + + FLAG_Z = res; + FLAG_N = NFLAG_32(res); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(mull, 32, ., d) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = DY; + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = DY; + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(mull, 32, ., .) +{ +#if M68K_USE_64_BIT + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint64 src = M68KMAKE_GET_OPER_AY_32; + uint64 dst = REG_D[(word2 >> 12) & 7]; + uint64 res; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + res = (sint64)((sint32)src) * (sint64)((sint32)dst); + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = ((sint64)res != (sint32)res)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + + res = src * dst; + if(!BIT_A(word2)) + { + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_N = NFLAG_32(res); + FLAG_V = (res > 0xffffffff)<<7; + REG_D[(word2 >> 12) & 7] = FLAG_Z; + return; + } + FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); + FLAG_N = NFLAG_64(res); + FLAG_V = VFLAG_CLEAR; + REG_D[word2 & 7] = (res >> 32); + REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); + return; + } + m68ki_exception_illegal(); + +#else + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint word2 = OPER_I_16(); + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = REG_D[(word2 >> 12) & 7]; + uint neg = GET_MSB_32(src ^ dst); + uint src1; + uint src2; + uint dst1; + uint dst2; + uint r1; + uint r2; + uint r3; + uint r4; + uint lo; + uint hi; + + FLAG_C = CFLAG_CLEAR; + + if(BIT_B(word2)) /* signed */ + { + if(GET_MSB_32(src)) + src = (uint)MASK_OUT_ABOVE_32(-(sint)src); + if(GET_MSB_32(dst)) + dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); + } + + src1 = MASK_OUT_ABOVE_16(src); + src2 = src>>16; + dst1 = MASK_OUT_ABOVE_16(dst); + dst2 = dst>>16; + + + r1 = src1 * dst1; + r2 = src1 * dst2; + r3 = src2 * dst1; + r4 = src2 * dst2; + + lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); + hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); + + if(BIT_B(word2) && neg) + { + hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); + lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); + } + + if(BIT_A(word2)) + { + REG_D[word2 & 7] = hi; + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(hi); + FLAG_Z = hi | lo; + FLAG_V = VFLAG_CLEAR; + return; + } + + REG_D[(word2 >> 12) & 7] = lo; + FLAG_N = NFLAG_32(lo); + FLAG_Z = lo; + if(BIT_B(word2)) + FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; + else + FLAG_V = (hi != 0) << 7; + return; + } + m68ki_exception_illegal(); + +#endif +} + + +M68KMAKE_OP(nbcd, 8, ., d) +{ + uint* r_dst = &DY; + uint dst = *r_dst; + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +M68KMAKE_OP(nbcd, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); + + if(res != 0x9a) + { + FLAG_V = ~res; /* Undefined V behavior */ + + if((res & 0x0f) == 0xa) + res = (res & 0xf0) + 0x10; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + + m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); + + FLAG_Z |= res; + FLAG_C = CFLAG_SET; + FLAG_X = XFLAG_SET; + } + else + { + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + } + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ +} + + +M68KMAKE_OP(neg, 8, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_8(*r_dst); + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = *r_dst & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(neg, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_8(res); + FLAG_C = FLAG_X = CFLAG_8(res); + FLAG_V = src & res; + FLAG_Z = MASK_OUT_ABOVE_8(res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(neg, 16, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_16(*r_dst); + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (*r_dst & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(neg, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_16(res); + FLAG_C = FLAG_X = CFLAG_16(res); + FLAG_V = (src & res)>>8; + FLAG_Z = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(neg, 32, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - *r_dst; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(*r_dst, 0, res); + FLAG_V = (*r_dst & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(neg, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = m68ki_read_32(ea); + uint res = 0 - src; + + FLAG_N = NFLAG_32(res); + FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + FLAG_Z = MASK_OUT_ABOVE_32(res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(negx, 8, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_8(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = *r_dst & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(negx, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = m68ki_read_8(ea); + uint res = 0 - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = src & res; + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(negx, 16, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_16(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (*r_dst & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(negx, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = (src & res)>>8; + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(negx, 32, ., d) +{ + uint* r_dst = &DY; + uint res = 0 - MASK_OUT_ABOVE_32(*r_dst) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(*r_dst, 0, res); + FLAG_V = (*r_dst & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(negx, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = m68ki_read_32(ea); + uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); + FLAG_V = (src & res)>>24; + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(nop, 0, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ +} + + +M68KMAKE_OP(not, 8, ., d) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_8(~*r_dst); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 16, ., d) +{ + uint* r_dst = &DY; + uint res = MASK_OUT_ABOVE_16(~*r_dst); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 32, ., d) +{ + uint* r_dst = &DY; + uint res = *r_dst = MASK_OUT_ABOVE_32(~*r_dst); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(not, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, er, d) +{ + uint res = MASK_OUT_ABOVE_8((DX |= MASK_OUT_ABOVE_8(DY))); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, er, .) +{ + uint res = MASK_OUT_ABOVE_8((DX |= M68KMAKE_GET_OPER_AY_8)); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, er, d) +{ + uint res = MASK_OUT_ABOVE_16((DX |= MASK_OUT_ABOVE_16(DY))); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, er, .) +{ + uint res = MASK_OUT_ABOVE_16((DX |= M68KMAKE_GET_OPER_AY_16)); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, er, d) +{ + uint res = DX |= DY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, er, .) +{ + uint res = DX |= M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(or, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = DX | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8((DY |= OPER_I_8())); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); + + m68ki_write_8(ea, res); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY |= OPER_I_16()); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 32, ., d) +{ + uint res = DY |= OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint res = src | m68ki_read_32(ea); + + m68ki_write_32(ea, res); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ori, 16, toc, .) +{ + m68ki_set_ccr(m68ki_get_ccr() | OPER_I_8()); +} + + +M68KMAKE_OP(ori, 16, tos, .) +{ + if(FLAG_S) + { + uint src = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_sr(m68ki_get_sr() | src); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(pack, 16, rr, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: DX and DY are reversed in Motorola's docs */ + uint src = DY + OPER_I_16(); + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | ((src >> 4) & 0x00f0) | (src & 0x000f); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, ax7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_AY_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_AY_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, ay7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_A7_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_A7_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, axy7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint ea_src = EA_A7_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_A7_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pack, 16, mm, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint ea_src = EA_AY_PD_8(); + uint src = m68ki_read_8(ea_src); + ea_src = EA_AY_PD_8(); + src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); + + m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(pea, 32, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + + m68ki_push_32(ea); +} + +M68KMAKE_OP(pflush, 32, ., .) +{ + if ((CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) && (HAS_PMMU)) + { + fprintf(stderr,"68040: unhandled PFLUSH\n"); + return; + } + m68ki_exception_1111(); +} + +M68KMAKE_OP(pmmu, 32, ., .) +{ + if ((CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) && (HAS_PMMU)) + { + m68881_mmu_ops(); + } + else + { + m68ki_exception_1111(); + } +} + +M68KMAKE_OP(reset, 0, ., .) +{ + if(FLAG_S) + { + m68ki_output_reset(); /* auto-disable (see m68kcpu.h) */ + USE_CYCLES(CYC_RESET); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(ror, 8, s, .) +{ + uint* r_dst = &DY; + uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_8(src, shift); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_16(src, shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint res = ROR_32(src, shift); + + if(shift != 0) + USE_CYCLES(shift<> ((shift - 1) & 15)) << 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 32, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 31; + uint64 src = *r_dst; + uint res = ROR_32(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<> ((shift - 1) & 31)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(ror, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = ROR_16(src, 1); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src << 8; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 8, s, .) +{ + uint* r_dst = &DY; + uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_8(src, shift); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_16(src, shift); + + if(shift != 0) + USE_CYCLES(shift<> (8-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 32, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint res = ROL_32(src, shift); + + if(shift != 0) + USE_CYCLES(shift<> (24-shift); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 8, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 7; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_8(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<> 8; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + FLAG_C = (src & 1)<<8; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_16(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 32, r, .) +{ + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift & 31; + uint64 src = *r_dst; + uint res = ROL_32(src, shift); + + if(orig_shift != 0) + { + USE_CYCLES(orig_shift<> ((32 - shift) & 0x1f)) << 8; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = CFLAG_CLEAR; + FLAG_N = NFLAG_32(src); + FLAG_Z = src; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rol, 16, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = m68ki_read_16(ea); + uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_C = src >> 7; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROR_9(src | (XFLAG_AS_1() << 8), shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROR_17(src | (XFLAG_AS_1() << 16), shift); + + if(shift != 0) + USE_CYCLES(shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 32, s, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + if(shift != 0) + USE_CYCLES(shift<> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); + uint new_x_flag = src & (1 << (shift - 1)); + + if(shift != 0) + USE_CYCLES(shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxr, 32, r, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 33; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROR_33_64(res, shift); + + USE_CYCLES(orig_shift<> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift % 33; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); + uint new_x_flag = src & (1 << (shift - 1)); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 8, s, .) +{ + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_8(*r_dst); + uint res = ROL_9(src | (XFLAG_AS_1() << 8), shift); + + if(shift != 0) + USE_CYCLES(shift<> 9) - 1) & 7) + 1; + uint src = MASK_OUT_ABOVE_16(*r_dst); + uint res = ROL_17(src | (XFLAG_AS_1() << 16), shift); + + if(shift != 0) + USE_CYCLES(shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 32, s, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + if(shift != 0) + USE_CYCLES(shift<> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint shift = (((REG_IR >> 9) - 1) & 7) + 1; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); + uint new_x_flag = src & (1 << (32 - shift)); + + if(shift != 0) + USE_CYCLES(shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_16(*r_dst); + FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(roxl, 32, r, .) +{ +#if M68K_USE_64_BIT + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + + if(orig_shift != 0) + { + uint shift = orig_shift % 33; + uint64 src = *r_dst; + uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); + + res = ROL_33_64(res, shift); + + USE_CYCLES(orig_shift<> 24; + res = MASK_OUT_ABOVE_32(res); + + *r_dst = res; + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + return; + } + + FLAG_C = FLAG_X; + FLAG_N = NFLAG_32(*r_dst); + FLAG_Z = *r_dst; + FLAG_V = VFLAG_CLEAR; + +#else + + uint* r_dst = &DY; + uint orig_shift = DX & 0x3f; + uint shift = orig_shift % 33; + uint src = *r_dst; + uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); + uint new_x_flag = src & (1 << (32 - shift)); + + if(orig_shift != 0) + USE_CYCLES(orig_shift<> 8; + res = MASK_OUT_ABOVE_16(res); + + m68ki_write_16(ea, res); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(rtd, 32, ., .) +{ + if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) + { + uint new_pc = m68ki_pull_32(); + + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); + m68ki_jump(new_pc); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(rte, 32, ., .) +{ + if(FLAG_S) + { + uint new_sr; + uint new_pc; + uint format_word; + + m68ki_rte_callback(); /* auto-disable (see m68kcpu.h) */ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + + return; + } + + if(CPU_TYPE_IS_010(CPU_TYPE)) + { + format_word = m68ki_read_16(REG_A[7]+6) >> 12; + if(format_word == 0) + { + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + } else if (format_word == 8) { + /* Format 8 stack frame -- 68010 only. 29 word bus/address error */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_fake_pull_16(); /* special status word */ + m68ki_fake_pull_32(); /* fault address */ + m68ki_fake_pull_16(); /* unused/reserved */ + m68ki_fake_pull_16(); /* data output buffer */ + m68ki_fake_pull_16(); /* unused/reserved */ + m68ki_fake_pull_16(); /* data input buffer */ + m68ki_fake_pull_16(); /* unused/reserved */ + m68ki_fake_pull_16(); /* instruction input buffer */ + m68ki_fake_pull_32(); /* internal information, 16 words */ + m68ki_fake_pull_32(); /* (actually, we use 8 DWORDs) */ + m68ki_fake_pull_32(); + m68ki_fake_pull_32(); + m68ki_fake_pull_32(); + m68ki_fake_pull_32(); + m68ki_fake_pull_32(); + m68ki_fake_pull_32(); + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + } + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + /* Not handling other exception types (9) */ + m68ki_exception_format_error(); + return; + } + + /* Otherwise it's 020 */ +rte_loop: + format_word = m68ki_read_16(REG_A[7]+6) >> 12; + switch(format_word) + { + case 0: /* Normal */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + case 1: /* Throwaway */ + new_sr = m68ki_pull_16(); + m68ki_fake_pull_32(); /* program counter */ + m68ki_fake_pull_16(); /* format word */ + m68ki_set_sr_noint(new_sr); + goto rte_loop; + case 2: /* Trap */ + new_sr = m68ki_pull_16(); + new_pc = m68ki_pull_32(); + m68ki_fake_pull_16(); /* format word */ + m68ki_fake_pull_32(); /* address */ + m68ki_jump(new_pc); + m68ki_set_sr(new_sr); + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + return; + } + /* Not handling long or short bus fault */ + CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_NORMAL; + m68ki_exception_format_error(); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(rtm, 32, ., .) +{ + if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, + m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(rtr, 32, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_set_ccr(m68ki_pull_16()); + m68ki_jump(m68ki_pull_32()); +} + + +M68KMAKE_OP(rts, 32, ., .) +{ + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_jump(m68ki_pull_32()); +} + + +M68KMAKE_OP(sbcd, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(sbcd, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(sbcd, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); + + FLAG_V = ~res; /* Undefined V behavior */ + + if(res > 9) + res -= 6; + res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); + FLAG_X = FLAG_C = (res > 0x99) << 8; + if(FLAG_C) + res += 0xa0; + + res = MASK_OUT_ABOVE_8(res); + + FLAG_V &= res; /* Undefined V behavior part II */ + FLAG_N = NFLAG_8(res); /* Undefined N behavior */ + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(st, 8, ., d) +{ + DY |= 0xff; +} + + +M68KMAKE_OP(st, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0xff); +} + + +M68KMAKE_OP(sf, 8, ., d) +{ + DY &= 0xffffff00; +} + + +M68KMAKE_OP(sf, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); +} + + +M68KMAKE_OP(scc, 8, ., d) +{ + if(M68KMAKE_CC) + { + DY |= 0xff; + USE_CYCLES(CYC_SCC_R_TRUE); + return; + } + DY &= 0xffffff00; +} + + +M68KMAKE_OP(scc, 8, ., .) +{ + m68ki_write_8(M68KMAKE_GET_EA_AY_8, M68KMAKE_CC ? 0xff : 0); +} + + +M68KMAKE_OP(stop, 0, ., .) +{ + if(FLAG_S) + { + uint new_sr = OPER_I_16(); + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + CPU_STOPPED |= STOP_LEVEL_STOP; + m68ki_set_sr(new_sr); + if(m68ki_remaining_cycles >= CYC_INSTRUCTION[REG_IR]) + m68ki_remaining_cycles = CYC_INSTRUCTION[REG_IR]; + else + USE_ALL_CYCLES(); + return; + } + m68ki_exception_privilege_violation(); +} + + +M68KMAKE_OP(sub, 8, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 8, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_8; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, d) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, a) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(AY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 16, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_16; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, d) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, a) +{ + uint* r_dst = &DX; + uint src = AY; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 32, er, .) +{ + uint* r_dst = &DX; + uint src = M68KMAKE_GET_OPER_AY_32; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(sub, 8, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint src = MASK_OUT_ABOVE_8(DX); + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(sub, 16, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_16; + uint src = MASK_OUT_ABOVE_16(DX); + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(sub, 32, re, .) +{ + uint ea = M68KMAKE_GET_EA_AY_32; + uint src = DX; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(suba, 16, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(DY)); +} + + +M68KMAKE_OP(suba, 16, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(AY)); +} + + +M68KMAKE_OP(suba, 16, ., .) +{ + uint* r_dst = &AX; + uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - src); +} + + +M68KMAKE_OP(suba, 32, ., d) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - DY); +} + + +M68KMAKE_OP(suba, 32, ., a) +{ + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - AY); +} + + +M68KMAKE_OP(suba, 32, ., .) +{ + uint src = M68KMAKE_GET_OPER_AY_32; + uint* r_dst = &AX; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - src); +} + + +M68KMAKE_OP(subi, 8, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_8(); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subi, 8, ., .) +{ + uint src = OPER_I_8(); + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(subi, 16, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_16(); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subi, 16, ., .) +{ + uint src = OPER_I_16(); + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(subi, 32, ., d) +{ + uint* r_dst = &DY; + uint src = OPER_I_32(); + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(subi, 32, ., .) +{ + uint src = OPER_I_32(); + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 8, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subq, 8, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint res = dst - src; + + FLAG_N = NFLAG_8(res); + FLAG_Z = MASK_OUT_ABOVE_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + m68ki_write_8(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 16, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; +} + + +M68KMAKE_OP(subq, 16, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); +} + + +M68KMAKE_OP(subq, 16, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_16; + uint dst = m68ki_read_16(ea); + uint res = dst - src; + + FLAG_N = NFLAG_16(res); + FLAG_Z = MASK_OUT_ABOVE_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + m68ki_write_16(ea, FLAG_Z); +} + + +M68KMAKE_OP(subq, 32, ., d) +{ + uint* r_dst = &DY; + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint dst = *r_dst; + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + *r_dst = FLAG_Z; +} + + +M68KMAKE_OP(subq, 32, ., a) +{ + uint* r_dst = &AY; + + *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); +} + + +M68KMAKE_OP(subq, 32, ., .) +{ + uint src = (((REG_IR >> 9) - 1) & 7) + 1; + uint ea = M68KMAKE_GET_EA_AY_32; + uint dst = m68ki_read_32(ea); + uint res = dst - src; + + FLAG_N = NFLAG_32(res); + FLAG_Z = MASK_OUT_ABOVE_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + m68ki_write_32(ea, FLAG_Z); +} + + +M68KMAKE_OP(subx, 8, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_8(DY); + uint dst = MASK_OUT_ABOVE_8(*r_dst); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; +} + + +M68KMAKE_OP(subx, 16, rr, .) +{ + uint* r_dst = &DX; + uint src = MASK_OUT_ABOVE_16(DY); + uint dst = MASK_OUT_ABOVE_16(*r_dst); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; +} + + +M68KMAKE_OP(subx, 32, rr, .) +{ + uint* r_dst = &DX; + uint src = DY; + uint dst = *r_dst; + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + *r_dst = res; +} + + +M68KMAKE_OP(subx, 8, mm, ax7) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, ay7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, axy7) +{ + uint src = OPER_A7_PD_8(); + uint ea = EA_A7_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 8, mm, .) +{ + uint src = OPER_AY_PD_8(); + uint ea = EA_AX_PD_8(); + uint dst = m68ki_read_8(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_8(res); + FLAG_X = FLAG_C = CFLAG_8(res); + FLAG_V = VFLAG_SUB_8(src, dst, res); + + res = MASK_OUT_ABOVE_8(res); + FLAG_Z |= res; + + m68ki_write_8(ea, res); +} + + +M68KMAKE_OP(subx, 16, mm, .) +{ + uint src = OPER_AY_PD_16(); + uint ea = EA_AX_PD_16(); + uint dst = m68ki_read_16(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_16(res); + FLAG_X = FLAG_C = CFLAG_16(res); + FLAG_V = VFLAG_SUB_16(src, dst, res); + + res = MASK_OUT_ABOVE_16(res); + FLAG_Z |= res; + + m68ki_write_16(ea, res); +} + + +M68KMAKE_OP(subx, 32, mm, .) +{ + uint src = OPER_AY_PD_32(); + uint ea = EA_AX_PD_32(); + uint dst = m68ki_read_32(ea); + uint res = dst - src - XFLAG_AS_1(); + + FLAG_N = NFLAG_32(res); + FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); + FLAG_V = VFLAG_SUB_32(src, dst, res); + + res = MASK_OUT_ABOVE_32(res); + FLAG_Z |= res; + + m68ki_write_32(ea, res); +} + + +M68KMAKE_OP(swap, 32, ., .) +{ + uint* r_dst = &DY; + + FLAG_Z = MASK_OUT_ABOVE_32(*r_dst<<16); + *r_dst = (*r_dst>>16) | FLAG_Z; + + FLAG_Z = *r_dst; + FLAG_N = NFLAG_32(*r_dst); + FLAG_C = CFLAG_CLEAR; + FLAG_V = VFLAG_CLEAR; +} + + +M68KMAKE_OP(tas, 8, ., d) +{ + uint* r_dst = &DY; + + FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); + FLAG_N = NFLAG_8(*r_dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + *r_dst |= 0x80; +} + + +M68KMAKE_OP(tas, 8, ., .) +{ + uint ea = M68KMAKE_GET_EA_AY_8; + uint dst = m68ki_read_8(ea); + uint allow_writeback; + + FLAG_Z = dst; + FLAG_N = NFLAG_8(dst); + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + + /* The Genesis/Megadrive games Gargoyles and Ex-Mutants need the TAS writeback + disabled in order to function properly. Some Amiga software may also rely + on this, but only when accessing specific addresses so additional functionality + will be needed. */ + allow_writeback = m68ki_tas_callback(); + + if (allow_writeback==1) m68ki_write_8(ea, dst | 0x80); +} + + +M68KMAKE_OP(trap, 0, ., .) +{ + /* Trap#n stacks exception frame type 0 */ + m68ki_exception_trapN(EXCEPTION_TRAP_BASE + (REG_IR & 0xf)); /* HJB 990403 */ +} + + +M68KMAKE_OP(trapt, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapt, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 2; // JFF else stackframe & return addresses are incorrect + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapt, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 4; // JFF else stackframe & return addresses are incorrect + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 2; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapf, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 4; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 0, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + if(M68KMAKE_CC) + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 16, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 2; /* JFF increase before or 1) stackframe is incorrect 2) RTE address is wrong if trap is taken */ + if(M68KMAKE_CC) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapcc, 32, ., .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + REG_PC += 4; /* JFF increase before or 1) stackframe is incorrect 2) RTE address is wrong if trap is taken */ + if(M68KMAKE_CC) + { + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ + return; + } + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(trapv, 0, ., .) +{ + if(COND_VC()) + { + return; + } + m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ +} + + +M68KMAKE_OP(tst, 8, ., d) +{ + uint res = MASK_OUT_ABOVE_8(DY); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 8, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_8; + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 8, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 8, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 8, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_8(); + + FLAG_N = NFLAG_8(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., d) +{ + uint res = MASK_OUT_ABOVE_16(DY); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 16, ., a) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = MAKE_INT_16(AY); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_16; + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 16, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 16, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_16(); + + FLAG_N = NFLAG_16(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., d) +{ + uint res = DY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 32, ., a) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = AY; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., .) +{ + uint res = M68KMAKE_GET_OPER_AY_32; + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; +} + + +M68KMAKE_OP(tst, 32, ., pcdi) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCDI_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., pcix) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_PCIX_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(tst, 32, ., i) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint res = OPER_I_32(); + + FLAG_N = NFLAG_32(res); + FLAG_Z = res; + FLAG_V = VFLAG_CLEAR; + FLAG_C = CFLAG_CLEAR; + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unlk, 32, ., a7) +{ + REG_A[7] = m68ki_read_32(REG_A[7]); +} + + +M68KMAKE_OP(unlk, 32, ., .) +{ + uint* r_dst = &AY; + + REG_A[7] = *r_dst; + *r_dst = m68ki_pull_32(); +} + + +M68KMAKE_OP(unpk, 16, rr, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: DX and DY are reversed in Motorola's docs */ + uint src = DY; + uint* r_dst = &DX; + + *r_dst = MASK_OUT_BELOW_16(*r_dst) | (((((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16()) & 0xffff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, ax7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_AY_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, ay7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_A7_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, axy7) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + uint src = OPER_A7_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_A7_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + +M68KMAKE_OP(unpk, 16, mm, .) +{ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Note: AX and AY are reversed in Motorola's docs */ + uint src = OPER_AY_PD_8(); + uint ea_dst; + + src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, (src >> 8) & 0xff); + ea_dst = EA_AX_PD_8(); + m68ki_write_8(ea_dst, src & 0xff); + return; + } + m68ki_exception_illegal(); +} + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +M68KMAKE_END diff --git a/AltairZ80/m68k/m68kasm.c b/AltairZ80/m68k/m68kasm.c index 4158ece7..2fac834c 100644 --- a/AltairZ80/m68k/m68kasm.c +++ b/AltairZ80/m68k/m68kasm.c @@ -1,4052 +1,4052 @@ -/* A Bison parser, made by GNU Bison 3.6.2. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, - Inc. - - 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 3 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, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Bison version. */ -#define YYBISON_VERSION "3.6.2" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* First part of user prologue. */ -#line 1 "m68kasm.y" - - -/* m68k_parse.c: line assembler for generic m68k_cpu - - - - Copyright (c) 2009-2010, Holger Veit - - - - Permission is hereby granted, free of charge, to any person obtaining a - - copy of this software and associated documentation files (the "Software"), - - to deal in the Software without restriction, including without limitation - - the rights to use, copy, modify, merge, publish, distribute, sublicense, - - and/or sell copies of the Software, and to permit persons to whom the - - Software is furnished to do so, subject to the following conditions: - - - - The above copyright notice and this permission notice shall be included in - - all copies or substantial portions of the Software. - - - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - - HOLGER VEIT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - - IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - - Except as contained in this notice, the name of Holger Veit et al shall not be - - used in advertising or otherwise to promote the sale, use or other dealings - - in this Software without prior written authorization from Holger Veit et al. - - - - 04-Oct-09 HV Initial version - - 20-Sep-14 PS Adapted for AltairZ80 - - - - use "bison m68kasm.y -o m68kasm.c" to create m68kasm.c - -*/ - - - -#include "sim_defs.h" - -#include - -#include - - - -struct _ea { - - int ea; - - int cnt; - - t_value arg[10]; - -}; - -struct _rea { - - int reg; - - struct _ea ea; - -}; - -struct _mask { - - int x; - - int d; - -}; - -struct _brop { - - int opc; - - int len; - -}; - - - -static int oplen; - -const static int movemx[] = { 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, - - 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080 }; - -const static int movemd[] = { 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001, - - 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100 }; - -static int yyrc; - -static int yyerrc; - -static int yylex(void); - -static int _genop(t_value arg); - -static int _genea(struct _ea arg); - -static int _genbr(t_value arg,t_value,int); - -static void yyerror(char* s); - - - -#define YYDEBUG 1 - - -#line 141 "m68kasm.c" - -# ifndef YY_CAST -# ifdef __cplusplus -# define YY_CAST(Type, Val) static_cast (Val) -# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) -# else -# define YY_CAST(Type, Val) ((Type) (Val)) -# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) -# endif -# endif -# ifndef YY_NULLPTR -# if defined __cplusplus -# if 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# else -# define YY_NULLPTR ((void*)0) -# endif -# endif - - -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token kinds. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - YYEMPTY = -2, - YYEOF = 0, /* "end of file" */ - YYerror = 256, /* error */ - YYUNDEF = 257, /* "invalid token" */ - A0 = 258, /* A0 */ - A1 = 259, /* A1 */ - A2 = 260, /* A2 */ - A3 = 261, /* A3 */ - A4 = 262, /* A4 */ - A5 = 263, /* A5 */ - A6 = 264, /* A6 */ - A7 = 265, /* A7 */ - D0 = 266, /* D0 */ - D1 = 267, /* D1 */ - D2 = 268, /* D2 */ - D3 = 269, /* D3 */ - D4 = 270, /* D4 */ - D5 = 271, /* D5 */ - D6 = 272, /* D6 */ - D7 = 273, /* D7 */ - CCR = 274, /* CCR */ - SR = 275, /* SR */ - USP = 276, /* USP */ - PC = 277, /* PC */ - NUMBER = 278, /* NUMBER */ - ABCD = 279, /* ABCD */ - ADD = 280, /* ADD */ - ADDA = 281, /* ADDA */ - ADDI = 282, /* ADDI */ - ADDQ = 283, /* ADDQ */ - ADDX = 284, /* ADDX */ - AND = 285, /* AND */ - ANDI = 286, /* ANDI */ - OR = 287, /* OR */ - ORI = 288, /* ORI */ - SBCD = 289, /* SBCD */ - SUB = 290, /* SUB */ - SUBA = 291, /* SUBA */ - SUBI = 292, /* SUBI */ - SUBQ = 293, /* SUBQ */ - SUBX = 294, /* SUBX */ - ASL = 295, /* ASL */ - ASR = 296, /* ASR */ - LSL = 297, /* LSL */ - LSR = 298, /* LSR */ - ROL = 299, /* ROL */ - ROR = 300, /* ROR */ - ROXL = 301, /* ROXL */ - ROXR = 302, /* ROXR */ - BCC = 303, /* BCC */ - BCS = 304, /* BCS */ - BEQ = 305, /* BEQ */ - BGE = 306, /* BGE */ - BGT = 307, /* BGT */ - BHI = 308, /* BHI */ - BLE = 309, /* BLE */ - BLS = 310, /* BLS */ - BLT = 311, /* BLT */ - BMI = 312, /* BMI */ - BNE = 313, /* BNE */ - BPL = 314, /* BPL */ - BVC = 315, /* BVC */ - BVS = 316, /* BVS */ - BSR = 317, /* BSR */ - BRA = 318, /* BRA */ - BCLR = 319, /* BCLR */ - BSET = 320, /* BSET */ - BCHG = 321, /* BCHG */ - BTST = 322, /* BTST */ - CHK = 323, /* CHK */ - CMP = 324, /* CMP */ - CMPA = 325, /* CMPA */ - CMPI = 326, /* CMPI */ - CMPM = 327, /* CMPM */ - EOR = 328, /* EOR */ - EORI = 329, /* EORI */ - EXG = 330, /* EXG */ - EXT = 331, /* EXT */ - DIVU = 332, /* DIVU */ - DIVS = 333, /* DIVS */ - MULU = 334, /* MULU */ - MULS = 335, /* MULS */ - DBCC = 336, /* DBCC */ - DBCS = 337, /* DBCS */ - DBEQ = 338, /* DBEQ */ - DBF = 339, /* DBF */ - DBGE = 340, /* DBGE */ - DBGT = 341, /* DBGT */ - DBHI = 342, /* DBHI */ - DBLE = 343, /* DBLE */ - DBLS = 344, /* DBLS */ - DBLT = 345, /* DBLT */ - DBMI = 346, /* DBMI */ - DBNE = 347, /* DBNE */ - DBPL = 348, /* DBPL */ - DBT = 349, /* DBT */ - DBVC = 350, /* DBVC */ - DBVS = 351, /* DBVS */ - SCC = 352, /* SCC */ - SCS = 353, /* SCS */ - SEQ = 354, /* SEQ */ - SF = 355, /* SF */ - SGE = 356, /* SGE */ - SGT = 357, /* SGT */ - SHI = 358, /* SHI */ - SLE = 359, /* SLE */ - SLS = 360, /* SLS */ - SLT = 361, /* SLT */ - SMI = 362, /* SMI */ - SNE = 363, /* SNE */ - SPL = 364, /* SPL */ - ST = 365, /* ST */ - SVC = 366, /* SVC */ - SVS = 367, /* SVS */ - ILLEGAL = 368, /* ILLEGAL */ - NOP = 369, /* NOP */ - RESET = 370, /* RESET */ - RTE = 371, /* RTE */ - RTR = 372, /* RTR */ - RTS = 373, /* RTS */ - TRAPV = 374, /* TRAPV */ - JMP = 375, /* JMP */ - JSR = 376, /* JSR */ - LEA = 377, /* LEA */ - LINK = 378, /* LINK */ - MOVE = 379, /* MOVE */ - MOVEA = 380, /* MOVEA */ - MOVEM = 381, /* MOVEM */ - MOVEP = 382, /* MOVEP */ - MOVEQ = 383, /* MOVEQ */ - CLR = 384, /* CLR */ - NEG = 385, /* NEG */ - NEGX = 386, /* NEGX */ - NBCD = 387, /* NBCD */ - NOT = 388, /* NOT */ - PEA = 389, /* PEA */ - STOP = 390, /* STOP */ - TAS = 391, /* TAS */ - SWAP = 392, /* SWAP */ - TRAP = 393, /* TRAP */ - TST = 394, /* TST */ - UNLK = 395, /* UNLK */ - PREDEC = 396, /* PREDEC */ - POSTINC = 397, /* POSTINC */ - BSIZE = 398, /* BSIZE */ - WSIZE = 399, /* WSIZE */ - LSIZE = 400, /* LSIZE */ - SSIZE = 401 /* SSIZE */ - }; - typedef enum yytokentype yytoken_kind_t; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -union YYSTYPE -{ -#line 71 "m68kasm.y" - - - int rc; - - int reg; - - int wl; - - int opc; - - struct _ea ea; - - t_value num; - - struct _rea rea; - - struct _mask mask; - - struct _brop brop; - - -#line 346 "m68kasm.c" - -}; -typedef union YYSTYPE YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - -extern YYSTYPE yylval; - -int yyparse (void); - - -/* Symbol kind. */ -enum yysymbol_kind_t -{ - YYSYMBOL_YYEMPTY = -2, - YYSYMBOL_YYEOF = 0, /* "end of file" */ - YYSYMBOL_YYerror = 1, /* error */ - YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ - YYSYMBOL_A0 = 3, /* A0 */ - YYSYMBOL_A1 = 4, /* A1 */ - YYSYMBOL_A2 = 5, /* A2 */ - YYSYMBOL_A3 = 6, /* A3 */ - YYSYMBOL_A4 = 7, /* A4 */ - YYSYMBOL_A5 = 8, /* A5 */ - YYSYMBOL_A6 = 9, /* A6 */ - YYSYMBOL_A7 = 10, /* A7 */ - YYSYMBOL_D0 = 11, /* D0 */ - YYSYMBOL_D1 = 12, /* D1 */ - YYSYMBOL_D2 = 13, /* D2 */ - YYSYMBOL_D3 = 14, /* D3 */ - YYSYMBOL_D4 = 15, /* D4 */ - YYSYMBOL_D5 = 16, /* D5 */ - YYSYMBOL_D6 = 17, /* D6 */ - YYSYMBOL_D7 = 18, /* D7 */ - YYSYMBOL_CCR = 19, /* CCR */ - YYSYMBOL_SR = 20, /* SR */ - YYSYMBOL_USP = 21, /* USP */ - YYSYMBOL_PC = 22, /* PC */ - YYSYMBOL_NUMBER = 23, /* NUMBER */ - YYSYMBOL_ABCD = 24, /* ABCD */ - YYSYMBOL_ADD = 25, /* ADD */ - YYSYMBOL_ADDA = 26, /* ADDA */ - YYSYMBOL_ADDI = 27, /* ADDI */ - YYSYMBOL_ADDQ = 28, /* ADDQ */ - YYSYMBOL_ADDX = 29, /* ADDX */ - YYSYMBOL_AND = 30, /* AND */ - YYSYMBOL_ANDI = 31, /* ANDI */ - YYSYMBOL_OR = 32, /* OR */ - YYSYMBOL_ORI = 33, /* ORI */ - YYSYMBOL_SBCD = 34, /* SBCD */ - YYSYMBOL_SUB = 35, /* SUB */ - YYSYMBOL_SUBA = 36, /* SUBA */ - YYSYMBOL_SUBI = 37, /* SUBI */ - YYSYMBOL_SUBQ = 38, /* SUBQ */ - YYSYMBOL_SUBX = 39, /* SUBX */ - YYSYMBOL_ASL = 40, /* ASL */ - YYSYMBOL_ASR = 41, /* ASR */ - YYSYMBOL_LSL = 42, /* LSL */ - YYSYMBOL_LSR = 43, /* LSR */ - YYSYMBOL_ROL = 44, /* ROL */ - YYSYMBOL_ROR = 45, /* ROR */ - YYSYMBOL_ROXL = 46, /* ROXL */ - YYSYMBOL_ROXR = 47, /* ROXR */ - YYSYMBOL_BCC = 48, /* BCC */ - YYSYMBOL_BCS = 49, /* BCS */ - YYSYMBOL_BEQ = 50, /* BEQ */ - YYSYMBOL_BGE = 51, /* BGE */ - YYSYMBOL_BGT = 52, /* BGT */ - YYSYMBOL_BHI = 53, /* BHI */ - YYSYMBOL_BLE = 54, /* BLE */ - YYSYMBOL_BLS = 55, /* BLS */ - YYSYMBOL_BLT = 56, /* BLT */ - YYSYMBOL_BMI = 57, /* BMI */ - YYSYMBOL_BNE = 58, /* BNE */ - YYSYMBOL_BPL = 59, /* BPL */ - YYSYMBOL_BVC = 60, /* BVC */ - YYSYMBOL_BVS = 61, /* BVS */ - YYSYMBOL_BSR = 62, /* BSR */ - YYSYMBOL_BRA = 63, /* BRA */ - YYSYMBOL_BCLR = 64, /* BCLR */ - YYSYMBOL_BSET = 65, /* BSET */ - YYSYMBOL_BCHG = 66, /* BCHG */ - YYSYMBOL_BTST = 67, /* BTST */ - YYSYMBOL_CHK = 68, /* CHK */ - YYSYMBOL_CMP = 69, /* CMP */ - YYSYMBOL_CMPA = 70, /* CMPA */ - YYSYMBOL_CMPI = 71, /* CMPI */ - YYSYMBOL_CMPM = 72, /* CMPM */ - YYSYMBOL_EOR = 73, /* EOR */ - YYSYMBOL_EORI = 74, /* EORI */ - YYSYMBOL_EXG = 75, /* EXG */ - YYSYMBOL_EXT = 76, /* EXT */ - YYSYMBOL_DIVU = 77, /* DIVU */ - YYSYMBOL_DIVS = 78, /* DIVS */ - YYSYMBOL_MULU = 79, /* MULU */ - YYSYMBOL_MULS = 80, /* MULS */ - YYSYMBOL_DBCC = 81, /* DBCC */ - YYSYMBOL_DBCS = 82, /* DBCS */ - YYSYMBOL_DBEQ = 83, /* DBEQ */ - YYSYMBOL_DBF = 84, /* DBF */ - YYSYMBOL_DBGE = 85, /* DBGE */ - YYSYMBOL_DBGT = 86, /* DBGT */ - YYSYMBOL_DBHI = 87, /* DBHI */ - YYSYMBOL_DBLE = 88, /* DBLE */ - YYSYMBOL_DBLS = 89, /* DBLS */ - YYSYMBOL_DBLT = 90, /* DBLT */ - YYSYMBOL_DBMI = 91, /* DBMI */ - YYSYMBOL_DBNE = 92, /* DBNE */ - YYSYMBOL_DBPL = 93, /* DBPL */ - YYSYMBOL_DBT = 94, /* DBT */ - YYSYMBOL_DBVC = 95, /* DBVC */ - YYSYMBOL_DBVS = 96, /* DBVS */ - YYSYMBOL_SCC = 97, /* SCC */ - YYSYMBOL_SCS = 98, /* SCS */ - YYSYMBOL_SEQ = 99, /* SEQ */ - YYSYMBOL_SF = 100, /* SF */ - YYSYMBOL_SGE = 101, /* SGE */ - YYSYMBOL_SGT = 102, /* SGT */ - YYSYMBOL_SHI = 103, /* SHI */ - YYSYMBOL_SLE = 104, /* SLE */ - YYSYMBOL_SLS = 105, /* SLS */ - YYSYMBOL_SLT = 106, /* SLT */ - YYSYMBOL_SMI = 107, /* SMI */ - YYSYMBOL_SNE = 108, /* SNE */ - YYSYMBOL_SPL = 109, /* SPL */ - YYSYMBOL_ST = 110, /* ST */ - YYSYMBOL_SVC = 111, /* SVC */ - YYSYMBOL_SVS = 112, /* SVS */ - YYSYMBOL_ILLEGAL = 113, /* ILLEGAL */ - YYSYMBOL_NOP = 114, /* NOP */ - YYSYMBOL_RESET = 115, /* RESET */ - YYSYMBOL_RTE = 116, /* RTE */ - YYSYMBOL_RTR = 117, /* RTR */ - YYSYMBOL_RTS = 118, /* RTS */ - YYSYMBOL_TRAPV = 119, /* TRAPV */ - YYSYMBOL_JMP = 120, /* JMP */ - YYSYMBOL_JSR = 121, /* JSR */ - YYSYMBOL_LEA = 122, /* LEA */ - YYSYMBOL_LINK = 123, /* LINK */ - YYSYMBOL_MOVE = 124, /* MOVE */ - YYSYMBOL_MOVEA = 125, /* MOVEA */ - YYSYMBOL_MOVEM = 126, /* MOVEM */ - YYSYMBOL_MOVEP = 127, /* MOVEP */ - YYSYMBOL_MOVEQ = 128, /* MOVEQ */ - YYSYMBOL_CLR = 129, /* CLR */ - YYSYMBOL_NEG = 130, /* NEG */ - YYSYMBOL_NEGX = 131, /* NEGX */ - YYSYMBOL_NBCD = 132, /* NBCD */ - YYSYMBOL_NOT = 133, /* NOT */ - YYSYMBOL_PEA = 134, /* PEA */ - YYSYMBOL_STOP = 135, /* STOP */ - YYSYMBOL_TAS = 136, /* TAS */ - YYSYMBOL_SWAP = 137, /* SWAP */ - YYSYMBOL_TRAP = 138, /* TRAP */ - YYSYMBOL_TST = 139, /* TST */ - YYSYMBOL_UNLK = 140, /* UNLK */ - YYSYMBOL_PREDEC = 141, /* PREDEC */ - YYSYMBOL_POSTINC = 142, /* POSTINC */ - YYSYMBOL_BSIZE = 143, /* BSIZE */ - YYSYMBOL_WSIZE = 144, /* WSIZE */ - YYSYMBOL_LSIZE = 145, /* LSIZE */ - YYSYMBOL_SSIZE = 146, /* SSIZE */ - YYSYMBOL_147_ = 147, /* '#' */ - YYSYMBOL_148_ = 148, /* ',' */ - YYSYMBOL_149_ = 149, /* '/' */ - YYSYMBOL_150_ = 150, /* '-' */ - YYSYMBOL_151_ = 151, /* '(' */ - YYSYMBOL_152_ = 152, /* ')' */ - YYSYMBOL_YYACCEPT = 153, /* $accept */ - YYSYMBOL_stmt = 154, /* stmt */ - YYSYMBOL_arop = 155, /* arop */ - YYSYMBOL_bcdop = 156, /* bcdop */ - YYSYMBOL_dualop = 157, /* dualop */ - YYSYMBOL_immop = 158, /* immop */ - YYSYMBOL_immop2 = 159, /* immop2 */ - YYSYMBOL_qop = 160, /* qop */ - YYSYMBOL_shftop = 161, /* shftop */ - YYSYMBOL_brop = 162, /* brop */ - YYSYMBOL_btop = 163, /* btop */ - YYSYMBOL_monop = 164, /* monop */ - YYSYMBOL_mdop = 165, /* mdop */ - YYSYMBOL_dbop = 166, /* dbop */ - YYSYMBOL_direct = 167, /* direct */ - YYSYMBOL_jop = 168, /* jop */ - YYSYMBOL_shftarg = 169, /* shftarg */ - YYSYMBOL_bcdarg = 170, /* bcdarg */ - YYSYMBOL_dualarg = 171, /* dualarg */ - YYSYMBOL_areg = 172, /* areg */ - YYSYMBOL_dreg = 173, /* dreg */ - YYSYMBOL_szs = 174, /* szs */ - YYSYMBOL_szwl = 175, /* szwl */ - YYSYMBOL_szbwl = 176, /* szbwl */ - YYSYMBOL_szmv = 177, /* szmv */ - YYSYMBOL_szm = 178, /* szm */ - YYSYMBOL_reglist = 179, /* reglist */ - YYSYMBOL_regs = 180, /* regs */ - YYSYMBOL_eama = 181, /* eama */ - YYSYMBOL_eaa = 182, /* eaa */ - YYSYMBOL_ead = 183, /* ead */ - YYSYMBOL_eaall = 184, /* eaall */ - YYSYMBOL_eada = 185, /* eada */ - YYSYMBOL_eadas = 186, /* eadas */ - YYSYMBOL_eac = 187, /* eac */ - YYSYMBOL_eacai = 188, /* eacai */ - YYSYMBOL_eacad = 189, /* eacad */ - YYSYMBOL_ea0 = 190, /* ea0 */ - YYSYMBOL_ea1 = 191, /* ea1 */ - YYSYMBOL_ea2 = 192, /* ea2 */ - YYSYMBOL_ea3 = 193, /* ea3 */ - YYSYMBOL_ea4 = 194, /* ea4 */ - YYSYMBOL_ea5 = 195, /* ea5 */ - YYSYMBOL_ea6 = 196, /* ea6 */ - YYSYMBOL_ea70 = 197, /* ea70 */ - YYSYMBOL_ea72 = 198, /* ea72 */ - YYSYMBOL_ea73 = 199, /* ea73 */ - YYSYMBOL_ea74 = 200, /* ea74 */ - YYSYMBOL_easr = 201 /* easr */ -}; -typedef enum yysymbol_kind_t yysymbol_kind_t; - - - - -#ifdef short -# undef short -#endif - -/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure - and (if available) are included - so that the code can choose integer types of a good width. */ - -#ifndef __PTRDIFF_MAX__ -# include /* INFRINGES ON USER NAME SPACE */ -# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_STDINT_H -# endif -#endif - -/* Narrow types that promote to a signed type and that can represent a - signed or unsigned integer of at least N bits. In tables they can - save space and decrease cache pressure. Promoting to a signed type - helps avoid bugs in integer arithmetic. */ - -#ifdef __INT_LEAST8_MAX__ -typedef __INT_LEAST8_TYPE__ yytype_int8; -#elif defined YY_STDINT_H -typedef int_least8_t yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef __INT_LEAST16_MAX__ -typedef __INT_LEAST16_TYPE__ yytype_int16; -#elif defined YY_STDINT_H -typedef int_least16_t yytype_int16; -#else -typedef short yytype_int16; -#endif - -#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST8_TYPE__ yytype_uint8; -#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST8_MAX <= INT_MAX) -typedef uint_least8_t yytype_uint8; -#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX -typedef unsigned char yytype_uint8; -#else -typedef short yytype_uint8; -#endif - -#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST16_TYPE__ yytype_uint16; -#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST16_MAX <= INT_MAX) -typedef uint_least16_t yytype_uint16; -#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX -typedef unsigned short yytype_uint16; -#else -typedef int yytype_uint16; -#endif - -#ifndef YYPTRDIFF_T -# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ -# define YYPTRDIFF_T __PTRDIFF_TYPE__ -# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ -# elif defined PTRDIFF_MAX -# ifndef ptrdiff_t -# include /* INFRINGES ON USER NAME SPACE */ -# endif -# define YYPTRDIFF_T ptrdiff_t -# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX -# else -# define YYPTRDIFF_T long -# define YYPTRDIFF_MAXIMUM LONG_MAX -# endif -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned -# endif -#endif - -#define YYSIZE_MAXIMUM \ - YY_CAST (YYPTRDIFF_T, \ - (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ - ? YYPTRDIFF_MAXIMUM \ - : YY_CAST (YYSIZE_T, -1))) - -#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) - - -/* Stored state numbers (used for stacks). */ -typedef yytype_int16 yy_state_t; - -/* State numbers in computations. */ -typedef int yy_state_fast_t; - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - - -#ifndef YY_ATTRIBUTE_PURE -# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# else -# define YY_ATTRIBUTE_PURE -# endif -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -# else -# define YY_ATTRIBUTE_UNUSED -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) -#else -# define YYUSE(E) /* empty */ -#endif - -#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - -#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ -# define YY_IGNORE_USELESS_CAST_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") -# define YY_IGNORE_USELESS_CAST_END \ - _Pragma ("GCC diagnostic pop") -#endif -#ifndef YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_END -#endif - - -#define YY_ASSERT(E) ((void) (0 && (E))) - -#if !defined yyoverflow - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* !defined yyoverflow */ - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yy_state_t yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYPTRDIFF_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / YYSIZEOF (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYPTRDIFF_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 266 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 928 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 153 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 49 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 276 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 462 - -#define YYMAXUTOK 401 - - -/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, with out-of-bounds checking. */ -#define YYTRANSLATE(YYX) \ - (0 <= (YYX) && (YYX) <= YYMAXUTOK \ - ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ - : YYSYMBOL_YYUNDEF) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex. */ -static const yytype_uint8 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 147, 2, 2, 2, 2, - 151, 152, 2, 2, 148, 150, 2, 149, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146 -}; - -#if YYDEBUG - /* YYRLINEYYN -- Source line where rule number YYN was defined. */ -static const yytype_int16 yyrline[] = -{ - 0, 112, 112, 113, 114, 116, 117, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 160, 161, 164, 165, 166, 167, 171, - 172, 173, 174, 178, 179, 180, 184, 185, 186, 190, - 191, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 249, - 250, 251, 252, 256, 257, 258, 259, 260, 261, 262, - 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, - 273, 274, 275, 276, 277, 278, 282, 283, 284, 285, - 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 308, 309, 310, 311, - 312, 313, 314, 318, 319, 320, 323, 324, 327, 328, - 331, 334, 337, 338, 339, 340, 341, 342, 343, 344, - 347, 348, 349, 350, 351, 352, 353, 354, 357, 360, - 361, 364, 365, 366, 369, 370, 371, 374, 375, 378, - 379, 382, 383, 384, 386, 390, 390, 390, 390, 390, - 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, - 391, 391, 391, 392, 392, 392, 392, 392, 392, 392, - 392, 392, 392, 393, 393, 394, 394, 394, 394, 394, - 394, 394, 395, 395, 396, 396, 396, 396, 396, 396, - 397, 397, 397, 397, 397, 398, 398, 398, 398, 398, - 401, 403, 405, 407, 409, 411, 413, 415, 418, 420, - 423, 424, 426, 428, 431, 435, 436 -}; -#endif - -/** Accessing symbol of state STATE. */ -#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) - -#if YYDEBUG || 0 -/* The user-facing name of the symbol whose (internal) number is - YYSYMBOL. No bounds checking. */ -static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; - -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "\"end of file\"", "error", "\"invalid token\"", "A0", "A1", "A2", "A3", - "A4", "A5", "A6", "A7", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", - "CCR", "SR", "USP", "PC", "NUMBER", "ABCD", "ADD", "ADDA", "ADDI", - "ADDQ", "ADDX", "AND", "ANDI", "OR", "ORI", "SBCD", "SUB", "SUBA", - "SUBI", "SUBQ", "SUBX", "ASL", "ASR", "LSL", "LSR", "ROL", "ROR", "ROXL", - "ROXR", "BCC", "BCS", "BEQ", "BGE", "BGT", "BHI", "BLE", "BLS", "BLT", - "BMI", "BNE", "BPL", "BVC", "BVS", "BSR", "BRA", "BCLR", "BSET", "BCHG", - "BTST", "CHK", "CMP", "CMPA", "CMPI", "CMPM", "EOR", "EORI", "EXG", - "EXT", "DIVU", "DIVS", "MULU", "MULS", "DBCC", "DBCS", "DBEQ", "DBF", - "DBGE", "DBGT", "DBHI", "DBLE", "DBLS", "DBLT", "DBMI", "DBNE", "DBPL", - "DBT", "DBVC", "DBVS", "SCC", "SCS", "SEQ", "SF", "SGE", "SGT", "SHI", - "SLE", "SLS", "SLT", "SMI", "SNE", "SPL", "ST", "SVC", "SVS", "ILLEGAL", - "NOP", "RESET", "RTE", "RTR", "RTS", "TRAPV", "JMP", "JSR", "LEA", - "LINK", "MOVE", "MOVEA", "MOVEM", "MOVEP", "MOVEQ", "CLR", "NEG", "NEGX", - "NBCD", "NOT", "PEA", "STOP", "TAS", "SWAP", "TRAP", "TST", "UNLK", - "PREDEC", "POSTINC", "BSIZE", "WSIZE", "LSIZE", "SSIZE", "'#'", "','", - "'/'", "'-'", "'('", "')'", "$accept", "stmt", "arop", "bcdop", "dualop", - "immop", "immop2", "qop", "shftop", "brop", "btop", "monop", "mdop", - "dbop", "direct", "jop", "shftarg", "bcdarg", "dualarg", "areg", "dreg", - "szs", "szwl", "szbwl", "szmv", "szm", "reglist", "regs", "eama", "eaa", - "ead", "eaall", "eada", "eadas", "eac", "eacai", "eacad", "ea0", "ea1", - "ea2", "ea3", "ea4", "ea5", "ea6", "ea70", "ea72", "ea73", "ea74", - "easr", YY_NULLPTR -}; - -static const char * -yysymbol_name (yysymbol_kind_t yysymbol) -{ - return yytname[yysymbol]; -} -#endif - -#ifdef YYPRINT -/* YYTOKNUM[NUM] -- (External) token number corresponding to the - (internal) symbol number NUM (which must be that of a token). */ -static const yytype_int16 yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, 35, 44, 47, - 45, 40, 41 -}; -#endif - -#define YYPACT_NINF (-343) - -#define yypact_value_is_default(Yyn) \ - ((Yyn) == YYPACT_NINF) - -#define YYTABLE_NINF (-1) - -#define yytable_value_is_error(Yyn) \ - 0 - - /* YYPACTSTATE-NUM -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - 675, -343, -126, -343, -126, -126, -126, -126, -126, -126, - -126, -343, -126, -343, -126, -126, -126, 456, 456, 456, - 456, 456, 456, 456, 456, -139, -139, -139, -139, -139, - -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, - -139, -343, -343, -343, -343, 477, -126, -107, -126, -126, - -126, -126, 626, -107, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, -343, -343, -343, -20, - 642, 141, -105, -107, -107, -137, -126, -126, -126, -343, - -126, -343, -82, -343, 646, -80, -126, 642, 72, -107, - 557, 18, -72, -65, -50, -343, 78, 31, 76, 477, - 646, -343, -20, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, -343, 642, 85, 203, - -343, 236, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, 236, -343, 236, -343, 236, -343, 236, - -343, 236, -343, 236, -343, 236, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -37, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, 18, -343, -343, 18, -343, -42, - 646, -343, -36, -35, 646, 203, -32, -343, -343, -343, - -343, -343, -343, -29, -27, -19, -343, -343, -343, -13, - 18, -343, -343, 76, 538, 41, 92, -343, -343, -343, - -343, 100, -343, 113, -343, -343, -343, 18, -343, -10, - -9, -343, -8, -7, 119, 120, 129, -343, 131, 8, - 581, -343, -343, -343, -343, -343, -343, -343, -343, 15, - 16, -343, 19, -343, -143, -138, 149, -343, 25, -343, - -343, -343, -343, -343, -343, -343, 646, -343, 27, -343, - 29, 642, 32, 33, 626, 626, -343, 22, 642, 37, - 76, 642, 155, 39, 40, 35, 36, 43, 45, 47, - -343, -343, -343, -343, -343, 166, 51, 54, 57, -343, - -343, 66, 646, 77, 515, 646, 71, 73, 74, 83, - 76, -84, 646, 197, -343, 605, -107, -343, -343, 84, - 646, -343, 646, 642, 93, -42, 76, -343, -343, -343, - -343, -343, 211, -343, -343, -343, 546, 642, 642, 646, - -135, 626, 626, 90, 88, 646, 646, 642, -343, -343, - -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, - 76, 546, 515, 76, -343, 642, -343, -343, -68, -67, - -343, 646, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, 581, -343, -343, -343, - -343, -343, -343, -343, -343, 642, -343, -343, -343, -343, - -343, -343, -343, -343, 626, -343, 626, -343, -343, 91, - -107, -107, -107, -107, 104, 106, 107, 109, -343, -343, - -343, -343 -}; - - /* YYDEFACTSTATE-NUM -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_int16 yydefact[] = -{ - 0, 45, 0, 43, 0, 0, 0, 0, 0, 0, - 0, 47, 0, 44, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 110, 111, 109, 112, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 137, 136, 139, 138, 140, 141, - 142, 154, 143, 144, 145, 146, 147, 148, 149, 150, - 151, 155, 152, 153, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, - 0, 165, 0, 134, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, - 0, 24, 0, 191, 192, 193, 49, 53, 59, 46, - 50, 56, 51, 58, 52, 55, 60, 48, 172, 173, - 174, 175, 176, 177, 178, 179, 271, 0, 0, 0, - 261, 0, 61, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 0, 63, 0, 65, 0, 67, 0, - 69, 0, 71, 0, 73, 0, 75, 188, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 180, 181, 182, 183, 184, 185, - 186, 187, 260, 0, 223, 224, 225, 226, 227, 228, - 229, 230, 231, 232, 0, 189, 190, 0, 54, 0, - 0, 57, 0, 0, 0, 0, 0, 244, 245, 246, - 247, 248, 249, 0, 0, 0, 194, 195, 196, 0, - 0, 197, 198, 0, 0, 0, 0, 113, 115, 116, - 117, 0, 40, 0, 135, 42, 1, 0, 2, 0, - 0, 3, 0, 0, 0, 0, 0, 8, 0, 0, - 0, 12, 235, 236, 237, 238, 239, 240, 241, 0, - 0, 25, 0, 274, 0, 0, 0, 62, 0, 64, - 66, 68, 70, 72, 74, 76, 0, 234, 0, 233, - 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, - 0, 0, 0, 0, 0, 201, 202, 0, 199, 0, - 250, 251, 252, 253, 254, 0, 0, 0, 0, 38, - 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 264, 0, 269, 263, 262, 0, - 0, 11, 0, 0, 0, 0, 0, 20, 21, 22, - 19, 26, 0, 29, 30, 31, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 168, 169, - 170, 215, 216, 217, 218, 219, 220, 221, 222, 171, - 0, 0, 0, 0, 9, 0, 14, 17, 0, 0, - 268, 0, 166, 13, 15, 16, 18, 27, 275, 276, - 242, 28, 243, 32, 203, 204, 0, 33, 255, 256, - 257, 258, 259, 200, 34, 0, 35, 36, 37, 39, - 4, 6, 5, 10, 0, 270, 0, 265, 167, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 273, 272, - 267, 266 -}; - - /* YYPGOTONTERM-NUM. */ -static const yytype_int16 yypgoto[] = -{ - -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, - -343, -343, -343, -343, -343, -343, 248, -343, -343, -39, - -51, 811, -53, 812, -343, -343, -276, -343, 559, -162, - 115, -150, -120, -159, 128, -343, -343, -34, -342, -25, - 108, 137, -30, 38, 69, 26, 28, -33, -343 -}; - - /* YYDEFGOTONTERM-NUM. */ -static const yytype_int16 yydefgoto[] = -{ - -1, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 297, 268, 271, 160, - 212, 188, 227, 136, 250, 253, 327, 328, 307, 390, - 213, 308, 420, 421, 236, 329, 427, 282, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 422 -}; - - /* YYTABLEYYPACT[STATE-NUM] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 234, 233, 392, 156, 357, 355, 157, 187, 281, 356, - 256, 214, 223, 232, 358, 218, 426, 133, 134, 135, - 215, 148, 149, 150, 151, 152, 153, 154, 155, 204, - 205, 206, 207, 208, 209, 210, 211, 225, 226, 251, - 252, 156, 204, 205, 206, 207, 208, 209, 210, 211, - 254, 255, 204, 205, 206, 207, 208, 209, 210, 211, - 392, 243, 249, 262, 405, 261, 267, 263, 356, 238, - 272, 221, 266, 222, 237, 274, 279, 310, 265, 290, - 444, 446, 275, 219, 445, 447, 269, 204, 205, 206, - 207, 208, 209, 210, 211, 214, 223, 276, 286, 218, - 323, 277, 238, 283, 215, 433, 434, 237, 293, 311, - 298, 306, 314, 315, 220, 338, 318, 341, 292, 319, - 295, 320, 298, 339, 298, 241, 298, 242, 298, 321, - 298, 235, 298, 324, 298, 322, 340, 239, 342, 343, - 344, 345, 346, 347, 148, 149, 150, 151, 152, 153, - 154, 155, 348, 216, 349, 221, 350, 222, 241, 157, - 242, 244, 245, 352, 353, 158, 287, 219, 240, 159, - 239, 354, 359, 360, 358, 362, 375, 363, 278, 313, - 365, 366, 217, 316, 372, 378, 379, 376, 377, 383, - 309, 380, 335, 309, 381, 382, 317, 288, 220, 384, - 373, 240, 385, 326, 336, 386, 148, 149, 150, 151, - 152, 153, 154, 155, 387, 325, 309, 157, 157, 400, - 407, 401, 402, 286, 332, 337, 294, 280, 283, 330, - 404, 403, 411, 309, 417, 357, 284, 216, 435, 335, - 442, 295, 441, 447, 289, 0, 416, 204, 205, 206, - 207, 208, 209, 210, 211, 361, 458, 270, 459, 460, - 291, 461, 0, 368, 370, 285, 217, 0, 0, 0, - 0, 0, 364, 0, 0, 367, 369, 0, 0, 371, - 440, 0, 374, 443, 246, 247, 248, 0, 0, 0, - 286, 287, 333, 0, 399, 283, 0, 0, 0, 0, - 0, 406, 0, 410, 0, 0, 0, 0, 388, 412, - 391, 413, 0, 0, 396, 0, 409, 0, 0, 393, - 286, 0, 288, 334, 414, 283, 0, 0, 425, 0, - 326, 326, 0, 0, 437, 438, 286, 312, 423, 424, - 0, 283, 325, 325, 0, 0, 286, 0, 439, 0, - 430, 283, 0, 0, 436, 428, 0, 0, 287, 0, - 448, 284, 331, 0, 0, 0, 409, 0, 391, 0, - 286, 286, 396, 286, 0, 283, 283, 393, 283, 0, - 0, 0, 397, 296, 0, 0, 0, 317, 287, 288, - 285, 0, 0, 451, 0, 453, 449, 454, 455, 456, - 457, 0, 0, 0, 287, 450, 0, 452, 0, 0, - 0, 0, 0, 398, 287, 0, 0, 0, 431, 288, - 0, 299, 0, 300, 0, 301, 0, 302, 284, 303, - 0, 304, 0, 305, 0, 288, 0, 0, 287, 287, - 397, 287, 0, 0, 0, 288, 0, 0, 0, 432, - 0, 0, 394, 0, 0, 0, 0, 285, 284, 148, - 149, 150, 151, 152, 153, 154, 155, 0, 0, 288, - 288, 398, 288, 415, 284, 0, 0, 0, 0, 156, - 389, 395, 0, 0, 284, 0, 0, 285, 204, 205, - 206, 207, 208, 209, 210, 211, 0, 0, 0, 0, - 156, 0, 0, 285, 0, 0, 0, 0, 284, 284, - 394, 284, 0, 285, 0, 0, 0, 429, 148, 149, - 150, 151, 152, 153, 154, 155, 204, 205, 206, 207, - 208, 209, 210, 211, 0, 0, 0, 285, 285, 395, - 285, 148, 149, 150, 151, 152, 153, 154, 155, 204, - 205, 206, 207, 208, 209, 210, 211, 204, 205, 206, - 207, 208, 209, 210, 211, 418, 419, 0, 204, 205, - 206, 207, 208, 209, 210, 211, 162, 174, 176, 178, - 180, 182, 184, 186, 148, 149, 150, 151, 152, 153, - 154, 155, 0, 0, 0, 0, 0, 157, 0, 133, - 134, 135, 0, 158, 351, 0, 0, 159, 148, 149, - 150, 151, 152, 153, 154, 155, 0, 0, 157, 0, - 0, 0, 0, 0, 158, 0, 0, 408, 159, 148, - 149, 150, 151, 152, 153, 154, 155, 204, 205, 206, - 207, 208, 209, 210, 211, 148, 149, 150, 151, 152, - 153, 154, 155, 0, 0, 0, 157, 204, 205, 206, - 207, 208, 209, 210, 211, 0, 280, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 273, 0, 0, 0, 0, 0, 0, 157, 0, 280, - 0, 0, 0, 0, 0, 0, 0, 280, 157, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 137, 138, 139, 140, - 141, 142, 143, 0, 144, 0, 145, 146, 147, 161, - 173, 175, 177, 179, 181, 183, 185, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 0, 0, 0, 0, 0, 0, 224, 0, - 228, 229, 230, 231, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 257, 258, - 259, 0, 260, 0, 0, 0, 0, 0, 264 -}; - -static const yytype_int16 yycheck[] = -{ - 53, 52, 344, 23, 142, 148, 141, 146, 128, 152, - 147, 45, 45, 52, 152, 45, 151, 143, 144, 145, - 45, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 144, 145, 144, - 145, 23, 11, 12, 13, 14, 15, 16, 17, 18, - 103, 104, 11, 12, 13, 14, 15, 16, 17, 18, - 402, 100, 101, 114, 148, 147, 119, 147, 152, 99, - 121, 45, 0, 45, 99, 147, 127, 227, 117, 130, - 148, 148, 147, 45, 152, 152, 120, 11, 12, 13, - 14, 15, 16, 17, 18, 129, 129, 147, 128, 129, - 250, 23, 132, 128, 129, 381, 382, 132, 23, 151, - 161, 148, 148, 148, 45, 23, 148, 267, 157, 148, - 159, 148, 173, 23, 175, 99, 177, 99, 179, 148, - 181, 151, 183, 253, 185, 148, 23, 99, 148, 148, - 148, 148, 23, 23, 3, 4, 5, 6, 7, 8, - 9, 10, 23, 45, 23, 129, 148, 129, 132, 141, - 132, 20, 21, 148, 148, 147, 128, 129, 99, 151, - 132, 152, 23, 148, 152, 148, 21, 148, 147, 230, - 148, 148, 45, 234, 147, 150, 150, 148, 148, 23, - 224, 148, 151, 227, 149, 148, 235, 128, 129, 148, - 320, 132, 148, 254, 255, 148, 3, 4, 5, 6, - 7, 8, 9, 10, 148, 254, 250, 141, 141, 148, - 23, 148, 148, 253, 254, 255, 23, 151, 253, 254, - 350, 148, 148, 267, 23, 142, 128, 129, 148, 151, - 402, 280, 401, 152, 129, -1, 366, 11, 12, 13, - 14, 15, 16, 17, 18, 306, 152, 120, 152, 152, - 132, 152, -1, 314, 315, 128, 129, -1, -1, -1, - -1, -1, 311, -1, -1, 314, 315, -1, -1, 318, - 400, -1, 321, 403, 143, 144, 145, -1, -1, -1, - 320, 253, 254, -1, 345, 320, -1, -1, -1, -1, - -1, 352, -1, 356, -1, -1, -1, -1, 342, 360, - 344, 362, -1, -1, 344, -1, 355, -1, -1, 344, - 350, -1, 253, 254, 363, 350, -1, -1, 379, -1, - 381, 382, -1, -1, 385, 386, 366, 229, 377, 378, - -1, 366, 381, 382, -1, -1, 376, -1, 387, -1, - 380, 376, -1, -1, 384, 380, -1, -1, 320, -1, - 411, 253, 254, -1, -1, -1, 405, -1, 402, -1, - 400, 401, 402, 403, -1, 400, 401, 402, 403, -1, - -1, -1, 344, 147, -1, -1, -1, 426, 350, 320, - 253, -1, -1, 444, -1, 446, 435, 450, 451, 452, - 453, -1, -1, -1, 366, 444, -1, 446, -1, -1, - -1, -1, -1, 344, 376, -1, -1, -1, 380, 350, - -1, 173, -1, 175, -1, 177, -1, 179, 320, 181, - -1, 183, -1, 185, -1, 366, -1, -1, 400, 401, - 402, 403, -1, -1, -1, 376, -1, -1, -1, 380, - -1, -1, 344, -1, -1, -1, -1, 320, 350, 3, - 4, 5, 6, 7, 8, 9, 10, -1, -1, 400, - 401, 402, 403, 365, 366, -1, -1, -1, -1, 23, - 343, 344, -1, -1, 376, -1, -1, 350, 11, 12, - 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, - 23, -1, -1, 366, -1, -1, -1, -1, 400, 401, - 402, 403, -1, 376, -1, -1, -1, 380, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, -1, -1, -1, 400, 401, 402, - 403, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, -1, 11, 12, - 13, 14, 15, 16, 17, 18, 17, 18, 19, 20, - 21, 22, 23, 24, 3, 4, 5, 6, 7, 8, - 9, 10, -1, -1, -1, -1, -1, 141, -1, 143, - 144, 145, -1, 147, 23, -1, -1, 151, 3, 4, - 5, 6, 7, 8, 9, 10, -1, -1, 141, -1, - -1, -1, -1, -1, 147, -1, -1, 22, 151, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 3, 4, 5, 6, 7, - 8, 9, 10, -1, -1, -1, 141, 11, 12, 13, - 14, 15, 16, 17, 18, -1, 151, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 121, -1, -1, -1, -1, -1, -1, 141, -1, 151, - -1, -1, -1, -1, -1, -1, -1, 151, 141, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 4, 5, 6, 7, - 8, 9, 10, -1, 12, -1, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, -1, -1, -1, -1, -1, -1, 46, -1, - 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 106, 107, - 108, -1, 110, -1, -1, -1, -1, -1, 116 -}; - - /* YYSTOSSTATE-NUM -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const yytype_uint8 yystos[] = -{ - 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, - 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, - 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, - 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 143, 144, 145, 176, 176, 176, 176, - 176, 176, 176, 176, 176, 176, 176, 176, 3, 4, - 5, 6, 7, 8, 9, 10, 23, 141, 147, 151, - 172, 176, 181, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 176, 181, 176, 181, 176, 181, 176, - 181, 176, 181, 176, 181, 176, 181, 146, 174, 174, - 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 174, 174, 11, 12, 13, 14, 15, 16, - 17, 18, 173, 183, 190, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 176, 144, 145, 175, 176, 176, - 176, 176, 172, 173, 175, 151, 187, 192, 195, 196, - 197, 198, 199, 172, 20, 21, 143, 144, 145, 172, - 177, 144, 145, 178, 175, 175, 147, 176, 176, 176, - 176, 147, 173, 147, 176, 172, 0, 175, 170, 190, - 194, 171, 173, 181, 147, 147, 147, 23, 147, 173, - 151, 185, 190, 192, 193, 194, 195, 196, 197, 183, - 173, 187, 172, 23, 23, 172, 147, 169, 173, 169, - 169, 169, 169, 169, 169, 169, 148, 181, 184, 190, - 184, 151, 193, 173, 148, 148, 173, 172, 148, 148, - 148, 148, 148, 184, 185, 172, 173, 179, 180, 188, - 192, 193, 195, 196, 197, 151, 173, 195, 23, 23, - 23, 184, 148, 148, 148, 148, 23, 23, 23, 23, - 148, 23, 148, 148, 152, 148, 152, 142, 152, 23, - 148, 173, 148, 148, 172, 148, 148, 172, 173, 172, - 173, 172, 147, 185, 172, 21, 148, 148, 150, 150, - 148, 149, 148, 23, 148, 148, 148, 148, 190, 194, - 182, 190, 191, 192, 193, 194, 195, 196, 197, 173, - 148, 148, 148, 148, 185, 148, 173, 23, 22, 172, - 175, 148, 173, 173, 172, 193, 185, 23, 19, 20, - 185, 186, 201, 172, 172, 173, 151, 189, 192, 194, - 195, 196, 197, 179, 179, 148, 195, 173, 173, 172, - 185, 186, 182, 185, 148, 152, 148, 152, 173, 172, - 172, 173, 172, 173, 175, 175, 175, 175, 152, 152, - 152, 152 -}; - - /* YYR1YYN -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 153, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 154, 154, 155, 155, 156, 156, 156, 156, 157, - 157, 157, 157, 158, 158, 158, 159, 159, 159, 160, - 160, 161, 161, 161, 161, 161, 161, 161, 161, 161, - 161, 161, 161, 161, 161, 161, 161, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 162, 162, 162, 163, - 163, 163, 163, 164, 164, 164, 164, 164, 164, 164, - 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, - 164, 164, 164, 164, 164, 164, 165, 165, 165, 165, - 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, - 166, 166, 166, 166, 166, 166, 167, 167, 167, 167, - 167, 167, 167, 168, 168, 168, 169, 169, 170, 170, - 171, 171, 172, 172, 172, 172, 172, 172, 172, 172, - 173, 173, 173, 173, 173, 173, 173, 173, 174, 175, - 175, 176, 176, 176, 177, 177, 177, 178, 178, 179, - 179, 180, 180, 180, 180, 181, 181, 181, 181, 181, - 181, 181, 181, 181, 181, 182, 182, 182, 182, 182, - 182, 182, 182, 183, 183, 183, 183, 183, 183, 183, - 183, 183, 183, 184, 184, 185, 185, 185, 185, 185, - 185, 185, 186, 186, 187, 187, 187, 187, 187, 187, - 188, 188, 188, 188, 188, 189, 189, 189, 189, 189, - 190, 191, 192, 193, 194, 195, 196, 196, 197, 197, - 198, 198, 199, 199, 200, 201, 201 -}; - - /* YYR2YYN -- Number of symbols on the right hand side of rule YYN. */ -static const yytype_int8 yyr2[] = -{ - 0, 2, 2, 2, 5, 5, 5, 1, 2, 4, - 5, 4, 2, 5, 4, 5, 5, 4, 5, 4, - 4, 4, 4, 3, 1, 2, 4, 5, 5, 4, - 4, 4, 5, 5, 5, 5, 5, 5, 3, 5, - 2, 3, 2, 1, 1, 1, 2, 1, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, - 3, 2, 3, 2, 3, 2, 3, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, - 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 3, 4, 3, 3, - 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 3, 1, 1, 3, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 3, 3, 3, 5, 8, 8, 4, 3, - 5, 1, 8, 8, 2, 1, 1 -}; - - -enum { YYENOMEM = -2 }; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ - do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ - while (0) - -/* Backward compatibility with an undocumented macro. - Use YYerror or YYUNDEF. */ -#define YYERRCODE YYUNDEF - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - -/* This macro is provided for backward compatibility. */ -# ifndef YY_LOCATION_PRINT -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif - - -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Kind, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*-----------------------------------. -| Print this symbol's value on YYO. | -`-----------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) -{ - FILE *yyoutput = yyo; - YYUSE (yyoutput); - if (!yyvaluep) - return; -# ifdef YYPRINT - if (yykind < YYNTOKENS) - YYPRINT (yyo, yytoknum[yykind], *yyvaluep); -# endif - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - -/*---------------------------. -| Print this symbol on YYO. | -`---------------------------*/ - -static void -yy_symbol_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) -{ - YYFPRINTF (yyo, "%s %s (", - yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - - yy_symbol_value_print (yyo, yykind, yyvaluep); - YYFPRINTF (yyo, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, - int yyrule) -{ - int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), - &yyvsp[(yyi + 1) - (yynrhs)]); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) ((void) 0) -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - - - - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, - yysymbol_kind_t yykind, YYSTYPE *yyvaluep) -{ - YYUSE (yyvaluep); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YYUSE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - -/* The lookahead symbol. */ -int yychar; - -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; -/* Number of syntax errors so far. */ -int yynerrs; - - - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (void) -{ - yy_state_fast_t yystate; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - - Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* Their size. */ - YYPTRDIFF_T yystacksize; - - /* The state stack. */ - yy_state_t yyssa[YYINITDEPTH]; - yy_state_t *yyss; - yy_state_t *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; - - int yyn; - /* The return value of yyparse. */ - int yyresult; - /* Lookahead token as an internal (translated) token number. */ - yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - - - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - yynerrs = 0; - yystate = 0; - yyerrstatus = 0; - - yystacksize = YYINITDEPTH; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - - - YYDPRINTF ((stderr, "Starting parse\n")); - - yychar = YYEMPTY; /* Cause a token to be read. */ - goto yysetstate; - - -/*------------------------------------------------------------. -| yynewstate -- push a new state, which is found in yystate. | -`------------------------------------------------------------*/ -yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - -/*--------------------------------------------------------------------. -| yysetstate -- set current state (the top of the stack) to yystate. | -`--------------------------------------------------------------------*/ -yysetstate: - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - YY_ASSERT (0 <= yystate && yystate < YYNSTATES); - YY_IGNORE_USELESS_CAST_BEGIN - *yyssp = YY_CAST (yy_state_t, yystate); - YY_IGNORE_USELESS_CAST_END - YY_STACK_PRINT (yyss, yyssp); - - if (yyss + yystacksize - 1 <= yyssp) -#if !defined yyoverflow && !defined YYSTACK_RELOCATE - goto yyexhaustedlab; -#else - { - /* Get the current used size of the three stacks, in elements. */ - YYPTRDIFF_T yysize = yyssp - yyss + 1; - -# if defined yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - yy_state_t *yyss1 = yyss; - YYSTYPE *yyvs1 = yyvs; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * YYSIZEOF (*yyssp), - &yyvs1, yysize * YYSIZEOF (*yyvsp), - &yystacksize); - yyss = yyss1; - yyvs = yyvs1; - } -# else /* defined YYSTACK_RELOCATE */ - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yy_state_t *yyss1 = yyss; - union yyalloc *yyptr = - YY_CAST (union yyalloc *, - YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YY_IGNORE_USELESS_CAST_BEGIN - YYDPRINTF ((stderr, "Stack size increased to %ld\n", - YY_CAST (long, yystacksize))); - YY_IGNORE_USELESS_CAST_END - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } -#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token\n")); - yychar = yylex (); - } - - if (yychar <= YYEOF) - { - yychar = YYEOF; - yytoken = YYSYMBOL_YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else if (yychar == YYerror) - { - /* The scanner already issued an error message, process directly - to error recovery. But do not keep the error token as - lookahead, it is too special and may lead us to an endless - loop in error recovery. */ - yychar = YYUNDEF; - yytoken = YYSYMBOL_YYerror; - goto yyerrlab1; - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - /* Discard the shifted token. */ - yychar = YYEMPTY; - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: -#line 112 "m68kasm.y" - { _genop((yyvsp[-1].opc) | (yyvsp[0].opc)); yyrc = -1; } -#line 1979 "m68kasm.c" - break; - - case 3: -#line 113 "m68kasm.y" - { _genop((yyvsp[-1].opc) | (yyvsp[0].rea).reg | (yyvsp[0].rea).ea.ea); yyrc = _genea((yyvsp[0].rea).ea) -1; } -#line 1985 "m68kasm.c" - break; - - case 4: -#line 114 "m68kasm.y" - { _genop((yyvsp[-4].opc) | (yyvsp[0].ea).ea); if (oplen==0) { _genop((yyvsp[-2].num) & 0xff); yyrc = _genea((yyvsp[0].ea)) - 3; } - - else if (oplen==1) { _genop((yyvsp[-2].num)); yyrc = _genea((yyvsp[0].ea)) - 3; } else { _genop((yyvsp[-2].num)>>16); _genop((yyvsp[-2].num) & 0xffff); yyrc = _genea((yyvsp[0].ea))-5; } } -#line 1992 "m68kasm.c" - break; - - case 5: -#line 116 "m68kasm.y" - { _genop((yyvsp[-4].opc) | (((yyvsp[-2].num)&7)<<9) | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } -#line 1998 "m68kasm.c" - break; - - case 6: -#line 117 "m68kasm.y" - { _genop((yyvsp[-4].opc) | (yyvsp[0].ea).ea); if (oplen==0) { _genop((yyvsp[-2].num) & 0xff); yyrc = _genea((yyvsp[0].ea)) - 3; } - - else if (oplen==1) { _genop((yyvsp[-2].num)); yyrc = _genea((yyvsp[0].ea)) - 3; } else { _genop((yyvsp[-2].num)>>16); _genop((yyvsp[-2].num) & 0xffff); yyrc = _genea((yyvsp[0].ea))-5; } } -#line 2005 "m68kasm.c" - break; - - case 7: -#line 119 "m68kasm.y" - { _genop((yyvsp[0].rea).reg); if (((yyvsp[0].rea).reg&0xc0)==0xc0) yyrc = _genea((yyvsp[0].rea).ea) - 1; else { yyrc = -1; } } -#line 2011 "m68kasm.c" - break; - - case 8: -#line 120 "m68kasm.y" - { yyrc = _genbr((yyvsp[-1].brop).opc,(yyvsp[0].num),(yyvsp[-1].brop).len); } -#line 2017 "m68kasm.c" - break; - - case 9: -#line 121 "m68kasm.y" - { _genop((yyvsp[-3].opc) | ((yyvsp[-2].reg)<<9) | 0x100 | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } -#line 2023 "m68kasm.c" - break; - - case 10: -#line 122 "m68kasm.y" - { _genop((yyvsp[-4].opc) | 0x0800 | (yyvsp[0].ea).ea); _genop((yyvsp[-2].num)); yyrc = _genea((yyvsp[0].ea)) - 3; } -#line 2029 "m68kasm.c" - break; - - case 11: -#line 123 "m68kasm.y" - { _genop(0x4180 | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } -#line 2035 "m68kasm.c" - break; - - case 12: -#line 124 "m68kasm.y" - { _genop((yyvsp[-1].opc) | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } -#line 2041 "m68kasm.c" - break; - - case 13: -#line 125 "m68kasm.y" - { _genop(0xb000 | ((yyvsp[-3].wl)<<6) | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } -#line 2047 "m68kasm.c" - break; - - case 14: -#line 126 "m68kasm.y" - { _genop((yyvsp[-3].opc) | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } -#line 2053 "m68kasm.c" - break; - - case 15: -#line 127 "m68kasm.y" - { _genop(0xb0c0 | ((yyvsp[-3].wl)<<8) | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } -#line 2059 "m68kasm.c" - break; - - case 16: -#line 128 "m68kasm.y" - { _genop(0xb108 | ((yyvsp[0].ea).ea<<9) | ((yyvsp[-3].wl)<<6) | (yyvsp[-2].ea).ea); yyrc = -1; } -#line 2065 "m68kasm.c" - break; - - case 17: -#line 129 "m68kasm.y" - { yyrc = _genbr((yyvsp[-3].opc) | (yyvsp[-2].reg), (yyvsp[0].num), 1); } -#line 2071 "m68kasm.c" - break; - - case 18: -#line 130 "m68kasm.y" - { _genop(0xb000 | ((yyvsp[-3].wl) << 6) | 0x100 | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } -#line 2077 "m68kasm.c" - break; - - case 19: -#line 131 "m68kasm.y" - { _genop(0xc140 | ((yyvsp[-2].reg)<<9) | (yyvsp[0].reg)); yyrc = -1; } -#line 2083 "m68kasm.c" - break; - - case 20: -#line 132 "m68kasm.y" - { _genop(0xc148 | ((yyvsp[-2].reg)<<9) | (yyvsp[0].reg)); yyrc = -1; } -#line 2089 "m68kasm.c" - break; - - case 21: -#line 133 "m68kasm.y" - { _genop(0xc188 | ((yyvsp[0].reg)<<9) | (yyvsp[-2].reg)); yyrc = -1; } -#line 2095 "m68kasm.c" - break; - - case 22: -#line 134 "m68kasm.y" - { _genop(0xc188 | ((yyvsp[-2].reg)<<9) | (yyvsp[0].reg)); yyrc = -1; } -#line 2101 "m68kasm.c" - break; - - case 23: -#line 135 "m68kasm.y" - { _genop(0x4840 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].reg)); yyrc = -1; } -#line 2107 "m68kasm.c" - break; - - case 24: -#line 136 "m68kasm.y" - { _genop((yyvsp[0].opc)); yyrc = -1; } -#line 2113 "m68kasm.c" - break; - - case 25: -#line 137 "m68kasm.y" - { _genop((yyvsp[-1].opc) | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) -1; } -#line 2119 "m68kasm.c" - break; - - case 26: -#line 138 "m68kasm.y" - { _genop(0x41c0 | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } -#line 2125 "m68kasm.c" - break; - - case 27: -#line 139 "m68kasm.y" - { _genop(0x4e50 | (yyvsp[-3].reg)); _genop((yyvsp[0].num)); yyrc = -3; } -#line 2131 "m68kasm.c" - break; - - case 28: -#line 140 "m68kasm.y" - { if ((yyvsp[0].ea).ea==074) { _genop(0x44c0 | ((yyvsp[0].ea).cnt==1?0x0200:0x0000) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } - - else { int tmp = (((yyvsp[0].ea).ea&070)>>3)|(((yyvsp[0].ea).ea&7)<<3); _genop(0x0000 | ((yyvsp[-3].wl)<<12) | (tmp<<6) | (yyvsp[-2].ea).ea); - - yyrc = _genea((yyvsp[-2].ea)) - 1; yyrc += _genea((yyvsp[0].ea)); } } -#line 2139 "m68kasm.c" - break; - - case 29: -#line 143 "m68kasm.y" - { _genop(0x40c0 | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } -#line 2145 "m68kasm.c" - break; - - case 30: -#line 144 "m68kasm.y" - { _genop(0x4e68 | (yyvsp[0].reg)); yyrc = -1; } -#line 2151 "m68kasm.c" - break; - - case 31: -#line 145 "m68kasm.y" - { _genop(0x4e60 | (yyvsp[-2].reg)); yyrc = -1; } -#line 2157 "m68kasm.c" - break; - - case 32: -#line 146 "m68kasm.y" - { _genop(0x0040 | ((yyvsp[-3].wl)<<12) | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } -#line 2163 "m68kasm.c" - break; - - case 33: -#line 147 "m68kasm.y" - { _genop(0x4880 | ((yyvsp[-3].wl)<<6) | (yyvsp[0].ea).ea); _genop(((yyvsp[0].ea).ea&070)==040 ? (yyvsp[-2].mask).d : (yyvsp[-2].mask).x); yyrc = _genea((yyvsp[0].ea)) - 3; } -#line 2169 "m68kasm.c" - break; - - case 34: -#line 148 "m68kasm.y" - { _genop(0x4c80 | ((yyvsp[-3].wl)<<6) | (yyvsp[-2].ea).ea); _genop((yyvsp[0].mask).x); yyrc = _genea((yyvsp[-2].ea)) - 3; } -#line 2175 "m68kasm.c" - break; - - case 35: -#line 149 "m68kasm.y" - { _genop(0x0108 | ((yyvsp[-2].reg)<<9) | ((yyvsp[-3].wl)<<6) | ((yyvsp[0].ea).ea & 7)); yyrc = _genea((yyvsp[0].ea)) - 1; } -#line 2181 "m68kasm.c" - break; - - case 36: -#line 150 "m68kasm.y" - { _genop(0x0188 | ((yyvsp[0].reg)<<9) | ((yyvsp[-3].wl)<<6) | ((yyvsp[-2].ea).ea & 7)); yyrc = _genea((yyvsp[-2].ea)) - 1; } -#line 2187 "m68kasm.c" - break; - - case 37: -#line 151 "m68kasm.y" - { _genop(0x7000 | ((yyvsp[0].reg)<<9) | ((yyvsp[-2].num)&0xff)); yyrc = -1; } -#line 2193 "m68kasm.c" - break; - - case 38: -#line 152 "m68kasm.y" - { _genop(0x4e72); yyrc = _genop((yyvsp[0].num)&0xffff) - 1; } -#line 2199 "m68kasm.c" - break; - - case 39: -#line 153 "m68kasm.y" - { _genop((yyvsp[-4].opc) | ((yyvsp[0].reg)<<9) | ((yyvsp[-3].wl)<<8) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } -#line 2205 "m68kasm.c" - break; - - case 40: -#line 154 "m68kasm.y" - { _genop(0x4840 | (yyvsp[0].reg)); yyrc = -1; } -#line 2211 "m68kasm.c" - break; - - case 41: -#line 155 "m68kasm.y" - { _genop(0x4e40 | ((yyvsp[0].num) & 0x0f)); yyrc = -1; } -#line 2217 "m68kasm.c" - break; - - case 42: -#line 156 "m68kasm.y" - { _genop(0x4e58 | (yyvsp[0].reg)); yyrc = -1; } -#line 2223 "m68kasm.c" - break; - - case 43: -#line 160 "m68kasm.y" - { (yyval.opc) = 0xd0c0; } -#line 2229 "m68kasm.c" - break; - - case 44: -#line 161 "m68kasm.y" - { (yyval.opc) = 0x90c0; } -#line 2235 "m68kasm.c" - break; - - case 45: -#line 164 "m68kasm.y" - { (yyval.opc) = 0xc100; } -#line 2241 "m68kasm.c" - break; - - case 46: -#line 165 "m68kasm.y" - { (yyval.opc) = 0xd100 | ((yyvsp[0].wl)<<6); } -#line 2247 "m68kasm.c" - break; - - case 47: -#line 166 "m68kasm.y" - { (yyval.opc) = 0x8100; } -#line 2253 "m68kasm.c" - break; - - case 48: -#line 167 "m68kasm.y" - { (yyval.opc) = 0x9100 | ((yyvsp[0].wl)<<6); } -#line 2259 "m68kasm.c" - break; - - case 49: -#line 171 "m68kasm.y" - { (yyval.opc) = 0xd000 | ((yyvsp[0].wl)<<6); } -#line 2265 "m68kasm.c" - break; - - case 50: -#line 172 "m68kasm.y" - { (yyval.opc) = 0xc000 | ((yyvsp[0].wl)<<6); } -#line 2271 "m68kasm.c" - break; - - case 51: -#line 173 "m68kasm.y" - { (yyval.opc) = 0x8000 | ((yyvsp[0].wl)<<6); } -#line 2277 "m68kasm.c" - break; - - case 52: -#line 174 "m68kasm.y" - { (yyval.opc) = 0x9000 | ((yyvsp[0].wl)<<6); } -#line 2283 "m68kasm.c" - break; - - case 53: -#line 178 "m68kasm.y" - { (yyval.opc) = 0x0600 | ((yyvsp[0].wl)<<6); } -#line 2289 "m68kasm.c" - break; - - case 54: -#line 179 "m68kasm.y" - { (yyval.opc) = 0x0c00 | ((yyvsp[0].wl)<<6); } -#line 2295 "m68kasm.c" - break; - - case 55: -#line 180 "m68kasm.y" - { (yyval.opc) = 0x0400 | ((yyvsp[0].wl)<<6); } -#line 2301 "m68kasm.c" - break; - - case 56: -#line 184 "m68kasm.y" - { (yyval.opc) = 0x0200 | ((yyvsp[0].wl)<<6); } -#line 2307 "m68kasm.c" - break; - - case 57: -#line 185 "m68kasm.y" - { (yyval.opc) = 0x0a00 | ((yyvsp[0].wl)<<6); } -#line 2313 "m68kasm.c" - break; - - case 58: -#line 186 "m68kasm.y" - { (yyval.opc) = 0x0000 | ((yyvsp[0].wl)<<6); } -#line 2319 "m68kasm.c" - break; - - case 59: -#line 190 "m68kasm.y" - { (yyval.opc) = 0x5000 | ((yyvsp[0].wl)<<6); } -#line 2325 "m68kasm.c" - break; - - case 60: -#line 191 "m68kasm.y" - { (yyval.opc) = 0x5100 | ((yyvsp[0].wl)<<6); } -#line 2331 "m68kasm.c" - break; - - case 61: -#line 195 "m68kasm.y" - { (yyval.rea).reg = 0xe1c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } -#line 2337 "m68kasm.c" - break; - - case 62: -#line 196 "m68kasm.y" - { (yyval.rea).reg = 0xe100 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } -#line 2343 "m68kasm.c" - break; - - case 63: -#line 197 "m68kasm.y" - { (yyval.rea).reg = 0xe0c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } -#line 2349 "m68kasm.c" - break; - - case 64: -#line 198 "m68kasm.y" - { (yyval.rea).reg = 0xe000 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } -#line 2355 "m68kasm.c" - break; - - case 65: -#line 199 "m68kasm.y" - { (yyval.rea).reg = 0xe3c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } -#line 2361 "m68kasm.c" - break; - - case 66: -#line 200 "m68kasm.y" - { (yyval.rea).reg = 0xe108 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } -#line 2367 "m68kasm.c" - break; - - case 67: -#line 201 "m68kasm.y" - { (yyval.rea).reg = 0xe2c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } -#line 2373 "m68kasm.c" - break; - - case 68: -#line 202 "m68kasm.y" - { (yyval.rea).reg = 0xe008 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } -#line 2379 "m68kasm.c" - break; - - case 69: -#line 203 "m68kasm.y" - { (yyval.rea).reg = 0xe7c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } -#line 2385 "m68kasm.c" - break; - - case 70: -#line 204 "m68kasm.y" - { (yyval.rea).reg = 0xe118 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } -#line 2391 "m68kasm.c" - break; - - case 71: -#line 205 "m68kasm.y" - { (yyval.rea).reg = 0xe6c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } -#line 2397 "m68kasm.c" - break; - - case 72: -#line 206 "m68kasm.y" - { (yyval.rea).reg = 0xe018 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } -#line 2403 "m68kasm.c" - break; - - case 73: -#line 207 "m68kasm.y" - { (yyval.rea).reg = 0xe5c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } -#line 2409 "m68kasm.c" - break; - - case 74: -#line 208 "m68kasm.y" - { (yyval.rea).reg = 0xe100 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } -#line 2415 "m68kasm.c" - break; - - case 75: -#line 209 "m68kasm.y" - { (yyval.rea).reg = 0xe4c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } -#line 2421 "m68kasm.c" - break; - - case 76: -#line 210 "m68kasm.y" - { (yyval.rea).reg = 0xe000 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } -#line 2427 "m68kasm.c" - break; - - case 77: -#line 214 "m68kasm.y" - { (yyval.brop).opc = 0x6400; (yyval.brop).len = 1; } -#line 2433 "m68kasm.c" - break; - - case 78: -#line 215 "m68kasm.y" - { (yyval.brop).opc = 0x6500; (yyval.brop).len = 1; } -#line 2439 "m68kasm.c" - break; - - case 79: -#line 216 "m68kasm.y" - { (yyval.brop).opc = 0x6700; (yyval.brop).len = 1; } -#line 2445 "m68kasm.c" - break; - - case 80: -#line 217 "m68kasm.y" - { (yyval.brop).opc = 0x6c00; (yyval.brop).len = 1; } -#line 2451 "m68kasm.c" - break; - - case 81: -#line 218 "m68kasm.y" - { (yyval.brop).opc = 0x6e00; (yyval.brop).len = 1; } -#line 2457 "m68kasm.c" - break; - - case 82: -#line 219 "m68kasm.y" - { (yyval.brop).opc = 0x6200; (yyval.brop).len = 1; } -#line 2463 "m68kasm.c" - break; - - case 83: -#line 220 "m68kasm.y" - { (yyval.brop).opc = 0x6f00; (yyval.brop).len = 1; } -#line 2469 "m68kasm.c" - break; - - case 84: -#line 221 "m68kasm.y" - { (yyval.brop).opc = 0x6300; (yyval.brop).len = 1; } -#line 2475 "m68kasm.c" - break; - - case 85: -#line 222 "m68kasm.y" - { (yyval.brop).opc = 0x6d00; (yyval.brop).len = 1; } -#line 2481 "m68kasm.c" - break; - - case 86: -#line 223 "m68kasm.y" - { (yyval.brop).opc = 0x6b00; (yyval.brop).len = 1; } -#line 2487 "m68kasm.c" - break; - - case 87: -#line 224 "m68kasm.y" - { (yyval.brop).opc = 0x6600; (yyval.brop).len = 1; } -#line 2493 "m68kasm.c" - break; - - case 88: -#line 225 "m68kasm.y" - { (yyval.brop).opc = 0x6a00; (yyval.brop).len = 1; } -#line 2499 "m68kasm.c" - break; - - case 89: -#line 226 "m68kasm.y" - { (yyval.brop).opc = 0x6800; (yyval.brop).len = 1; } -#line 2505 "m68kasm.c" - break; - - case 90: -#line 227 "m68kasm.y" - { (yyval.brop).opc = 0x6900; (yyval.brop).len = 1; } -#line 2511 "m68kasm.c" - break; - - case 91: -#line 228 "m68kasm.y" - { (yyval.brop).opc = 0x6100; (yyval.brop).len = 1; } -#line 2517 "m68kasm.c" - break; - - case 92: -#line 229 "m68kasm.y" - { (yyval.brop).opc = 0x6000; (yyval.brop).len = 1; } -#line 2523 "m68kasm.c" - break; - - case 93: -#line 230 "m68kasm.y" - { (yyval.brop).opc = 0x6400; (yyval.brop).len = 0; } -#line 2529 "m68kasm.c" - break; - - case 94: -#line 231 "m68kasm.y" - { (yyval.brop).opc = 0x6500; (yyval.brop).len = 0; } -#line 2535 "m68kasm.c" - break; - - case 95: -#line 232 "m68kasm.y" - { (yyval.brop).opc = 0x6700; (yyval.brop).len = 0; } -#line 2541 "m68kasm.c" - break; - - case 96: -#line 233 "m68kasm.y" - { (yyval.brop).opc = 0x6c00; (yyval.brop).len = 0; } -#line 2547 "m68kasm.c" - break; - - case 97: -#line 234 "m68kasm.y" - { (yyval.brop).opc = 0x6e00; (yyval.brop).len = 0; } -#line 2553 "m68kasm.c" - break; - - case 98: -#line 235 "m68kasm.y" - { (yyval.brop).opc = 0x6200; (yyval.brop).len = 0; } -#line 2559 "m68kasm.c" - break; - - case 99: -#line 236 "m68kasm.y" - { (yyval.brop).opc = 0x6f00; (yyval.brop).len = 0; } -#line 2565 "m68kasm.c" - break; - - case 100: -#line 237 "m68kasm.y" - { (yyval.brop).opc = 0x6300; (yyval.brop).len = 0; } -#line 2571 "m68kasm.c" - break; - - case 101: -#line 238 "m68kasm.y" - { (yyval.brop).opc = 0x6d00; (yyval.brop).len = 0; } -#line 2577 "m68kasm.c" - break; - - case 102: -#line 239 "m68kasm.y" - { (yyval.brop).opc = 0x6b00; (yyval.brop).len = 0; } -#line 2583 "m68kasm.c" - break; - - case 103: -#line 240 "m68kasm.y" - { (yyval.brop).opc = 0x6600; (yyval.brop).len = 0; } -#line 2589 "m68kasm.c" - break; - - case 104: -#line 241 "m68kasm.y" - { (yyval.brop).opc = 0x6a00; (yyval.brop).len = 0; } -#line 2595 "m68kasm.c" - break; - - case 105: -#line 242 "m68kasm.y" - { (yyval.brop).opc = 0x6800; (yyval.brop).len = 0; } -#line 2601 "m68kasm.c" - break; - - case 106: -#line 243 "m68kasm.y" - { (yyval.brop).opc = 0x6900; (yyval.brop).len = 0; } -#line 2607 "m68kasm.c" - break; - - case 107: -#line 244 "m68kasm.y" - { (yyval.brop).opc = 0x6100; (yyval.brop).len = 0; } -#line 2613 "m68kasm.c" - break; - - case 108: -#line 245 "m68kasm.y" - { (yyval.brop).opc = 0x6000; (yyval.brop).len = 0; } -#line 2619 "m68kasm.c" - break; - - case 109: -#line 249 "m68kasm.y" - { (yyval.opc) = 0x0040; } -#line 2625 "m68kasm.c" - break; - - case 110: -#line 250 "m68kasm.y" - { (yyval.opc) = 0x0080; } -#line 2631 "m68kasm.c" - break; - - case 111: -#line 251 "m68kasm.y" - { (yyval.opc) = 0x00c0; } -#line 2637 "m68kasm.c" - break; - - case 112: -#line 252 "m68kasm.y" - { (yyval.opc) = 0x0000; } -#line 2643 "m68kasm.c" - break; - - case 113: -#line 256 "m68kasm.y" - { (yyval.opc) = 0x4200 | ((yyvsp[0].wl)<<6); } -#line 2649 "m68kasm.c" - break; - - case 114: -#line 257 "m68kasm.y" - { (yyval.opc) = 0x4800; } -#line 2655 "m68kasm.c" - break; - - case 115: -#line 258 "m68kasm.y" - { (yyval.opc) = 0x4400 | ((yyvsp[0].wl)<<6); } -#line 2661 "m68kasm.c" - break; - - case 116: -#line 259 "m68kasm.y" - { (yyval.opc) = 0x4000 | ((yyvsp[0].wl)<<6); } -#line 2667 "m68kasm.c" - break; - - case 117: -#line 260 "m68kasm.y" - { (yyval.opc) = 0x4600 | ((yyvsp[0].wl)<<6); } -#line 2673 "m68kasm.c" - break; - - case 118: -#line 261 "m68kasm.y" - { (yyval.opc) = 0x54c0; } -#line 2679 "m68kasm.c" - break; - - case 119: -#line 262 "m68kasm.y" - { (yyval.opc) = 0x55c0; } -#line 2685 "m68kasm.c" - break; - - case 120: -#line 263 "m68kasm.y" - { (yyval.opc) = 0x57c0; } -#line 2691 "m68kasm.c" - break; - - case 121: -#line 264 "m68kasm.y" - { (yyval.opc) = 0x51c0; } -#line 2697 "m68kasm.c" - break; - - case 122: -#line 265 "m68kasm.y" - { (yyval.opc) = 0x5cc0; } -#line 2703 "m68kasm.c" - break; - - case 123: -#line 266 "m68kasm.y" - { (yyval.opc) = 0x5ec0; } -#line 2709 "m68kasm.c" - break; - - case 124: -#line 267 "m68kasm.y" - { (yyval.opc) = 0x52c0; } -#line 2715 "m68kasm.c" - break; - - case 125: -#line 268 "m68kasm.y" - { (yyval.opc) = 0x5fc0; } -#line 2721 "m68kasm.c" - break; - - case 126: -#line 269 "m68kasm.y" - { (yyval.opc) = 0x53c0; } -#line 2727 "m68kasm.c" - break; - - case 127: -#line 270 "m68kasm.y" - { (yyval.opc) = 0x5dc0; } -#line 2733 "m68kasm.c" - break; - - case 128: -#line 271 "m68kasm.y" - { (yyval.opc) = 0x5bc0; } -#line 2739 "m68kasm.c" - break; - - case 129: -#line 272 "m68kasm.y" - { (yyval.opc) = 0x56c0; } -#line 2745 "m68kasm.c" - break; - - case 130: -#line 273 "m68kasm.y" - { (yyval.opc) = 0x5ac0; } -#line 2751 "m68kasm.c" - break; - - case 131: -#line 274 "m68kasm.y" - { (yyval.opc) = 0x50c0; } -#line 2757 "m68kasm.c" - break; - - case 132: -#line 275 "m68kasm.y" - { (yyval.opc) = 0x58c0; } -#line 2763 "m68kasm.c" - break; - - case 133: -#line 276 "m68kasm.y" - { (yyval.opc) = 0x59c0; } -#line 2769 "m68kasm.c" - break; - - case 134: -#line 277 "m68kasm.y" - { (yyval.opc) = 0x4ac0; } -#line 2775 "m68kasm.c" - break; - - case 135: -#line 278 "m68kasm.y" - { (yyval.opc) = 0x4a00 | ((yyvsp[0].wl)<<6); } -#line 2781 "m68kasm.c" - break; - - case 136: -#line 282 "m68kasm.y" - { (yyval.opc) = 0x81c0; } -#line 2787 "m68kasm.c" - break; - - case 137: -#line 283 "m68kasm.y" - { (yyval.opc) = 0x80c0; } -#line 2793 "m68kasm.c" - break; - - case 138: -#line 284 "m68kasm.y" - { (yyval.opc) = 0xc1c0; } -#line 2799 "m68kasm.c" - break; - - case 139: -#line 285 "m68kasm.y" - { (yyval.opc) = 0xc0c0; } -#line 2805 "m68kasm.c" - break; - - case 140: -#line 289 "m68kasm.y" - { (yyval.opc) = 0x54c8; } -#line 2811 "m68kasm.c" - break; - - case 141: -#line 290 "m68kasm.y" - { (yyval.opc) = 0x55c8; } -#line 2817 "m68kasm.c" - break; - - case 142: -#line 291 "m68kasm.y" - { (yyval.opc) = 0x57c8; } -#line 2823 "m68kasm.c" - break; - - case 143: -#line 292 "m68kasm.y" - { (yyval.opc) = 0x5cc8; } -#line 2829 "m68kasm.c" - break; - - case 144: -#line 293 "m68kasm.y" - { (yyval.opc) = 0x5ec8; } -#line 2835 "m68kasm.c" - break; - - case 145: -#line 294 "m68kasm.y" - { (yyval.opc) = 0x52c8; } -#line 2841 "m68kasm.c" - break; - - case 146: -#line 295 "m68kasm.y" - { (yyval.opc) = 0x5fc8; } -#line 2847 "m68kasm.c" - break; - - case 147: -#line 296 "m68kasm.y" - { (yyval.opc) = 0x53c8; } -#line 2853 "m68kasm.c" - break; - - case 148: -#line 297 "m68kasm.y" - { (yyval.opc) = 0x5dc8; } -#line 2859 "m68kasm.c" - break; - - case 149: -#line 298 "m68kasm.y" - { (yyval.opc) = 0x5bc8; } -#line 2865 "m68kasm.c" - break; - - case 150: -#line 299 "m68kasm.y" - { (yyval.opc) = 0x56c8; } -#line 2871 "m68kasm.c" - break; - - case 151: -#line 300 "m68kasm.y" - { (yyval.opc) = 0x5ac8; } -#line 2877 "m68kasm.c" - break; - - case 152: -#line 301 "m68kasm.y" - { (yyval.opc) = 0x58c8; } -#line 2883 "m68kasm.c" - break; - - case 153: -#line 302 "m68kasm.y" - { (yyval.opc) = 0x59c8; } -#line 2889 "m68kasm.c" - break; - - case 154: -#line 303 "m68kasm.y" - { (yyval.opc) = 0x51c8; } -#line 2895 "m68kasm.c" - break; - - case 155: -#line 304 "m68kasm.y" - { (yyval.opc) = 0x50c8; } -#line 2901 "m68kasm.c" - break; - - case 156: -#line 308 "m68kasm.y" - { (yyval.opc) = 0x4afc; } -#line 2907 "m68kasm.c" - break; - - case 157: -#line 309 "m68kasm.y" - { (yyval.opc) = 0x4e71; } -#line 2913 "m68kasm.c" - break; - - case 158: -#line 310 "m68kasm.y" - { (yyval.opc) = 0x4e70; } -#line 2919 "m68kasm.c" - break; - - case 159: -#line 311 "m68kasm.y" - { (yyval.opc) = 0x4e73; } -#line 2925 "m68kasm.c" - break; - - case 160: -#line 312 "m68kasm.y" - { (yyval.opc) = 0x4e77; } -#line 2931 "m68kasm.c" - break; - - case 161: -#line 313 "m68kasm.y" - { (yyval.opc) = 0x4e75; } -#line 2937 "m68kasm.c" - break; - - case 162: -#line 314 "m68kasm.y" - { (yyval.opc) = 0x4e76; } -#line 2943 "m68kasm.c" - break; - - case 163: -#line 318 "m68kasm.y" - { (yyval.opc) = 0x4ec0; } -#line 2949 "m68kasm.c" - break; - - case 164: -#line 319 "m68kasm.y" - { (yyval.opc) = 0x4e80; } -#line 2955 "m68kasm.c" - break; - - case 165: -#line 320 "m68kasm.y" - { (yyval.opc) = 0x4840; } -#line 2961 "m68kasm.c" - break; - - case 166: -#line 323 "m68kasm.y" - { (yyval.opc) = ((yyvsp[-2].reg)<<9) | 0x20 | (yyvsp[0].reg); } -#line 2967 "m68kasm.c" - break; - - case 167: -#line 324 "m68kasm.y" - { (yyval.opc) = (((yyvsp[-2].num) & 7)<<9) | (yyvsp[0].reg); } -#line 2973 "m68kasm.c" - break; - - case 168: -#line 327 "m68kasm.y" - { (yyval.opc) = (((yyvsp[-2].ea).ea & 7) << 9) | ((yyvsp[0].ea).ea & 7); } -#line 2979 "m68kasm.c" - break; - - case 169: -#line 328 "m68kasm.y" - { (yyval.opc) = (((yyvsp[-2].ea).ea & 7) << 9) | 0x0008 | ((yyvsp[0].ea).ea & 7); } -#line 2985 "m68kasm.c" - break; - - case 170: -#line 331 "m68kasm.y" - { if (((yyvsp[0].ea).ea & 070)==0) { /* dx,dy must be swapped */ - - (yyval.rea).reg = ((yyvsp[0].ea).ea & 7)<<9; (yyvsp[0].ea).ea = (yyvsp[-2].reg) & 7; (yyval.rea).ea = (yyvsp[0].ea); } - - else { (yyval.rea).reg = ((yyvsp[-2].reg)<<9) | 0x100; (yyval.rea).ea = (yyvsp[0].ea); } } -#line 2993 "m68kasm.c" - break; - - case 171: -#line 334 "m68kasm.y" - { (yyval.rea).reg = ((yyvsp[0].reg)<<9); (yyval.rea).ea = (yyvsp[-2].ea); } -#line 2999 "m68kasm.c" - break; - - case 172: -#line 337 "m68kasm.y" - { (yyval.reg)=0; } -#line 3005 "m68kasm.c" - break; - - case 173: -#line 338 "m68kasm.y" - { (yyval.reg)=1; } -#line 3011 "m68kasm.c" - break; - - case 174: -#line 339 "m68kasm.y" - { (yyval.reg)=2; } -#line 3017 "m68kasm.c" - break; - - case 175: -#line 340 "m68kasm.y" - { (yyval.reg)=3; } -#line 3023 "m68kasm.c" - break; - - case 176: -#line 341 "m68kasm.y" - { (yyval.reg)=4; } -#line 3029 "m68kasm.c" - break; - - case 177: -#line 342 "m68kasm.y" - { (yyval.reg)=5; } -#line 3035 "m68kasm.c" - break; - - case 178: -#line 343 "m68kasm.y" - { (yyval.reg)=6; } -#line 3041 "m68kasm.c" - break; - - case 179: -#line 344 "m68kasm.y" - { (yyval.reg)=7; } -#line 3047 "m68kasm.c" - break; - - case 180: -#line 347 "m68kasm.y" - { (yyval.reg)=0; } -#line 3053 "m68kasm.c" - break; - - case 181: -#line 348 "m68kasm.y" - { (yyval.reg)=1; } -#line 3059 "m68kasm.c" - break; - - case 182: -#line 349 "m68kasm.y" - { (yyval.reg)=2; } -#line 3065 "m68kasm.c" - break; - - case 183: -#line 350 "m68kasm.y" - { (yyval.reg)=3; } -#line 3071 "m68kasm.c" - break; - - case 184: -#line 351 "m68kasm.y" - { (yyval.reg)=4; } -#line 3077 "m68kasm.c" - break; - - case 185: -#line 352 "m68kasm.y" - { (yyval.reg)=5; } -#line 3083 "m68kasm.c" - break; - - case 186: -#line 353 "m68kasm.y" - { (yyval.reg)=6; } -#line 3089 "m68kasm.c" - break; - - case 187: -#line 354 "m68kasm.y" - { (yyval.reg)=7; } -#line 3095 "m68kasm.c" - break; - - case 188: -#line 357 "m68kasm.y" - { (yyval.wl) = 1; oplen = 0; } -#line 3101 "m68kasm.c" - break; - - case 189: -#line 360 "m68kasm.y" - { (yyval.wl) = 0; oplen = 1; } -#line 3107 "m68kasm.c" - break; - - case 190: -#line 361 "m68kasm.y" - { (yyval.wl) = 1; oplen = 2; } -#line 3113 "m68kasm.c" - break; - - case 191: -#line 364 "m68kasm.y" - { (yyval.wl) = 0; oplen = 0; } -#line 3119 "m68kasm.c" - break; - - case 192: -#line 365 "m68kasm.y" - { (yyval.wl) = 1; oplen = 1; } -#line 3125 "m68kasm.c" - break; - - case 193: -#line 366 "m68kasm.y" - { (yyval.wl) = 2; oplen = 2; } -#line 3131 "m68kasm.c" - break; - - case 194: -#line 369 "m68kasm.y" - { (yyval.wl) = 1; oplen = 0; } -#line 3137 "m68kasm.c" - break; - - case 195: -#line 370 "m68kasm.y" - { (yyval.wl) = 3; oplen = 1; } -#line 3143 "m68kasm.c" - break; - - case 196: -#line 371 "m68kasm.y" - { (yyval.wl) = 2; oplen = 2; } -#line 3149 "m68kasm.c" - break; - - case 197: -#line 374 "m68kasm.y" - { (yyval.wl) = 3; oplen = 1; } -#line 3155 "m68kasm.c" - break; - - case 198: -#line 375 "m68kasm.y" - { (yyval.wl) = 2; oplen = 2; } -#line 3161 "m68kasm.c" - break; - - case 199: -#line 378 "m68kasm.y" - { (yyval.mask) = (yyvsp[0].mask); } -#line 3167 "m68kasm.c" - break; - - case 200: -#line 379 "m68kasm.y" - { (yyval.mask).x = (yyvsp[-2].mask).x | (yyvsp[0].mask).x; (yyval.mask).d = (yyvsp[-2].mask).d | (yyvsp[0].mask).d; } -#line 3173 "m68kasm.c" - break; - - case 201: -#line 382 "m68kasm.y" - { (yyval.mask).x = movemx[(yyvsp[0].reg)]; (yyval.mask).d = movemd[(yyvsp[0].reg)]; } -#line 3179 "m68kasm.c" - break; - - case 202: -#line 383 "m68kasm.y" - { (yyval.mask).x = movemx[(yyvsp[0].reg)+8]; (yyval.mask).d = movemd[(yyvsp[0].reg)+8]; } -#line 3185 "m68kasm.c" - break; - - case 203: -#line 384 "m68kasm.y" - { int i,l=(yyvsp[-2].reg),h=(yyvsp[0].reg); if (l>h) { l=(yyvsp[0].reg); h=(yyvsp[-2].reg); } (yyval.mask).x = (yyval.mask).d = 0; - - for (i=l; i<=h; i++) { (yyval.mask).d |= movemx[i]; (yyval.mask).d |= movemd[i]; } } -#line 3192 "m68kasm.c" - break; - - case 204: -#line 386 "m68kasm.y" - { int i,l=(yyvsp[-2].reg),h=(yyvsp[0].reg); if (l>h) { l=(yyvsp[0].reg); h=(yyvsp[-2].reg); } (yyval.mask).x = (yyval.mask).d = 0; - - for (i=l; i<=h; i++) { (yyval.mask).x |= movemx[i+8]; (yyval.mask).d |= movemd[i+8]; } } -#line 3199 "m68kasm.c" - break; - - case 260: -#line 401 "m68kasm.y" - { (yyval.ea).ea = (yyvsp[0].reg); (yyval.ea).cnt = 0; } -#line 3205 "m68kasm.c" - break; - - case 261: -#line 403 "m68kasm.y" - { (yyval.ea).ea = 010 | (yyvsp[0].reg); (yyval.ea).cnt = 0; } -#line 3211 "m68kasm.c" - break; - - case 262: -#line 405 "m68kasm.y" - { (yyval.ea).ea = 020 | (yyvsp[-1].reg); (yyval.ea).cnt = 0; } -#line 3217 "m68kasm.c" - break; - - case 263: -#line 407 "m68kasm.y" - { (yyval.ea).ea = 030 | (yyvsp[-1].reg); (yyval.ea).cnt = 0; } -#line 3223 "m68kasm.c" - break; - - case 264: -#line 409 "m68kasm.y" - { (yyval.ea).ea = 040 | (yyvsp[-1].reg); (yyval.ea).cnt = 0; } -#line 3229 "m68kasm.c" - break; - - case 265: -#line 411 "m68kasm.y" - { (yyval.ea).ea = 050 | (yyvsp[-1].reg); (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[-3].num); } -#line 3235 "m68kasm.c" - break; - - case 266: -#line 414 "m68kasm.y" - { (yyval.ea).ea = 060 | (yyvsp[-4].reg); (yyval.ea).cnt = 1; (yyval.ea).arg[0] = 0x8000 | ((yyvsp[-2].reg)<<12) | ((yyvsp[-1].wl)<<11) | ((yyvsp[-6].num) & 0xff); } -#line 3241 "m68kasm.c" - break; - - case 267: -#line 416 "m68kasm.y" - { (yyval.ea).ea = 060 | (yyvsp[-4].reg); (yyval.ea).cnt = 1; (yyval.ea).arg[0] = ((yyvsp[-2].reg)<<12) | ((yyvsp[-1].wl)<<11) | ((yyvsp[-6].num) & 0xff); } -#line 3247 "m68kasm.c" - break; - - case 268: -#line 418 "m68kasm.y" - { if ((yyvsp[0].wl)==0) { (yyval.ea).ea = 070; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[-2].num); } - - else { (yyval.ea).ea = 071; (yyval.ea).cnt = 2; (yyval.ea).arg[0] = (yyvsp[-2].num) >> 16; (yyval.ea).arg[1] = (yyvsp[-2].num) & 0xffff; } } -#line 3254 "m68kasm.c" - break; - - case 269: -#line 420 "m68kasm.y" - { int tmp = ((yyvsp[-1].num)>>15) & 0x1ffff; if (tmp==0 || tmp==0x1ffff) { (yyval.ea).ea = 070; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[-1].num); } - - else { (yyval.ea).ea = 070; (yyval.ea).cnt = 2; (yyval.ea).arg[0] = (yyvsp[-1].num) >> 16; (yyval.ea).arg[1] = (yyvsp[-1].num) & 0xffff; } } -#line 3261 "m68kasm.c" - break; - - case 270: -#line 423 "m68kasm.y" - { (yyval.ea).ea = 072; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[-3].num); } -#line 3267 "m68kasm.c" - break; - - case 271: -#line 424 "m68kasm.y" - { (yyval.ea).ea = 072; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[0].num); } -#line 3273 "m68kasm.c" - break; - - case 272: -#line 427 "m68kasm.y" - { (yyval.ea).ea = 073; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = 0x8000 | ((yyvsp[-2].reg)<<12) | ((yyvsp[-1].wl)<<11) | ((yyvsp[-6].num) & 0xff); } -#line 3279 "m68kasm.c" - break; - - case 273: -#line 429 "m68kasm.y" - { (yyval.ea).ea = 073; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = ((yyvsp[-2].reg)<<12) | ((yyvsp[-1].wl)<<11) | ((yyvsp[-6].num) & 0xff); } -#line 3285 "m68kasm.c" - break; - - case 274: -#line 431 "m68kasm.y" - { (yyval.ea).ea = 074; if (oplen==0) { (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[0].num) & 0xff; } - - else if (oplen==1) { (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[0].num) & 0xffff; } - - else { (yyval.ea).cnt = 2; (yyval.ea).arg[0] = (yyvsp[0].num) >> 16; (yyval.ea).arg[1] = (yyvsp[0].num) & 0xffff; } } -#line 3293 "m68kasm.c" - break; - - case 275: -#line 435 "m68kasm.y" - { (yyval.ea).ea = 074; (yyval.ea).cnt = 0; } -#line 3299 "m68kasm.c" - break; - - case 276: -#line 436 "m68kasm.y" - { (yyval.ea).ea = 074; (yyval.ea).cnt = 1; } -#line 3305 "m68kasm.c" - break; - - -#line 3309 "m68kasm.c" - - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - - *++yyvsp = yyval; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - { - const int yylhs = yyr1[yyn] - YYNTOKENS; - const int yyi = yypgoto[yylhs] + *yyssp; - yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp - ? yytable[yyi] - : yydefgoto[yylhs]); - } - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; - yyerror (YY_("syntax error")); - } - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - /* Pacify compilers when the user code never invokes YYERROR and the - label yyerrorlab therefore never appears in user code. */ - if (0) - YYERROR; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - /* Pop stack until we find a state that shifts the error token. */ - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYSYMBOL_YYerror; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - YY_ACCESSING_SYMBOL (yystate), yyvsp); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - - -#if !defined yyoverflow -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ -#endif - - -/*-----------------------------------------------------. -| yyreturn -- parsing is finished, return the result. | -`-----------------------------------------------------*/ -yyreturn: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - YY_ACCESSING_SYMBOL (+*yyssp), yyvsp); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif - - return yyresult; -} - -#line 437 "m68kasm.y" - - - - -static void yyerror(char* s) - -{ - - /* do not emit anything, but set error flag */ - - yyerrc = 1; - -} - - - -struct _optable { - - char* mnem; - - int token; - -}; - - - -static struct _optable ops[] = { - - { "abcd", ABCD }, { "add", ADD }, { "adda", ADDA }, { "addi", ADDI }, - - { "addq", ADDQ }, { "addx", ADDX }, { "and", AND }, { "andi", ANDI }, - - { "asl", ASL }, { "asr", ASR }, { "bcc", BCC }, { "bcs", BCS }, - - { "beq", BEQ }, { "bge", BGE }, { "bgt", BGT }, { "bhi", BHI }, - - { "ble", BLE }, { "bls", BLS }, { "blt", BLT }, { "bmi", BMI }, - - { "bne", BNE }, { "bpl", BPL }, { "bvc", BVC }, { "bvs", BVS }, - - { "bchg", BCHG }, { "bclr", BCLR }, { "bra", BRA }, { "bset", BSET }, - - { "bsr", BSR }, { "btst", BTST }, { "chk", CHK }, { "clr", CLR }, - - { "cmp", CMP }, { "cmpa", CMPA }, { "cmpi", CMPI }, { "cmpm", CMPM }, - - { "dbcc", DBCC }, { "dbcs", DBCS }, { "dbeq", DBEQ }, { "dbf", DBF }, - - { "dbge", DBGE }, { "dbgt", DBGT }, { "dbhi", DBHI }, { "dble", DBLE }, - - { "dbls", DBLS }, { "dblt", DBLT }, { "dbmi", DBMI }, { "dbne", DBNE }, - - { "dbpl", DBPL }, { "dbt", DBT }, { "dbvc", DBVC }, { "dbvs", DBVS }, - - { "divs", DIVS }, { "divu", DIVU }, { "eor", EOR }, { "eori", EORI }, - - { "exg", EXG }, { "ext", EXT }, { "illegal",ILLEGAL }, { "jmp", JMP }, - - { "jsr", JSR }, { "lea", LEA }, { "link", LINK }, { "lsl", LSL }, - - { "lsr", LSR }, { "move", MOVE }, { "movea", MOVEA }, { "movem", MOVEM }, - - { "movep", MOVEP }, { "moveq", MOVEQ }, { "muls", MULS }, { "mulu", MULU }, - - { "nbcd", NBCD }, { "neg", NEG }, { "negx", NEGX }, { "nop", NOP }, - - { "not", NOT }, { "or", OR }, { "ori", ORI }, { "pea", PEA }, - - { "reset", RESET }, { "rol", ROL }, { "ror", ROR }, { "roxl", ROXL }, - - { "roxr", ROXR }, { "rte", RTE }, { "rtr", RTR }, - - { "rts", RTS }, { "scc", SCC }, { "scs", SCS }, { "seq", SEQ }, - - { "sf", SF }, { "sge", SGE }, { "sgt", SGT }, { "shi", SHI }, - - { "sle", SLE }, { "sls", SLS }, { "slt", SLT }, { "smi", SMI }, - - { "sne", SNE }, { "spl", SPL }, { "st", ST }, { "svc", SVC }, - - { "svs", SVS }, { "stop", STOP }, { "sub", SUB }, { "suba", SUBA }, - - { "subi", SUBI }, { "subq", SUBQ }, { "subx", SUBX }, { "swap", SWAP }, - - { "tas", TAS }, { "trap", TRAP }, { "trapv", TRAPV }, { "tst", TST }, - - { "unlk", UNLK }, { "a0", A0 }, { "a1", A1 }, { "a2", A2 }, - - { "a3", A3 }, { "a4", A4 }, { "a5", A5 }, { "a6", A6 }, - - { "a7", A7 }, { "d0", D0 }, { "d1", D1 }, { "d2", D2 }, - - { "d3", D3 }, { "d4", D4 }, { "d5", D5 }, { "d6", D6 }, - - { "d7", D7 }, { "ccr", CCR }, { "sr", SR }, { "usp", USP }, - - { "pc", PC }, - - { 0, 0 } - -}; - - - -typedef struct _ophash { - - struct _ophash* next; - - struct _optable* op; - -} OPHASH; - -#define OPHASHSIZE 97 - - - -static OPHASH **ophash = 0; - - - -static int getophash(const char* s) - -{ - - int h = 0; - - while (*s++) h += (int)*s; - - return h % OPHASHSIZE; - -} - - - -static int oplookup(const char* s) - -{ - - int idx = getophash(s); - - OPHASH* oph = ophash[idx]; - - if (oph) { - - if (oph->next) { - - while (oph) { - - if (!strcmp(s,oph->op->mnem)) return oph->op->token; - - oph = oph->next; - - } - - return 0; - - } - - return oph->op->token; - - } - - return 0; - -} - - - -static void init_ophash() - -{ - - struct _optable* op = ops; - - OPHASH* oph; - - ophash = (OPHASH**)calloc(sizeof(OPHASH*),OPHASHSIZE); - - while (op->mnem) { - - int idx = getophash(op->mnem); - - oph = (OPHASH*)malloc(sizeof(OPHASH)); - - oph->next = ophash[idx]; - - oph->op = op; - - ophash[idx] = oph; - - op++; - - } - -} - - - -static char* yystream; - - - -static int yylex() - -{ - - char ident[30]; - - char *p = ident; - - char c = yystream[0]; - - - - while (c != 0 && (c=='\t' || c==' ')) { - - c = *++yystream; - - } - - if (c==0) return EOF; - - - - if (isalpha(c)) { - - while (isalnum(c) && (p-ident)<28) { - - *p++ = tolower(c); c = *++yystream; - - } - - *p = 0; - - if (p>ident) { return oplookup(ident); } - - return EOF; - - } else if (isdigit(c)) { - - *p++ = c; - - if (yystream[1]=='x' || yystream[1]=='X') { *p++ = 'x'; yystream++; } - - c = *++yystream; - - while ((isdigit(c) || isxdigit(c)) && (p-ident)<28) { - - *p++ = c; c = *++yystream; - - } - - *p = 0; - - yylval.num = strtol(ident,0,0); - - return NUMBER; - - } else if (c=='$') { - - if (isdigit(yystream[1]) || isxdigit(yystream[1])) { - - c = *++yystream; - - while ((isdigit(c) || isxdigit(c)) && (p-ident)<28) { - - *p++ = c; c = *++yystream; - - } - - *p = 0; - - yylval.num = strtol(ident,0,16); - - return NUMBER; - - } else return '$'; - - } else if (c == '-' && yystream[1] == '(') { - - yystream += 2; return PREDEC; - - } else if (c == ')' && yystream[1] == '+') { - - yystream += 2; return POSTINC; - - } else if (c == '.') { - - switch (yystream[1]) { - - case 'b': yystream += 2; return BSIZE; - - case 'w': yystream += 2; return WSIZE; - - case 'l': yystream += 2; return LSIZE; - - case 's': yystream += 2; return SSIZE; - - default: yystream++; return '.'; - - } - - } else { - - ++yystream; return c; - - } - -} - - - -static t_value *yyvalptr; - -static t_addr yyaddr; - - - -t_stat parse_sym_m68k(char* c, t_addr a, UNIT* u, t_value* val, int32 sw) - -{ - - char ch; - - - - if (!ophash) init_ophash(); - - - - yyvalptr = val; - - yyaddr = a; - - - - yystream = c; - - yyerrc = 0; - - - - ch = *yystream; - - while (ch != 0 && (ch=='\t' || ch==' ')) { - - ch = *++yystream; - - } - - if (ch == 0) return 0; - - - - if (sw & SWMASK('Y')) yydebug = 1 - yydebug; - - if ((sw & SWMASK('A')) || ch=='\'') { - - if ((ch = yystream[1])) { - - val[0] = (uint32)ch; - - return SCPE_OK; - - } else return SCPE_ARG; - - } - - if ((sw & SWMASK('C')) || ch=='"') { - - if ((ch = yystream[1])) { - - val[0] = ((uint32)ch << 8) | (uint32)yystream[1]; - - return SCPE_OK; - - } else return SCPE_ARG; - - } - - - - yyparse(); - -// sim_printf("rc=%d\n",yyrc); - - if (yyerrc) return SCPE_ARG; - - return yyrc; - -} - - - -static int _genop(t_value arg) - -{ - -// sim_printf("_genop(%x)@%x\n",arg,(int)yyvalptr); - - *yyvalptr = (arg >> 8) & 0xff; - - yyvalptr++; - - *yyvalptr = arg & 0xff; - - yyvalptr++; - - return -1; - -} - - - -static int _genea(struct _ea arg) - -{ - - int i; - - for (i=0; i. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.6.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* First part of user prologue. */ +#line 1 "m68kasm.y" + + +/* m68k_parse.c: line assembler for generic m68k_cpu + + + + Copyright (c) 2009-2010, Holger Veit + + + + Permission is hereby granted, free of charge, to any person obtaining a + + copy of this software and associated documentation files (the "Software"), + + to deal in the Software without restriction, including without limitation + + the rights to use, copy, modify, merge, publish, distribute, sublicense, + + and/or sell copies of the Software, and to permit persons to whom the + + Software is furnished to do so, subject to the following conditions: + + + + The above copyright notice and this permission notice shall be included in + + all copies or substantial portions of the Software. + + + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + + HOLGER VEIT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + Except as contained in this notice, the name of Holger Veit et al shall not be + + used in advertising or otherwise to promote the sale, use or other dealings + + in this Software without prior written authorization from Holger Veit et al. + + + + 04-Oct-09 HV Initial version + + 20-Sep-14 PS Adapted for AltairZ80 + + + + use "bison m68kasm.y -o m68kasm.c" to create m68kasm.c + +*/ + + + +#include "sim_defs.h" + +#include + +#include + + + +struct _ea { + + int ea; + + int cnt; + + t_value arg[10]; + +}; + +struct _rea { + + int reg; + + struct _ea ea; + +}; + +struct _mask { + + int x; + + int d; + +}; + +struct _brop { + + int opc; + + int len; + +}; + + + +static int oplen; + +const static int movemx[] = { 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, + + 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080 }; + +const static int movemd[] = { 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001, + + 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100 }; + +static int yyrc; + +static int yyerrc; + +static int yylex(void); + +static int _genop(t_value arg); + +static int _genea(struct _ea arg); + +static int _genbr(t_value arg,t_value,int); + +static void yyerror(char* s); + + + +#define YYDEBUG 1 + + +#line 141 "m68kasm.c" + +# ifndef YY_CAST +# ifdef __cplusplus +# define YY_CAST(Type, Val) static_cast (Val) +# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) +# else +# define YY_CAST(Type, Val) ((Type) (Val)) +# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) +# endif +# endif +# ifndef YY_NULLPTR +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# else +# define YY_NULLPTR ((void*)0) +# endif +# endif + + +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token kinds. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + A0 = 258, /* A0 */ + A1 = 259, /* A1 */ + A2 = 260, /* A2 */ + A3 = 261, /* A3 */ + A4 = 262, /* A4 */ + A5 = 263, /* A5 */ + A6 = 264, /* A6 */ + A7 = 265, /* A7 */ + D0 = 266, /* D0 */ + D1 = 267, /* D1 */ + D2 = 268, /* D2 */ + D3 = 269, /* D3 */ + D4 = 270, /* D4 */ + D5 = 271, /* D5 */ + D6 = 272, /* D6 */ + D7 = 273, /* D7 */ + CCR = 274, /* CCR */ + SR = 275, /* SR */ + USP = 276, /* USP */ + PC = 277, /* PC */ + NUMBER = 278, /* NUMBER */ + ABCD = 279, /* ABCD */ + ADD = 280, /* ADD */ + ADDA = 281, /* ADDA */ + ADDI = 282, /* ADDI */ + ADDQ = 283, /* ADDQ */ + ADDX = 284, /* ADDX */ + AND = 285, /* AND */ + ANDI = 286, /* ANDI */ + OR = 287, /* OR */ + ORI = 288, /* ORI */ + SBCD = 289, /* SBCD */ + SUB = 290, /* SUB */ + SUBA = 291, /* SUBA */ + SUBI = 292, /* SUBI */ + SUBQ = 293, /* SUBQ */ + SUBX = 294, /* SUBX */ + ASL = 295, /* ASL */ + ASR = 296, /* ASR */ + LSL = 297, /* LSL */ + LSR = 298, /* LSR */ + ROL = 299, /* ROL */ + ROR = 300, /* ROR */ + ROXL = 301, /* ROXL */ + ROXR = 302, /* ROXR */ + BCC = 303, /* BCC */ + BCS = 304, /* BCS */ + BEQ = 305, /* BEQ */ + BGE = 306, /* BGE */ + BGT = 307, /* BGT */ + BHI = 308, /* BHI */ + BLE = 309, /* BLE */ + BLS = 310, /* BLS */ + BLT = 311, /* BLT */ + BMI = 312, /* BMI */ + BNE = 313, /* BNE */ + BPL = 314, /* BPL */ + BVC = 315, /* BVC */ + BVS = 316, /* BVS */ + BSR = 317, /* BSR */ + BRA = 318, /* BRA */ + BCLR = 319, /* BCLR */ + BSET = 320, /* BSET */ + BCHG = 321, /* BCHG */ + BTST = 322, /* BTST */ + CHK = 323, /* CHK */ + CMP = 324, /* CMP */ + CMPA = 325, /* CMPA */ + CMPI = 326, /* CMPI */ + CMPM = 327, /* CMPM */ + EOR = 328, /* EOR */ + EORI = 329, /* EORI */ + EXG = 330, /* EXG */ + EXT = 331, /* EXT */ + DIVU = 332, /* DIVU */ + DIVS = 333, /* DIVS */ + MULU = 334, /* MULU */ + MULS = 335, /* MULS */ + DBCC = 336, /* DBCC */ + DBCS = 337, /* DBCS */ + DBEQ = 338, /* DBEQ */ + DBF = 339, /* DBF */ + DBGE = 340, /* DBGE */ + DBGT = 341, /* DBGT */ + DBHI = 342, /* DBHI */ + DBLE = 343, /* DBLE */ + DBLS = 344, /* DBLS */ + DBLT = 345, /* DBLT */ + DBMI = 346, /* DBMI */ + DBNE = 347, /* DBNE */ + DBPL = 348, /* DBPL */ + DBT = 349, /* DBT */ + DBVC = 350, /* DBVC */ + DBVS = 351, /* DBVS */ + SCC = 352, /* SCC */ + SCS = 353, /* SCS */ + SEQ = 354, /* SEQ */ + SF = 355, /* SF */ + SGE = 356, /* SGE */ + SGT = 357, /* SGT */ + SHI = 358, /* SHI */ + SLE = 359, /* SLE */ + SLS = 360, /* SLS */ + SLT = 361, /* SLT */ + SMI = 362, /* SMI */ + SNE = 363, /* SNE */ + SPL = 364, /* SPL */ + ST = 365, /* ST */ + SVC = 366, /* SVC */ + SVS = 367, /* SVS */ + ILLEGAL = 368, /* ILLEGAL */ + NOP = 369, /* NOP */ + RESET = 370, /* RESET */ + RTE = 371, /* RTE */ + RTR = 372, /* RTR */ + RTS = 373, /* RTS */ + TRAPV = 374, /* TRAPV */ + JMP = 375, /* JMP */ + JSR = 376, /* JSR */ + LEA = 377, /* LEA */ + LINK = 378, /* LINK */ + MOVE = 379, /* MOVE */ + MOVEA = 380, /* MOVEA */ + MOVEM = 381, /* MOVEM */ + MOVEP = 382, /* MOVEP */ + MOVEQ = 383, /* MOVEQ */ + CLR = 384, /* CLR */ + NEG = 385, /* NEG */ + NEGX = 386, /* NEGX */ + NBCD = 387, /* NBCD */ + NOT = 388, /* NOT */ + PEA = 389, /* PEA */ + STOP = 390, /* STOP */ + TAS = 391, /* TAS */ + SWAP = 392, /* SWAP */ + TRAP = 393, /* TRAP */ + TST = 394, /* TST */ + UNLK = 395, /* UNLK */ + PREDEC = 396, /* PREDEC */ + POSTINC = 397, /* POSTINC */ + BSIZE = 398, /* BSIZE */ + WSIZE = 399, /* WSIZE */ + LSIZE = 400, /* LSIZE */ + SSIZE = 401 /* SSIZE */ + }; + typedef enum yytokentype yytoken_kind_t; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +union YYSTYPE +{ +#line 71 "m68kasm.y" + + + int rc; + + int reg; + + int wl; + + int opc; + + struct _ea ea; + + t_value num; + + struct _rea rea; + + struct _mask mask; + + struct _brop brop; + + +#line 346 "m68kasm.c" + +}; +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); + + +/* Symbol kind. */ +enum yysymbol_kind_t +{ + YYSYMBOL_YYEMPTY = -2, + YYSYMBOL_YYEOF = 0, /* "end of file" */ + YYSYMBOL_YYerror = 1, /* error */ + YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ + YYSYMBOL_A0 = 3, /* A0 */ + YYSYMBOL_A1 = 4, /* A1 */ + YYSYMBOL_A2 = 5, /* A2 */ + YYSYMBOL_A3 = 6, /* A3 */ + YYSYMBOL_A4 = 7, /* A4 */ + YYSYMBOL_A5 = 8, /* A5 */ + YYSYMBOL_A6 = 9, /* A6 */ + YYSYMBOL_A7 = 10, /* A7 */ + YYSYMBOL_D0 = 11, /* D0 */ + YYSYMBOL_D1 = 12, /* D1 */ + YYSYMBOL_D2 = 13, /* D2 */ + YYSYMBOL_D3 = 14, /* D3 */ + YYSYMBOL_D4 = 15, /* D4 */ + YYSYMBOL_D5 = 16, /* D5 */ + YYSYMBOL_D6 = 17, /* D6 */ + YYSYMBOL_D7 = 18, /* D7 */ + YYSYMBOL_CCR = 19, /* CCR */ + YYSYMBOL_SR = 20, /* SR */ + YYSYMBOL_USP = 21, /* USP */ + YYSYMBOL_PC = 22, /* PC */ + YYSYMBOL_NUMBER = 23, /* NUMBER */ + YYSYMBOL_ABCD = 24, /* ABCD */ + YYSYMBOL_ADD = 25, /* ADD */ + YYSYMBOL_ADDA = 26, /* ADDA */ + YYSYMBOL_ADDI = 27, /* ADDI */ + YYSYMBOL_ADDQ = 28, /* ADDQ */ + YYSYMBOL_ADDX = 29, /* ADDX */ + YYSYMBOL_AND = 30, /* AND */ + YYSYMBOL_ANDI = 31, /* ANDI */ + YYSYMBOL_OR = 32, /* OR */ + YYSYMBOL_ORI = 33, /* ORI */ + YYSYMBOL_SBCD = 34, /* SBCD */ + YYSYMBOL_SUB = 35, /* SUB */ + YYSYMBOL_SUBA = 36, /* SUBA */ + YYSYMBOL_SUBI = 37, /* SUBI */ + YYSYMBOL_SUBQ = 38, /* SUBQ */ + YYSYMBOL_SUBX = 39, /* SUBX */ + YYSYMBOL_ASL = 40, /* ASL */ + YYSYMBOL_ASR = 41, /* ASR */ + YYSYMBOL_LSL = 42, /* LSL */ + YYSYMBOL_LSR = 43, /* LSR */ + YYSYMBOL_ROL = 44, /* ROL */ + YYSYMBOL_ROR = 45, /* ROR */ + YYSYMBOL_ROXL = 46, /* ROXL */ + YYSYMBOL_ROXR = 47, /* ROXR */ + YYSYMBOL_BCC = 48, /* BCC */ + YYSYMBOL_BCS = 49, /* BCS */ + YYSYMBOL_BEQ = 50, /* BEQ */ + YYSYMBOL_BGE = 51, /* BGE */ + YYSYMBOL_BGT = 52, /* BGT */ + YYSYMBOL_BHI = 53, /* BHI */ + YYSYMBOL_BLE = 54, /* BLE */ + YYSYMBOL_BLS = 55, /* BLS */ + YYSYMBOL_BLT = 56, /* BLT */ + YYSYMBOL_BMI = 57, /* BMI */ + YYSYMBOL_BNE = 58, /* BNE */ + YYSYMBOL_BPL = 59, /* BPL */ + YYSYMBOL_BVC = 60, /* BVC */ + YYSYMBOL_BVS = 61, /* BVS */ + YYSYMBOL_BSR = 62, /* BSR */ + YYSYMBOL_BRA = 63, /* BRA */ + YYSYMBOL_BCLR = 64, /* BCLR */ + YYSYMBOL_BSET = 65, /* BSET */ + YYSYMBOL_BCHG = 66, /* BCHG */ + YYSYMBOL_BTST = 67, /* BTST */ + YYSYMBOL_CHK = 68, /* CHK */ + YYSYMBOL_CMP = 69, /* CMP */ + YYSYMBOL_CMPA = 70, /* CMPA */ + YYSYMBOL_CMPI = 71, /* CMPI */ + YYSYMBOL_CMPM = 72, /* CMPM */ + YYSYMBOL_EOR = 73, /* EOR */ + YYSYMBOL_EORI = 74, /* EORI */ + YYSYMBOL_EXG = 75, /* EXG */ + YYSYMBOL_EXT = 76, /* EXT */ + YYSYMBOL_DIVU = 77, /* DIVU */ + YYSYMBOL_DIVS = 78, /* DIVS */ + YYSYMBOL_MULU = 79, /* MULU */ + YYSYMBOL_MULS = 80, /* MULS */ + YYSYMBOL_DBCC = 81, /* DBCC */ + YYSYMBOL_DBCS = 82, /* DBCS */ + YYSYMBOL_DBEQ = 83, /* DBEQ */ + YYSYMBOL_DBF = 84, /* DBF */ + YYSYMBOL_DBGE = 85, /* DBGE */ + YYSYMBOL_DBGT = 86, /* DBGT */ + YYSYMBOL_DBHI = 87, /* DBHI */ + YYSYMBOL_DBLE = 88, /* DBLE */ + YYSYMBOL_DBLS = 89, /* DBLS */ + YYSYMBOL_DBLT = 90, /* DBLT */ + YYSYMBOL_DBMI = 91, /* DBMI */ + YYSYMBOL_DBNE = 92, /* DBNE */ + YYSYMBOL_DBPL = 93, /* DBPL */ + YYSYMBOL_DBT = 94, /* DBT */ + YYSYMBOL_DBVC = 95, /* DBVC */ + YYSYMBOL_DBVS = 96, /* DBVS */ + YYSYMBOL_SCC = 97, /* SCC */ + YYSYMBOL_SCS = 98, /* SCS */ + YYSYMBOL_SEQ = 99, /* SEQ */ + YYSYMBOL_SF = 100, /* SF */ + YYSYMBOL_SGE = 101, /* SGE */ + YYSYMBOL_SGT = 102, /* SGT */ + YYSYMBOL_SHI = 103, /* SHI */ + YYSYMBOL_SLE = 104, /* SLE */ + YYSYMBOL_SLS = 105, /* SLS */ + YYSYMBOL_SLT = 106, /* SLT */ + YYSYMBOL_SMI = 107, /* SMI */ + YYSYMBOL_SNE = 108, /* SNE */ + YYSYMBOL_SPL = 109, /* SPL */ + YYSYMBOL_ST = 110, /* ST */ + YYSYMBOL_SVC = 111, /* SVC */ + YYSYMBOL_SVS = 112, /* SVS */ + YYSYMBOL_ILLEGAL = 113, /* ILLEGAL */ + YYSYMBOL_NOP = 114, /* NOP */ + YYSYMBOL_RESET = 115, /* RESET */ + YYSYMBOL_RTE = 116, /* RTE */ + YYSYMBOL_RTR = 117, /* RTR */ + YYSYMBOL_RTS = 118, /* RTS */ + YYSYMBOL_TRAPV = 119, /* TRAPV */ + YYSYMBOL_JMP = 120, /* JMP */ + YYSYMBOL_JSR = 121, /* JSR */ + YYSYMBOL_LEA = 122, /* LEA */ + YYSYMBOL_LINK = 123, /* LINK */ + YYSYMBOL_MOVE = 124, /* MOVE */ + YYSYMBOL_MOVEA = 125, /* MOVEA */ + YYSYMBOL_MOVEM = 126, /* MOVEM */ + YYSYMBOL_MOVEP = 127, /* MOVEP */ + YYSYMBOL_MOVEQ = 128, /* MOVEQ */ + YYSYMBOL_CLR = 129, /* CLR */ + YYSYMBOL_NEG = 130, /* NEG */ + YYSYMBOL_NEGX = 131, /* NEGX */ + YYSYMBOL_NBCD = 132, /* NBCD */ + YYSYMBOL_NOT = 133, /* NOT */ + YYSYMBOL_PEA = 134, /* PEA */ + YYSYMBOL_STOP = 135, /* STOP */ + YYSYMBOL_TAS = 136, /* TAS */ + YYSYMBOL_SWAP = 137, /* SWAP */ + YYSYMBOL_TRAP = 138, /* TRAP */ + YYSYMBOL_TST = 139, /* TST */ + YYSYMBOL_UNLK = 140, /* UNLK */ + YYSYMBOL_PREDEC = 141, /* PREDEC */ + YYSYMBOL_POSTINC = 142, /* POSTINC */ + YYSYMBOL_BSIZE = 143, /* BSIZE */ + YYSYMBOL_WSIZE = 144, /* WSIZE */ + YYSYMBOL_LSIZE = 145, /* LSIZE */ + YYSYMBOL_SSIZE = 146, /* SSIZE */ + YYSYMBOL_147_ = 147, /* '#' */ + YYSYMBOL_148_ = 148, /* ',' */ + YYSYMBOL_149_ = 149, /* '/' */ + YYSYMBOL_150_ = 150, /* '-' */ + YYSYMBOL_151_ = 151, /* '(' */ + YYSYMBOL_152_ = 152, /* ')' */ + YYSYMBOL_YYACCEPT = 153, /* $accept */ + YYSYMBOL_stmt = 154, /* stmt */ + YYSYMBOL_arop = 155, /* arop */ + YYSYMBOL_bcdop = 156, /* bcdop */ + YYSYMBOL_dualop = 157, /* dualop */ + YYSYMBOL_immop = 158, /* immop */ + YYSYMBOL_immop2 = 159, /* immop2 */ + YYSYMBOL_qop = 160, /* qop */ + YYSYMBOL_shftop = 161, /* shftop */ + YYSYMBOL_brop = 162, /* brop */ + YYSYMBOL_btop = 163, /* btop */ + YYSYMBOL_monop = 164, /* monop */ + YYSYMBOL_mdop = 165, /* mdop */ + YYSYMBOL_dbop = 166, /* dbop */ + YYSYMBOL_direct = 167, /* direct */ + YYSYMBOL_jop = 168, /* jop */ + YYSYMBOL_shftarg = 169, /* shftarg */ + YYSYMBOL_bcdarg = 170, /* bcdarg */ + YYSYMBOL_dualarg = 171, /* dualarg */ + YYSYMBOL_areg = 172, /* areg */ + YYSYMBOL_dreg = 173, /* dreg */ + YYSYMBOL_szs = 174, /* szs */ + YYSYMBOL_szwl = 175, /* szwl */ + YYSYMBOL_szbwl = 176, /* szbwl */ + YYSYMBOL_szmv = 177, /* szmv */ + YYSYMBOL_szm = 178, /* szm */ + YYSYMBOL_reglist = 179, /* reglist */ + YYSYMBOL_regs = 180, /* regs */ + YYSYMBOL_eama = 181, /* eama */ + YYSYMBOL_eaa = 182, /* eaa */ + YYSYMBOL_ead = 183, /* ead */ + YYSYMBOL_eaall = 184, /* eaall */ + YYSYMBOL_eada = 185, /* eada */ + YYSYMBOL_eadas = 186, /* eadas */ + YYSYMBOL_eac = 187, /* eac */ + YYSYMBOL_eacai = 188, /* eacai */ + YYSYMBOL_eacad = 189, /* eacad */ + YYSYMBOL_ea0 = 190, /* ea0 */ + YYSYMBOL_ea1 = 191, /* ea1 */ + YYSYMBOL_ea2 = 192, /* ea2 */ + YYSYMBOL_ea3 = 193, /* ea3 */ + YYSYMBOL_ea4 = 194, /* ea4 */ + YYSYMBOL_ea5 = 195, /* ea5 */ + YYSYMBOL_ea6 = 196, /* ea6 */ + YYSYMBOL_ea70 = 197, /* ea70 */ + YYSYMBOL_ea72 = 198, /* ea72 */ + YYSYMBOL_ea73 = 199, /* ea73 */ + YYSYMBOL_ea74 = 200, /* ea74 */ + YYSYMBOL_easr = 201 /* easr */ +}; +typedef enum yysymbol_kind_t yysymbol_kind_t; + + + + +#ifdef short +# undef short +#endif + +/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure + and (if available) are included + so that the code can choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_STDINT_H +# endif +#endif + +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#ifdef __INT_LEAST8_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined YY_STDINT_H +typedef int_least8_t yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef __INT_LEAST16_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined YY_STDINT_H +typedef int_least16_t yytype_int16; +#else +typedef short yytype_int16; +#endif + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST8_MAX <= INT_MAX) +typedef uint_least8_t yytype_uint8; +#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ + && UINT_LEAST16_MAX <= INT_MAX) +typedef uint_least16_t yytype_uint16; +#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX +typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; +#endif + +#ifndef YYPTRDIFF_T +# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ +# define YYPTRDIFF_T __PTRDIFF_TYPE__ +# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif +# define YYPTRDIFF_T ptrdiff_t +# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX +# else +# define YYPTRDIFF_T long +# define YYPTRDIFF_MAXIMUM LONG_MAX +# endif +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned +# endif +#endif + +#define YYSIZE_MAXIMUM \ + YY_CAST (YYPTRDIFF_T, \ + (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ + ? YYPTRDIFF_MAXIMUM \ + : YY_CAST (YYSIZE_T, -1))) + +#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) + + +/* Stored state numbers (used for stacks). */ +typedef yytype_int16 yy_state_t; + +/* State numbers in computations. */ +typedef int yy_state_fast_t; + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + + +#ifndef YY_ATTRIBUTE_PURE +# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define YY_ATTRIBUTE_PURE +# endif +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) +# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# else +# define YY_ATTRIBUTE_UNUSED +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + +#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ +# define YY_IGNORE_USELESS_CAST_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") +# define YY_IGNORE_USELESS_CAST_END \ + _Pragma ("GCC diagnostic pop") +#endif +#ifndef YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_BEGIN +# define YY_IGNORE_USELESS_CAST_END +#endif + + +#define YY_ASSERT(E) ((void) (0 && (E))) + +#if !defined yyoverflow + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* !defined yyoverflow */ + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yy_state_t yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYPTRDIFF_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / YYSIZEOF (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYPTRDIFF_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 266 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 928 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 153 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 49 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 276 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 462 + +#define YYMAXUTOK 401 + + +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ +#define YYTRANSLATE(YYX) \ + (0 <= (YYX) && (YYX) <= YYMAXUTOK \ + ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ + : YYSYMBOL_YYUNDEF) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 147, 2, 2, 2, 2, + 151, 152, 2, 2, 148, 150, 2, 149, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 146 +}; + +#if YYDEBUG + /* YYRLINEYYN -- Source line where rule number YYN was defined. */ +static const yytype_int16 yyrline[] = +{ + 0, 112, 112, 113, 114, 116, 117, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, 140, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 160, 161, 164, 165, 166, 167, 171, + 172, 173, 174, 178, 179, 180, 184, 185, 186, 190, + 191, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 249, + 250, 251, 252, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, + 273, 274, 275, 276, 277, 278, 282, 283, 284, 285, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, 301, 302, 303, 304, 308, 309, 310, 311, + 312, 313, 314, 318, 319, 320, 323, 324, 327, 328, + 331, 334, 337, 338, 339, 340, 341, 342, 343, 344, + 347, 348, 349, 350, 351, 352, 353, 354, 357, 360, + 361, 364, 365, 366, 369, 370, 371, 374, 375, 378, + 379, 382, 383, 384, 386, 390, 390, 390, 390, 390, + 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, + 391, 391, 391, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 393, 393, 394, 394, 394, 394, 394, + 394, 394, 395, 395, 396, 396, 396, 396, 396, 396, + 397, 397, 397, 397, 397, 398, 398, 398, 398, 398, + 401, 403, 405, 407, 409, 411, 413, 415, 418, 420, + 423, 424, 426, 428, 431, 435, 436 +}; +#endif + +/** Accessing symbol of state STATE. */ +#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) + +#if YYDEBUG || 0 +/* The user-facing name of the symbol whose (internal) number is + YYSYMBOL. No bounds checking. */ +static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; + +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "\"end of file\"", "error", "\"invalid token\"", "A0", "A1", "A2", "A3", + "A4", "A5", "A6", "A7", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", + "CCR", "SR", "USP", "PC", "NUMBER", "ABCD", "ADD", "ADDA", "ADDI", + "ADDQ", "ADDX", "AND", "ANDI", "OR", "ORI", "SBCD", "SUB", "SUBA", + "SUBI", "SUBQ", "SUBX", "ASL", "ASR", "LSL", "LSR", "ROL", "ROR", "ROXL", + "ROXR", "BCC", "BCS", "BEQ", "BGE", "BGT", "BHI", "BLE", "BLS", "BLT", + "BMI", "BNE", "BPL", "BVC", "BVS", "BSR", "BRA", "BCLR", "BSET", "BCHG", + "BTST", "CHK", "CMP", "CMPA", "CMPI", "CMPM", "EOR", "EORI", "EXG", + "EXT", "DIVU", "DIVS", "MULU", "MULS", "DBCC", "DBCS", "DBEQ", "DBF", + "DBGE", "DBGT", "DBHI", "DBLE", "DBLS", "DBLT", "DBMI", "DBNE", "DBPL", + "DBT", "DBVC", "DBVS", "SCC", "SCS", "SEQ", "SF", "SGE", "SGT", "SHI", + "SLE", "SLS", "SLT", "SMI", "SNE", "SPL", "ST", "SVC", "SVS", "ILLEGAL", + "NOP", "RESET", "RTE", "RTR", "RTS", "TRAPV", "JMP", "JSR", "LEA", + "LINK", "MOVE", "MOVEA", "MOVEM", "MOVEP", "MOVEQ", "CLR", "NEG", "NEGX", + "NBCD", "NOT", "PEA", "STOP", "TAS", "SWAP", "TRAP", "TST", "UNLK", + "PREDEC", "POSTINC", "BSIZE", "WSIZE", "LSIZE", "SSIZE", "'#'", "','", + "'/'", "'-'", "'('", "')'", "$accept", "stmt", "arop", "bcdop", "dualop", + "immop", "immop2", "qop", "shftop", "brop", "btop", "monop", "mdop", + "dbop", "direct", "jop", "shftarg", "bcdarg", "dualarg", "areg", "dreg", + "szs", "szwl", "szbwl", "szmv", "szm", "reglist", "regs", "eama", "eaa", + "ead", "eaall", "eada", "eadas", "eac", "eacai", "eacad", "ea0", "ea1", + "ea2", "ea3", "ea4", "ea5", "ea6", "ea70", "ea72", "ea73", "ea74", + "easr", YY_NULLPTR +}; + +static const char * +yysymbol_name (yysymbol_kind_t yysymbol) +{ + return yytname[yysymbol]; +} +#endif + +#ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_int16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 401, 35, 44, 47, + 45, 40, 41 +}; +#endif + +#define YYPACT_NINF (-343) + +#define yypact_value_is_default(Yyn) \ + ((Yyn) == YYPACT_NINF) + +#define YYTABLE_NINF (-1) + +#define yytable_value_is_error(Yyn) \ + 0 + + /* YYPACTSTATE-NUM -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = +{ + 675, -343, -126, -343, -126, -126, -126, -126, -126, -126, + -126, -343, -126, -343, -126, -126, -126, 456, 456, 456, + 456, 456, 456, 456, 456, -139, -139, -139, -139, -139, + -139, -139, -139, -139, -139, -139, -139, -139, -139, -139, + -139, -343, -343, -343, -343, 477, -126, -107, -126, -126, + -126, -126, 626, -107, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, -343, -343, -343, -20, + 642, 141, -105, -107, -107, -137, -126, -126, -126, -343, + -126, -343, -82, -343, 646, -80, -126, 642, 72, -107, + 557, 18, -72, -65, -50, -343, 78, 31, 76, 477, + 646, -343, -20, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, -343, 642, 85, 203, + -343, 236, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, 236, -343, 236, -343, 236, -343, 236, + -343, 236, -343, 236, -343, 236, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -37, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, 18, -343, -343, 18, -343, -42, + 646, -343, -36, -35, 646, 203, -32, -343, -343, -343, + -343, -343, -343, -29, -27, -19, -343, -343, -343, -13, + 18, -343, -343, 76, 538, 41, 92, -343, -343, -343, + -343, 100, -343, 113, -343, -343, -343, 18, -343, -10, + -9, -343, -8, -7, 119, 120, 129, -343, 131, 8, + 581, -343, -343, -343, -343, -343, -343, -343, -343, 15, + 16, -343, 19, -343, -143, -138, 149, -343, 25, -343, + -343, -343, -343, -343, -343, -343, 646, -343, 27, -343, + 29, 642, 32, 33, 626, 626, -343, 22, 642, 37, + 76, 642, 155, 39, 40, 35, 36, 43, 45, 47, + -343, -343, -343, -343, -343, 166, 51, 54, 57, -343, + -343, 66, 646, 77, 515, 646, 71, 73, 74, 83, + 76, -84, 646, 197, -343, 605, -107, -343, -343, 84, + 646, -343, 646, 642, 93, -42, 76, -343, -343, -343, + -343, -343, 211, -343, -343, -343, 546, 642, 642, 646, + -135, 626, 626, 90, 88, 646, 646, 642, -343, -343, + -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, + 76, 546, 515, 76, -343, 642, -343, -343, -68, -67, + -343, 646, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, 581, -343, -343, -343, + -343, -343, -343, -343, -343, 642, -343, -343, -343, -343, + -343, -343, -343, -343, 626, -343, 626, -343, -343, 91, + -107, -107, -107, -107, 104, 106, 107, 109, -343, -343, + -343, -343 +}; + + /* YYDEFACTSTATE-NUM -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_int16 yydefact[] = +{ + 0, 45, 0, 43, 0, 0, 0, 0, 0, 0, + 0, 47, 0, 44, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 110, 111, 109, 112, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 137, 136, 139, 138, 140, 141, + 142, 154, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 155, 152, 153, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, + 0, 165, 0, 134, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 24, 0, 191, 192, 193, 49, 53, 59, 46, + 50, 56, 51, 58, 52, 55, 60, 48, 172, 173, + 174, 175, 176, 177, 178, 179, 271, 0, 0, 0, + 261, 0, 61, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, 0, 63, 0, 65, 0, 67, 0, + 69, 0, 71, 0, 73, 0, 75, 188, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 180, 181, 182, 183, 184, 185, + 186, 187, 260, 0, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 0, 189, 190, 0, 54, 0, + 0, 57, 0, 0, 0, 0, 0, 244, 245, 246, + 247, 248, 249, 0, 0, 0, 194, 195, 196, 0, + 0, 197, 198, 0, 0, 0, 0, 113, 115, 116, + 117, 0, 40, 0, 135, 42, 1, 0, 2, 0, + 0, 3, 0, 0, 0, 0, 0, 8, 0, 0, + 0, 12, 235, 236, 237, 238, 239, 240, 241, 0, + 0, 25, 0, 274, 0, 0, 0, 62, 0, 64, + 66, 68, 70, 72, 74, 76, 0, 234, 0, 233, + 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, + 0, 0, 0, 0, 0, 201, 202, 0, 199, 0, + 250, 251, 252, 253, 254, 0, 0, 0, 0, 38, + 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 264, 0, 269, 263, 262, 0, + 0, 11, 0, 0, 0, 0, 0, 20, 21, 22, + 19, 26, 0, 29, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 168, 169, + 170, 215, 216, 217, 218, 219, 220, 221, 222, 171, + 0, 0, 0, 0, 9, 0, 14, 17, 0, 0, + 268, 0, 166, 13, 15, 16, 18, 27, 275, 276, + 242, 28, 243, 32, 203, 204, 0, 33, 255, 256, + 257, 258, 259, 200, 34, 0, 35, 36, 37, 39, + 4, 6, 5, 10, 0, 270, 0, 265, 167, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 273, 272, + 267, 266 +}; + + /* YYPGOTONTERM-NUM. */ +static const yytype_int16 yypgoto[] = +{ + -343, -343, -343, -343, -343, -343, -343, -343, -343, -343, + -343, -343, -343, -343, -343, -343, 248, -343, -343, -39, + -51, 811, -53, 812, -343, -343, -276, -343, 559, -162, + 115, -150, -120, -159, 128, -343, -343, -34, -342, -25, + 108, 137, -30, 38, 69, 26, 28, -33, -343 +}; + + /* YYDEFGOTONTERM-NUM. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 118, 119, 120, 121, 122, 123, 124, 125, 126, + 127, 128, 129, 130, 131, 132, 297, 268, 271, 160, + 212, 188, 227, 136, 250, 253, 327, 328, 307, 390, + 213, 308, 420, 421, 236, 329, 427, 282, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 422 +}; + + /* YYTABLEYYPACT[STATE-NUM] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = +{ + 234, 233, 392, 156, 357, 355, 157, 187, 281, 356, + 256, 214, 223, 232, 358, 218, 426, 133, 134, 135, + 215, 148, 149, 150, 151, 152, 153, 154, 155, 204, + 205, 206, 207, 208, 209, 210, 211, 225, 226, 251, + 252, 156, 204, 205, 206, 207, 208, 209, 210, 211, + 254, 255, 204, 205, 206, 207, 208, 209, 210, 211, + 392, 243, 249, 262, 405, 261, 267, 263, 356, 238, + 272, 221, 266, 222, 237, 274, 279, 310, 265, 290, + 444, 446, 275, 219, 445, 447, 269, 204, 205, 206, + 207, 208, 209, 210, 211, 214, 223, 276, 286, 218, + 323, 277, 238, 283, 215, 433, 434, 237, 293, 311, + 298, 306, 314, 315, 220, 338, 318, 341, 292, 319, + 295, 320, 298, 339, 298, 241, 298, 242, 298, 321, + 298, 235, 298, 324, 298, 322, 340, 239, 342, 343, + 344, 345, 346, 347, 148, 149, 150, 151, 152, 153, + 154, 155, 348, 216, 349, 221, 350, 222, 241, 157, + 242, 244, 245, 352, 353, 158, 287, 219, 240, 159, + 239, 354, 359, 360, 358, 362, 375, 363, 278, 313, + 365, 366, 217, 316, 372, 378, 379, 376, 377, 383, + 309, 380, 335, 309, 381, 382, 317, 288, 220, 384, + 373, 240, 385, 326, 336, 386, 148, 149, 150, 151, + 152, 153, 154, 155, 387, 325, 309, 157, 157, 400, + 407, 401, 402, 286, 332, 337, 294, 280, 283, 330, + 404, 403, 411, 309, 417, 357, 284, 216, 435, 335, + 442, 295, 441, 447, 289, 0, 416, 204, 205, 206, + 207, 208, 209, 210, 211, 361, 458, 270, 459, 460, + 291, 461, 0, 368, 370, 285, 217, 0, 0, 0, + 0, 0, 364, 0, 0, 367, 369, 0, 0, 371, + 440, 0, 374, 443, 246, 247, 248, 0, 0, 0, + 286, 287, 333, 0, 399, 283, 0, 0, 0, 0, + 0, 406, 0, 410, 0, 0, 0, 0, 388, 412, + 391, 413, 0, 0, 396, 0, 409, 0, 0, 393, + 286, 0, 288, 334, 414, 283, 0, 0, 425, 0, + 326, 326, 0, 0, 437, 438, 286, 312, 423, 424, + 0, 283, 325, 325, 0, 0, 286, 0, 439, 0, + 430, 283, 0, 0, 436, 428, 0, 0, 287, 0, + 448, 284, 331, 0, 0, 0, 409, 0, 391, 0, + 286, 286, 396, 286, 0, 283, 283, 393, 283, 0, + 0, 0, 397, 296, 0, 0, 0, 317, 287, 288, + 285, 0, 0, 451, 0, 453, 449, 454, 455, 456, + 457, 0, 0, 0, 287, 450, 0, 452, 0, 0, + 0, 0, 0, 398, 287, 0, 0, 0, 431, 288, + 0, 299, 0, 300, 0, 301, 0, 302, 284, 303, + 0, 304, 0, 305, 0, 288, 0, 0, 287, 287, + 397, 287, 0, 0, 0, 288, 0, 0, 0, 432, + 0, 0, 394, 0, 0, 0, 0, 285, 284, 148, + 149, 150, 151, 152, 153, 154, 155, 0, 0, 288, + 288, 398, 288, 415, 284, 0, 0, 0, 0, 156, + 389, 395, 0, 0, 284, 0, 0, 285, 204, 205, + 206, 207, 208, 209, 210, 211, 0, 0, 0, 0, + 156, 0, 0, 285, 0, 0, 0, 0, 284, 284, + 394, 284, 0, 285, 0, 0, 0, 429, 148, 149, + 150, 151, 152, 153, 154, 155, 204, 205, 206, 207, + 208, 209, 210, 211, 0, 0, 0, 285, 285, 395, + 285, 148, 149, 150, 151, 152, 153, 154, 155, 204, + 205, 206, 207, 208, 209, 210, 211, 204, 205, 206, + 207, 208, 209, 210, 211, 418, 419, 0, 204, 205, + 206, 207, 208, 209, 210, 211, 162, 174, 176, 178, + 180, 182, 184, 186, 148, 149, 150, 151, 152, 153, + 154, 155, 0, 0, 0, 0, 0, 157, 0, 133, + 134, 135, 0, 158, 351, 0, 0, 159, 148, 149, + 150, 151, 152, 153, 154, 155, 0, 0, 157, 0, + 0, 0, 0, 0, 158, 0, 0, 408, 159, 148, + 149, 150, 151, 152, 153, 154, 155, 204, 205, 206, + 207, 208, 209, 210, 211, 148, 149, 150, 151, 152, + 153, 154, 155, 0, 0, 0, 157, 204, 205, 206, + 207, 208, 209, 210, 211, 0, 280, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 273, 0, 0, 0, 0, 0, 0, 157, 0, 280, + 0, 0, 0, 0, 0, 0, 0, 280, 157, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 137, 138, 139, 140, + 141, 142, 143, 0, 144, 0, 145, 146, 147, 161, + 173, 175, 177, 179, 181, 183, 185, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 0, 0, 0, 0, 0, 0, 224, 0, + 228, 229, 230, 231, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 257, 258, + 259, 0, 260, 0, 0, 0, 0, 0, 264 +}; + +static const yytype_int16 yycheck[] = +{ + 53, 52, 344, 23, 142, 148, 141, 146, 128, 152, + 147, 45, 45, 52, 152, 45, 151, 143, 144, 145, + 45, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 144, 145, 144, + 145, 23, 11, 12, 13, 14, 15, 16, 17, 18, + 103, 104, 11, 12, 13, 14, 15, 16, 17, 18, + 402, 100, 101, 114, 148, 147, 119, 147, 152, 99, + 121, 45, 0, 45, 99, 147, 127, 227, 117, 130, + 148, 148, 147, 45, 152, 152, 120, 11, 12, 13, + 14, 15, 16, 17, 18, 129, 129, 147, 128, 129, + 250, 23, 132, 128, 129, 381, 382, 132, 23, 151, + 161, 148, 148, 148, 45, 23, 148, 267, 157, 148, + 159, 148, 173, 23, 175, 99, 177, 99, 179, 148, + 181, 151, 183, 253, 185, 148, 23, 99, 148, 148, + 148, 148, 23, 23, 3, 4, 5, 6, 7, 8, + 9, 10, 23, 45, 23, 129, 148, 129, 132, 141, + 132, 20, 21, 148, 148, 147, 128, 129, 99, 151, + 132, 152, 23, 148, 152, 148, 21, 148, 147, 230, + 148, 148, 45, 234, 147, 150, 150, 148, 148, 23, + 224, 148, 151, 227, 149, 148, 235, 128, 129, 148, + 320, 132, 148, 254, 255, 148, 3, 4, 5, 6, + 7, 8, 9, 10, 148, 254, 250, 141, 141, 148, + 23, 148, 148, 253, 254, 255, 23, 151, 253, 254, + 350, 148, 148, 267, 23, 142, 128, 129, 148, 151, + 402, 280, 401, 152, 129, -1, 366, 11, 12, 13, + 14, 15, 16, 17, 18, 306, 152, 120, 152, 152, + 132, 152, -1, 314, 315, 128, 129, -1, -1, -1, + -1, -1, 311, -1, -1, 314, 315, -1, -1, 318, + 400, -1, 321, 403, 143, 144, 145, -1, -1, -1, + 320, 253, 254, -1, 345, 320, -1, -1, -1, -1, + -1, 352, -1, 356, -1, -1, -1, -1, 342, 360, + 344, 362, -1, -1, 344, -1, 355, -1, -1, 344, + 350, -1, 253, 254, 363, 350, -1, -1, 379, -1, + 381, 382, -1, -1, 385, 386, 366, 229, 377, 378, + -1, 366, 381, 382, -1, -1, 376, -1, 387, -1, + 380, 376, -1, -1, 384, 380, -1, -1, 320, -1, + 411, 253, 254, -1, -1, -1, 405, -1, 402, -1, + 400, 401, 402, 403, -1, 400, 401, 402, 403, -1, + -1, -1, 344, 147, -1, -1, -1, 426, 350, 320, + 253, -1, -1, 444, -1, 446, 435, 450, 451, 452, + 453, -1, -1, -1, 366, 444, -1, 446, -1, -1, + -1, -1, -1, 344, 376, -1, -1, -1, 380, 350, + -1, 173, -1, 175, -1, 177, -1, 179, 320, 181, + -1, 183, -1, 185, -1, 366, -1, -1, 400, 401, + 402, 403, -1, -1, -1, 376, -1, -1, -1, 380, + -1, -1, 344, -1, -1, -1, -1, 320, 350, 3, + 4, 5, 6, 7, 8, 9, 10, -1, -1, 400, + 401, 402, 403, 365, 366, -1, -1, -1, -1, 23, + 343, 344, -1, -1, 376, -1, -1, 350, 11, 12, + 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, + 23, -1, -1, 366, -1, -1, -1, -1, 400, 401, + 402, 403, -1, 376, -1, -1, -1, 380, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, -1, -1, -1, 400, 401, 402, + 403, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, -1, 11, 12, + 13, 14, 15, 16, 17, 18, 17, 18, 19, 20, + 21, 22, 23, 24, 3, 4, 5, 6, 7, 8, + 9, 10, -1, -1, -1, -1, -1, 141, -1, 143, + 144, 145, -1, 147, 23, -1, -1, 151, 3, 4, + 5, 6, 7, 8, 9, 10, -1, -1, 141, -1, + -1, -1, -1, -1, 147, -1, -1, 22, 151, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 3, 4, 5, 6, 7, + 8, 9, 10, -1, -1, -1, 141, 11, 12, 13, + 14, 15, 16, 17, 18, -1, 151, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 121, -1, -1, -1, -1, -1, -1, 141, -1, 151, + -1, -1, -1, -1, -1, -1, -1, 151, 141, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 4, 5, 6, 7, + 8, 9, 10, -1, 12, -1, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, -1, -1, -1, -1, -1, -1, 46, -1, + 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 106, 107, + 108, -1, 110, -1, -1, -1, -1, -1, 116 +}; + + /* YYSTOSSTATE-NUM -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, + 166, 167, 168, 143, 144, 145, 176, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 176, 3, 4, + 5, 6, 7, 8, 9, 10, 23, 141, 147, 151, + 172, 176, 181, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 176, 181, 176, 181, 176, 181, 176, + 181, 176, 181, 176, 181, 176, 181, 146, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 11, 12, 13, 14, 15, 16, + 17, 18, 173, 183, 190, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 176, 144, 145, 175, 176, 176, + 176, 176, 172, 173, 175, 151, 187, 192, 195, 196, + 197, 198, 199, 172, 20, 21, 143, 144, 145, 172, + 177, 144, 145, 178, 175, 175, 147, 176, 176, 176, + 176, 147, 173, 147, 176, 172, 0, 175, 170, 190, + 194, 171, 173, 181, 147, 147, 147, 23, 147, 173, + 151, 185, 190, 192, 193, 194, 195, 196, 197, 183, + 173, 187, 172, 23, 23, 172, 147, 169, 173, 169, + 169, 169, 169, 169, 169, 169, 148, 181, 184, 190, + 184, 151, 193, 173, 148, 148, 173, 172, 148, 148, + 148, 148, 148, 184, 185, 172, 173, 179, 180, 188, + 192, 193, 195, 196, 197, 151, 173, 195, 23, 23, + 23, 184, 148, 148, 148, 148, 23, 23, 23, 23, + 148, 23, 148, 148, 152, 148, 152, 142, 152, 23, + 148, 173, 148, 148, 172, 148, 148, 172, 173, 172, + 173, 172, 147, 185, 172, 21, 148, 148, 150, 150, + 148, 149, 148, 23, 148, 148, 148, 148, 190, 194, + 182, 190, 191, 192, 193, 194, 195, 196, 197, 173, + 148, 148, 148, 148, 185, 148, 173, 23, 22, 172, + 175, 148, 173, 173, 172, 193, 185, 23, 19, 20, + 185, 186, 201, 172, 172, 173, 151, 189, 192, 194, + 195, 196, 197, 179, 179, 148, 195, 173, 173, 172, + 185, 186, 182, 185, 148, 152, 148, 152, 173, 172, + 172, 173, 172, 173, 175, 175, 175, 175, 152, 152, + 152, 152 +}; + + /* YYR1YYN -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 153, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, + 154, 154, 154, 155, 155, 156, 156, 156, 156, 157, + 157, 157, 157, 158, 158, 158, 159, 159, 159, 160, + 160, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 163, + 163, 163, 163, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 165, 165, 165, 165, + 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 167, 167, 167, 167, + 167, 167, 167, 168, 168, 168, 169, 169, 170, 170, + 171, 171, 172, 172, 172, 172, 172, 172, 172, 172, + 173, 173, 173, 173, 173, 173, 173, 173, 174, 175, + 175, 176, 176, 176, 177, 177, 177, 178, 178, 179, + 179, 180, 180, 180, 180, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 182, 182, 182, 182, 182, + 182, 182, 182, 183, 183, 183, 183, 183, 183, 183, + 183, 183, 183, 184, 184, 185, 185, 185, 185, 185, + 185, 185, 186, 186, 187, 187, 187, 187, 187, 187, + 188, 188, 188, 188, 188, 189, 189, 189, 189, 189, + 190, 191, 192, 193, 194, 195, 196, 196, 197, 197, + 198, 198, 199, 199, 200, 201, 201 +}; + + /* YYR2YYN -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_int8 yyr2[] = +{ + 0, 2, 2, 2, 5, 5, 5, 1, 2, 4, + 5, 4, 2, 5, 4, 5, 5, 4, 5, 4, + 4, 4, 4, 3, 1, 2, 4, 5, 5, 4, + 4, 4, 5, 5, 5, 5, 5, 5, 3, 5, + 2, 3, 2, 1, 1, 1, 2, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, + 3, 2, 3, 2, 3, 2, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 4, 3, 3, + 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 1, 3, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 3, 3, 5, 8, 8, 4, 3, + 5, 1, 8, 8, 2, 1, 1 +}; + + +enum { YYENOMEM = -2 }; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) + +/* Backward compatibility with an undocumented macro. + Use YYerror or YYUNDEF. */ +#define YYERRCODE YYUNDEF + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +# ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif + + +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Kind, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) +{ + FILE *yyoutput = yyo; + YYUSE (yyoutput); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yykind < YYNTOKENS) + YYPRINT (yyo, yytoknum[yykind], *yyvaluep); +# endif + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ + +static void +yy_symbol_print (FILE *yyo, + yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyo, "%s %s (", + yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); + + yy_symbol_value_print (yyo, yykind, yyvaluep); + YYFPRINTF (yyo, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, + int yyrule) +{ + int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), + &yyvsp[(yyi + 1) - (yynrhs)]); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) ((void) 0) +# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + + + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, + yysymbol_kind_t yykind, YYSTYPE *yyvaluep) +{ + YYUSE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yykind); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + yy_state_fast_t yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* Their size. */ + YYPTRDIFF_T yystacksize; + + /* The state stack. */ + yy_state_t yyssa[YYINITDEPTH]; + yy_state_t *yyss; + yy_state_t *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + int yyn; + /* The return value of yyparse. */ + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yynerrs = 0; + yystate = 0; + yyerrstatus = 0; + + yystacksize = YYINITDEPTH; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + + + YYDPRINTF ((stderr, "Starting parse\n")); + + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + + +/*------------------------------------------------------------. +| yynewstate -- push a new state, which is found in yystate. | +`------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + +/*--------------------------------------------------------------------. +| yysetstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + YY_ASSERT (0 <= yystate && yystate < YYNSTATES); + YY_IGNORE_USELESS_CAST_BEGIN + *yyssp = YY_CAST (yy_state_t, yystate); + YY_IGNORE_USELESS_CAST_END + YY_STACK_PRINT (yyss, yyssp); + + if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else + { + /* Get the current used size of the three stacks, in elements. */ + YYPTRDIFF_T yysize = yyssp - yyss + 1; + +# if defined yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + yy_state_t *yyss1 = yyss; + YYSTYPE *yyvs1 = yyvs; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * YYSIZEOF (*yyssp), + &yyvs1, yysize * YYSIZEOF (*yyvsp), + &yystacksize); + yyss = yyss1; + yyvs = yyvs1; + } +# else /* defined YYSTACK_RELOCATE */ + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yy_state_t *yyss1 = yyss; + union yyalloc *yyptr = + YY_CAST (union yyalloc *, + YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YY_IGNORE_USELESS_CAST_BEGIN + YYDPRINTF ((stderr, "Stack size increased to %ld\n", + YY_CAST (long, yystacksize))); + YY_IGNORE_USELESS_CAST_END + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token\n")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = YYEOF; + yytoken = YYSYMBOL_YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else if (yychar == YYerror) + { + /* The scanner already issued an error message, process directly + to error recovery. But do not keep the error token as + lookahead, it is too special and may lead us to an endless + loop in error recovery. */ + yychar = YYUNDEF; + yytoken = YYSYMBOL_YYerror; + goto yyerrlab1; + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + /* Discard the shifted token. */ + yychar = YYEMPTY; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 112 "m68kasm.y" + { _genop((yyvsp[-1].opc) | (yyvsp[0].opc)); yyrc = -1; } +#line 1979 "m68kasm.c" + break; + + case 3: +#line 113 "m68kasm.y" + { _genop((yyvsp[-1].opc) | (yyvsp[0].rea).reg | (yyvsp[0].rea).ea.ea); yyrc = _genea((yyvsp[0].rea).ea) -1; } +#line 1985 "m68kasm.c" + break; + + case 4: +#line 114 "m68kasm.y" + { _genop((yyvsp[-4].opc) | (yyvsp[0].ea).ea); if (oplen==0) { _genop((yyvsp[-2].num) & 0xff); yyrc = _genea((yyvsp[0].ea)) - 3; } + + else if (oplen==1) { _genop((yyvsp[-2].num)); yyrc = _genea((yyvsp[0].ea)) - 3; } else { _genop((yyvsp[-2].num)>>16); _genop((yyvsp[-2].num) & 0xffff); yyrc = _genea((yyvsp[0].ea))-5; } } +#line 1992 "m68kasm.c" + break; + + case 5: +#line 116 "m68kasm.y" + { _genop((yyvsp[-4].opc) | (((yyvsp[-2].num)&7)<<9) | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } +#line 1998 "m68kasm.c" + break; + + case 6: +#line 117 "m68kasm.y" + { _genop((yyvsp[-4].opc) | (yyvsp[0].ea).ea); if (oplen==0) { _genop((yyvsp[-2].num) & 0xff); yyrc = _genea((yyvsp[0].ea)) - 3; } + + else if (oplen==1) { _genop((yyvsp[-2].num)); yyrc = _genea((yyvsp[0].ea)) - 3; } else { _genop((yyvsp[-2].num)>>16); _genop((yyvsp[-2].num) & 0xffff); yyrc = _genea((yyvsp[0].ea))-5; } } +#line 2005 "m68kasm.c" + break; + + case 7: +#line 119 "m68kasm.y" + { _genop((yyvsp[0].rea).reg); if (((yyvsp[0].rea).reg&0xc0)==0xc0) yyrc = _genea((yyvsp[0].rea).ea) - 1; else { yyrc = -1; } } +#line 2011 "m68kasm.c" + break; + + case 8: +#line 120 "m68kasm.y" + { yyrc = _genbr((yyvsp[-1].brop).opc,(yyvsp[0].num),(yyvsp[-1].brop).len); } +#line 2017 "m68kasm.c" + break; + + case 9: +#line 121 "m68kasm.y" + { _genop((yyvsp[-3].opc) | ((yyvsp[-2].reg)<<9) | 0x100 | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } +#line 2023 "m68kasm.c" + break; + + case 10: +#line 122 "m68kasm.y" + { _genop((yyvsp[-4].opc) | 0x0800 | (yyvsp[0].ea).ea); _genop((yyvsp[-2].num)); yyrc = _genea((yyvsp[0].ea)) - 3; } +#line 2029 "m68kasm.c" + break; + + case 11: +#line 123 "m68kasm.y" + { _genop(0x4180 | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } +#line 2035 "m68kasm.c" + break; + + case 12: +#line 124 "m68kasm.y" + { _genop((yyvsp[-1].opc) | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } +#line 2041 "m68kasm.c" + break; + + case 13: +#line 125 "m68kasm.y" + { _genop(0xb000 | ((yyvsp[-3].wl)<<6) | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } +#line 2047 "m68kasm.c" + break; + + case 14: +#line 126 "m68kasm.y" + { _genop((yyvsp[-3].opc) | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } +#line 2053 "m68kasm.c" + break; + + case 15: +#line 127 "m68kasm.y" + { _genop(0xb0c0 | ((yyvsp[-3].wl)<<8) | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } +#line 2059 "m68kasm.c" + break; + + case 16: +#line 128 "m68kasm.y" + { _genop(0xb108 | ((yyvsp[0].ea).ea<<9) | ((yyvsp[-3].wl)<<6) | (yyvsp[-2].ea).ea); yyrc = -1; } +#line 2065 "m68kasm.c" + break; + + case 17: +#line 129 "m68kasm.y" + { yyrc = _genbr((yyvsp[-3].opc) | (yyvsp[-2].reg), (yyvsp[0].num), 1); } +#line 2071 "m68kasm.c" + break; + + case 18: +#line 130 "m68kasm.y" + { _genop(0xb000 | ((yyvsp[-3].wl) << 6) | 0x100 | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } +#line 2077 "m68kasm.c" + break; + + case 19: +#line 131 "m68kasm.y" + { _genop(0xc140 | ((yyvsp[-2].reg)<<9) | (yyvsp[0].reg)); yyrc = -1; } +#line 2083 "m68kasm.c" + break; + + case 20: +#line 132 "m68kasm.y" + { _genop(0xc148 | ((yyvsp[-2].reg)<<9) | (yyvsp[0].reg)); yyrc = -1; } +#line 2089 "m68kasm.c" + break; + + case 21: +#line 133 "m68kasm.y" + { _genop(0xc188 | ((yyvsp[0].reg)<<9) | (yyvsp[-2].reg)); yyrc = -1; } +#line 2095 "m68kasm.c" + break; + + case 22: +#line 134 "m68kasm.y" + { _genop(0xc188 | ((yyvsp[-2].reg)<<9) | (yyvsp[0].reg)); yyrc = -1; } +#line 2101 "m68kasm.c" + break; + + case 23: +#line 135 "m68kasm.y" + { _genop(0x4840 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].reg)); yyrc = -1; } +#line 2107 "m68kasm.c" + break; + + case 24: +#line 136 "m68kasm.y" + { _genop((yyvsp[0].opc)); yyrc = -1; } +#line 2113 "m68kasm.c" + break; + + case 25: +#line 137 "m68kasm.y" + { _genop((yyvsp[-1].opc) | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) -1; } +#line 2119 "m68kasm.c" + break; + + case 26: +#line 138 "m68kasm.y" + { _genop(0x41c0 | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } +#line 2125 "m68kasm.c" + break; + + case 27: +#line 139 "m68kasm.y" + { _genop(0x4e50 | (yyvsp[-3].reg)); _genop((yyvsp[0].num)); yyrc = -3; } +#line 2131 "m68kasm.c" + break; + + case 28: +#line 140 "m68kasm.y" + { if ((yyvsp[0].ea).ea==074) { _genop(0x44c0 | ((yyvsp[0].ea).cnt==1?0x0200:0x0000) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } + + else { int tmp = (((yyvsp[0].ea).ea&070)>>3)|(((yyvsp[0].ea).ea&7)<<3); _genop(0x0000 | ((yyvsp[-3].wl)<<12) | (tmp<<6) | (yyvsp[-2].ea).ea); + + yyrc = _genea((yyvsp[-2].ea)) - 1; yyrc += _genea((yyvsp[0].ea)); } } +#line 2139 "m68kasm.c" + break; + + case 29: +#line 143 "m68kasm.y" + { _genop(0x40c0 | (yyvsp[0].ea).ea); yyrc = _genea((yyvsp[0].ea)) - 1; } +#line 2145 "m68kasm.c" + break; + + case 30: +#line 144 "m68kasm.y" + { _genop(0x4e68 | (yyvsp[0].reg)); yyrc = -1; } +#line 2151 "m68kasm.c" + break; + + case 31: +#line 145 "m68kasm.y" + { _genop(0x4e60 | (yyvsp[-2].reg)); yyrc = -1; } +#line 2157 "m68kasm.c" + break; + + case 32: +#line 146 "m68kasm.y" + { _genop(0x0040 | ((yyvsp[-3].wl)<<12) | ((yyvsp[0].reg)<<9) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } +#line 2163 "m68kasm.c" + break; + + case 33: +#line 147 "m68kasm.y" + { _genop(0x4880 | ((yyvsp[-3].wl)<<6) | (yyvsp[0].ea).ea); _genop(((yyvsp[0].ea).ea&070)==040 ? (yyvsp[-2].mask).d : (yyvsp[-2].mask).x); yyrc = _genea((yyvsp[0].ea)) - 3; } +#line 2169 "m68kasm.c" + break; + + case 34: +#line 148 "m68kasm.y" + { _genop(0x4c80 | ((yyvsp[-3].wl)<<6) | (yyvsp[-2].ea).ea); _genop((yyvsp[0].mask).x); yyrc = _genea((yyvsp[-2].ea)) - 3; } +#line 2175 "m68kasm.c" + break; + + case 35: +#line 149 "m68kasm.y" + { _genop(0x0108 | ((yyvsp[-2].reg)<<9) | ((yyvsp[-3].wl)<<6) | ((yyvsp[0].ea).ea & 7)); yyrc = _genea((yyvsp[0].ea)) - 1; } +#line 2181 "m68kasm.c" + break; + + case 36: +#line 150 "m68kasm.y" + { _genop(0x0188 | ((yyvsp[0].reg)<<9) | ((yyvsp[-3].wl)<<6) | ((yyvsp[-2].ea).ea & 7)); yyrc = _genea((yyvsp[-2].ea)) - 1; } +#line 2187 "m68kasm.c" + break; + + case 37: +#line 151 "m68kasm.y" + { _genop(0x7000 | ((yyvsp[0].reg)<<9) | ((yyvsp[-2].num)&0xff)); yyrc = -1; } +#line 2193 "m68kasm.c" + break; + + case 38: +#line 152 "m68kasm.y" + { _genop(0x4e72); yyrc = _genop((yyvsp[0].num)&0xffff) - 1; } +#line 2199 "m68kasm.c" + break; + + case 39: +#line 153 "m68kasm.y" + { _genop((yyvsp[-4].opc) | ((yyvsp[0].reg)<<9) | ((yyvsp[-3].wl)<<8) | (yyvsp[-2].ea).ea); yyrc = _genea((yyvsp[-2].ea)) - 1; } +#line 2205 "m68kasm.c" + break; + + case 40: +#line 154 "m68kasm.y" + { _genop(0x4840 | (yyvsp[0].reg)); yyrc = -1; } +#line 2211 "m68kasm.c" + break; + + case 41: +#line 155 "m68kasm.y" + { _genop(0x4e40 | ((yyvsp[0].num) & 0x0f)); yyrc = -1; } +#line 2217 "m68kasm.c" + break; + + case 42: +#line 156 "m68kasm.y" + { _genop(0x4e58 | (yyvsp[0].reg)); yyrc = -1; } +#line 2223 "m68kasm.c" + break; + + case 43: +#line 160 "m68kasm.y" + { (yyval.opc) = 0xd0c0; } +#line 2229 "m68kasm.c" + break; + + case 44: +#line 161 "m68kasm.y" + { (yyval.opc) = 0x90c0; } +#line 2235 "m68kasm.c" + break; + + case 45: +#line 164 "m68kasm.y" + { (yyval.opc) = 0xc100; } +#line 2241 "m68kasm.c" + break; + + case 46: +#line 165 "m68kasm.y" + { (yyval.opc) = 0xd100 | ((yyvsp[0].wl)<<6); } +#line 2247 "m68kasm.c" + break; + + case 47: +#line 166 "m68kasm.y" + { (yyval.opc) = 0x8100; } +#line 2253 "m68kasm.c" + break; + + case 48: +#line 167 "m68kasm.y" + { (yyval.opc) = 0x9100 | ((yyvsp[0].wl)<<6); } +#line 2259 "m68kasm.c" + break; + + case 49: +#line 171 "m68kasm.y" + { (yyval.opc) = 0xd000 | ((yyvsp[0].wl)<<6); } +#line 2265 "m68kasm.c" + break; + + case 50: +#line 172 "m68kasm.y" + { (yyval.opc) = 0xc000 | ((yyvsp[0].wl)<<6); } +#line 2271 "m68kasm.c" + break; + + case 51: +#line 173 "m68kasm.y" + { (yyval.opc) = 0x8000 | ((yyvsp[0].wl)<<6); } +#line 2277 "m68kasm.c" + break; + + case 52: +#line 174 "m68kasm.y" + { (yyval.opc) = 0x9000 | ((yyvsp[0].wl)<<6); } +#line 2283 "m68kasm.c" + break; + + case 53: +#line 178 "m68kasm.y" + { (yyval.opc) = 0x0600 | ((yyvsp[0].wl)<<6); } +#line 2289 "m68kasm.c" + break; + + case 54: +#line 179 "m68kasm.y" + { (yyval.opc) = 0x0c00 | ((yyvsp[0].wl)<<6); } +#line 2295 "m68kasm.c" + break; + + case 55: +#line 180 "m68kasm.y" + { (yyval.opc) = 0x0400 | ((yyvsp[0].wl)<<6); } +#line 2301 "m68kasm.c" + break; + + case 56: +#line 184 "m68kasm.y" + { (yyval.opc) = 0x0200 | ((yyvsp[0].wl)<<6); } +#line 2307 "m68kasm.c" + break; + + case 57: +#line 185 "m68kasm.y" + { (yyval.opc) = 0x0a00 | ((yyvsp[0].wl)<<6); } +#line 2313 "m68kasm.c" + break; + + case 58: +#line 186 "m68kasm.y" + { (yyval.opc) = 0x0000 | ((yyvsp[0].wl)<<6); } +#line 2319 "m68kasm.c" + break; + + case 59: +#line 190 "m68kasm.y" + { (yyval.opc) = 0x5000 | ((yyvsp[0].wl)<<6); } +#line 2325 "m68kasm.c" + break; + + case 60: +#line 191 "m68kasm.y" + { (yyval.opc) = 0x5100 | ((yyvsp[0].wl)<<6); } +#line 2331 "m68kasm.c" + break; + + case 61: +#line 195 "m68kasm.y" + { (yyval.rea).reg = 0xe1c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } +#line 2337 "m68kasm.c" + break; + + case 62: +#line 196 "m68kasm.y" + { (yyval.rea).reg = 0xe100 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } +#line 2343 "m68kasm.c" + break; + + case 63: +#line 197 "m68kasm.y" + { (yyval.rea).reg = 0xe0c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } +#line 2349 "m68kasm.c" + break; + + case 64: +#line 198 "m68kasm.y" + { (yyval.rea).reg = 0xe000 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } +#line 2355 "m68kasm.c" + break; + + case 65: +#line 199 "m68kasm.y" + { (yyval.rea).reg = 0xe3c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } +#line 2361 "m68kasm.c" + break; + + case 66: +#line 200 "m68kasm.y" + { (yyval.rea).reg = 0xe108 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } +#line 2367 "m68kasm.c" + break; + + case 67: +#line 201 "m68kasm.y" + { (yyval.rea).reg = 0xe2c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } +#line 2373 "m68kasm.c" + break; + + case 68: +#line 202 "m68kasm.y" + { (yyval.rea).reg = 0xe008 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } +#line 2379 "m68kasm.c" + break; + + case 69: +#line 203 "m68kasm.y" + { (yyval.rea).reg = 0xe7c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } +#line 2385 "m68kasm.c" + break; + + case 70: +#line 204 "m68kasm.y" + { (yyval.rea).reg = 0xe118 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } +#line 2391 "m68kasm.c" + break; + + case 71: +#line 205 "m68kasm.y" + { (yyval.rea).reg = 0xe6c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } +#line 2397 "m68kasm.c" + break; + + case 72: +#line 206 "m68kasm.y" + { (yyval.rea).reg = 0xe018 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } +#line 2403 "m68kasm.c" + break; + + case 73: +#line 207 "m68kasm.y" + { (yyval.rea).reg = 0xe5c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } +#line 2409 "m68kasm.c" + break; + + case 74: +#line 208 "m68kasm.y" + { (yyval.rea).reg = 0xe100 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } +#line 2415 "m68kasm.c" + break; + + case 75: +#line 209 "m68kasm.y" + { (yyval.rea).reg = 0xe4c0 | (yyvsp[0].ea).ea; (yyval.rea).ea = (yyvsp[0].ea); } +#line 2421 "m68kasm.c" + break; + + case 76: +#line 210 "m68kasm.y" + { (yyval.rea).reg = 0xe000 | ((yyvsp[-1].wl)<<6) | (yyvsp[0].opc); } +#line 2427 "m68kasm.c" + break; + + case 77: +#line 214 "m68kasm.y" + { (yyval.brop).opc = 0x6400; (yyval.brop).len = 1; } +#line 2433 "m68kasm.c" + break; + + case 78: +#line 215 "m68kasm.y" + { (yyval.brop).opc = 0x6500; (yyval.brop).len = 1; } +#line 2439 "m68kasm.c" + break; + + case 79: +#line 216 "m68kasm.y" + { (yyval.brop).opc = 0x6700; (yyval.brop).len = 1; } +#line 2445 "m68kasm.c" + break; + + case 80: +#line 217 "m68kasm.y" + { (yyval.brop).opc = 0x6c00; (yyval.brop).len = 1; } +#line 2451 "m68kasm.c" + break; + + case 81: +#line 218 "m68kasm.y" + { (yyval.brop).opc = 0x6e00; (yyval.brop).len = 1; } +#line 2457 "m68kasm.c" + break; + + case 82: +#line 219 "m68kasm.y" + { (yyval.brop).opc = 0x6200; (yyval.brop).len = 1; } +#line 2463 "m68kasm.c" + break; + + case 83: +#line 220 "m68kasm.y" + { (yyval.brop).opc = 0x6f00; (yyval.brop).len = 1; } +#line 2469 "m68kasm.c" + break; + + case 84: +#line 221 "m68kasm.y" + { (yyval.brop).opc = 0x6300; (yyval.brop).len = 1; } +#line 2475 "m68kasm.c" + break; + + case 85: +#line 222 "m68kasm.y" + { (yyval.brop).opc = 0x6d00; (yyval.brop).len = 1; } +#line 2481 "m68kasm.c" + break; + + case 86: +#line 223 "m68kasm.y" + { (yyval.brop).opc = 0x6b00; (yyval.brop).len = 1; } +#line 2487 "m68kasm.c" + break; + + case 87: +#line 224 "m68kasm.y" + { (yyval.brop).opc = 0x6600; (yyval.brop).len = 1; } +#line 2493 "m68kasm.c" + break; + + case 88: +#line 225 "m68kasm.y" + { (yyval.brop).opc = 0x6a00; (yyval.brop).len = 1; } +#line 2499 "m68kasm.c" + break; + + case 89: +#line 226 "m68kasm.y" + { (yyval.brop).opc = 0x6800; (yyval.brop).len = 1; } +#line 2505 "m68kasm.c" + break; + + case 90: +#line 227 "m68kasm.y" + { (yyval.brop).opc = 0x6900; (yyval.brop).len = 1; } +#line 2511 "m68kasm.c" + break; + + case 91: +#line 228 "m68kasm.y" + { (yyval.brop).opc = 0x6100; (yyval.brop).len = 1; } +#line 2517 "m68kasm.c" + break; + + case 92: +#line 229 "m68kasm.y" + { (yyval.brop).opc = 0x6000; (yyval.brop).len = 1; } +#line 2523 "m68kasm.c" + break; + + case 93: +#line 230 "m68kasm.y" + { (yyval.brop).opc = 0x6400; (yyval.brop).len = 0; } +#line 2529 "m68kasm.c" + break; + + case 94: +#line 231 "m68kasm.y" + { (yyval.brop).opc = 0x6500; (yyval.brop).len = 0; } +#line 2535 "m68kasm.c" + break; + + case 95: +#line 232 "m68kasm.y" + { (yyval.brop).opc = 0x6700; (yyval.brop).len = 0; } +#line 2541 "m68kasm.c" + break; + + case 96: +#line 233 "m68kasm.y" + { (yyval.brop).opc = 0x6c00; (yyval.brop).len = 0; } +#line 2547 "m68kasm.c" + break; + + case 97: +#line 234 "m68kasm.y" + { (yyval.brop).opc = 0x6e00; (yyval.brop).len = 0; } +#line 2553 "m68kasm.c" + break; + + case 98: +#line 235 "m68kasm.y" + { (yyval.brop).opc = 0x6200; (yyval.brop).len = 0; } +#line 2559 "m68kasm.c" + break; + + case 99: +#line 236 "m68kasm.y" + { (yyval.brop).opc = 0x6f00; (yyval.brop).len = 0; } +#line 2565 "m68kasm.c" + break; + + case 100: +#line 237 "m68kasm.y" + { (yyval.brop).opc = 0x6300; (yyval.brop).len = 0; } +#line 2571 "m68kasm.c" + break; + + case 101: +#line 238 "m68kasm.y" + { (yyval.brop).opc = 0x6d00; (yyval.brop).len = 0; } +#line 2577 "m68kasm.c" + break; + + case 102: +#line 239 "m68kasm.y" + { (yyval.brop).opc = 0x6b00; (yyval.brop).len = 0; } +#line 2583 "m68kasm.c" + break; + + case 103: +#line 240 "m68kasm.y" + { (yyval.brop).opc = 0x6600; (yyval.brop).len = 0; } +#line 2589 "m68kasm.c" + break; + + case 104: +#line 241 "m68kasm.y" + { (yyval.brop).opc = 0x6a00; (yyval.brop).len = 0; } +#line 2595 "m68kasm.c" + break; + + case 105: +#line 242 "m68kasm.y" + { (yyval.brop).opc = 0x6800; (yyval.brop).len = 0; } +#line 2601 "m68kasm.c" + break; + + case 106: +#line 243 "m68kasm.y" + { (yyval.brop).opc = 0x6900; (yyval.brop).len = 0; } +#line 2607 "m68kasm.c" + break; + + case 107: +#line 244 "m68kasm.y" + { (yyval.brop).opc = 0x6100; (yyval.brop).len = 0; } +#line 2613 "m68kasm.c" + break; + + case 108: +#line 245 "m68kasm.y" + { (yyval.brop).opc = 0x6000; (yyval.brop).len = 0; } +#line 2619 "m68kasm.c" + break; + + case 109: +#line 249 "m68kasm.y" + { (yyval.opc) = 0x0040; } +#line 2625 "m68kasm.c" + break; + + case 110: +#line 250 "m68kasm.y" + { (yyval.opc) = 0x0080; } +#line 2631 "m68kasm.c" + break; + + case 111: +#line 251 "m68kasm.y" + { (yyval.opc) = 0x00c0; } +#line 2637 "m68kasm.c" + break; + + case 112: +#line 252 "m68kasm.y" + { (yyval.opc) = 0x0000; } +#line 2643 "m68kasm.c" + break; + + case 113: +#line 256 "m68kasm.y" + { (yyval.opc) = 0x4200 | ((yyvsp[0].wl)<<6); } +#line 2649 "m68kasm.c" + break; + + case 114: +#line 257 "m68kasm.y" + { (yyval.opc) = 0x4800; } +#line 2655 "m68kasm.c" + break; + + case 115: +#line 258 "m68kasm.y" + { (yyval.opc) = 0x4400 | ((yyvsp[0].wl)<<6); } +#line 2661 "m68kasm.c" + break; + + case 116: +#line 259 "m68kasm.y" + { (yyval.opc) = 0x4000 | ((yyvsp[0].wl)<<6); } +#line 2667 "m68kasm.c" + break; + + case 117: +#line 260 "m68kasm.y" + { (yyval.opc) = 0x4600 | ((yyvsp[0].wl)<<6); } +#line 2673 "m68kasm.c" + break; + + case 118: +#line 261 "m68kasm.y" + { (yyval.opc) = 0x54c0; } +#line 2679 "m68kasm.c" + break; + + case 119: +#line 262 "m68kasm.y" + { (yyval.opc) = 0x55c0; } +#line 2685 "m68kasm.c" + break; + + case 120: +#line 263 "m68kasm.y" + { (yyval.opc) = 0x57c0; } +#line 2691 "m68kasm.c" + break; + + case 121: +#line 264 "m68kasm.y" + { (yyval.opc) = 0x51c0; } +#line 2697 "m68kasm.c" + break; + + case 122: +#line 265 "m68kasm.y" + { (yyval.opc) = 0x5cc0; } +#line 2703 "m68kasm.c" + break; + + case 123: +#line 266 "m68kasm.y" + { (yyval.opc) = 0x5ec0; } +#line 2709 "m68kasm.c" + break; + + case 124: +#line 267 "m68kasm.y" + { (yyval.opc) = 0x52c0; } +#line 2715 "m68kasm.c" + break; + + case 125: +#line 268 "m68kasm.y" + { (yyval.opc) = 0x5fc0; } +#line 2721 "m68kasm.c" + break; + + case 126: +#line 269 "m68kasm.y" + { (yyval.opc) = 0x53c0; } +#line 2727 "m68kasm.c" + break; + + case 127: +#line 270 "m68kasm.y" + { (yyval.opc) = 0x5dc0; } +#line 2733 "m68kasm.c" + break; + + case 128: +#line 271 "m68kasm.y" + { (yyval.opc) = 0x5bc0; } +#line 2739 "m68kasm.c" + break; + + case 129: +#line 272 "m68kasm.y" + { (yyval.opc) = 0x56c0; } +#line 2745 "m68kasm.c" + break; + + case 130: +#line 273 "m68kasm.y" + { (yyval.opc) = 0x5ac0; } +#line 2751 "m68kasm.c" + break; + + case 131: +#line 274 "m68kasm.y" + { (yyval.opc) = 0x50c0; } +#line 2757 "m68kasm.c" + break; + + case 132: +#line 275 "m68kasm.y" + { (yyval.opc) = 0x58c0; } +#line 2763 "m68kasm.c" + break; + + case 133: +#line 276 "m68kasm.y" + { (yyval.opc) = 0x59c0; } +#line 2769 "m68kasm.c" + break; + + case 134: +#line 277 "m68kasm.y" + { (yyval.opc) = 0x4ac0; } +#line 2775 "m68kasm.c" + break; + + case 135: +#line 278 "m68kasm.y" + { (yyval.opc) = 0x4a00 | ((yyvsp[0].wl)<<6); } +#line 2781 "m68kasm.c" + break; + + case 136: +#line 282 "m68kasm.y" + { (yyval.opc) = 0x81c0; } +#line 2787 "m68kasm.c" + break; + + case 137: +#line 283 "m68kasm.y" + { (yyval.opc) = 0x80c0; } +#line 2793 "m68kasm.c" + break; + + case 138: +#line 284 "m68kasm.y" + { (yyval.opc) = 0xc1c0; } +#line 2799 "m68kasm.c" + break; + + case 139: +#line 285 "m68kasm.y" + { (yyval.opc) = 0xc0c0; } +#line 2805 "m68kasm.c" + break; + + case 140: +#line 289 "m68kasm.y" + { (yyval.opc) = 0x54c8; } +#line 2811 "m68kasm.c" + break; + + case 141: +#line 290 "m68kasm.y" + { (yyval.opc) = 0x55c8; } +#line 2817 "m68kasm.c" + break; + + case 142: +#line 291 "m68kasm.y" + { (yyval.opc) = 0x57c8; } +#line 2823 "m68kasm.c" + break; + + case 143: +#line 292 "m68kasm.y" + { (yyval.opc) = 0x5cc8; } +#line 2829 "m68kasm.c" + break; + + case 144: +#line 293 "m68kasm.y" + { (yyval.opc) = 0x5ec8; } +#line 2835 "m68kasm.c" + break; + + case 145: +#line 294 "m68kasm.y" + { (yyval.opc) = 0x52c8; } +#line 2841 "m68kasm.c" + break; + + case 146: +#line 295 "m68kasm.y" + { (yyval.opc) = 0x5fc8; } +#line 2847 "m68kasm.c" + break; + + case 147: +#line 296 "m68kasm.y" + { (yyval.opc) = 0x53c8; } +#line 2853 "m68kasm.c" + break; + + case 148: +#line 297 "m68kasm.y" + { (yyval.opc) = 0x5dc8; } +#line 2859 "m68kasm.c" + break; + + case 149: +#line 298 "m68kasm.y" + { (yyval.opc) = 0x5bc8; } +#line 2865 "m68kasm.c" + break; + + case 150: +#line 299 "m68kasm.y" + { (yyval.opc) = 0x56c8; } +#line 2871 "m68kasm.c" + break; + + case 151: +#line 300 "m68kasm.y" + { (yyval.opc) = 0x5ac8; } +#line 2877 "m68kasm.c" + break; + + case 152: +#line 301 "m68kasm.y" + { (yyval.opc) = 0x58c8; } +#line 2883 "m68kasm.c" + break; + + case 153: +#line 302 "m68kasm.y" + { (yyval.opc) = 0x59c8; } +#line 2889 "m68kasm.c" + break; + + case 154: +#line 303 "m68kasm.y" + { (yyval.opc) = 0x51c8; } +#line 2895 "m68kasm.c" + break; + + case 155: +#line 304 "m68kasm.y" + { (yyval.opc) = 0x50c8; } +#line 2901 "m68kasm.c" + break; + + case 156: +#line 308 "m68kasm.y" + { (yyval.opc) = 0x4afc; } +#line 2907 "m68kasm.c" + break; + + case 157: +#line 309 "m68kasm.y" + { (yyval.opc) = 0x4e71; } +#line 2913 "m68kasm.c" + break; + + case 158: +#line 310 "m68kasm.y" + { (yyval.opc) = 0x4e70; } +#line 2919 "m68kasm.c" + break; + + case 159: +#line 311 "m68kasm.y" + { (yyval.opc) = 0x4e73; } +#line 2925 "m68kasm.c" + break; + + case 160: +#line 312 "m68kasm.y" + { (yyval.opc) = 0x4e77; } +#line 2931 "m68kasm.c" + break; + + case 161: +#line 313 "m68kasm.y" + { (yyval.opc) = 0x4e75; } +#line 2937 "m68kasm.c" + break; + + case 162: +#line 314 "m68kasm.y" + { (yyval.opc) = 0x4e76; } +#line 2943 "m68kasm.c" + break; + + case 163: +#line 318 "m68kasm.y" + { (yyval.opc) = 0x4ec0; } +#line 2949 "m68kasm.c" + break; + + case 164: +#line 319 "m68kasm.y" + { (yyval.opc) = 0x4e80; } +#line 2955 "m68kasm.c" + break; + + case 165: +#line 320 "m68kasm.y" + { (yyval.opc) = 0x4840; } +#line 2961 "m68kasm.c" + break; + + case 166: +#line 323 "m68kasm.y" + { (yyval.opc) = ((yyvsp[-2].reg)<<9) | 0x20 | (yyvsp[0].reg); } +#line 2967 "m68kasm.c" + break; + + case 167: +#line 324 "m68kasm.y" + { (yyval.opc) = (((yyvsp[-2].num) & 7)<<9) | (yyvsp[0].reg); } +#line 2973 "m68kasm.c" + break; + + case 168: +#line 327 "m68kasm.y" + { (yyval.opc) = (((yyvsp[-2].ea).ea & 7) << 9) | ((yyvsp[0].ea).ea & 7); } +#line 2979 "m68kasm.c" + break; + + case 169: +#line 328 "m68kasm.y" + { (yyval.opc) = (((yyvsp[-2].ea).ea & 7) << 9) | 0x0008 | ((yyvsp[0].ea).ea & 7); } +#line 2985 "m68kasm.c" + break; + + case 170: +#line 331 "m68kasm.y" + { if (((yyvsp[0].ea).ea & 070)==0) { /* dx,dy must be swapped */ + + (yyval.rea).reg = ((yyvsp[0].ea).ea & 7)<<9; (yyvsp[0].ea).ea = (yyvsp[-2].reg) & 7; (yyval.rea).ea = (yyvsp[0].ea); } + + else { (yyval.rea).reg = ((yyvsp[-2].reg)<<9) | 0x100; (yyval.rea).ea = (yyvsp[0].ea); } } +#line 2993 "m68kasm.c" + break; + + case 171: +#line 334 "m68kasm.y" + { (yyval.rea).reg = ((yyvsp[0].reg)<<9); (yyval.rea).ea = (yyvsp[-2].ea); } +#line 2999 "m68kasm.c" + break; + + case 172: +#line 337 "m68kasm.y" + { (yyval.reg)=0; } +#line 3005 "m68kasm.c" + break; + + case 173: +#line 338 "m68kasm.y" + { (yyval.reg)=1; } +#line 3011 "m68kasm.c" + break; + + case 174: +#line 339 "m68kasm.y" + { (yyval.reg)=2; } +#line 3017 "m68kasm.c" + break; + + case 175: +#line 340 "m68kasm.y" + { (yyval.reg)=3; } +#line 3023 "m68kasm.c" + break; + + case 176: +#line 341 "m68kasm.y" + { (yyval.reg)=4; } +#line 3029 "m68kasm.c" + break; + + case 177: +#line 342 "m68kasm.y" + { (yyval.reg)=5; } +#line 3035 "m68kasm.c" + break; + + case 178: +#line 343 "m68kasm.y" + { (yyval.reg)=6; } +#line 3041 "m68kasm.c" + break; + + case 179: +#line 344 "m68kasm.y" + { (yyval.reg)=7; } +#line 3047 "m68kasm.c" + break; + + case 180: +#line 347 "m68kasm.y" + { (yyval.reg)=0; } +#line 3053 "m68kasm.c" + break; + + case 181: +#line 348 "m68kasm.y" + { (yyval.reg)=1; } +#line 3059 "m68kasm.c" + break; + + case 182: +#line 349 "m68kasm.y" + { (yyval.reg)=2; } +#line 3065 "m68kasm.c" + break; + + case 183: +#line 350 "m68kasm.y" + { (yyval.reg)=3; } +#line 3071 "m68kasm.c" + break; + + case 184: +#line 351 "m68kasm.y" + { (yyval.reg)=4; } +#line 3077 "m68kasm.c" + break; + + case 185: +#line 352 "m68kasm.y" + { (yyval.reg)=5; } +#line 3083 "m68kasm.c" + break; + + case 186: +#line 353 "m68kasm.y" + { (yyval.reg)=6; } +#line 3089 "m68kasm.c" + break; + + case 187: +#line 354 "m68kasm.y" + { (yyval.reg)=7; } +#line 3095 "m68kasm.c" + break; + + case 188: +#line 357 "m68kasm.y" + { (yyval.wl) = 1; oplen = 0; } +#line 3101 "m68kasm.c" + break; + + case 189: +#line 360 "m68kasm.y" + { (yyval.wl) = 0; oplen = 1; } +#line 3107 "m68kasm.c" + break; + + case 190: +#line 361 "m68kasm.y" + { (yyval.wl) = 1; oplen = 2; } +#line 3113 "m68kasm.c" + break; + + case 191: +#line 364 "m68kasm.y" + { (yyval.wl) = 0; oplen = 0; } +#line 3119 "m68kasm.c" + break; + + case 192: +#line 365 "m68kasm.y" + { (yyval.wl) = 1; oplen = 1; } +#line 3125 "m68kasm.c" + break; + + case 193: +#line 366 "m68kasm.y" + { (yyval.wl) = 2; oplen = 2; } +#line 3131 "m68kasm.c" + break; + + case 194: +#line 369 "m68kasm.y" + { (yyval.wl) = 1; oplen = 0; } +#line 3137 "m68kasm.c" + break; + + case 195: +#line 370 "m68kasm.y" + { (yyval.wl) = 3; oplen = 1; } +#line 3143 "m68kasm.c" + break; + + case 196: +#line 371 "m68kasm.y" + { (yyval.wl) = 2; oplen = 2; } +#line 3149 "m68kasm.c" + break; + + case 197: +#line 374 "m68kasm.y" + { (yyval.wl) = 3; oplen = 1; } +#line 3155 "m68kasm.c" + break; + + case 198: +#line 375 "m68kasm.y" + { (yyval.wl) = 2; oplen = 2; } +#line 3161 "m68kasm.c" + break; + + case 199: +#line 378 "m68kasm.y" + { (yyval.mask) = (yyvsp[0].mask); } +#line 3167 "m68kasm.c" + break; + + case 200: +#line 379 "m68kasm.y" + { (yyval.mask).x = (yyvsp[-2].mask).x | (yyvsp[0].mask).x; (yyval.mask).d = (yyvsp[-2].mask).d | (yyvsp[0].mask).d; } +#line 3173 "m68kasm.c" + break; + + case 201: +#line 382 "m68kasm.y" + { (yyval.mask).x = movemx[(yyvsp[0].reg)]; (yyval.mask).d = movemd[(yyvsp[0].reg)]; } +#line 3179 "m68kasm.c" + break; + + case 202: +#line 383 "m68kasm.y" + { (yyval.mask).x = movemx[(yyvsp[0].reg)+8]; (yyval.mask).d = movemd[(yyvsp[0].reg)+8]; } +#line 3185 "m68kasm.c" + break; + + case 203: +#line 384 "m68kasm.y" + { int i,l=(yyvsp[-2].reg),h=(yyvsp[0].reg); if (l>h) { l=(yyvsp[0].reg); h=(yyvsp[-2].reg); } (yyval.mask).x = (yyval.mask).d = 0; + + for (i=l; i<=h; i++) { (yyval.mask).d |= movemx[i]; (yyval.mask).d |= movemd[i]; } } +#line 3192 "m68kasm.c" + break; + + case 204: +#line 386 "m68kasm.y" + { int i,l=(yyvsp[-2].reg),h=(yyvsp[0].reg); if (l>h) { l=(yyvsp[0].reg); h=(yyvsp[-2].reg); } (yyval.mask).x = (yyval.mask).d = 0; + + for (i=l; i<=h; i++) { (yyval.mask).x |= movemx[i+8]; (yyval.mask).d |= movemd[i+8]; } } +#line 3199 "m68kasm.c" + break; + + case 260: +#line 401 "m68kasm.y" + { (yyval.ea).ea = (yyvsp[0].reg); (yyval.ea).cnt = 0; } +#line 3205 "m68kasm.c" + break; + + case 261: +#line 403 "m68kasm.y" + { (yyval.ea).ea = 010 | (yyvsp[0].reg); (yyval.ea).cnt = 0; } +#line 3211 "m68kasm.c" + break; + + case 262: +#line 405 "m68kasm.y" + { (yyval.ea).ea = 020 | (yyvsp[-1].reg); (yyval.ea).cnt = 0; } +#line 3217 "m68kasm.c" + break; + + case 263: +#line 407 "m68kasm.y" + { (yyval.ea).ea = 030 | (yyvsp[-1].reg); (yyval.ea).cnt = 0; } +#line 3223 "m68kasm.c" + break; + + case 264: +#line 409 "m68kasm.y" + { (yyval.ea).ea = 040 | (yyvsp[-1].reg); (yyval.ea).cnt = 0; } +#line 3229 "m68kasm.c" + break; + + case 265: +#line 411 "m68kasm.y" + { (yyval.ea).ea = 050 | (yyvsp[-1].reg); (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[-3].num); } +#line 3235 "m68kasm.c" + break; + + case 266: +#line 414 "m68kasm.y" + { (yyval.ea).ea = 060 | (yyvsp[-4].reg); (yyval.ea).cnt = 1; (yyval.ea).arg[0] = 0x8000 | ((yyvsp[-2].reg)<<12) | ((yyvsp[-1].wl)<<11) | ((yyvsp[-6].num) & 0xff); } +#line 3241 "m68kasm.c" + break; + + case 267: +#line 416 "m68kasm.y" + { (yyval.ea).ea = 060 | (yyvsp[-4].reg); (yyval.ea).cnt = 1; (yyval.ea).arg[0] = ((yyvsp[-2].reg)<<12) | ((yyvsp[-1].wl)<<11) | ((yyvsp[-6].num) & 0xff); } +#line 3247 "m68kasm.c" + break; + + case 268: +#line 418 "m68kasm.y" + { if ((yyvsp[0].wl)==0) { (yyval.ea).ea = 070; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[-2].num); } + + else { (yyval.ea).ea = 071; (yyval.ea).cnt = 2; (yyval.ea).arg[0] = (yyvsp[-2].num) >> 16; (yyval.ea).arg[1] = (yyvsp[-2].num) & 0xffff; } } +#line 3254 "m68kasm.c" + break; + + case 269: +#line 420 "m68kasm.y" + { int tmp = ((yyvsp[-1].num)>>15) & 0x1ffff; if (tmp==0 || tmp==0x1ffff) { (yyval.ea).ea = 070; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[-1].num); } + + else { (yyval.ea).ea = 070; (yyval.ea).cnt = 2; (yyval.ea).arg[0] = (yyvsp[-1].num) >> 16; (yyval.ea).arg[1] = (yyvsp[-1].num) & 0xffff; } } +#line 3261 "m68kasm.c" + break; + + case 270: +#line 423 "m68kasm.y" + { (yyval.ea).ea = 072; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[-3].num); } +#line 3267 "m68kasm.c" + break; + + case 271: +#line 424 "m68kasm.y" + { (yyval.ea).ea = 072; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[0].num); } +#line 3273 "m68kasm.c" + break; + + case 272: +#line 427 "m68kasm.y" + { (yyval.ea).ea = 073; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = 0x8000 | ((yyvsp[-2].reg)<<12) | ((yyvsp[-1].wl)<<11) | ((yyvsp[-6].num) & 0xff); } +#line 3279 "m68kasm.c" + break; + + case 273: +#line 429 "m68kasm.y" + { (yyval.ea).ea = 073; (yyval.ea).cnt = 1; (yyval.ea).arg[0] = ((yyvsp[-2].reg)<<12) | ((yyvsp[-1].wl)<<11) | ((yyvsp[-6].num) & 0xff); } +#line 3285 "m68kasm.c" + break; + + case 274: +#line 431 "m68kasm.y" + { (yyval.ea).ea = 074; if (oplen==0) { (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[0].num) & 0xff; } + + else if (oplen==1) { (yyval.ea).cnt = 1; (yyval.ea).arg[0] = (yyvsp[0].num) & 0xffff; } + + else { (yyval.ea).cnt = 2; (yyval.ea).arg[0] = (yyvsp[0].num) >> 16; (yyval.ea).arg[1] = (yyvsp[0].num) & 0xffff; } } +#line 3293 "m68kasm.c" + break; + + case 275: +#line 435 "m68kasm.y" + { (yyval.ea).ea = 074; (yyval.ea).cnt = 0; } +#line 3299 "m68kasm.c" + break; + + case 276: +#line 436 "m68kasm.y" + { (yyval.ea).ea = 074; (yyval.ea).cnt = 1; } +#line 3305 "m68kasm.c" + break; + + +#line 3309 "m68kasm.c" + + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + yyerror (YY_("syntax error")); + } + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + /* Pop stack until we find a state that shifts the error token. */ + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYSYMBOL_YYerror; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + YY_ACCESSING_SYMBOL (yystate), yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + + +#if !defined yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + YY_ACCESSING_SYMBOL (+*yyssp), yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + + return yyresult; +} + +#line 437 "m68kasm.y" + + + + +static void yyerror(char* s) + +{ + + /* do not emit anything, but set error flag */ + + yyerrc = 1; + +} + + + +struct _optable { + + char* mnem; + + int token; + +}; + + + +static struct _optable ops[] = { + + { "abcd", ABCD }, { "add", ADD }, { "adda", ADDA }, { "addi", ADDI }, + + { "addq", ADDQ }, { "addx", ADDX }, { "and", AND }, { "andi", ANDI }, + + { "asl", ASL }, { "asr", ASR }, { "bcc", BCC }, { "bcs", BCS }, + + { "beq", BEQ }, { "bge", BGE }, { "bgt", BGT }, { "bhi", BHI }, + + { "ble", BLE }, { "bls", BLS }, { "blt", BLT }, { "bmi", BMI }, + + { "bne", BNE }, { "bpl", BPL }, { "bvc", BVC }, { "bvs", BVS }, + + { "bchg", BCHG }, { "bclr", BCLR }, { "bra", BRA }, { "bset", BSET }, + + { "bsr", BSR }, { "btst", BTST }, { "chk", CHK }, { "clr", CLR }, + + { "cmp", CMP }, { "cmpa", CMPA }, { "cmpi", CMPI }, { "cmpm", CMPM }, + + { "dbcc", DBCC }, { "dbcs", DBCS }, { "dbeq", DBEQ }, { "dbf", DBF }, + + { "dbge", DBGE }, { "dbgt", DBGT }, { "dbhi", DBHI }, { "dble", DBLE }, + + { "dbls", DBLS }, { "dblt", DBLT }, { "dbmi", DBMI }, { "dbne", DBNE }, + + { "dbpl", DBPL }, { "dbt", DBT }, { "dbvc", DBVC }, { "dbvs", DBVS }, + + { "divs", DIVS }, { "divu", DIVU }, { "eor", EOR }, { "eori", EORI }, + + { "exg", EXG }, { "ext", EXT }, { "illegal",ILLEGAL }, { "jmp", JMP }, + + { "jsr", JSR }, { "lea", LEA }, { "link", LINK }, { "lsl", LSL }, + + { "lsr", LSR }, { "move", MOVE }, { "movea", MOVEA }, { "movem", MOVEM }, + + { "movep", MOVEP }, { "moveq", MOVEQ }, { "muls", MULS }, { "mulu", MULU }, + + { "nbcd", NBCD }, { "neg", NEG }, { "negx", NEGX }, { "nop", NOP }, + + { "not", NOT }, { "or", OR }, { "ori", ORI }, { "pea", PEA }, + + { "reset", RESET }, { "rol", ROL }, { "ror", ROR }, { "roxl", ROXL }, + + { "roxr", ROXR }, { "rte", RTE }, { "rtr", RTR }, + + { "rts", RTS }, { "scc", SCC }, { "scs", SCS }, { "seq", SEQ }, + + { "sf", SF }, { "sge", SGE }, { "sgt", SGT }, { "shi", SHI }, + + { "sle", SLE }, { "sls", SLS }, { "slt", SLT }, { "smi", SMI }, + + { "sne", SNE }, { "spl", SPL }, { "st", ST }, { "svc", SVC }, + + { "svs", SVS }, { "stop", STOP }, { "sub", SUB }, { "suba", SUBA }, + + { "subi", SUBI }, { "subq", SUBQ }, { "subx", SUBX }, { "swap", SWAP }, + + { "tas", TAS }, { "trap", TRAP }, { "trapv", TRAPV }, { "tst", TST }, + + { "unlk", UNLK }, { "a0", A0 }, { "a1", A1 }, { "a2", A2 }, + + { "a3", A3 }, { "a4", A4 }, { "a5", A5 }, { "a6", A6 }, + + { "a7", A7 }, { "d0", D0 }, { "d1", D1 }, { "d2", D2 }, + + { "d3", D3 }, { "d4", D4 }, { "d5", D5 }, { "d6", D6 }, + + { "d7", D7 }, { "ccr", CCR }, { "sr", SR }, { "usp", USP }, + + { "pc", PC }, + + { 0, 0 } + +}; + + + +typedef struct _ophash { + + struct _ophash* next; + + struct _optable* op; + +} OPHASH; + +#define OPHASHSIZE 97 + + + +static OPHASH **ophash = 0; + + + +static int getophash(const char* s) + +{ + + int h = 0; + + while (*s++) h += (int)*s; + + return h % OPHASHSIZE; + +} + + + +static int oplookup(const char* s) + +{ + + int idx = getophash(s); + + OPHASH* oph = ophash[idx]; + + if (oph) { + + if (oph->next) { + + while (oph) { + + if (!strcmp(s,oph->op->mnem)) return oph->op->token; + + oph = oph->next; + + } + + return 0; + + } + + return oph->op->token; + + } + + return 0; + +} + + + +static void init_ophash() + +{ + + struct _optable* op = ops; + + OPHASH* oph; + + ophash = (OPHASH**)calloc(sizeof(OPHASH*),OPHASHSIZE); + + while (op->mnem) { + + int idx = getophash(op->mnem); + + oph = (OPHASH*)malloc(sizeof(OPHASH)); + + oph->next = ophash[idx]; + + oph->op = op; + + ophash[idx] = oph; + + op++; + + } + +} + + + +static char* yystream; + + + +static int yylex() + +{ + + char ident[30]; + + char *p = ident; + + char c = yystream[0]; + + + + while (c != 0 && (c=='\t' || c==' ')) { + + c = *++yystream; + + } + + if (c==0) return EOF; + + + + if (isalpha(c)) { + + while (isalnum(c) && (p-ident)<28) { + + *p++ = tolower(c); c = *++yystream; + + } + + *p = 0; + + if (p>ident) { return oplookup(ident); } + + return EOF; + + } else if (isdigit(c)) { + + *p++ = c; + + if (yystream[1]=='x' || yystream[1]=='X') { *p++ = 'x'; yystream++; } + + c = *++yystream; + + while ((isdigit(c) || isxdigit(c)) && (p-ident)<28) { + + *p++ = c; c = *++yystream; + + } + + *p = 0; + + yylval.num = strtol(ident,0,0); + + return NUMBER; + + } else if (c=='$') { + + if (isdigit(yystream[1]) || isxdigit(yystream[1])) { + + c = *++yystream; + + while ((isdigit(c) || isxdigit(c)) && (p-ident)<28) { + + *p++ = c; c = *++yystream; + + } + + *p = 0; + + yylval.num = strtol(ident,0,16); + + return NUMBER; + + } else return '$'; + + } else if (c == '-' && yystream[1] == '(') { + + yystream += 2; return PREDEC; + + } else if (c == ')' && yystream[1] == '+') { + + yystream += 2; return POSTINC; + + } else if (c == '.') { + + switch (yystream[1]) { + + case 'b': yystream += 2; return BSIZE; + + case 'w': yystream += 2; return WSIZE; + + case 'l': yystream += 2; return LSIZE; + + case 's': yystream += 2; return SSIZE; + + default: yystream++; return '.'; + + } + + } else { + + ++yystream; return c; + + } + +} + + + +static t_value *yyvalptr; + +static t_addr yyaddr; + + + +t_stat parse_sym_m68k(char* c, t_addr a, UNIT* u, t_value* val, int32 sw) + +{ + + char ch; + + + + if (!ophash) init_ophash(); + + + + yyvalptr = val; + + yyaddr = a; + + + + yystream = c; + + yyerrc = 0; + + + + ch = *yystream; + + while (ch != 0 && (ch=='\t' || ch==' ')) { + + ch = *++yystream; + + } + + if (ch == 0) return 0; + + + + if (sw & SWMASK('Y')) yydebug = 1 - yydebug; + + if ((sw & SWMASK('A')) || ch=='\'') { + + if ((ch = yystream[1])) { + + val[0] = (uint32)ch; + + return SCPE_OK; + + } else return SCPE_ARG; + + } + + if ((sw & SWMASK('C')) || ch=='"') { + + if ((ch = yystream[1])) { + + val[0] = ((uint32)ch << 8) | (uint32)yystream[1]; + + return SCPE_OK; + + } else return SCPE_ARG; + + } + + + + yyparse(); + +// sim_printf("rc=%d\n",yyrc); + + if (yyerrc) return SCPE_ARG; + + return yyrc; + +} + + + +static int _genop(t_value arg) + +{ + +// sim_printf("_genop(%x)@%x\n",arg,(int)yyvalptr); + + *yyvalptr = (arg >> 8) & 0xff; + + yyvalptr++; + + *yyvalptr = arg & 0xff; + + yyvalptr++; + + return -1; + +} + + + +static int _genea(struct _ea arg) + +{ + + int i; + + for (i=0; i - #ifdef _BSD_SETJMP_H - sigjmp_buf m68ki_aerr_trap; - #else - jmp_buf m68ki_aerr_trap; - #endif + #include + #ifdef _BSD_SETJMP_H + sigjmp_buf m68ki_aerr_trap; + #else + jmp_buf m68ki_aerr_trap; + #endif #endif /* M68K_EMULATE_ADDRESS_ERROR */ /* ======================================================================== */ @@ -616,422 +616,422 @@ static void default_instr_hook_callback(unsigned int pc) /* Access the internals of the CPU */ unsigned int m68k_get_reg(void* context, m68k_register_t regnum) { - m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu; + m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu; - switch(regnum) - { - case M68K_REG_D0: return cpu->dar[0]; - case M68K_REG_D1: return cpu->dar[1]; - case M68K_REG_D2: return cpu->dar[2]; - case M68K_REG_D3: return cpu->dar[3]; - case M68K_REG_D4: return cpu->dar[4]; - case M68K_REG_D5: return cpu->dar[5]; - case M68K_REG_D6: return cpu->dar[6]; - case M68K_REG_D7: return cpu->dar[7]; - case M68K_REG_A0: return cpu->dar[8]; - case M68K_REG_A1: return cpu->dar[9]; - case M68K_REG_A2: return cpu->dar[10]; - case M68K_REG_A3: return cpu->dar[11]; - case M68K_REG_A4: return cpu->dar[12]; - case M68K_REG_A5: return cpu->dar[13]; - case M68K_REG_A6: return cpu->dar[14]; - case M68K_REG_A7: return cpu->dar[15]; - case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc); - case M68K_REG_SR: return cpu->t1_flag | - cpu->t0_flag | - (cpu->s_flag << 11) | - (cpu->m_flag << 11) | - cpu->int_mask | - ((cpu->x_flag & XFLAG_SET) >> 4) | - ((cpu->n_flag & NFLAG_SET) >> 4) | - ((!cpu->not_z_flag) << 2) | - ((cpu->v_flag & VFLAG_SET) >> 6) | - ((cpu->c_flag & CFLAG_SET) >> 8); - case M68K_REG_SP: return cpu->dar[15]; - case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15]; - case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4]; - case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6]; - case M68K_REG_SFC: return cpu->sfc; - case M68K_REG_DFC: return cpu->dfc; - case M68K_REG_VBR: return cpu->vbr; - case M68K_REG_CACR: return cpu->cacr; - case M68K_REG_CAAR: return cpu->caar; - case M68K_REG_PREF_ADDR: return cpu->pref_addr; - case M68K_REG_PREF_DATA: return cpu->pref_data; - case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc); - case M68K_REG_IR: return cpu->ir; - case M68K_REG_CPU_TYPE: - switch(cpu->cpu_type) - { - case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000; - case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010; - case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020; - case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020; - case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040; - } - return M68K_CPU_TYPE_INVALID; - default: return 0; - } - return 0; + switch(regnum) + { + case M68K_REG_D0: return cpu->dar[0]; + case M68K_REG_D1: return cpu->dar[1]; + case M68K_REG_D2: return cpu->dar[2]; + case M68K_REG_D3: return cpu->dar[3]; + case M68K_REG_D4: return cpu->dar[4]; + case M68K_REG_D5: return cpu->dar[5]; + case M68K_REG_D6: return cpu->dar[6]; + case M68K_REG_D7: return cpu->dar[7]; + case M68K_REG_A0: return cpu->dar[8]; + case M68K_REG_A1: return cpu->dar[9]; + case M68K_REG_A2: return cpu->dar[10]; + case M68K_REG_A3: return cpu->dar[11]; + case M68K_REG_A4: return cpu->dar[12]; + case M68K_REG_A5: return cpu->dar[13]; + case M68K_REG_A6: return cpu->dar[14]; + case M68K_REG_A7: return cpu->dar[15]; + case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc); + case M68K_REG_SR: return cpu->t1_flag | + cpu->t0_flag | + (cpu->s_flag << 11) | + (cpu->m_flag << 11) | + cpu->int_mask | + ((cpu->x_flag & XFLAG_SET) >> 4) | + ((cpu->n_flag & NFLAG_SET) >> 4) | + ((!cpu->not_z_flag) << 2) | + ((cpu->v_flag & VFLAG_SET) >> 6) | + ((cpu->c_flag & CFLAG_SET) >> 8); + case M68K_REG_SP: return cpu->dar[15]; + case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15]; + case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4]; + case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6]; + case M68K_REG_SFC: return cpu->sfc; + case M68K_REG_DFC: return cpu->dfc; + case M68K_REG_VBR: return cpu->vbr; + case M68K_REG_CACR: return cpu->cacr; + case M68K_REG_CAAR: return cpu->caar; + case M68K_REG_PREF_ADDR: return cpu->pref_addr; + case M68K_REG_PREF_DATA: return cpu->pref_data; + case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc); + case M68K_REG_IR: return cpu->ir; + case M68K_REG_CPU_TYPE: + switch(cpu->cpu_type) + { + case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000; + case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010; + case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020; + case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020; + case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040; + } + return M68K_CPU_TYPE_INVALID; + default: return 0; + } + return 0; } void m68k_set_reg(m68k_register_t regnum, unsigned int value) { - switch(regnum) - { - case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return; - case M68K_REG_SR: m68ki_set_sr_noint_nosp(value); return; - case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_USP: if(FLAG_S) - REG_USP = MASK_OUT_ABOVE_32(value); - else - REG_SP = MASK_OUT_ABOVE_32(value); - return; - case M68K_REG_ISP: if(FLAG_S && !FLAG_M) - REG_SP = MASK_OUT_ABOVE_32(value); - else - REG_ISP = MASK_OUT_ABOVE_32(value); - return; - case M68K_REG_MSP: if(FLAG_S && FLAG_M) - REG_SP = MASK_OUT_ABOVE_32(value); - else - REG_MSP = MASK_OUT_ABOVE_32(value); - return; - case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_SFC: REG_SFC = value & 7; return; - case M68K_REG_DFC: REG_DFC = value & 7; return; - case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return; - case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return; - default: return; - } + switch(regnum) + { + case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return; + case M68K_REG_SR: m68ki_set_sr_noint_nosp(value); return; + case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_USP: if(FLAG_S) + REG_USP = MASK_OUT_ABOVE_32(value); + else + REG_SP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_ISP: if(FLAG_S && !FLAG_M) + REG_SP = MASK_OUT_ABOVE_32(value); + else + REG_ISP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_MSP: if(FLAG_S && FLAG_M) + REG_SP = MASK_OUT_ABOVE_32(value); + else + REG_MSP = MASK_OUT_ABOVE_32(value); + return; + case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_SFC: REG_SFC = value & 7; return; + case M68K_REG_DFC: REG_DFC = value & 7; return; + case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return; + case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return; + case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return; + default: return; + } } /* Set the callbacks */ void m68k_set_int_ack_callback(int (*callback)(int int_level)) { - CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback; + CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback; } void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data)) { - CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback; + CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback; } void m68k_set_reset_instr_callback(void (*callback)(void)) { - CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback; + CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback; } void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int)) { - CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback; + CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback; } void m68k_set_rte_instr_callback(void (*callback)(void)) { - CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback; + CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback; } void m68k_set_tas_instr_callback(int (*callback)(void)) { - CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback; + CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback; } void m68k_set_illg_instr_callback(int (*callback)(int)) { - CALLBACK_ILLG_INSTR = callback ? callback : default_illg_instr_callback; + CALLBACK_ILLG_INSTR = callback ? callback : default_illg_instr_callback; } void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc)) { - CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback; + CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback; } void m68k_set_fc_callback(void (*callback)(unsigned int new_fc)) { - CALLBACK_SET_FC = callback ? callback : default_set_fc_callback; + CALLBACK_SET_FC = callback ? callback : default_set_fc_callback; } void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc)) { - CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback; + CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback; } /* Set the CPU type. */ void m68k_set_cpu_type(unsigned int cpu_type) { - switch(cpu_type) - { - case M68K_CPU_TYPE_68000: - CPU_TYPE = CPU_TYPE_000; - CPU_ADDRESS_MASK = 0x00ffffff; - CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[0]; - CYC_EXCEPTION = m68ki_exception_cycle_table[0]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 2; - CYC_DBCC_F_NOEXP = -2; - CYC_DBCC_F_EXP = 2; - CYC_SCC_R_TRUE = 2; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 3; - CYC_SHIFT = 1; - CYC_RESET = 132; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_SCC68070: - m68k_set_cpu_type(M68K_CPU_TYPE_68010); - CPU_ADDRESS_MASK = 0xffffffff; - CPU_TYPE = CPU_TYPE_SCC070; - return; - case M68K_CPU_TYPE_68010: - CPU_TYPE = CPU_TYPE_010; - CPU_ADDRESS_MASK = 0x00ffffff; - CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[1]; - CYC_EXCEPTION = m68ki_exception_cycle_table[1]; - CYC_BCC_NOTAKE_B = -4; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 6; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 3; - CYC_SHIFT = 1; - CYC_RESET = 130; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_68EC020: - CPU_TYPE = CPU_TYPE_EC020; - CPU_ADDRESS_MASK = 0x00ffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[2]; - CYC_EXCEPTION = m68ki_exception_cycle_table[2]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_68020: - CPU_TYPE = CPU_TYPE_020; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[2]; - CYC_EXCEPTION = m68ki_exception_cycle_table[2]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_68030: - CPU_TYPE = CPU_TYPE_030; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[3]; - CYC_EXCEPTION = m68ki_exception_cycle_table[3]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 1; - return; - case M68K_CPU_TYPE_68EC030: - CPU_TYPE = CPU_TYPE_EC030; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[3]; - CYC_EXCEPTION = m68ki_exception_cycle_table[3]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */ - return; - case M68K_CPU_TYPE_68040: // TODO: these values are not correct - CPU_TYPE = CPU_TYPE_040; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[4]; - CYC_EXCEPTION = m68ki_exception_cycle_table[4]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 1; - return; - case M68K_CPU_TYPE_68EC040: // Just a 68040 without pmmu apparently... - CPU_TYPE = CPU_TYPE_EC040; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[4]; - CYC_EXCEPTION = m68ki_exception_cycle_table[4]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_68LC040: - CPU_TYPE = CPU_TYPE_LC040; - m68ki_cpu.sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - m68ki_cpu.cyc_instruction = m68ki_cycles[4]; - m68ki_cpu.cyc_exception = m68ki_exception_cycle_table[4]; - m68ki_cpu.cyc_bcc_notake_b = -2; - m68ki_cpu.cyc_bcc_notake_w = 0; - m68ki_cpu.cyc_dbcc_f_noexp = 0; - m68ki_cpu.cyc_dbcc_f_exp = 4; - m68ki_cpu.cyc_scc_r_true = 0; - m68ki_cpu.cyc_movem_w = 2; - m68ki_cpu.cyc_movem_l = 2; - m68ki_cpu.cyc_shift = 0; - m68ki_cpu.cyc_reset = 518; - HAS_PMMU = 1; - return; - } + switch(cpu_type) + { + case M68K_CPU_TYPE_68000: + CPU_TYPE = CPU_TYPE_000; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[0]; + CYC_EXCEPTION = m68ki_exception_cycle_table[0]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 2; + CYC_DBCC_F_NOEXP = -2; + CYC_DBCC_F_EXP = 2; + CYC_SCC_R_TRUE = 2; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 3; + CYC_SHIFT = 1; + CYC_RESET = 132; + HAS_PMMU = 0; + return; + case M68K_CPU_TYPE_SCC68070: + m68k_set_cpu_type(M68K_CPU_TYPE_68010); + CPU_ADDRESS_MASK = 0xffffffff; + CPU_TYPE = CPU_TYPE_SCC070; + return; + case M68K_CPU_TYPE_68010: + CPU_TYPE = CPU_TYPE_010; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[1]; + CYC_EXCEPTION = m68ki_exception_cycle_table[1]; + CYC_BCC_NOTAKE_B = -4; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 6; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 3; + CYC_SHIFT = 1; + CYC_RESET = 130; + HAS_PMMU = 0; + return; + case M68K_CPU_TYPE_68EC020: + CPU_TYPE = CPU_TYPE_EC020; + CPU_ADDRESS_MASK = 0x00ffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[2]; + CYC_EXCEPTION = m68ki_exception_cycle_table[2]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + HAS_PMMU = 0; + return; + case M68K_CPU_TYPE_68020: + CPU_TYPE = CPU_TYPE_020; + CPU_ADDRESS_MASK = 0xffffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[2]; + CYC_EXCEPTION = m68ki_exception_cycle_table[2]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + HAS_PMMU = 0; + return; + case M68K_CPU_TYPE_68030: + CPU_TYPE = CPU_TYPE_030; + CPU_ADDRESS_MASK = 0xffffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[3]; + CYC_EXCEPTION = m68ki_exception_cycle_table[3]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + HAS_PMMU = 1; + return; + case M68K_CPU_TYPE_68EC030: + CPU_TYPE = CPU_TYPE_EC030; + CPU_ADDRESS_MASK = 0xffffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[3]; + CYC_EXCEPTION = m68ki_exception_cycle_table[3]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + HAS_PMMU = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */ + return; + case M68K_CPU_TYPE_68040: // TODO: these values are not correct + CPU_TYPE = CPU_TYPE_040; + CPU_ADDRESS_MASK = 0xffffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[4]; + CYC_EXCEPTION = m68ki_exception_cycle_table[4]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + HAS_PMMU = 1; + return; + case M68K_CPU_TYPE_68EC040: // Just a 68040 without pmmu apparently... + CPU_TYPE = CPU_TYPE_EC040; + CPU_ADDRESS_MASK = 0xffffffff; + CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + CYC_INSTRUCTION = m68ki_cycles[4]; + CYC_EXCEPTION = m68ki_exception_cycle_table[4]; + CYC_BCC_NOTAKE_B = -2; + CYC_BCC_NOTAKE_W = 0; + CYC_DBCC_F_NOEXP = 0; + CYC_DBCC_F_EXP = 4; + CYC_SCC_R_TRUE = 0; + CYC_MOVEM_W = 2; + CYC_MOVEM_L = 2; + CYC_SHIFT = 0; + CYC_RESET = 518; + HAS_PMMU = 0; + return; + case M68K_CPU_TYPE_68LC040: + CPU_TYPE = CPU_TYPE_LC040; + m68ki_cpu.sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ + m68ki_cpu.cyc_instruction = m68ki_cycles[4]; + m68ki_cpu.cyc_exception = m68ki_exception_cycle_table[4]; + m68ki_cpu.cyc_bcc_notake_b = -2; + m68ki_cpu.cyc_bcc_notake_w = 0; + m68ki_cpu.cyc_dbcc_f_noexp = 0; + m68ki_cpu.cyc_dbcc_f_exp = 4; + m68ki_cpu.cyc_scc_r_true = 0; + m68ki_cpu.cyc_movem_w = 2; + m68ki_cpu.cyc_movem_l = 2; + m68ki_cpu.cyc_shift = 0; + m68ki_cpu.cyc_reset = 518; + HAS_PMMU = 1; + return; + } } /* Execute some instructions until we use up num_cycles clock cycles */ /* ASG: removed per-instruction interrupt checks */ int m68k_execute(int num_cycles) { - /* eat up any reset cycles */ - if (RESET_CYCLES) { - int rc = RESET_CYCLES; - RESET_CYCLES = 0; - num_cycles -= rc; - if (num_cycles <= 0) - return rc; - } + /* eat up any reset cycles */ + if (RESET_CYCLES) { + int rc = RESET_CYCLES; + RESET_CYCLES = 0; + num_cycles -= rc; + if (num_cycles <= 0) + return rc; + } - /* Set our pool of clock cycles available */ - SET_CYCLES(num_cycles); - m68ki_initial_cycles = num_cycles; + /* Set our pool of clock cycles available */ + SET_CYCLES(num_cycles); + m68ki_initial_cycles = num_cycles; - /* See if interrupts came in */ - m68ki_check_interrupts(); + /* See if interrupts came in */ + m68ki_check_interrupts(); - /* Make sure we're not stopped */ - if(!CPU_STOPPED) - { - /* Return point if we had an address error */ - m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */ + /* Make sure we're not stopped */ + if(!CPU_STOPPED) + { + /* Return point if we had an address error */ + m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */ - m68ki_check_bus_error_trap(); + m68ki_check_bus_error_trap(); - /* Main loop. Keep going until we run out of clock cycles */ - do - { - int i; - /* Set tracing accodring to T1. (T0 is done inside instruction) */ - m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */ + /* Main loop. Keep going until we run out of clock cycles */ + do + { + int i; + /* Set tracing accodring to T1. (T0 is done inside instruction) */ + m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */ - /* Set the address space for reads */ - m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */ + /* Set the address space for reads */ + m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */ - /* Call external hook to peek at CPU */ - m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */ + /* Call external hook to peek at CPU */ + m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */ - /* Record previous program counter */ - REG_PPC = REG_PC; + /* Record previous program counter */ + REG_PPC = REG_PC; - /* Record previous D/A register state (in case of bus error) */ - for (i = 15; i >= 0; i--){ - REG_DA_SAVE[i] = REG_DA[i]; - } + /* Record previous D/A register state (in case of bus error) */ + for (i = 15; i >= 0; i--){ + REG_DA_SAVE[i] = REG_DA[i]; + } - /* Read an instruction and call its handler */ - REG_IR = m68ki_read_imm_16(); - m68ki_instruction_jump_table[REG_IR](); - USE_CYCLES(CYC_INSTRUCTION[REG_IR]); + /* Read an instruction and call its handler */ + REG_IR = m68ki_read_imm_16(); + m68ki_instruction_jump_table[REG_IR](); + USE_CYCLES(CYC_INSTRUCTION[REG_IR]); - /* Trace m68k_exception, if necessary */ - m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ - } while(GET_CYCLES() > 0); + /* Trace m68k_exception, if necessary */ + m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ + } while(GET_CYCLES() > 0); - /* set previous PC to current PC for the next entry into the loop */ - REG_PPC = REG_PC; - } - else - SET_CYCLES(0); + /* set previous PC to current PC for the next entry into the loop */ + REG_PPC = REG_PC; + } + else + SET_CYCLES(0); - /* return how many clocks we used */ - return m68ki_initial_cycles - GET_CYCLES(); + /* return how many clocks we used */ + return m68ki_initial_cycles - GET_CYCLES(); } int m68k_cycles_run(void) { - return m68ki_initial_cycles - GET_CYCLES(); + return m68ki_initial_cycles - GET_CYCLES(); } int m68k_cycles_remaining(void) { - return GET_CYCLES(); + return GET_CYCLES(); } /* Change the timeslice */ void m68k_modify_timeslice(int cycles) { - m68ki_initial_cycles += cycles; - ADD_CYCLES(cycles); + m68ki_initial_cycles += cycles; + ADD_CYCLES(cycles); } void m68k_end_timeslice(void) { - m68ki_initial_cycles = GET_CYCLES(); - SET_CYCLES(0); + m68ki_initial_cycles = GET_CYCLES(); + SET_CYCLES(0); } @@ -1041,130 +1041,130 @@ void m68k_end_timeslice(void) */ void m68k_set_irq(unsigned int int_level) { - uint old_level = CPU_INT_LEVEL; - CPU_INT_LEVEL = int_level << 8; + uint old_level = CPU_INT_LEVEL; + CPU_INT_LEVEL = int_level << 8; - /* A transition from < 7 to 7 always interrupts (NMI) */ - /* Note: Level 7 can also level trigger like a normal IRQ */ - if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700) - m68ki_cpu.nmi_pending = TRUE; + /* A transition from < 7 to 7 always interrupts (NMI) */ + /* Note: Level 7 can also level trigger like a normal IRQ */ + if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700) + m68ki_cpu.nmi_pending = TRUE; } void m68k_set_virq(unsigned int level, unsigned int active) { - uint state = m68ki_cpu.virq_state; - uint blevel; + uint state = m68ki_cpu.virq_state; + uint blevel; - if(active) - state |= 1 << level; - else - state &= ~(1 << level); - m68ki_cpu.virq_state = state; + if(active) + state |= 1 << level; + else + state &= ~(1 << level); + m68ki_cpu.virq_state = state; - for(blevel = 7; blevel > 0; blevel--) - if(state & (1 << blevel)) - break; - m68k_set_irq(blevel); + for(blevel = 7; blevel > 0; blevel--) + if(state & (1 << blevel)) + break; + m68k_set_irq(blevel); } unsigned int m68k_get_virq(unsigned int level) { - return (m68ki_cpu.virq_state & (1 << level)) ? 1 : 0; + return (m68ki_cpu.virq_state & (1 << level)) ? 1 : 0; } void m68k_init(void) { - static uint emulation_initialized = 0; + static uint emulation_initialized = 0; - /* The first call to this function initializes the opcode handler jump table */ - if(!emulation_initialized) - { - m68ki_build_opcode_table(); - emulation_initialized = 1; - } + /* The first call to this function initializes the opcode handler jump table */ + if(!emulation_initialized) + { + m68ki_build_opcode_table(); + emulation_initialized = 1; + } - m68k_set_int_ack_callback(NULL); - m68k_set_bkpt_ack_callback(NULL); - m68k_set_reset_instr_callback(NULL); - m68k_set_cmpild_instr_callback(NULL); - m68k_set_rte_instr_callback(NULL); - m68k_set_tas_instr_callback(NULL); - m68k_set_illg_instr_callback(NULL); - m68k_set_pc_changed_callback(NULL); - m68k_set_fc_callback(NULL); - m68k_set_instr_hook_callback(NULL); + m68k_set_int_ack_callback(NULL); + m68k_set_bkpt_ack_callback(NULL); + m68k_set_reset_instr_callback(NULL); + m68k_set_cmpild_instr_callback(NULL); + m68k_set_rte_instr_callback(NULL); + m68k_set_tas_instr_callback(NULL); + m68k_set_illg_instr_callback(NULL); + m68k_set_pc_changed_callback(NULL); + m68k_set_fc_callback(NULL); + m68k_set_instr_hook_callback(NULL); } /* Trigger a Bus Error exception */ void m68k_pulse_bus_error(void) { - m68ki_exception_bus_error(); + m68ki_exception_bus_error(); } /* Pulse the RESET line on the CPU */ void m68k_pulse_reset(void) { - /* Disable the PMMU on reset */ - m68ki_cpu.pmmu_enabled = 0; + /* Disable the PMMU on reset */ + m68ki_cpu.pmmu_enabled = 0; - /* Clear all stop levels and eat up all remaining cycles */ - CPU_STOPPED = 0; - SET_CYCLES(0); + /* Clear all stop levels and eat up all remaining cycles */ + CPU_STOPPED = 0; + SET_CYCLES(0); - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; - CPU_INSTR_MODE = INSTRUCTION_YES; + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; + CPU_INSTR_MODE = INSTRUCTION_YES; - /* Turn off tracing */ - FLAG_T1 = FLAG_T0 = 0; - m68ki_clear_trace(); - /* Interrupt mask to level 7 */ - FLAG_INT_MASK = 0x0700; - CPU_INT_LEVEL = 0; - m68ki_cpu.virq_state = 0; - /* Reset VBR */ - REG_VBR = 0; - /* Go to supervisor mode */ - m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR); + /* Turn off tracing */ + FLAG_T1 = FLAG_T0 = 0; + m68ki_clear_trace(); + /* Interrupt mask to level 7 */ + FLAG_INT_MASK = 0x0700; + CPU_INT_LEVEL = 0; + m68ki_cpu.virq_state = 0; + /* Reset VBR */ + REG_VBR = 0; + /* Go to supervisor mode */ + m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR); - /* Invalidate the prefetch queue */ + /* Invalidate the prefetch queue */ #if M68K_EMULATE_PREFETCH - /* Set to arbitrary number since our first fetch is from 0 */ - CPU_PREF_ADDR = 0x1000; + /* Set to arbitrary number since our first fetch is from 0 */ + CPU_PREF_ADDR = 0x1000; #endif /* M68K_EMULATE_PREFETCH */ - /* Read the initial stack pointer and program counter */ - m68ki_jump(0); - REG_SP = m68ki_read_imm_32(); - REG_PC = m68ki_read_imm_32(); - m68ki_jump(REG_PC); + /* Read the initial stack pointer and program counter */ + m68ki_jump(0); + REG_SP = m68ki_read_imm_32(); + REG_PC = m68ki_read_imm_32(); + m68ki_jump(REG_PC); - CPU_RUN_MODE = RUN_MODE_NORMAL; + CPU_RUN_MODE = RUN_MODE_NORMAL; - RESET_CYCLES = CYC_EXCEPTION[EXCEPTION_RESET]; + RESET_CYCLES = CYC_EXCEPTION[EXCEPTION_RESET]; } /* Pulse the HALT line on the CPU */ void m68k_pulse_halt(void) { - CPU_STOPPED |= STOP_LEVEL_HALT; + CPU_STOPPED |= STOP_LEVEL_HALT; } /* Get and set the current CPU context */ /* This is to allow for multiple CPUs */ unsigned int m68k_context_size() { - return sizeof(m68ki_cpu_core); + return sizeof(m68ki_cpu_core); } unsigned int m68k_get_context(void* dst) { - if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu; - return sizeof(m68ki_cpu_core); + if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu; + return sizeof(m68ki_cpu_core); } void m68k_set_context(void* src) { - if(src) m68ki_cpu = *(m68ki_cpu_core*)src; + if(src) m68ki_cpu = *(m68ki_cpu_core*)src; } /* ======================================================================== */ @@ -1174,48 +1174,48 @@ void m68k_set_context(void* src) #if M68K_COMPILE_FOR_MAME == OPT_ON static struct { - UINT16 sr; - UINT8 stopped; - UINT8 halted; + UINT16 sr; + UINT8 stopped; + UINT8 halted; } m68k_substate; static void m68k_prepare_substate(void) { - m68k_substate.sr = m68ki_get_sr(); - m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0; - m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0; + m68k_substate.sr = m68ki_get_sr(); + m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0; + m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0; } static void m68k_post_load(void) { - m68ki_set_sr_noint_nosp(m68k_substate.sr); - CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0 - | m68k_substate.halted ? STOP_LEVEL_HALT : 0; - m68ki_jump(REG_PC); + m68ki_set_sr_noint_nosp(m68k_substate.sr); + CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0 + | m68k_substate.halted ? STOP_LEVEL_HALT : 0; + m68ki_jump(REG_PC); } void m68k_state_register(const char *type, int index) { - /* Note, D covers A because the dar array is common, REG_A=REG_D+8 */ - state_save_register_item_array(type, index, REG_D); - state_save_register_item(type, index, REG_PPC); - state_save_register_item(type, index, REG_PC); - state_save_register_item(type, index, REG_USP); - state_save_register_item(type, index, REG_ISP); - state_save_register_item(type, index, REG_MSP); - state_save_register_item(type, index, REG_VBR); - state_save_register_item(type, index, REG_SFC); - state_save_register_item(type, index, REG_DFC); - state_save_register_item(type, index, REG_CACR); - state_save_register_item(type, index, REG_CAAR); - state_save_register_item(type, index, m68k_substate.sr); - state_save_register_item(type, index, CPU_INT_LEVEL); - state_save_register_item(type, index, m68k_substate.stopped); - state_save_register_item(type, index, m68k_substate.halted); - state_save_register_item(type, index, CPU_PREF_ADDR); - state_save_register_item(type, index, CPU_PREF_DATA); - state_save_register_func_presave(m68k_prepare_substate); - state_save_register_func_postload(m68k_post_load); + /* Note, D covers A because the dar array is common, REG_A=REG_D+8 */ + state_save_register_item_array(type, index, REG_D); + state_save_register_item(type, index, REG_PPC); + state_save_register_item(type, index, REG_PC); + state_save_register_item(type, index, REG_USP); + state_save_register_item(type, index, REG_ISP); + state_save_register_item(type, index, REG_MSP); + state_save_register_item(type, index, REG_VBR); + state_save_register_item(type, index, REG_SFC); + state_save_register_item(type, index, REG_DFC); + state_save_register_item(type, index, REG_CACR); + state_save_register_item(type, index, REG_CAAR); + state_save_register_item(type, index, m68k_substate.sr); + state_save_register_item(type, index, CPU_INT_LEVEL); + state_save_register_item(type, index, m68k_substate.stopped); + state_save_register_item(type, index, m68k_substate.halted); + state_save_register_item(type, index, CPU_PREF_ADDR); + state_save_register_item(type, index, CPU_PREF_DATA); + state_save_register_func_presave(m68k_prepare_substate); + state_save_register_func_postload(m68k_post_load); } #endif /* M68K_COMPILE_FOR_MAME */ diff --git a/AltairZ80/m68k/m68kcpu.h b/AltairZ80/m68k/m68kcpu.h index 5adca63e..5befb393 100755 --- a/AltairZ80/m68k/m68kcpu.h +++ b/AltairZ80/m68k/m68kcpu.h @@ -49,9 +49,9 @@ extern "C" { /* Check for > 32bit sizes */ #if UINT_MAX > 0xffffffff - #define M68K_INT_GT_32_BIT 1 + #define M68K_INT_GT_32_BIT 1 #else - #define M68K_INT_GT_32_BIT 0 + #define M68K_INT_GT_32_BIT 0 #endif /* Data types used in this emulation core */ @@ -66,9 +66,9 @@ extern "C" { #undef sint #undef uint -typedef signed char sint8; /* ASG: changed from char to signed char */ +typedef signed char sint8; /* ASG: changed from char to signed char */ typedef signed short sint16; -typedef signed int sint32; /* AWJ: changed from long to int */ +typedef signed int sint32; /* AWJ: changed from long to int */ /* signed and unsigned int must be at least 32 bits wide */ typedef signed int sint; @@ -98,46 +98,46 @@ typedef uint32 uint64; /* Allow for architectures that don't have 8-bit sizes */ #if UCHAR_MAX == 0xff - #define MAKE_INT_8(A) (sint8)(A) + #define MAKE_INT_8(A) (sint8)(A) #else - #undef sint8 - #define sint8 signed int - #undef uint8 - #define uint8 unsigned int - static inline sint MAKE_INT_8(uint value) - { - return (value & 0x80) ? value | ~0xff : value & 0xff; - } + #undef sint8 + #define sint8 signed int + #undef uint8 + #define uint8 unsigned int + static inline sint MAKE_INT_8(uint value) + { + return (value & 0x80) ? value | ~0xff : value & 0xff; + } #endif /* UCHAR_MAX == 0xff */ /* Allow for architectures that don't have 16-bit sizes */ #if USHRT_MAX == 0xffff - #define MAKE_INT_16(A) (sint16)(A) + #define MAKE_INT_16(A) (sint16)(A) #else - #undef sint16 - #define sint16 signed int - #undef uint16 - #define uint16 unsigned int - static inline sint MAKE_INT_16(uint value) - { - return (value & 0x8000) ? value | ~0xffff : value & 0xffff; - } + #undef sint16 + #define sint16 signed int + #undef uint16 + #define uint16 unsigned int + static inline sint MAKE_INT_16(uint value) + { + return (value & 0x8000) ? value | ~0xffff : value & 0xffff; + } #endif /* USHRT_MAX == 0xffff */ /* Allow for architectures that don't have 32-bit sizes */ #if UINT_MAX == 0xffffffff - #define MAKE_INT_32(A) (sint32)(A) + #define MAKE_INT_32(A) (sint32)(A) #else - #undef sint32 - #define sint32 signed int - #undef uint32 - #define uint32 unsigned int - static inline sint MAKE_INT_32(uint value) - { - return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; - } + #undef sint32 + #define sint32 signed int + #undef uint32 + #define uint32 unsigned int + static inline sint MAKE_INT_32(uint value) + { + return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; + } #endif /* UINT_MAX == 0xffffffff */ @@ -173,7 +173,7 @@ typedef uint32 uint64; #define FUNCTION_CODE_CPU_SPACE 7 /* CPU types for deciding what to emulate */ -#define CPU_TYPE_000 (0x00000001) +#define CPU_TYPE_000 (0x00000001) #define CPU_TYPE_008 (0x00000002) #define CPU_TYPE_010 (0x00000004) #define CPU_TYPE_EC020 (0x00000008) @@ -268,11 +268,11 @@ typedef uint32 uint64; /* No need to mask if we are 32 bit */ #if M68K_INT_GT_32_BIT || M68K_USE_64_BIT - #define MASK_OUT_ABOVE_32(A) ((A) & 0xffffffff) - #define MASK_OUT_BELOW_32(A) ((A) & ~0xffffffff) + #define MASK_OUT_ABOVE_32(A) ((A) & 0xffffffff) + #define MASK_OUT_BELOW_32(A) ((A) & ~0xffffffff) #else - #define MASK_OUT_ABOVE_32(A) (A) - #define MASK_OUT_BELOW_32(A) 0 + #define MASK_OUT_ABOVE_32(A) (A) + #define MASK_OUT_BELOW_32(A) 0 #endif /* M68K_INT_GT_32_BIT || M68K_USE_64_BIT */ /* Simulate address lines of 68k family */ @@ -285,22 +285,22 @@ typedef uint32 uint64; /* Some > 32-bit optimizations */ #if M68K_INT_GT_32_BIT - /* Shift left and right */ - #define LSR_32(A, C) ((A) >> (C)) - #define LSL_32(A, C) ((A) << (C)) + /* Shift left and right */ + #define LSR_32(A, C) ((A) >> (C)) + #define LSL_32(A, C) ((A) << (C)) #else - /* We have to do this because the morons at ANSI decided that shifts - * by >= data size are undefined. - */ - #define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0) - #define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0) + /* We have to do this because the morons at ANSI decided that shifts + * by >= data size are undefined. + */ + #define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0) + #define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0) #endif /* M68K_INT_GT_32_BIT */ #if M68K_USE_64_BIT - #define LSL_32_64(A, C) ((A) << (C)) - #define LSR_32_64(A, C) ((A) >> (C)) - #define ROL_33_64(A, C) (LSL_32_64(A, C) | LSR_32_64(A, 33-(C))) - #define ROR_33_64(A, C) (LSR_32_64(A, C) | LSL_32_64(A, 33-(C))) + #define LSL_32_64(A, C) ((A) << (C)) + #define LSR_32_64(A, C) ((A) >> (C)) + #define ROL_33_64(A, C) (LSL_32_64(A, C) | LSR_32_64(A, 33-(C))) + #define ROR_33_64(A, C) (LSR_32_64(A, C) | LSL_32_64(A, 33-(C))) #endif /* M68K_USE_64_BIT */ #define ROL_8(A, C) MASK_OUT_ABOVE_8(LSL(A, C) | LSR(A, 8-(C))) @@ -328,7 +328,7 @@ typedef uint32 uint64; #define REG_DA_SAVE m68ki_cpu.dar_save #define REG_D m68ki_cpu.dar #define REG_A (m68ki_cpu.dar+8) -#define REG_PPC m68ki_cpu.ppc +#define REG_PPC m68ki_cpu.ppc #define REG_PC m68ki_cpu.pc #define REG_SP_BASE m68ki_cpu.sp #define REG_USP m68ki_cpu.sp[0] @@ -378,9 +378,9 @@ typedef uint32 uint64; #define CYC_MOVEM_L m68ki_cpu.cyc_movem_l #define CYC_SHIFT m68ki_cpu.cyc_shift #define CYC_RESET m68ki_cpu.cyc_reset -#define HAS_PMMU m68ki_cpu.has_pmmu -#define PMMU_ENABLED m68ki_cpu.pmmu_enabled -#define RESET_CYCLES m68ki_cpu.reset_cycles +#define HAS_PMMU m68ki_cpu.has_pmmu +#define PMMU_ENABLED m68ki_cpu.pmmu_enabled +#define RESET_CYCLES m68ki_cpu.reset_cycles #define CALLBACK_INT_ACK m68ki_cpu.int_ack_callback @@ -403,56 +403,56 @@ typedef uint32 uint64; /* Disable certain comparisons if we're not using all CPU types */ #if M68K_EMULATE_040 #define CPU_TYPE_IS_040_PLUS(A) ((A) & (CPU_TYPE_040 | CPU_TYPE_EC040)) - #define CPU_TYPE_IS_040_LESS(A) 1 + #define CPU_TYPE_IS_040_LESS(A) 1 #else - #define CPU_TYPE_IS_040_PLUS(A) 0 - #define CPU_TYPE_IS_040_LESS(A) 1 + #define CPU_TYPE_IS_040_PLUS(A) 0 + #define CPU_TYPE_IS_040_LESS(A) 1 #endif #if M68K_EMULATE_030 #define CPU_TYPE_IS_030_PLUS(A) ((A) & (CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040)) #define CPU_TYPE_IS_030_LESS(A) 1 #else -#define CPU_TYPE_IS_030_PLUS(A) 0 +#define CPU_TYPE_IS_030_PLUS(A) 0 #define CPU_TYPE_IS_030_LESS(A) 1 #endif #if M68K_EMULATE_020 #define CPU_TYPE_IS_020_PLUS(A) ((A) & (CPU_TYPE_020 | CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040)) - #define CPU_TYPE_IS_020_LESS(A) 1 + #define CPU_TYPE_IS_020_LESS(A) 1 #else - #define CPU_TYPE_IS_020_PLUS(A) 0 - #define CPU_TYPE_IS_020_LESS(A) 1 + #define CPU_TYPE_IS_020_PLUS(A) 0 + #define CPU_TYPE_IS_020_LESS(A) 1 #endif #if M68K_EMULATE_EC020 #define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040)) - #define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010 | CPU_TYPE_EC020)) + #define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010 | CPU_TYPE_EC020)) #else - #define CPU_TYPE_IS_EC020_PLUS(A) CPU_TYPE_IS_020_PLUS(A) - #define CPU_TYPE_IS_EC020_LESS(A) CPU_TYPE_IS_020_LESS(A) + #define CPU_TYPE_IS_EC020_PLUS(A) CPU_TYPE_IS_020_PLUS(A) + #define CPU_TYPE_IS_EC020_LESS(A) CPU_TYPE_IS_020_LESS(A) #endif #if M68K_EMULATE_010 - #define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010) + #define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010) #define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_EC030 | CPU_TYPE_030 | CPU_TYPE_040 | CPU_TYPE_EC040)) #define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010)) #else - #define CPU_TYPE_IS_010(A) 0 - #define CPU_TYPE_IS_010_PLUS(A) CPU_TYPE_IS_EC020_PLUS(A) - #define CPU_TYPE_IS_010_LESS(A) CPU_TYPE_IS_EC020_LESS(A) + #define CPU_TYPE_IS_010(A) 0 + #define CPU_TYPE_IS_010_PLUS(A) CPU_TYPE_IS_EC020_PLUS(A) + #define CPU_TYPE_IS_010_LESS(A) CPU_TYPE_IS_EC020_LESS(A) #endif #if M68K_EMULATE_020 || M68K_EMULATE_EC020 - #define CPU_TYPE_IS_020_VARIANT(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020)) + #define CPU_TYPE_IS_020_VARIANT(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020)) #else - #define CPU_TYPE_IS_020_VARIANT(A) 0 + #define CPU_TYPE_IS_020_VARIANT(A) 0 #endif #if M68K_EMULATE_040 || M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010 - #define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000) + #define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000) #else - #define CPU_TYPE_IS_000(A) 1 + #define CPU_TYPE_IS_000(A) 1 #endif @@ -468,217 +468,217 @@ typedef uint32 uint64; /* Enable or disable callback functions */ #if M68K_EMULATE_INT_ACK - #if M68K_EMULATE_INT_ACK == OPT_SPECIFY_HANDLER - #define m68ki_int_ack(A) M68K_INT_ACK_CALLBACK(A) - #else - #define m68ki_int_ack(A) CALLBACK_INT_ACK(A) - #endif + #if M68K_EMULATE_INT_ACK == OPT_SPECIFY_HANDLER + #define m68ki_int_ack(A) M68K_INT_ACK_CALLBACK(A) + #else + #define m68ki_int_ack(A) CALLBACK_INT_ACK(A) + #endif #else - /* Default action is to used autovector mode, which is most common */ - #define m68ki_int_ack(A) M68K_INT_ACK_AUTOVECTOR + /* Default action is to used autovector mode, which is most common */ + #define m68ki_int_ack(A) M68K_INT_ACK_AUTOVECTOR #endif /* M68K_EMULATE_INT_ACK */ #if M68K_EMULATE_BKPT_ACK - #if M68K_EMULATE_BKPT_ACK == OPT_SPECIFY_HANDLER - #define m68ki_bkpt_ack(A) M68K_BKPT_ACK_CALLBACK(A) - #else - #define m68ki_bkpt_ack(A) CALLBACK_BKPT_ACK(A) - #endif + #if M68K_EMULATE_BKPT_ACK == OPT_SPECIFY_HANDLER + #define m68ki_bkpt_ack(A) M68K_BKPT_ACK_CALLBACK(A) + #else + #define m68ki_bkpt_ack(A) CALLBACK_BKPT_ACK(A) + #endif #else - #define m68ki_bkpt_ack(A) + #define m68ki_bkpt_ack(A) #endif /* M68K_EMULATE_BKPT_ACK */ #if M68K_EMULATE_RESET - #if M68K_EMULATE_RESET == OPT_SPECIFY_HANDLER - #define m68ki_output_reset() M68K_RESET_CALLBACK() - #else - #define m68ki_output_reset() CALLBACK_RESET_INSTR() - #endif + #if M68K_EMULATE_RESET == OPT_SPECIFY_HANDLER + #define m68ki_output_reset() M68K_RESET_CALLBACK() + #else + #define m68ki_output_reset() CALLBACK_RESET_INSTR() + #endif #else - #define m68ki_output_reset() + #define m68ki_output_reset() #endif /* M68K_EMULATE_RESET */ #if M68K_CMPILD_HAS_CALLBACK - #if M68K_CMPILD_HAS_CALLBACK == OPT_SPECIFY_HANDLER - #define m68ki_cmpild_callback(v,r) M68K_CMPILD_CALLBACK(v,r) - #else - #define m68ki_cmpild_callback(v,r) CALLBACK_CMPILD_INSTR(v,r) - #endif + #if M68K_CMPILD_HAS_CALLBACK == OPT_SPECIFY_HANDLER + #define m68ki_cmpild_callback(v,r) M68K_CMPILD_CALLBACK(v,r) + #else + #define m68ki_cmpild_callback(v,r) CALLBACK_CMPILD_INSTR(v,r) + #endif #else - #define m68ki_cmpild_callback(v,r) + #define m68ki_cmpild_callback(v,r) #endif /* M68K_CMPILD_HAS_CALLBACK */ #if M68K_RTE_HAS_CALLBACK - #if M68K_RTE_HAS_CALLBACK == OPT_SPECIFY_HANDLER - #define m68ki_rte_callback() M68K_RTE_CALLBACK() - #else - #define m68ki_rte_callback() CALLBACK_RTE_INSTR() - #endif + #if M68K_RTE_HAS_CALLBACK == OPT_SPECIFY_HANDLER + #define m68ki_rte_callback() M68K_RTE_CALLBACK() + #else + #define m68ki_rte_callback() CALLBACK_RTE_INSTR() + #endif #else - #define m68ki_rte_callback() + #define m68ki_rte_callback() #endif /* M68K_RTE_HAS_CALLBACK */ #if M68K_TAS_HAS_CALLBACK - #if M68K_TAS_HAS_CALLBACK == OPT_SPECIFY_HANDLER - #define m68ki_tas_callback() M68K_TAS_CALLBACK() - #else - #define m68ki_tas_callback() CALLBACK_TAS_INSTR() - #endif + #if M68K_TAS_HAS_CALLBACK == OPT_SPECIFY_HANDLER + #define m68ki_tas_callback() M68K_TAS_CALLBACK() + #else + #define m68ki_tas_callback() CALLBACK_TAS_INSTR() + #endif #else - #define m68ki_tas_callback() 1 + #define m68ki_tas_callback() 1 #endif /* M68K_TAS_HAS_CALLBACK */ #if M68K_ILLG_HAS_CALLBACK - #if M68K_ILLG_HAS_CALLBACK == OPT_SPECIFY_HANDLER - #define m68ki_illg_callback(opcode) M68K_ILLG_CALLBACK(opcode) - #else - #define m68ki_illg_callback(opcode) CALLBACK_ILLG_INSTR(opcode) - #endif + #if M68K_ILLG_HAS_CALLBACK == OPT_SPECIFY_HANDLER + #define m68ki_illg_callback(opcode) M68K_ILLG_CALLBACK(opcode) + #else + #define m68ki_illg_callback(opcode) CALLBACK_ILLG_INSTR(opcode) + #endif #else - #define m68ki_illg_callback(opcode) 0 // Default is 0 = not handled, exception will occur + #define m68ki_illg_callback(opcode) 0 // Default is 0 = not handled, exception will occur #endif /* M68K_ILLG_HAS_CALLBACK */ #if M68K_INSTRUCTION_HOOK - #if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER - #define m68ki_instr_hook(pc) M68K_INSTRUCTION_CALLBACK(pc) - #else - #define m68ki_instr_hook(pc) CALLBACK_INSTR_HOOK(pc) - #endif + #if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER + #define m68ki_instr_hook(pc) M68K_INSTRUCTION_CALLBACK(pc) + #else + #define m68ki_instr_hook(pc) CALLBACK_INSTR_HOOK(pc) + #endif #else - #define m68ki_instr_hook(pc) + #define m68ki_instr_hook(pc) #endif /* M68K_INSTRUCTION_HOOK */ #if M68K_MONITOR_PC - #if M68K_MONITOR_PC == OPT_SPECIFY_HANDLER - #define m68ki_pc_changed(A) M68K_SET_PC_CALLBACK(ADDRESS_68K(A)) - #else - #define m68ki_pc_changed(A) CALLBACK_PC_CHANGED(ADDRESS_68K(A)) - #endif + #if M68K_MONITOR_PC == OPT_SPECIFY_HANDLER + #define m68ki_pc_changed(A) M68K_SET_PC_CALLBACK(ADDRESS_68K(A)) + #else + #define m68ki_pc_changed(A) CALLBACK_PC_CHANGED(ADDRESS_68K(A)) + #endif #else - #define m68ki_pc_changed(A) + #define m68ki_pc_changed(A) #endif /* M68K_MONITOR_PC */ /* Enable or disable function code emulation */ #if M68K_EMULATE_FC - #if M68K_EMULATE_FC == OPT_SPECIFY_HANDLER - #define m68ki_set_fc(A) M68K_SET_FC_CALLBACK(A) - #else - #define m68ki_set_fc(A) CALLBACK_SET_FC(A) - #endif - #define m68ki_use_data_space() m68ki_address_space = FUNCTION_CODE_USER_DATA - #define m68ki_use_program_space() m68ki_address_space = FUNCTION_CODE_USER_PROGRAM - #define m68ki_get_address_space() m68ki_address_space + #if M68K_EMULATE_FC == OPT_SPECIFY_HANDLER + #define m68ki_set_fc(A) M68K_SET_FC_CALLBACK(A) + #else + #define m68ki_set_fc(A) CALLBACK_SET_FC(A) + #endif + #define m68ki_use_data_space() m68ki_address_space = FUNCTION_CODE_USER_DATA + #define m68ki_use_program_space() m68ki_address_space = FUNCTION_CODE_USER_PROGRAM + #define m68ki_get_address_space() m68ki_address_space #else - #define m68ki_set_fc(A) - #define m68ki_use_data_space() - #define m68ki_use_program_space() - #define m68ki_get_address_space() FUNCTION_CODE_USER_DATA + #define m68ki_set_fc(A) + #define m68ki_use_data_space() + #define m68ki_use_program_space() + #define m68ki_get_address_space() FUNCTION_CODE_USER_DATA #endif /* M68K_EMULATE_FC */ /* Enable or disable trace emulation */ #if M68K_EMULATE_TRACE - /* Initiates trace checking before each instruction (t1) */ - #define m68ki_trace_t1() m68ki_tracing = FLAG_T1 - /* adds t0 to trace checking if we encounter change of flow */ - #define m68ki_trace_t0() m68ki_tracing |= FLAG_T0 - /* Clear all tracing */ - #define m68ki_clear_trace() m68ki_tracing = 0 - /* Cause a trace exception if we are tracing */ - #define m68ki_exception_if_trace() if(m68ki_tracing) m68ki_exception_trace() + /* Initiates trace checking before each instruction (t1) */ + #define m68ki_trace_t1() m68ki_tracing = FLAG_T1 + /* adds t0 to trace checking if we encounter change of flow */ + #define m68ki_trace_t0() m68ki_tracing |= FLAG_T0 + /* Clear all tracing */ + #define m68ki_clear_trace() m68ki_tracing = 0 + /* Cause a trace exception if we are tracing */ + #define m68ki_exception_if_trace() if(m68ki_tracing) m68ki_exception_trace() #else - #define m68ki_trace_t1() - #define m68ki_trace_t0() - #define m68ki_clear_trace() - #define m68ki_exception_if_trace() + #define m68ki_trace_t1() + #define m68ki_trace_t0() + #define m68ki_clear_trace() + #define m68ki_exception_if_trace() #endif /* M68K_EMULATE_TRACE */ /* Address error */ #if M68K_EMULATE_ADDRESS_ERROR - #include + #include /* sigjmp() on Mac OS X and *BSD in general saves signal contexts and is super-slow, use sigsetjmp() to tell it not to */ #ifdef _BSD_SETJMP_H extern sigjmp_buf m68ki_aerr_trap; #define m68ki_set_address_error_trap(m68k) \ - if(sigsetjmp(m68ki_aerr_trap, 0) != 0) \ - { \ - m68ki_exception_address_error(m68k); \ - if(CPU_STOPPED) \ - { \ - if (m68ki_remaining_cycles > 0) \ - m68ki_remaining_cycles = 0; \ - return m68ki_initial_cycles; \ - } \ - } + if(sigsetjmp(m68ki_aerr_trap, 0) != 0) \ + { \ + m68ki_exception_address_error(m68k); \ + if(CPU_STOPPED) \ + { \ + if (m68ki_remaining_cycles > 0) \ + m68ki_remaining_cycles = 0; \ + return m68ki_initial_cycles; \ + } \ + } #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ - if((ADDR)&1) \ - { \ - m68ki_aerr_address = ADDR; \ - m68ki_aerr_write_mode = WRITE_MODE; \ - m68ki_aerr_fc = FC; \ - siglongjmp(m68ki_aerr_trap, 1); \ - } + if((ADDR)&1) \ + { \ + m68ki_aerr_address = ADDR; \ + m68ki_aerr_write_mode = WRITE_MODE; \ + m68ki_aerr_fc = FC; \ + siglongjmp(m68ki_aerr_trap, 1); \ + } #else extern jmp_buf m68ki_aerr_trap; - #define m68ki_set_address_error_trap() \ - if(setjmp(m68ki_aerr_trap) != 0) \ - { \ - m68ki_exception_address_error(); \ - if(CPU_STOPPED) \ - { \ - SET_CYCLES(0); \ - return m68ki_initial_cycles; \ - } \ - /* ensure we don't re-enter execution loop after an - address error if there's no more cycles remaining */ \ - if(GET_CYCLES() <= 0) \ - { \ - /* return how many clocks we used */ \ - return m68ki_initial_cycles - GET_CYCLES(); \ - } \ - } + #define m68ki_set_address_error_trap() \ + if(setjmp(m68ki_aerr_trap) != 0) \ + { \ + m68ki_exception_address_error(); \ + if(CPU_STOPPED) \ + { \ + SET_CYCLES(0); \ + return m68ki_initial_cycles; \ + } \ + /* ensure we don't re-enter execution loop after an + address error if there's no more cycles remaining */ \ + if(GET_CYCLES() <= 0) \ + { \ + /* return how many clocks we used */ \ + return m68ki_initial_cycles - GET_CYCLES(); \ + } \ + } - #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ - if((ADDR)&1) \ - { \ - m68ki_aerr_address = ADDR; \ - m68ki_aerr_write_mode = WRITE_MODE; \ - m68ki_aerr_fc = FC; \ - longjmp(m68ki_aerr_trap, 1); \ - } + #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ + if((ADDR)&1) \ + { \ + m68ki_aerr_address = ADDR; \ + m68ki_aerr_write_mode = WRITE_MODE; \ + m68ki_aerr_fc = FC; \ + longjmp(m68ki_aerr_trap, 1); \ + } #endif - #define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) \ - if (CPU_TYPE_IS_010_LESS(CPU_TYPE)) \ - { \ - m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ - } + #define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) \ + if (CPU_TYPE_IS_010_LESS(CPU_TYPE)) \ + { \ + m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ + } #else - #define m68ki_set_address_error_trap() - #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) - #define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) + #define m68ki_set_address_error_trap() + #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) + #define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) #endif /* M68K_ADDRESS_ERROR */ /* Logging */ #if M68K_LOG_ENABLE - #include - extern FILE* M68K_LOG_FILEHANDLE - extern const char *const m68ki_cpu_names[]; + #include + extern FILE* M68K_LOG_FILEHANDLE + extern const char *const m68ki_cpu_names[]; - #define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A - #if M68K_LOG_1010_1111 - #define M68K_DO_LOG_EMU(A) if(M68K_LOG_FILEHANDLE) fprintf A - #else - #define M68K_DO_LOG_EMU(A) - #endif + #define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A + #if M68K_LOG_1010_1111 + #define M68K_DO_LOG_EMU(A) if(M68K_LOG_FILEHANDLE) fprintf A + #else + #define M68K_DO_LOG_EMU(A) + #endif #else - #define M68K_DO_LOG(A) - #define M68K_DO_LOG_EMU(A) + #define M68K_DO_LOG(A) + #define M68K_DO_LOG_EMU(A) #endif @@ -761,11 +761,11 @@ extern jmp_buf m68ki_aerr_trap; #define CFLAG_16(A) ((A)>>8) #if M68K_INT_GT_32_BIT - #define CFLAG_ADD_32(S, D, R) ((R)>>24) - #define CFLAG_SUB_32(S, D, R) ((R)>>24) + #define CFLAG_ADD_32(S, D, R) ((R)>>24) + #define CFLAG_SUB_32(S, D, R) ((R)>>24) #else - #define CFLAG_ADD_32(S, D, R) (((S & D) | (~R & (S | D)))>>23) - #define CFLAG_SUB_32(S, D, R) (((S & R) | (~D & (S | R)))>>23) + #define CFLAG_ADD_32(S, D, R) (((S & D) | (~R & (S | D)))>>23) + #define CFLAG_SUB_32(S, D, R) (((S & R) | (~D & (S | R)))>>23) #endif /* M68K_INT_GT_32_BIT */ #define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R)) @@ -850,18 +850,18 @@ extern jmp_buf m68ki_aerr_trap; /* Get the condition code register */ #define m68ki_get_ccr() ((COND_XS() >> 4) | \ - (COND_MI() >> 4) | \ - (COND_EQ() << 2) | \ - (COND_VS() >> 6) | \ - (COND_CS() >> 8)) + (COND_MI() >> 4) | \ + (COND_EQ() << 2) | \ + (COND_VS() >> 6) | \ + (COND_CS() >> 8)) /* Get the status register */ #define m68ki_get_sr() ( FLAG_T1 | \ - FLAG_T0 | \ - (FLAG_S << 11) | \ - (FLAG_M << 11) | \ - FLAG_INT_MASK | \ - m68ki_get_ccr()) + FLAG_T0 | \ + (FLAG_S << 11) | \ + (FLAG_M << 11) | \ + FLAG_INT_MASK | \ + m68ki_get_ccr()) @@ -899,14 +899,14 @@ extern jmp_buf m68ki_aerr_trap; #define m68ki_read_pcrel_32(A) m68k_read_pcrelative_32(A) /* Read from the program space */ -#define m68ki_read_program_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) -#define m68ki_read_program_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) -#define m68ki_read_program_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) +#define m68ki_read_program_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) +#define m68ki_read_program_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) +#define m68ki_read_program_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) /* Read from the data space */ -#define m68ki_read_data_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) -#define m68ki_read_data_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) -#define m68ki_read_data_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) +#define m68ki_read_data_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) +#define m68ki_read_data_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) +#define m68ki_read_data_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) @@ -916,87 +916,87 @@ extern jmp_buf m68ki_aerr_trap; typedef union { - uint64 i; - double f; + uint64 i; + double f; } fp_reg; typedef struct { - uint cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, or 68040 */ - uint dar[16]; /* Data and Address Registers */ - uint dar_save[16]; /* Saved Data and Address Registers (pushed onto the - stack when a bus error occurs)*/ - uint ppc; /* Previous program counter */ - uint pc; /* Program Counter */ - uint sp[7]; /* User, Interrupt, and Master Stack Pointers */ - uint vbr; /* Vector Base Register (m68010+) */ - uint sfc; /* Source Function Code Register (m68010+) */ - uint dfc; /* Destination Function Code Register (m68010+) */ - uint cacr; /* Cache Control Register (m68020, unemulated) */ - uint caar; /* Cache Address Register (m68020, unemulated) */ - uint ir; /* Instruction Register */ - floatx80 fpr[8]; /* FPU Data Register (m68030/040) */ - uint fpiar; /* FPU Instruction Address Register (m68040) */ - uint fpsr; /* FPU Status Register (m68040) */ - uint fpcr; /* FPU Control Register (m68040) */ - uint t1_flag; /* Trace 1 */ - uint t0_flag; /* Trace 0 */ - uint s_flag; /* Supervisor */ - uint m_flag; /* Master/Interrupt state */ - uint x_flag; /* Extend */ - uint n_flag; /* Negative */ - uint not_z_flag; /* Zero, inverted for speedups */ - uint v_flag; /* Overflow */ - uint c_flag; /* Carry */ - uint int_mask; /* I0-I2 */ - uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */ - uint stopped; /* Stopped state */ - uint pref_addr; /* Last prefetch address */ - uint pref_data; /* Data in the prefetch queue */ - uint address_mask; /* Available address pins */ - uint sr_mask; /* Implemented status register bits */ - uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */ - uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */ - int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */ - int pmmu_enabled; /* Indicates if the PMMU is enabled */ - int fpu_just_reset; /* Indicates the FPU was just reset */ - uint reset_cycles; + uint cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, or 68040 */ + uint dar[16]; /* Data and Address Registers */ + uint dar_save[16]; /* Saved Data and Address Registers (pushed onto the + stack when a bus error occurs)*/ + uint ppc; /* Previous program counter */ + uint pc; /* Program Counter */ + uint sp[7]; /* User, Interrupt, and Master Stack Pointers */ + uint vbr; /* Vector Base Register (m68010+) */ + uint sfc; /* Source Function Code Register (m68010+) */ + uint dfc; /* Destination Function Code Register (m68010+) */ + uint cacr; /* Cache Control Register (m68020, unemulated) */ + uint caar; /* Cache Address Register (m68020, unemulated) */ + uint ir; /* Instruction Register */ + floatx80 fpr[8]; /* FPU Data Register (m68030/040) */ + uint fpiar; /* FPU Instruction Address Register (m68040) */ + uint fpsr; /* FPU Status Register (m68040) */ + uint fpcr; /* FPU Control Register (m68040) */ + uint t1_flag; /* Trace 1 */ + uint t0_flag; /* Trace 0 */ + uint s_flag; /* Supervisor */ + uint m_flag; /* Master/Interrupt state */ + uint x_flag; /* Extend */ + uint n_flag; /* Negative */ + uint not_z_flag; /* Zero, inverted for speedups */ + uint v_flag; /* Overflow */ + uint c_flag; /* Carry */ + uint int_mask; /* I0-I2 */ + uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */ + uint stopped; /* Stopped state */ + uint pref_addr; /* Last prefetch address */ + uint pref_data; /* Data in the prefetch queue */ + uint address_mask; /* Available address pins */ + uint sr_mask; /* Implemented status register bits */ + uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */ + uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */ + int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */ + int pmmu_enabled; /* Indicates if the PMMU is enabled */ + int fpu_just_reset; /* Indicates the FPU was just reset */ + uint reset_cycles; - /* Clocks required for instructions / exceptions */ - uint cyc_bcc_notake_b; - uint cyc_bcc_notake_w; - uint cyc_dbcc_f_noexp; - uint cyc_dbcc_f_exp; - uint cyc_scc_r_true; - uint cyc_movem_w; - uint cyc_movem_l; - uint cyc_shift; - uint cyc_reset; + /* Clocks required for instructions / exceptions */ + uint cyc_bcc_notake_b; + uint cyc_bcc_notake_w; + uint cyc_dbcc_f_noexp; + uint cyc_dbcc_f_exp; + uint cyc_scc_r_true; + uint cyc_movem_w; + uint cyc_movem_l; + uint cyc_shift; + uint cyc_reset; - /* Virtual IRQ lines state */ - uint virq_state; - uint nmi_pending; + /* Virtual IRQ lines state */ + uint virq_state; + uint nmi_pending; - /* PMMU registers */ - uint mmu_crp_aptr, mmu_crp_limit; - uint mmu_srp_aptr, mmu_srp_limit; - uint mmu_tc; - uint16 mmu_sr; + /* PMMU registers */ + uint mmu_crp_aptr, mmu_crp_limit; + uint mmu_srp_aptr, mmu_srp_limit; + uint mmu_tc; + uint16 mmu_sr; - const uint8* cyc_instruction; - const uint8* cyc_exception; + const uint8* cyc_instruction; + const uint8* cyc_exception; - /* Callbacks to host */ - int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */ - void (*bkpt_ack_callback)(unsigned int data); /* Breakpoint Acknowledge */ - void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */ - void (*cmpild_instr_callback)(unsigned int, int); /* Called when a CMPI.L #v, Dn instruction is encountered */ - void (*rte_instr_callback)(void); /* Called when a RTE instruction is encountered */ - int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */ - int (*illg_instr_callback)(int); /* Called when an illegal instruction is encountered, allows handling */ - void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */ - void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */ - void (*instr_hook_callback)(unsigned int pc); /* Called every instruction cycle prior to execution */ + /* Callbacks to host */ + int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */ + void (*bkpt_ack_callback)(unsigned int data); /* Breakpoint Acknowledge */ + void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */ + void (*cmpild_instr_callback)(unsigned int, int); /* Called when a CMPI.L #v, Dn instruction is encountered */ + void (*rte_instr_callback)(void); /* Called when a RTE instruction is encountered */ + int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */ + int (*illg_instr_callback)(int); /* Called when an illegal instruction is encountered, allows handling */ + void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */ + void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */ + void (*instr_hook_callback)(unsigned int pc); /* Called every instruction cycle prior to execution */ } m68ki_cpu_core; @@ -1039,78 +1039,78 @@ extern uint pmmu_translate_addr(uint addr_in); */ static inline uint m68ki_read_imm_16(void) { - m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ #if M68K_SEPARATE_READS #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif #endif #if M68K_EMULATE_PREFETCH { - uint result; - if(REG_PC != CPU_PREF_ADDR) - { - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - } - result = MASK_OUT_ABOVE_16(CPU_PREF_DATA); - REG_PC += 2; - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - return result; + uint result; + if(REG_PC != CPU_PREF_ADDR) + { + CPU_PREF_ADDR = REG_PC; + CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); + } + result = MASK_OUT_ABOVE_16(CPU_PREF_DATA); + REG_PC += 2; + CPU_PREF_ADDR = REG_PC; + CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); + return result; } #else - REG_PC += 2; - return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2)); + REG_PC += 2; + return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2)); #endif /* M68K_EMULATE_PREFETCH */ } static inline uint m68ki_read_imm_8(void) { - /* map read immediate 8 to read immediate 16 */ - return MASK_OUT_ABOVE_8(m68ki_read_imm_16()); + /* map read immediate 8 to read immediate 16 */ + return MASK_OUT_ABOVE_8(m68ki_read_imm_16()); } static inline uint m68ki_read_imm_32(void) { #if M68K_SEPARATE_READS #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif #endif #if M68K_EMULATE_PREFETCH - uint temp_val; + uint temp_val; - m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - if(REG_PC != CPU_PREF_ADDR) - { - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - } - temp_val = MASK_OUT_ABOVE_16(CPU_PREF_DATA); - REG_PC += 2; - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); + if(REG_PC != CPU_PREF_ADDR) + { + CPU_PREF_ADDR = REG_PC; + CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); + } + temp_val = MASK_OUT_ABOVE_16(CPU_PREF_DATA); + REG_PC += 2; + CPU_PREF_ADDR = REG_PC; + CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | MASK_OUT_ABOVE_16(CPU_PREF_DATA)); - REG_PC += 2; - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); + temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | MASK_OUT_ABOVE_16(CPU_PREF_DATA)); + REG_PC += 2; + CPU_PREF_ADDR = REG_PC; + CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - return temp_val; + return temp_val; #else - m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - REG_PC += 4; - return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4)); + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + REG_PC += 4; + return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4)); #endif /* M68K_EMULATE_PREFETCH */ } @@ -1124,95 +1124,95 @@ static inline uint m68ki_read_imm_32(void) */ static inline uint m68ki_read_8_fc(uint address, uint fc) { - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + (void)fc; + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif - return m68k_read_memory_8(ADDRESS_68K(address)); + return m68k_read_memory_8(ADDRESS_68K(address)); } static inline uint m68ki_read_16_fc(uint address, uint fc) { - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ + (void)fc; + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif - return m68k_read_memory_16(ADDRESS_68K(address)); + return m68k_read_memory_16(ADDRESS_68K(address)); } static inline uint m68ki_read_32_fc(uint address, uint fc) { - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ + (void)fc; + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif - return m68k_read_memory_32(ADDRESS_68K(address)); + return m68k_read_memory_32(ADDRESS_68K(address)); } static inline void m68ki_write_8_fc(uint address, uint fc, uint value) { - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + (void)fc; + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif - m68k_write_memory_8(ADDRESS_68K(address), value); + m68k_write_memory_8(ADDRESS_68K(address), value); } static inline void m68ki_write_16_fc(uint address, uint fc, uint value) { - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + (void)fc; + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif - m68k_write_memory_16(ADDRESS_68K(address), value); + m68k_write_memory_16(ADDRESS_68K(address), value); } static inline void m68ki_write_32_fc(uint address, uint fc, uint value) { - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + (void)fc; + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif - m68k_write_memory_32(ADDRESS_68K(address), value); + m68k_write_memory_32(ADDRESS_68K(address), value); } #if M68K_SIMULATE_PD_WRITES static inline void m68ki_write_32_pd_fc(uint address, uint fc, uint value) { - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ + (void)fc; + m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ + m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ #if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); + if (PMMU_ENABLED) + address = pmmu_translate_addr(address); #endif - m68k_write_memory_32_pd(ADDRESS_68K(address), value); + m68k_write_memory_32_pd(ADDRESS_68K(address), value); } #endif @@ -1223,16 +1223,16 @@ static inline void m68ki_write_32_pd_fc(uint address, uint fc, uint value) */ static inline uint m68ki_get_ea_pcdi(void) { - uint old_pc = REG_PC; - m68ki_use_program_space(); /* auto-disable */ - return old_pc + MAKE_INT_16(m68ki_read_imm_16()); + uint old_pc = REG_PC; + m68ki_use_program_space(); /* auto-disable */ + return old_pc + MAKE_INT_16(m68ki_read_imm_16()); } static inline uint m68ki_get_ea_pcix(void) { - m68ki_use_program_space(); /* auto-disable */ - return m68ki_get_ea_ix(REG_PC); + m68ki_use_program_space(); /* auto-disable */ + return m68ki_get_ea_ix(REG_PC); } /* Indexed addressing modes are encoded as follows: @@ -1279,73 +1279,73 @@ static inline uint m68ki_get_ea_pcix(void) */ static inline uint m68ki_get_ea_ix(uint An) { - /* An = base register */ - uint extension = m68ki_read_imm_16(); - uint Xn = 0; /* Index register */ - uint bd = 0; /* Base Displacement */ - uint od = 0; /* Outer Displacement */ + /* An = base register */ + uint extension = m68ki_read_imm_16(); + uint Xn = 0; /* Index register */ + uint bd = 0; /* Base Displacement */ + uint od = 0; /* Outer Displacement */ - if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) - { - /* Calculate index */ - Xn = REG_DA[extension>>12]; /* Xn */ - if(!BIT_B(extension)) /* W/L */ - Xn = MAKE_INT_16(Xn); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + { + /* Calculate index */ + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); - /* Add base register and displacement and return */ - return An + Xn + MAKE_INT_8(extension); - } + /* Add base register and displacement and return */ + return An + Xn + MAKE_INT_8(extension); + } - /* Brief extension format */ - if(!BIT_8(extension)) - { - /* Calculate index */ - Xn = REG_DA[extension>>12]; /* Xn */ - if(!BIT_B(extension)) /* W/L */ - Xn = MAKE_INT_16(Xn); - /* Add scale if proper CPU type */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - Xn <<= (extension>>9) & 3; /* SCALE */ + /* Brief extension format */ + if(!BIT_8(extension)) + { + /* Calculate index */ + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); + /* Add scale if proper CPU type */ + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + Xn <<= (extension>>9) & 3; /* SCALE */ - /* Add base register and displacement and return */ - return An + Xn + MAKE_INT_8(extension); - } + /* Add base register and displacement and return */ + return An + Xn + MAKE_INT_8(extension); + } - /* Full extension format */ + /* Full extension format */ - USE_CYCLES(m68ki_ea_idx_cycle_table[extension&0x3f]); + USE_CYCLES(m68ki_ea_idx_cycle_table[extension&0x3f]); - /* Check if base register is present */ - if(BIT_7(extension)) /* BS */ - An = 0; /* An */ + /* Check if base register is present */ + if(BIT_7(extension)) /* BS */ + An = 0; /* An */ - /* Check if index is present */ - if(!BIT_6(extension)) /* IS */ - { - Xn = REG_DA[extension>>12]; /* Xn */ - if(!BIT_B(extension)) /* W/L */ - Xn = MAKE_INT_16(Xn); - Xn <<= (extension>>9) & 3; /* SCALE */ - } + /* Check if index is present */ + if(!BIT_6(extension)) /* IS */ + { + Xn = REG_DA[extension>>12]; /* Xn */ + if(!BIT_B(extension)) /* W/L */ + Xn = MAKE_INT_16(Xn); + Xn <<= (extension>>9) & 3; /* SCALE */ + } - /* Check if base displacement is present */ - if(BIT_5(extension)) /* BD SIZE */ - bd = BIT_4(extension) ? m68ki_read_imm_32() : (uint32)MAKE_INT_16(m68ki_read_imm_16()); + /* Check if base displacement is present */ + if(BIT_5(extension)) /* BD SIZE */ + bd = BIT_4(extension) ? m68ki_read_imm_32() : (uint32)MAKE_INT_16(m68ki_read_imm_16()); - /* If no indirect action, we are done */ - if(!(extension&7)) /* No Memory Indirect */ - return An + bd + Xn; + /* If no indirect action, we are done */ + if(!(extension&7)) /* No Memory Indirect */ + return An + bd + Xn; - /* Check if outer displacement is present */ - if(BIT_1(extension)) /* I/IS: od */ - od = BIT_0(extension) ? m68ki_read_imm_32() : (uint32)MAKE_INT_16(m68ki_read_imm_16()); + /* Check if outer displacement is present */ + if(BIT_1(extension)) /* I/IS: od */ + od = BIT_0(extension) ? m68ki_read_imm_32() : (uint32)MAKE_INT_16(m68ki_read_imm_16()); - /* Postindex */ - if(BIT_2(extension)) /* I/IS: 0 = preindex, 1 = postindex */ - return m68ki_read_32(An + bd) + Xn + od; + /* Postindex */ + if(BIT_2(extension)) /* I/IS: 0 = preindex, 1 = postindex */ + return m68ki_read_32(An + bd) + Xn + od; - /* Preindex */ - return m68ki_read_32(An + bd + Xn) + od; + /* Preindex */ + return m68ki_read_32(An + bd + Xn) + od; } @@ -1405,26 +1405,26 @@ static inline uint OPER_PCIX_32(void) {uint ea = EA_PCIX_32(); return m68ki_re /* Push/pull data from the stack */ static inline void m68ki_push_16(uint value) { - REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); - m68ki_write_16(REG_SP, value); + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); + m68ki_write_16(REG_SP, value); } static inline void m68ki_push_32(uint value) { - REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); - m68ki_write_32(REG_SP, value); + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); + m68ki_write_32(REG_SP, value); } static inline uint m68ki_pull_16(void) { - REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); - return m68ki_read_16(REG_SP-2); + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); + return m68ki_read_16(REG_SP-2); } static inline uint m68ki_pull_32(void) { - REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); - return m68ki_read_32(REG_SP-4); + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); + return m68ki_read_32(REG_SP-4); } @@ -1433,22 +1433,22 @@ static inline uint m68ki_pull_32(void) */ static inline void m68ki_fake_push_16(void) { - REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); } static inline void m68ki_fake_push_32(void) { - REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); + REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); } static inline void m68ki_fake_pull_16(void) { - REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); } static inline void m68ki_fake_pull_32(void) { - REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); + REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); } @@ -1460,15 +1460,15 @@ static inline void m68ki_fake_pull_32(void) */ static inline void m68ki_jump(uint new_pc) { - REG_PC = new_pc; - m68ki_pc_changed(REG_PC); + REG_PC = new_pc; + m68ki_pc_changed(REG_PC); } static inline void m68ki_jump_vector(uint vector) { - REG_PC = (vector<<2) + REG_VBR; - REG_PC = m68ki_read_data_32(REG_PC); - m68ki_pc_changed(REG_PC); + REG_PC = (vector<<2) + REG_VBR; + REG_PC = m68ki_read_data_32(REG_PC); + m68ki_pc_changed(REG_PC); } @@ -1479,18 +1479,18 @@ static inline void m68ki_jump_vector(uint vector) */ static inline void m68ki_branch_8(uint offset) { - REG_PC += MAKE_INT_8(offset); + REG_PC += MAKE_INT_8(offset); } static inline void m68ki_branch_16(uint offset) { - REG_PC += MAKE_INT_16(offset); + REG_PC += MAKE_INT_16(offset); } static inline void m68ki_branch_32(uint offset) { - REG_PC += offset; - m68ki_pc_changed(REG_PC); + REG_PC += offset; + m68ki_pc_changed(REG_PC); } /* ---------------------------- Status Register --------------------------- */ @@ -1500,12 +1500,12 @@ static inline void m68ki_branch_32(uint offset) */ static inline void m68ki_set_s_flag(uint value) { - /* Backup the old stack pointer */ - REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; - /* Set the S flag */ - FLAG_S = value; - /* Set the new stack pointer */ - REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; + /* Backup the old stack pointer */ + REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; + /* Set the S flag */ + FLAG_S = value; + /* Set the new stack pointer */ + REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; } /* Set the S and M flags and change the active stack pointer. @@ -1513,46 +1513,46 @@ static inline void m68ki_set_s_flag(uint value) */ static inline void m68ki_set_sm_flag(uint value) { - /* Backup the old stack pointer */ - REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; - /* Set the S and M flags */ - FLAG_S = value & SFLAG_SET; - FLAG_M = value & MFLAG_SET; - /* Set the new stack pointer */ - REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; + /* Backup the old stack pointer */ + REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; + /* Set the S and M flags */ + FLAG_S = value & SFLAG_SET; + FLAG_M = value & MFLAG_SET; + /* Set the new stack pointer */ + REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; } /* Set the S and M flags. Don't touch the stack pointer. */ static inline void m68ki_set_sm_flag_nosp(uint value) { - /* Set the S and M flags */ - FLAG_S = value & SFLAG_SET; - FLAG_M = value & MFLAG_SET; + /* Set the S and M flags */ + FLAG_S = value & SFLAG_SET; + FLAG_M = value & MFLAG_SET; } /* Set the condition code register */ static inline void m68ki_set_ccr(uint value) { - FLAG_X = BIT_4(value) << 4; - FLAG_N = BIT_3(value) << 4; - FLAG_Z = !BIT_2(value); - FLAG_V = BIT_1(value) << 6; - FLAG_C = BIT_0(value) << 8; + FLAG_X = BIT_4(value) << 4; + FLAG_N = BIT_3(value) << 4; + FLAG_Z = !BIT_2(value); + FLAG_V = BIT_1(value) << 6; + FLAG_C = BIT_0(value) << 8; } /* Set the status register but don't check for interrupts */ static inline void m68ki_set_sr_noint(uint value) { - /* Mask out the "unimplemented" bits */ - value &= CPU_SR_MASK; + /* Mask out the "unimplemented" bits */ + value &= CPU_SR_MASK; - /* Now set the status register */ - FLAG_T1 = BIT_F(value); - FLAG_T0 = BIT_E(value); - FLAG_INT_MASK = value & 0x0700; - m68ki_set_ccr(value); - m68ki_set_sm_flag((value >> 11) & 6); + /* Now set the status register */ + FLAG_T1 = BIT_F(value); + FLAG_T0 = BIT_E(value); + FLAG_INT_MASK = value & 0x0700; + m68ki_set_ccr(value); + m68ki_set_sm_flag((value >> 11) & 6); } /* Set the status register but don't check for interrupts nor @@ -1560,22 +1560,22 @@ static inline void m68ki_set_sr_noint(uint value) */ static inline void m68ki_set_sr_noint_nosp(uint value) { - /* Mask out the "unimplemented" bits */ - value &= CPU_SR_MASK; + /* Mask out the "unimplemented" bits */ + value &= CPU_SR_MASK; - /* Now set the status register */ - FLAG_T1 = BIT_F(value); - FLAG_T0 = BIT_E(value); - FLAG_INT_MASK = value & 0x0700; - m68ki_set_ccr(value); - m68ki_set_sm_flag_nosp((value >> 11) & 6); + /* Now set the status register */ + FLAG_T1 = BIT_F(value); + FLAG_T0 = BIT_E(value); + FLAG_INT_MASK = value & 0x0700; + m68ki_set_ccr(value); + m68ki_set_sm_flag_nosp((value >> 11) & 6); } /* Set the status register and check for interrupts */ static inline void m68ki_set_sr(uint value) { - m68ki_set_sr_noint(value); - m68ki_check_interrupts(); + m68ki_set_sr_noint(value); + m68ki_check_interrupts(); } @@ -1584,23 +1584,23 @@ static inline void m68ki_set_sr(uint value) /* Initiate exception processing */ static inline uint m68ki_init_exception(void) { - /* Save the old status register */ - uint sr = m68ki_get_sr(); + /* Save the old status register */ + uint sr = m68ki_get_sr(); - /* Turn off trace flag, clear pending traces */ - FLAG_T1 = FLAG_T0 = 0; - m68ki_clear_trace(); - /* Enter supervisor mode */ - m68ki_set_s_flag(SFLAG_SET); + /* Turn off trace flag, clear pending traces */ + FLAG_T1 = FLAG_T0 = 0; + m68ki_clear_trace(); + /* Enter supervisor mode */ + m68ki_set_s_flag(SFLAG_SET); - return sr; + return sr; } /* 3 word stack frame (68000 only) */ static inline void m68ki_stack_frame_3word(uint pc, uint sr) { - m68ki_push_32(pc); - m68ki_push_16(sr); + m68ki_push_32(pc); + m68ki_push_16(sr); } /* Format 0 stack frame. @@ -1608,15 +1608,15 @@ static inline void m68ki_stack_frame_3word(uint pc, uint sr) */ static inline void m68ki_stack_frame_0000(uint pc, uint sr, uint vector) { - /* Stack a 3-word frame if we are 68000 */ - if(CPU_TYPE == CPU_TYPE_000) - { - m68ki_stack_frame_3word(pc, sr); - return; - } - m68ki_push_16(vector<<2); - m68ki_push_32(pc); - m68ki_push_16(sr); + /* Stack a 3-word frame if we are 68000 */ + if(CPU_TYPE == CPU_TYPE_000) + { + m68ki_stack_frame_3word(pc, sr); + return; + } + m68ki_push_16(vector<<2); + m68ki_push_32(pc); + m68ki_push_16(sr); } /* Format 1 stack frame (68020). @@ -1624,9 +1624,9 @@ static inline void m68ki_stack_frame_0000(uint pc, uint sr, uint vector) */ static inline void m68ki_stack_frame_0001(uint pc, uint sr, uint vector) { - m68ki_push_16(0x1000 | (vector<<2)); - m68ki_push_32(pc); - m68ki_push_16(sr); + m68ki_push_16(0x1000 | (vector<<2)); + m68ki_push_32(pc); + m68ki_push_16(sr); } /* Format 2 stack frame. @@ -1634,10 +1634,10 @@ static inline void m68ki_stack_frame_0001(uint pc, uint sr, uint vector) */ static inline void m68ki_stack_frame_0010(uint sr, uint vector) { - m68ki_push_32(REG_PPC); - m68ki_push_16(0x2000 | (vector<<2)); - m68ki_push_32(REG_PC); - m68ki_push_16(sr); + m68ki_push_32(REG_PPC); + m68ki_push_16(0x2000 | (vector<<2)); + m68ki_push_32(REG_PC); + m68ki_push_16(sr); } @@ -1645,16 +1645,16 @@ static inline void m68ki_stack_frame_0010(uint sr, uint vector) */ static inline void m68ki_stack_frame_buserr(uint sr) { - m68ki_push_32(REG_PC); - m68ki_push_16(sr); - m68ki_push_16(REG_IR); - m68ki_push_32(m68ki_aerr_address); /* access address */ - /* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC - * R/W 0 = write, 1 = read - * I/N 0 = instruction, 1 = not - * FC 3-bit function code - */ - m68ki_push_16(m68ki_aerr_write_mode | CPU_INSTR_MODE | m68ki_aerr_fc); + m68ki_push_32(REG_PC); + m68ki_push_16(sr); + m68ki_push_16(REG_IR); + m68ki_push_32(m68ki_aerr_address); /* access address */ + /* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC + * R/W 0 = write, 1 = read + * I/N 0 = instruction, 1 = not + * FC 3-bit function code + */ + m68ki_push_16(m68ki_aerr_write_mode | CPU_INSTR_MODE | m68ki_aerr_fc); } /* Format 8 stack frame (68010). @@ -1662,51 +1662,51 @@ static inline void m68ki_stack_frame_buserr(uint sr) */ static inline void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) { - /* VERSION - * NUMBER - * INTERNAL INFORMATION, 16 WORDS - */ - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); + /* VERSION + * NUMBER + * INTERNAL INFORMATION, 16 WORDS + */ + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); + m68ki_fake_push_32(); - /* INSTRUCTION INPUT BUFFER */ - m68ki_push_16(0); + /* INSTRUCTION INPUT BUFFER */ + m68ki_push_16(0); - /* UNUSED, RESERVED (not written) */ - m68ki_fake_push_16(); + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(); - /* DATA INPUT BUFFER */ - m68ki_push_16(0); + /* DATA INPUT BUFFER */ + m68ki_push_16(0); - /* UNUSED, RESERVED (not written) */ - m68ki_fake_push_16(); + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(); - /* DATA OUTPUT BUFFER */ - m68ki_push_16(0); + /* DATA OUTPUT BUFFER */ + m68ki_push_16(0); - /* UNUSED, RESERVED (not written) */ - m68ki_fake_push_16(); + /* UNUSED, RESERVED (not written) */ + m68ki_fake_push_16(); - /* FAULT ADDRESS */ - m68ki_push_32(0); + /* FAULT ADDRESS */ + m68ki_push_32(0); - /* SPECIAL STATUS WORD */ - m68ki_push_16(0); + /* SPECIAL STATUS WORD */ + m68ki_push_16(0); - /* 1000, VECTOR OFFSET */ - m68ki_push_16(0x8000 | (vector<<2)); + /* 1000, VECTOR OFFSET */ + m68ki_push_16(0x8000 | (vector<<2)); - /* PROGRAM COUNTER */ - m68ki_push_32(pc); + /* PROGRAM COUNTER */ + m68ki_push_32(pc); - /* STATUS REGISTER */ - m68ki_push_16(sr); + /* STATUS REGISTER */ + m68ki_push_16(sr); } /* Format A stack frame (short bus fault). @@ -1716,44 +1716,44 @@ static inline void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) */ static inline void m68ki_stack_frame_1010(uint sr, uint vector, uint pc) { - /* INTERNAL REGISTER */ - m68ki_push_16(0); + /* INTERNAL REGISTER */ + m68ki_push_16(0); - /* INTERNAL REGISTER */ - m68ki_push_16(0); + /* INTERNAL REGISTER */ + m68ki_push_16(0); - /* DATA OUTPUT BUFFER (2 words) */ - m68ki_push_32(0); + /* DATA OUTPUT BUFFER (2 words) */ + m68ki_push_32(0); - /* INTERNAL REGISTER */ - m68ki_push_16(0); + /* INTERNAL REGISTER */ + m68ki_push_16(0); - /* INTERNAL REGISTER */ - m68ki_push_16(0); + /* INTERNAL REGISTER */ + m68ki_push_16(0); - /* DATA CYCLE FAULT ADDRESS (2 words) */ - m68ki_push_32(0); + /* DATA CYCLE FAULT ADDRESS (2 words) */ + m68ki_push_32(0); - /* INSTRUCTION PIPE STAGE B */ - m68ki_push_16(0); + /* INSTRUCTION PIPE STAGE B */ + m68ki_push_16(0); - /* INSTRUCTION PIPE STAGE C */ - m68ki_push_16(0); + /* INSTRUCTION PIPE STAGE C */ + m68ki_push_16(0); - /* SPECIAL STATUS REGISTER */ - m68ki_push_16(0); + /* SPECIAL STATUS REGISTER */ + m68ki_push_16(0); - /* INTERNAL REGISTER */ - m68ki_push_16(0); + /* INTERNAL REGISTER */ + m68ki_push_16(0); - /* 1010, VECTOR OFFSET */ - m68ki_push_16(0xa000 | (vector<<2)); + /* 1010, VECTOR OFFSET */ + m68ki_push_16(0xa000 | (vector<<2)); - /* PROGRAM COUNTER */ - m68ki_push_32(pc); + /* PROGRAM COUNTER */ + m68ki_push_32(pc); - /* STATUS REGISTER */ - m68ki_push_16(sr); + /* STATUS REGISTER */ + m68ki_push_16(sr); } /* Format B stack frame (long bus fault). @@ -1763,69 +1763,69 @@ static inline void m68ki_stack_frame_1010(uint sr, uint vector, uint pc) */ static inline void m68ki_stack_frame_1011(uint sr, uint vector, uint pc) { - /* INTERNAL REGISTERS (18 words) */ - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); + /* INTERNAL REGISTERS (18 words) */ + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); + m68ki_push_32(0); - /* VERSION# (4 bits), INTERNAL INFORMATION */ - m68ki_push_16(0); + /* VERSION# (4 bits), INTERNAL INFORMATION */ + m68ki_push_16(0); - /* INTERNAL REGISTERS (3 words) */ - m68ki_push_32(0); - m68ki_push_16(0); + /* INTERNAL REGISTERS (3 words) */ + m68ki_push_32(0); + m68ki_push_16(0); - /* DATA INTPUT BUFFER (2 words) */ - m68ki_push_32(0); + /* DATA INTPUT BUFFER (2 words) */ + m68ki_push_32(0); - /* INTERNAL REGISTERS (2 words) */ - m68ki_push_32(0); + /* INTERNAL REGISTERS (2 words) */ + m68ki_push_32(0); - /* STAGE B ADDRESS (2 words) */ - m68ki_push_32(0); + /* STAGE B ADDRESS (2 words) */ + m68ki_push_32(0); - /* INTERNAL REGISTER (4 words) */ - m68ki_push_32(0); - m68ki_push_32(0); + /* INTERNAL REGISTER (4 words) */ + m68ki_push_32(0); + m68ki_push_32(0); - /* DATA OUTPUT BUFFER (2 words) */ - m68ki_push_32(0); + /* DATA OUTPUT BUFFER (2 words) */ + m68ki_push_32(0); - /* INTERNAL REGISTER */ - m68ki_push_16(0); + /* INTERNAL REGISTER */ + m68ki_push_16(0); - /* INTERNAL REGISTER */ - m68ki_push_16(0); + /* INTERNAL REGISTER */ + m68ki_push_16(0); - /* DATA CYCLE FAULT ADDRESS (2 words) */ - m68ki_push_32(0); + /* DATA CYCLE FAULT ADDRESS (2 words) */ + m68ki_push_32(0); - /* INSTRUCTION PIPE STAGE B */ - m68ki_push_16(0); + /* INSTRUCTION PIPE STAGE B */ + m68ki_push_16(0); - /* INSTRUCTION PIPE STAGE C */ - m68ki_push_16(0); + /* INSTRUCTION PIPE STAGE C */ + m68ki_push_16(0); - /* SPECIAL STATUS REGISTER */ - m68ki_push_16(0); + /* SPECIAL STATUS REGISTER */ + m68ki_push_16(0); - /* INTERNAL REGISTER */ - m68ki_push_16(0); + /* INTERNAL REGISTER */ + m68ki_push_16(0); - /* 1011, VECTOR OFFSET */ - m68ki_push_16(0xb000 | (vector<<2)); + /* 1011, VECTOR OFFSET */ + m68ki_push_16(0xb000 | (vector<<2)); - /* PROGRAM COUNTER */ - m68ki_push_32(pc); + /* PROGRAM COUNTER */ + m68ki_push_32(pc); - /* STATUS REGISTER */ - m68ki_push_16(sr); + /* STATUS REGISTER */ + m68ki_push_16(sr); } @@ -1834,74 +1834,74 @@ static inline void m68ki_stack_frame_1011(uint sr, uint vector, uint pc) */ static inline void m68ki_exception_trap(uint vector) { - uint sr = m68ki_init_exception(); + uint sr = m68ki_init_exception(); - if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) - m68ki_stack_frame_0000(REG_PC, sr, vector); - else - m68ki_stack_frame_0010(sr, vector); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + m68ki_stack_frame_0000(REG_PC, sr, vector); + else + m68ki_stack_frame_0010(sr, vector); - m68ki_jump_vector(vector); + m68ki_jump_vector(vector); - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[vector] - CYC_INSTRUCTION[REG_IR]); + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[vector] - CYC_INSTRUCTION[REG_IR]); } /* Trap#n stacks a 0 frame but behaves like group2 otherwise */ static inline void m68ki_exception_trapN(uint vector) { - uint sr = m68ki_init_exception(); - m68ki_stack_frame_0000(REG_PC, sr, vector); - m68ki_jump_vector(vector); + uint sr = m68ki_init_exception(); + m68ki_stack_frame_0000(REG_PC, sr, vector); + m68ki_jump_vector(vector); - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[vector] - CYC_INSTRUCTION[REG_IR]); + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[vector] - CYC_INSTRUCTION[REG_IR]); } /* Exception for trace mode */ static inline void m68ki_exception_trace(void) { - uint sr = m68ki_init_exception(); + uint sr = m68ki_init_exception(); - if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) - { - #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - CPU_INSTR_MODE = INSTRUCTION_NO; - } - #endif /* M68K_EMULATE_ADDRESS_ERROR */ - m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_TRACE); - } - else - m68ki_stack_frame_0010(sr, EXCEPTION_TRACE); + if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) + { + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ + m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_TRACE); + } + else + m68ki_stack_frame_0010(sr, EXCEPTION_TRACE); - m68ki_jump_vector(EXCEPTION_TRACE); + m68ki_jump_vector(EXCEPTION_TRACE); - /* Trace nullifies a STOP instruction */ - CPU_STOPPED &= ~STOP_LEVEL_STOP; + /* Trace nullifies a STOP instruction */ + CPU_STOPPED &= ~STOP_LEVEL_STOP; - /* Use up some clock cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_TRACE]); + /* Use up some clock cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_TRACE]); } /* Exception for privilege violation */ static inline void m68ki_exception_privilege_violation(void) { - uint sr = m68ki_init_exception(); + uint sr = m68ki_init_exception(); - #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - CPU_INSTR_MODE = INSTRUCTION_NO; - } - #endif /* M68K_EMULATE_ADDRESS_ERROR */ + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ - m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_PRIVILEGE_VIOLATION); - m68ki_jump_vector(EXCEPTION_PRIVILEGE_VIOLATION); + m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_PRIVILEGE_VIOLATION); + m68ki_jump_vector(EXCEPTION_PRIVILEGE_VIOLATION); - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_PRIVILEGE_VIOLATION] - CYC_INSTRUCTION[REG_IR]); + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_PRIVILEGE_VIOLATION] - CYC_INSTRUCTION[REG_IR]); } extern jmp_buf m68ki_bus_error_jmp_buf; @@ -1911,38 +1911,38 @@ extern jmp_buf m68ki_bus_error_jmp_buf; /* Exception for bus error */ static inline void m68ki_exception_bus_error(void) { - uint sr; - int i; + uint sr; + int i; - /* If we were processing a bus error, address error, or reset, - * while writing the stack frame, this is a catastrophic failure. - * Halt the CPU - */ - if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET_WSF) - { - m68k_read_memory_8(0x00ffff01); - CPU_STOPPED = STOP_LEVEL_HALT; - return; - } - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET_WSF; + /* If we were processing a bus error, address error, or reset, + * while writing the stack frame, this is a catastrophic failure. + * Halt the CPU + */ + if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET_WSF) + { + m68k_read_memory_8(0x00ffff01); + CPU_STOPPED = STOP_LEVEL_HALT; + return; + } + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET_WSF; - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_BUS_ERROR] - CYC_INSTRUCTION[REG_IR]); + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_BUS_ERROR] - CYC_INSTRUCTION[REG_IR]); - for (i = 15; i >= 0; i--){ - REG_DA[i] = REG_DA_SAVE[i]; - } + for (i = 15; i >= 0; i--){ + REG_DA[i] = REG_DA_SAVE[i]; + } - sr = m68ki_init_exception(); + sr = m68ki_init_exception(); - /* Note: This is implemented for 68010 only! */ - m68ki_stack_frame_1000(REG_PPC, sr, EXCEPTION_BUS_ERROR); + /* Note: This is implemented for 68010 only! */ + m68ki_stack_frame_1000(REG_PPC, sr, EXCEPTION_BUS_ERROR); - m68ki_jump_vector(EXCEPTION_BUS_ERROR); + m68ki_jump_vector(EXCEPTION_BUS_ERROR); - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; - longjmp(m68ki_bus_error_jmp_buf, 1); + longjmp(m68ki_bus_error_jmp_buf, 1); } extern int cpu_log_enabled; @@ -1950,38 +1950,38 @@ extern int cpu_log_enabled; /* Exception for A-Line instructions */ static inline void m68ki_exception_1010(void) { - uint sr; + uint sr; #if M68K_LOG_1010_1111 == OPT_ON - M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1010 instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, - m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1010 instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); #endif - sr = m68ki_init_exception(); - m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1010); - m68ki_jump_vector(EXCEPTION_1010); + sr = m68ki_init_exception(); + m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1010); + m68ki_jump_vector(EXCEPTION_1010); - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1010] - CYC_INSTRUCTION[REG_IR]); + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1010] - CYC_INSTRUCTION[REG_IR]); } /* Exception for F-Line instructions */ static inline void m68ki_exception_1111(void) { - uint sr; + uint sr; #if M68K_LOG_1010_1111 == OPT_ON - M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1111 instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, - m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1111 instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); #endif - sr = m68ki_init_exception(); - m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1111); - m68ki_jump_vector(EXCEPTION_1111); + sr = m68ki_init_exception(); + m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1111); + m68ki_jump_vector(EXCEPTION_1111); - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1111] - CYC_INSTRUCTION[REG_IR]); + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1111] - CYC_INSTRUCTION[REG_IR]); } #if M68K_ILLG_HAS_CALLBACK == OPT_SPECIFY_HANDLER @@ -1991,142 +1991,142 @@ extern int m68ki_illg_callback(int); /* Exception for illegal instructions */ static inline void m68ki_exception_illegal(void) { - uint sr; + uint sr; - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: illegal instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, - m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); - if (m68ki_illg_callback(REG_IR)) - return; + M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: illegal instruction %04x (%s)\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, + m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); + if (m68ki_illg_callback(REG_IR)) + return; - sr = m68ki_init_exception(); + sr = m68ki_init_exception(); - #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - CPU_INSTR_MODE = INSTRUCTION_NO; - } - #endif /* M68K_EMULATE_ADDRESS_ERROR */ + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ - m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_ILLEGAL_INSTRUCTION_M68K); - m68ki_jump_vector(EXCEPTION_ILLEGAL_INSTRUCTION_M68K); + m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_ILLEGAL_INSTRUCTION_M68K); + m68ki_jump_vector(EXCEPTION_ILLEGAL_INSTRUCTION_M68K); - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ILLEGAL_INSTRUCTION_M68K] - CYC_INSTRUCTION[REG_IR]); + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ILLEGAL_INSTRUCTION_M68K] - CYC_INSTRUCTION[REG_IR]); } /* Exception for format errror in RTE */ static inline void m68ki_exception_format_error(void) { - uint sr = m68ki_init_exception(); - m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_FORMAT_ERROR); - m68ki_jump_vector(EXCEPTION_FORMAT_ERROR); + uint sr = m68ki_init_exception(); + m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_FORMAT_ERROR); + m68ki_jump_vector(EXCEPTION_FORMAT_ERROR); - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_FORMAT_ERROR] - CYC_INSTRUCTION[REG_IR]); + /* Use up some clock cycles and undo the instruction's cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_FORMAT_ERROR] - CYC_INSTRUCTION[REG_IR]); } /* Exception for address error */ static inline void m68ki_exception_address_error(void) { - uint sr = m68ki_init_exception(); + uint sr = m68ki_init_exception(); - /* If we were processing a bus error, address error, or reset, - * while writing the stack frame, this is a catastrophic failure. - * Halt the CPU - */ - if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET_WSF) - { - m68k_read_memory_8(0x00ffff01); - CPU_STOPPED = STOP_LEVEL_HALT; - return; - } - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET_WSF; + /* If we were processing a bus error, address error, or reset, + * while writing the stack frame, this is a catastrophic failure. + * Halt the CPU + */ + if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET_WSF) + { + m68k_read_memory_8(0x00ffff01); + CPU_STOPPED = STOP_LEVEL_HALT; + return; + } + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET_WSF; - /* Note: This is implemented for 68000 only! */ - m68ki_stack_frame_buserr(sr); + /* Note: This is implemented for 68000 only! */ + m68ki_stack_frame_buserr(sr); - m68ki_jump_vector(EXCEPTION_ADDRESS_ERROR); + m68ki_jump_vector(EXCEPTION_ADDRESS_ERROR); - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; + CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; - /* Use up some clock cycles. Note that we don't need to undo the - instruction's cycles here as we've longjmp:ed directly from the - instruction handler without passing the part of the excecute loop - that deducts instruction cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ADDRESS_ERROR]); + /* Use up some clock cycles. Note that we don't need to undo the + instruction's cycles here as we've longjmp:ed directly from the + instruction handler without passing the part of the excecute loop + that deducts instruction cycles */ + USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ADDRESS_ERROR]); } /* Service an interrupt request and start exception processing */ static inline void m68ki_exception_interrupt(uint int_level) { - uint vector; - uint sr; - uint new_pc; + uint vector; + uint sr; + uint new_pc; - #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - CPU_INSTR_MODE = INSTRUCTION_NO; - } - #endif /* M68K_EMULATE_ADDRESS_ERROR */ + #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON + if(CPU_TYPE_IS_000(CPU_TYPE)) + { + CPU_INSTR_MODE = INSTRUCTION_NO; + } + #endif /* M68K_EMULATE_ADDRESS_ERROR */ - /* Turn off the stopped state */ - CPU_STOPPED &= ~STOP_LEVEL_STOP; + /* Turn off the stopped state */ + CPU_STOPPED &= ~STOP_LEVEL_STOP; - /* If we are halted, don't do anything */ - if(CPU_STOPPED) - return; + /* If we are halted, don't do anything */ + if(CPU_STOPPED) + return; - /* Acknowledge the interrupt */ - vector = m68ki_int_ack(int_level); + /* Acknowledge the interrupt */ + vector = m68ki_int_ack(int_level); - /* Get the interrupt vector */ - if(vector == M68K_INT_ACK_AUTOVECTOR) - /* Use the autovectors. This is the most commonly used implementation */ - vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level; - else if(vector == M68K_INT_ACK_SPURIOUS) - /* Called if no devices respond to the interrupt acknowledge */ - vector = EXCEPTION_SPURIOUS_INTERRUPT; - else if(vector > 255) - { - M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector)); - return; - } + /* Get the interrupt vector */ + if(vector == M68K_INT_ACK_AUTOVECTOR) + /* Use the autovectors. This is the most commonly used implementation */ + vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level; + else if(vector == M68K_INT_ACK_SPURIOUS) + /* Called if no devices respond to the interrupt acknowledge */ + vector = EXCEPTION_SPURIOUS_INTERRUPT; + else if(vector > 255) + { + M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n", + m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector)); + return; + } - /* Start exception processing */ - sr = m68ki_init_exception(); + /* Start exception processing */ + sr = m68ki_init_exception(); - /* Set the interrupt mask to the level of the one being serviced */ - FLAG_INT_MASK = int_level<<8; + /* Set the interrupt mask to the level of the one being serviced */ + FLAG_INT_MASK = int_level<<8; - /* Get the new PC */ - new_pc = m68ki_read_data_32((vector<<2) + REG_VBR); + /* Get the new PC */ + new_pc = m68ki_read_data_32((vector<<2) + REG_VBR); - /* If vector is uninitialized, call the uninitialized interrupt vector */ - if(new_pc == 0) - new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR); + /* If vector is uninitialized, call the uninitialized interrupt vector */ + if(new_pc == 0) + new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR); - /* Generate a stack frame */ - m68ki_stack_frame_0000(REG_PC, sr, vector); - if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Create throwaway frame */ - m68ki_set_sm_flag(FLAG_S); /* clear M */ - sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */ - m68ki_stack_frame_0001(REG_PC, sr, vector); - } + /* Generate a stack frame */ + m68ki_stack_frame_0000(REG_PC, sr, vector); + if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + /* Create throwaway frame */ + m68ki_set_sm_flag(FLAG_S); /* clear M */ + sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */ + m68ki_stack_frame_0001(REG_PC, sr, vector); + } - m68ki_jump(new_pc); + m68ki_jump(new_pc); - /* Defer cycle counting until later */ - USE_CYCLES(CYC_EXCEPTION[vector]); + /* Defer cycle counting until later */ + USE_CYCLES(CYC_EXCEPTION[vector]); #if !M68K_EMULATE_INT_ACK - /* Automatically clear IRQ if we are not using an acknowledge scheme */ - CPU_INT_LEVEL = 0; + /* Automatically clear IRQ if we are not using an acknowledge scheme */ + CPU_INT_LEVEL = 0; #endif /* M68K_EMULATE_INT_ACK */ } @@ -2134,13 +2134,13 @@ static inline void m68ki_exception_interrupt(uint int_level) /* ASG: Check for interrupts */ static inline void m68ki_check_interrupts(void) { - if(m68ki_cpu.nmi_pending) - { - m68ki_cpu.nmi_pending = FALSE; - m68ki_exception_interrupt(7); - } - else if(CPU_INT_LEVEL > FLAG_INT_MASK) - m68ki_exception_interrupt(CPU_INT_LEVEL>>8); + if(m68ki_cpu.nmi_pending) + { + m68ki_cpu.nmi_pending = FALSE; + m68ki_exception_interrupt(7); + } + else if(CPU_INT_LEVEL > FLAG_INT_MASK) + m68ki_exception_interrupt(CPU_INT_LEVEL>>8); } diff --git a/AltairZ80/m68k/m68kdasm.c b/AltairZ80/m68k/m68kdasm.c index 25cbcb07..f7ab7a6e 100755 --- a/AltairZ80/m68k/m68kdasm.c +++ b/AltairZ80/m68k/m68kdasm.c @@ -99,21 +99,21 @@ #define TYPE_68030 8 #define TYPE_68040 16 -#define M68000_ONLY TYPE_68000 +#define M68000_ONLY TYPE_68000 -#define M68010_ONLY TYPE_68010 -#define M68010_LESS (TYPE_68000 | TYPE_68010) -#define M68010_PLUS (TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040) +#define M68010_ONLY TYPE_68010 +#define M68010_LESS (TYPE_68000 | TYPE_68010) +#define M68010_PLUS (TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040) -#define M68020_ONLY TYPE_68020 -#define M68020_LESS (TYPE_68010 | TYPE_68020) -#define M68020_PLUS (TYPE_68020 | TYPE_68030 | TYPE_68040) +#define M68020_ONLY TYPE_68020 +#define M68020_LESS (TYPE_68010 | TYPE_68020) +#define M68020_PLUS (TYPE_68020 | TYPE_68030 | TYPE_68040) -#define M68030_ONLY TYPE_68030 -#define M68030_LESS (TYPE_68010 | TYPE_68020 | TYPE_68030) -#define M68030_PLUS (TYPE_68030 | TYPE_68040) +#define M68030_ONLY TYPE_68030 +#define M68030_LESS (TYPE_68010 | TYPE_68020 | TYPE_68030) +#define M68030_PLUS (TYPE_68030 | TYPE_68040) -#define M68040_PLUS TYPE_68040 +#define M68040_PLUS TYPE_68040 /* Extension word formats */ @@ -139,7 +139,7 @@ /* Opcode flags */ #if M68K_COMPILE_FOR_MAME == OPT_ON -#define SET_OPCODE_FLAGS(x) g_opcode_type = x; +#define SET_OPCODE_FLAGS(x) g_opcode_type = x; #define COMBINE_OPCODE_FLAGS(x) ((x) | g_opcode_type | DASMFLAG_SUPPORTED) #else #define SET_OPCODE_FLAGS(x) @@ -194,10 +194,10 @@ static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr); /* used to build opcode handler jump table */ typedef struct { - void (*opcode_handler)(void); /* handler function */ - uint mask; /* mask on opcode */ - uint match; /* what to match after masking */ - uint ea_mask; /* what ea modes are allowed */ + void (*opcode_handler)(void); /* handler function */ + uint mask; /* mask on opcode */ + uint match; /* what to match after masking */ + uint ea_mask; /* what ea modes are allowed */ } opcode_struct; @@ -228,8 +228,8 @@ static const uint g_3bit_qdata_table[8] = {8, 1, 2, 3, 4, 5, 6, 7}; static const uint g_5bit_data_table[32] = { - 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; static const char *const g_cc[16] = @@ -237,75 +237,75 @@ static const char *const g_cc[16] = static const char *const g_cpcc[64] = {/* 000 001 010 011 100 101 110 111 */ - "f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or", /* 000 */ - "un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t", /* 001 */ - "sf", "seq", "gt", "ge", "lt", "le", "gl", "gle", /* 010 */ + "f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or", /* 000 */ + "un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t", /* 001 */ + "sf", "seq", "gt", "ge", "lt", "le", "gl", "gle", /* 010 */ "ngle", "ngl", "nle", "nlt", "nge", "ngt", "sne", "st", /* 011 */ - "?", "?", "?", "?", "?", "?", "?", "?", /* 100 */ - "?", "?", "?", "?", "?", "?", "?", "?", /* 101 */ - "?", "?", "?", "?", "?", "?", "?", "?", /* 110 */ - "?", "?", "?", "?", "?", "?", "?", "?" /* 111 */ + "?", "?", "?", "?", "?", "?", "?", "?", /* 100 */ + "?", "?", "?", "?", "?", "?", "?", "?", /* 101 */ + "?", "?", "?", "?", "?", "?", "?", "?", /* 110 */ + "?", "?", "?", "?", "?", "?", "?", "?" /* 111 */ }; static const char *const g_mmuregs[8] = { - "tc", "drp", "srp", "crp", "cal", "val", "sccr", "acr" + "tc", "drp", "srp", "crp", "cal", "val", "sccr", "acr" }; static const char *const g_mmucond[16] = { - "bs", "bc", "ls", "lc", "ss", "sc", "as", "ac", - "ws", "wc", "is", "ic", "gs", "gc", "cs", "cc" + "bs", "bc", "ls", "lc", "ss", "sc", "as", "ac", + "ws", "wc", "is", "ic", "gs", "gc", "cs", "cc" }; /* ======================================================================== */ /* =========================== UTILITY FUNCTIONS ========================== */ /* ======================================================================== */ -#define LIMIT_CPU_TYPES(ALLOWED_CPU_TYPES) \ - if(!(g_cpu_type & ALLOWED_CPU_TYPES)) \ - { \ - if((g_cpu_ir & 0xf000) == 0xf000) \ - d68000_1111(); \ - else d68000_illegal(); \ - return; \ - } +#define LIMIT_CPU_TYPES(ALLOWED_CPU_TYPES) \ + if(!(g_cpu_type & ALLOWED_CPU_TYPES)) \ + { \ + if((g_cpu_ir & 0xf000) == 0xf000) \ + d68000_1111(); \ + else d68000_illegal(); \ + return; \ + } static uint dasm_read_imm_8(uint advance) { - uint result; - if (g_rawop) - result = g_rawop[g_cpu_pc + 1 - g_rawbasepc]; - else - result = m68k_read_disassembler_16(g_cpu_pc & g_address_mask) & 0xff; - g_cpu_pc += advance; - return result; + uint result; + if (g_rawop) + result = g_rawop[g_cpu_pc + 1 - g_rawbasepc]; + else + result = m68k_read_disassembler_16(g_cpu_pc & g_address_mask) & 0xff; + g_cpu_pc += advance; + return result; } static uint dasm_read_imm_16(uint advance) { - uint result; - if (g_rawop) - result = (g_rawop[g_cpu_pc + 0 - g_rawbasepc] << 8) | - g_rawop[g_cpu_pc + 1 - g_rawbasepc]; - else - result = m68k_read_disassembler_16(g_cpu_pc & g_address_mask) & 0xffff; - g_cpu_pc += advance; - return result; + uint result; + if (g_rawop) + result = (g_rawop[g_cpu_pc + 0 - g_rawbasepc] << 8) | + g_rawop[g_cpu_pc + 1 - g_rawbasepc]; + else + result = m68k_read_disassembler_16(g_cpu_pc & g_address_mask) & 0xffff; + g_cpu_pc += advance; + return result; } static uint dasm_read_imm_32(uint advance) { - uint result; - if (g_rawop) - result = (g_rawop[g_cpu_pc + 0 - g_rawbasepc] << 24) | - (g_rawop[g_cpu_pc + 1 - g_rawbasepc] << 16) | - (g_rawop[g_cpu_pc + 2 - g_rawbasepc] << 8) | - g_rawop[g_cpu_pc + 3 - g_rawbasepc]; - else - result = m68k_read_disassembler_32(g_cpu_pc & g_address_mask) & 0xffffffff; - g_cpu_pc += advance; - return result; + uint result; + if (g_rawop) + result = (g_rawop[g_cpu_pc + 0 - g_rawbasepc] << 24) | + (g_rawop[g_cpu_pc + 1 - g_rawbasepc] << 16) | + (g_rawop[g_cpu_pc + 2 - g_rawbasepc] << 8) | + g_rawop[g_cpu_pc + 3 - g_rawbasepc]; + else + result = m68k_read_disassembler_32(g_cpu_pc & g_address_mask) & 0xffffffff; + g_cpu_pc += advance; + return result; } #define read_imm_8() dasm_read_imm_8(2) @@ -331,331 +331,331 @@ static uint dasm_read_imm_32(uint advance) static int sext_7bit_int(int value) { - return (value & 0x40) ? (value | 0xffffff80) : (value & 0x7f); + return (value & 0x40) ? (value | 0xffffff80) : (value & 0x7f); } /* 100% portable signed int generators */ static int make_int_8(int value) { - return (value & 0x80) ? value | ~0xff : value & 0xff; + return (value & 0x80) ? value | ~0xff : value & 0xff; } static int make_int_16(int value) { - return (value & 0x8000) ? value | ~0xffff : value & 0xffff; + return (value & 0x8000) ? value | ~0xffff : value & 0xffff; } static int make_int_32(int value) { - return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; + return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; } /* Get string representation of hex values */ static char* make_signed_hex_str_8(uint val) { - static char str[20]; + static char str[20]; - val &= 0xff; + val &= 0xff; - if(val == 0x80) - sprintf(str, "-$80"); - else if(val & 0x80) - sprintf(str, "-$%x", (0-val) & 0x7f); - else - sprintf(str, "$%x", val & 0x7f); + if(val == 0x80) + sprintf(str, "-$80"); + else if(val & 0x80) + sprintf(str, "-$%x", (0-val) & 0x7f); + else + sprintf(str, "$%x", val & 0x7f); - return str; + return str; } static char* make_signed_hex_str_16(uint val) { - static char str[20]; + static char str[20]; - val &= 0xffff; + val &= 0xffff; - if(val == 0x8000) - sprintf(str, "-$8000"); - else if(val & 0x8000) - sprintf(str, "-$%x", (0-val) & 0x7fff); - else - sprintf(str, "$%x", val & 0x7fff); + if(val == 0x8000) + sprintf(str, "-$8000"); + else if(val & 0x8000) + sprintf(str, "-$%x", (0-val) & 0x7fff); + else + sprintf(str, "$%x", val & 0x7fff); - return str; + return str; } static char* make_signed_hex_str_32(uint val) { - static char str[20]; + static char str[20]; - val &= 0xffffffff; + val &= 0xffffffff; - if(val == 0x80000000) - sprintf(str, "-$80000000"); - else if(val & 0x80000000) - sprintf(str, "-$%x", (0-val) & 0x7fffffff); - else - sprintf(str, "$%x", val & 0x7fffffff); + if(val == 0x80000000) + sprintf(str, "-$80000000"); + else if(val & 0x80000000) + sprintf(str, "-$%x", (0-val) & 0x7fffffff); + else + sprintf(str, "$%x", val & 0x7fffffff); - return str; + return str; } /* make string of immediate value */ static char* get_imm_str_s(uint size) { - static char str[15]; - if(size == 0) - sprintf(str, "#%s", make_signed_hex_str_8(read_imm_8())); - else if(size == 1) - sprintf(str, "#%s", make_signed_hex_str_16(read_imm_16())); - else - sprintf(str, "#%s", make_signed_hex_str_32(read_imm_32())); - return str; + static char str[15]; + if(size == 0) + sprintf(str, "#%s", make_signed_hex_str_8(read_imm_8())); + else if(size == 1) + sprintf(str, "#%s", make_signed_hex_str_16(read_imm_16())); + else + sprintf(str, "#%s", make_signed_hex_str_32(read_imm_32())); + return str; } static char* get_imm_str_u(uint size) { - static char str[15]; - if(size == 0) - sprintf(str, "#$%x", read_imm_8() & 0xff); - else if(size == 1) - sprintf(str, "#$%x", read_imm_16() & 0xffff); - else - sprintf(str, "#$%x", read_imm_32() & 0xffffffff); - return str; + static char str[15]; + if(size == 0) + sprintf(str, "#$%x", read_imm_8() & 0xff); + else if(size == 1) + sprintf(str, "#$%x", read_imm_16() & 0xffff); + else + sprintf(str, "#$%x", read_imm_32() & 0xffffffff); + return str; } /* Make string of effective address mode */ static char* get_ea_mode_str(uint instruction, uint size) { - static char b1[64]; - static char b2[64]; - static char* mode = b2; - uint extension; - uint base; - uint outer; - char base_reg[4]; - char index_reg[8]; - uint preindex; - uint postindex; - uint comma = 0; - uint temp_value; + static char b1[64]; + static char b2[64]; + static char* mode = b2; + uint extension; + uint base; + uint outer; + char base_reg[4]; + char index_reg[8]; + uint preindex; + uint postindex; + uint comma = 0; + uint temp_value; - /* Switch buffers so we don't clobber on a double-call to this function */ - mode = mode == b1 ? b2 : b1; + /* Switch buffers so we don't clobber on a double-call to this function */ + mode = mode == b1 ? b2 : b1; - switch(instruction & 0x3f) - { - case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: - /* data register direct */ - sprintf(mode, "D%d", instruction&7); - break; - case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: - /* address register direct */ - sprintf(mode, "A%d", instruction&7); - break; - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - /* address register indirect */ - sprintf(mode, "(A%d)", instruction&7); - break; - case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: - /* address register indirect with postincrement */ - sprintf(mode, "(A%d)+", instruction&7); - break; - case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: - /* address register indirect with predecrement */ - sprintf(mode, "-(A%d)", instruction&7); - break; - case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: - /* address register indirect with displacement*/ - sprintf(mode, "(%s,A%d)", make_signed_hex_str_16(read_imm_16()), instruction&7); - break; - case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: - /* address register indirect with index */ - extension = read_imm_16(); + switch(instruction & 0x3f) + { + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + /* data register direct */ + sprintf(mode, "D%d", instruction&7); + break; + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + /* address register direct */ + sprintf(mode, "A%d", instruction&7); + break; + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + /* address register indirect */ + sprintf(mode, "(A%d)", instruction&7); + break; + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: + /* address register indirect with postincrement */ + sprintf(mode, "(A%d)+", instruction&7); + break; + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + /* address register indirect with predecrement */ + sprintf(mode, "-(A%d)", instruction&7); + break; + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + /* address register indirect with displacement*/ + sprintf(mode, "(%s,A%d)", make_signed_hex_str_16(read_imm_16()), instruction&7); + break; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + /* address register indirect with index */ + extension = read_imm_16(); - if(EXT_FULL(extension)) - { - if(EXT_EFFECTIVE_ZERO(extension)) - { - strcpy(mode, "0"); - break; - } - base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; - outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; - if(EXT_BASE_REGISTER_PRESENT(extension)) - sprintf(base_reg, "A%d", instruction&7); - else - *base_reg = 0; - if(EXT_INDEX_REGISTER_PRESENT(extension)) - { - sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - if(EXT_INDEX_SCALE(extension)) - sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension)); - } - else - *index_reg = 0; - preindex = (extension&7) > 0 && (extension&7) < 4; - postindex = (extension&7) > 4; + if(EXT_FULL(extension)) + { + if(EXT_EFFECTIVE_ZERO(extension)) + { + strcpy(mode, "0"); + break; + } + base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; + outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; + if(EXT_BASE_REGISTER_PRESENT(extension)) + sprintf(base_reg, "A%d", instruction&7); + else + *base_reg = 0; + if(EXT_INDEX_REGISTER_PRESENT(extension)) + { + sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + if(EXT_INDEX_SCALE(extension)) + sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension)); + } + else + *index_reg = 0; + preindex = (extension&7) > 0 && (extension&7) < 4; + postindex = (extension&7) > 4; - strcpy(mode, "("); - if(preindex || postindex) - strcat(mode, "["); - if(base) - { - if (EXT_BASE_DISPLACEMENT_LONG(extension)) - { - strcat(mode, make_signed_hex_str_32(base)); - } - else - { - strcat(mode, make_signed_hex_str_16(base)); - } - comma = 1; - } - if(*base_reg) - { - if(comma) - strcat(mode, ","); - strcat(mode, base_reg); - comma = 1; - } - if(postindex) - { - strcat(mode, "]"); - comma = 1; - } - if(*index_reg) - { - if(comma) - strcat(mode, ","); - strcat(mode, index_reg); - comma = 1; - } - if(preindex) - { - strcat(mode, "]"); - comma = 1; - } - if(outer) - { - if(comma) - strcat(mode, ","); - strcat(mode, make_signed_hex_str_16(outer)); - } - strcat(mode, ")"); - break; - } + strcpy(mode, "("); + if(preindex || postindex) + strcat(mode, "["); + if(base) + { + if (EXT_BASE_DISPLACEMENT_LONG(extension)) + { + strcat(mode, make_signed_hex_str_32(base)); + } + else + { + strcat(mode, make_signed_hex_str_16(base)); + } + comma = 1; + } + if(*base_reg) + { + if(comma) + strcat(mode, ","); + strcat(mode, base_reg); + comma = 1; + } + if(postindex) + { + strcat(mode, "]"); + comma = 1; + } + if(*index_reg) + { + if(comma) + strcat(mode, ","); + strcat(mode, index_reg); + comma = 1; + } + if(preindex) + { + strcat(mode, "]"); + comma = 1; + } + if(outer) + { + if(comma) + strcat(mode, ","); + strcat(mode, make_signed_hex_str_16(outer)); + } + strcat(mode, ")"); + break; + } - if(EXT_8BIT_DISPLACEMENT(extension) == 0) - sprintf(mode, "(A%d,%c%d.%c", instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - else - sprintf(mode, "(%s,A%d,%c%d.%c", make_signed_hex_str_8(extension), instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - if(EXT_INDEX_SCALE(extension)) - sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension)); - strcat(mode, ")"); - break; - case 0x38: - /* absolute short address */ - sprintf(mode, "$%x.w", read_imm_16()); - break; - case 0x39: - /* absolute long address */ - sprintf(mode, "$%x.l", read_imm_32()); - break; - case 0x3a: - /* program counter with displacement */ - temp_value = read_imm_16(); - sprintf(mode, "(%s,PC)", make_signed_hex_str_16(temp_value)); - sprintf(g_helper_str, "; ($%x)", (make_int_16(temp_value) + g_cpu_pc-2) & 0xffffffff); - break; - case 0x3b: - /* program counter with index */ - extension = read_imm_16(); + if(EXT_8BIT_DISPLACEMENT(extension) == 0) + sprintf(mode, "(A%d,%c%d.%c", instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + else + sprintf(mode, "(%s,A%d,%c%d.%c", make_signed_hex_str_8(extension), instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + if(EXT_INDEX_SCALE(extension)) + sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension)); + strcat(mode, ")"); + break; + case 0x38: + /* absolute short address */ + sprintf(mode, "$%x.w", read_imm_16()); + break; + case 0x39: + /* absolute long address */ + sprintf(mode, "$%x.l", read_imm_32()); + break; + case 0x3a: + /* program counter with displacement */ + temp_value = read_imm_16(); + sprintf(mode, "(%s,PC)", make_signed_hex_str_16(temp_value)); + sprintf(g_helper_str, "; ($%x)", (make_int_16(temp_value) + g_cpu_pc-2) & 0xffffffff); + break; + case 0x3b: + /* program counter with index */ + extension = read_imm_16(); - if(EXT_FULL(extension)) - { - if(EXT_EFFECTIVE_ZERO(extension)) - { - strcpy(mode, "0"); - break; - } - base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; - outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; - if(EXT_BASE_REGISTER_PRESENT(extension)) - strcpy(base_reg, "PC"); - else - *base_reg = 0; - if(EXT_INDEX_REGISTER_PRESENT(extension)) - { - sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - if(EXT_INDEX_SCALE(extension)) - sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension)); - } - else - *index_reg = 0; - preindex = (extension&7) > 0 && (extension&7) < 4; - postindex = (extension&7) > 4; + if(EXT_FULL(extension)) + { + if(EXT_EFFECTIVE_ZERO(extension)) + { + strcpy(mode, "0"); + break; + } + base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; + outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; + if(EXT_BASE_REGISTER_PRESENT(extension)) + strcpy(base_reg, "PC"); + else + *base_reg = 0; + if(EXT_INDEX_REGISTER_PRESENT(extension)) + { + sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + if(EXT_INDEX_SCALE(extension)) + sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension)); + } + else + *index_reg = 0; + preindex = (extension&7) > 0 && (extension&7) < 4; + postindex = (extension&7) > 4; - strcpy(mode, "("); - if(preindex || postindex) - strcat(mode, "["); - if(base) - { - strcat(mode, make_signed_hex_str_16(base)); - comma = 1; - } - if(*base_reg) - { - if(comma) - strcat(mode, ","); - strcat(mode, base_reg); - comma = 1; - } - if(postindex) - { - strcat(mode, "]"); - comma = 1; - } - if(*index_reg) - { - if(comma) - strcat(mode, ","); - strcat(mode, index_reg); - comma = 1; - } - if(preindex) - { - strcat(mode, "]"); - comma = 1; - } - if(outer) - { - if(comma) - strcat(mode, ","); - strcat(mode, make_signed_hex_str_16(outer)); - } - strcat(mode, ")"); - break; - } + strcpy(mode, "("); + if(preindex || postindex) + strcat(mode, "["); + if(base) + { + strcat(mode, make_signed_hex_str_16(base)); + comma = 1; + } + if(*base_reg) + { + if(comma) + strcat(mode, ","); + strcat(mode, base_reg); + comma = 1; + } + if(postindex) + { + strcat(mode, "]"); + comma = 1; + } + if(*index_reg) + { + if(comma) + strcat(mode, ","); + strcat(mode, index_reg); + comma = 1; + } + if(preindex) + { + strcat(mode, "]"); + comma = 1; + } + if(outer) + { + if(comma) + strcat(mode, ","); + strcat(mode, make_signed_hex_str_16(outer)); + } + strcat(mode, ")"); + break; + } - if(EXT_8BIT_DISPLACEMENT(extension) == 0) - sprintf(mode, "(PC,%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - else - sprintf(mode, "(%s,PC,%c%d.%c", make_signed_hex_str_8(extension), EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - if(EXT_INDEX_SCALE(extension)) - sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension)); - strcat(mode, ")"); - break; - case 0x3c: - /* Immediate */ - sprintf(mode, "%s", get_imm_str_u(size)); - break; - default: - sprintf(mode, "INVALID %x", instruction & 0x3f); - } - return mode; + if(EXT_8BIT_DISPLACEMENT(extension) == 0) + sprintf(mode, "(PC,%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + else + sprintf(mode, "(%s,PC,%c%d.%c", make_signed_hex_str_8(extension), EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); + if(EXT_INDEX_SCALE(extension)) + sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension)); + strcat(mode, ")"); + break; + case 0x3c: + /* Immediate */ + sprintf(mode, "%s", get_imm_str_u(size)); + break; + default: + sprintf(mode, "INVALID %x", instruction & 0x3f); + } + return mode; } @@ -700,573 +700,573 @@ static char* get_ea_mode_str(uint instruction, uint size) static void d68000_illegal(void) { - sprintf(g_dasm_str, "dc.w $%04x; ILLEGAL", g_cpu_ir); + sprintf(g_dasm_str, "dc.w $%04x; ILLEGAL", g_cpu_ir); } static void d68000_1010(void) { - sprintf(g_dasm_str, "dc.w $%04x; opcode 1010", g_cpu_ir); + sprintf(g_dasm_str, "dc.w $%04x; opcode 1010", g_cpu_ir); } static void d68000_1111(void) { - sprintf(g_dasm_str, "dc.w $%04x; opcode 1111", g_cpu_ir); + sprintf(g_dasm_str, "dc.w $%04x; opcode 1111", g_cpu_ir); } static void d68000_abcd_rr(void) { - sprintf(g_dasm_str, "abcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "abcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_abcd_mm(void) { - sprintf(g_dasm_str, "abcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "abcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_add_er_8(void) { - sprintf(g_dasm_str, "add.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "add.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_add_er_16(void) { - sprintf(g_dasm_str, "add.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "add.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_add_er_32(void) { - sprintf(g_dasm_str, "add.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "add.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_add_re_8(void) { - sprintf(g_dasm_str, "add.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "add.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_add_re_16(void) { - sprintf(g_dasm_str, "add.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "add.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_add_re_32(void) { - sprintf(g_dasm_str, "add.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "add.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_adda_16(void) { - sprintf(g_dasm_str, "adda.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "adda.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_adda_32(void) { - sprintf(g_dasm_str, "adda.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "adda.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_addi_8(void) { - char* str = get_imm_str_s8(); - sprintf(g_dasm_str, "addi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_s8(); + sprintf(g_dasm_str, "addi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_addi_16(void) { - char* str = get_imm_str_s16(); - sprintf(g_dasm_str, "addi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); + char* str = get_imm_str_s16(); + sprintf(g_dasm_str, "addi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_addi_32(void) { - char* str = get_imm_str_s32(); - sprintf(g_dasm_str, "addi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); + char* str = get_imm_str_s32(); + sprintf(g_dasm_str, "addi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_addq_8(void) { - sprintf(g_dasm_str, "addq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "addq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir)); } static void d68000_addq_16(void) { - sprintf(g_dasm_str, "addq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "addq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir)); } static void d68000_addq_32(void) { - sprintf(g_dasm_str, "addq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "addq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir)); } static void d68000_addx_rr_8(void) { - sprintf(g_dasm_str, "addx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "addx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_addx_rr_16(void) { - sprintf(g_dasm_str, "addx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "addx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_addx_rr_32(void) { - sprintf(g_dasm_str, "addx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "addx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_addx_mm_8(void) { - sprintf(g_dasm_str, "addx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "addx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_addx_mm_16(void) { - sprintf(g_dasm_str, "addx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "addx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_addx_mm_32(void) { - sprintf(g_dasm_str, "addx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "addx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_and_er_8(void) { - sprintf(g_dasm_str, "and.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "and.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_and_er_16(void) { - sprintf(g_dasm_str, "and.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "and.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_and_er_32(void) { - sprintf(g_dasm_str, "and.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "and.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_and_re_8(void) { - sprintf(g_dasm_str, "and.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "and.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_and_re_16(void) { - sprintf(g_dasm_str, "and.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "and.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_and_re_32(void) { - sprintf(g_dasm_str, "and.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "and.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_andi_8(void) { - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "andi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "andi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_andi_16(void) { - char* str = get_imm_str_u16(); - sprintf(g_dasm_str, "andi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); + char* str = get_imm_str_u16(); + sprintf(g_dasm_str, "andi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_andi_32(void) { - char* str = get_imm_str_u32(); - sprintf(g_dasm_str, "andi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); + char* str = get_imm_str_u32(); + sprintf(g_dasm_str, "andi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_andi_to_ccr(void) { - sprintf(g_dasm_str, "andi %s, CCR", get_imm_str_u8()); + sprintf(g_dasm_str, "andi %s, CCR", get_imm_str_u8()); } static void d68000_andi_to_sr(void) { - sprintf(g_dasm_str, "andi %s, SR", get_imm_str_u16()); + sprintf(g_dasm_str, "andi %s, SR", get_imm_str_u16()); } static void d68000_asr_s_8(void) { - sprintf(g_dasm_str, "asr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "asr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_asr_s_16(void) { - sprintf(g_dasm_str, "asr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "asr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_asr_s_32(void) { - sprintf(g_dasm_str, "asr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "asr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_asr_r_8(void) { - sprintf(g_dasm_str, "asr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "asr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_asr_r_16(void) { - sprintf(g_dasm_str, "asr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "asr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_asr_r_32(void) { - sprintf(g_dasm_str, "asr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "asr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_asr_ea(void) { - sprintf(g_dasm_str, "asr.w %s", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "asr.w %s", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_asl_s_8(void) { - sprintf(g_dasm_str, "asl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "asl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_asl_s_16(void) { - sprintf(g_dasm_str, "asl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "asl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_asl_s_32(void) { - sprintf(g_dasm_str, "asl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "asl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_asl_r_8(void) { - sprintf(g_dasm_str, "asl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "asl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_asl_r_16(void) { - sprintf(g_dasm_str, "asl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "asl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_asl_r_32(void) { - sprintf(g_dasm_str, "asl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "asl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_asl_ea(void) { - sprintf(g_dasm_str, "asl.w %s", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "asl.w %s", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_bcc_8(void) { - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "b%-2s $%x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_8(g_cpu_ir)); + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "b%-2s $%x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_8(g_cpu_ir)); } static void d68000_bcc_16(void) { - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "b%-2s $%x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_16(read_imm_16())); + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "b%-2s $%x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_16(read_imm_16())); } static void d68020_bcc_32(void) { - uint temp_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "b%-2s $%x; (2+)", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + read_imm_32()); + uint temp_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "b%-2s $%x; (2+)", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + read_imm_32()); } static void d68000_bchg_r(void) { - sprintf(g_dasm_str, "bchg D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "bchg D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_bchg_s(void) { - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "bchg %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "bchg %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_bclr_r(void) { - sprintf(g_dasm_str, "bclr D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "bclr D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_bclr_s(void) { - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "bclr %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "bclr %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68010_bkpt(void) { - LIMIT_CPU_TYPES(M68010_PLUS); - sprintf(g_dasm_str, "bkpt #%d; (1+)", g_cpu_ir&7); + LIMIT_CPU_TYPES(M68010_PLUS); + sprintf(g_dasm_str, "bkpt #%d; (1+)", g_cpu_ir&7); } static void d68020_bfchg(void) { - uint extension; - char offset[3]; - char width[3]; + uint extension; + char offset[3]; + char width[3]; - LIMIT_CPU_TYPES(M68020_PLUS); + LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfchg %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfchg %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); } static void d68020_bfclr(void) { - uint extension; - char offset[3]; - char width[3]; + uint extension; + char offset[3]; + char width[3]; - LIMIT_CPU_TYPES(M68020_PLUS); + LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfclr %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfclr %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); } static void d68020_bfexts(void) { - uint extension; - char offset[3]; - char width[3]; + uint extension; + char offset[3]; + char width[3]; - LIMIT_CPU_TYPES(M68020_PLUS); + LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfexts %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfexts %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); } static void d68020_bfextu(void) { - uint extension; - char offset[3]; - char width[3]; + uint extension; + char offset[3]; + char width[3]; - LIMIT_CPU_TYPES(M68020_PLUS); + LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfextu %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfextu %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); } static void d68020_bfffo(void) { - uint extension; - char offset[3]; - char width[3]; + uint extension; + char offset[3]; + char width[3]; - LIMIT_CPU_TYPES(M68020_PLUS); + LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfffo %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfffo %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); } static void d68020_bfins(void) { - uint extension; - char offset[3]; - char width[3]; + uint extension; + char offset[3]; + char width[3]; - LIMIT_CPU_TYPES(M68020_PLUS); + LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfins D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width); + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfins D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width); } static void d68020_bfset(void) { - uint extension; - char offset[3]; - char width[3]; + uint extension; + char offset[3]; + char width[3]; - LIMIT_CPU_TYPES(M68020_PLUS); + LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfset %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bfset %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); } static void d68020_bftst(void) { - uint extension; - char offset[3]; - char width[3]; + uint extension; + char offset[3]; + char width[3]; - LIMIT_CPU_TYPES(M68020_PLUS); + LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bftst %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); + if(BIT_B(extension)) + sprintf(offset, "D%d", (extension>>6)&7); + else + sprintf(offset, "%d", (extension>>6)&31); + if(BIT_5(extension)) + sprintf(width, "D%d", extension&7); + else + sprintf(width, "%d", g_5bit_data_table[extension&31]); + sprintf(g_dasm_str, "bftst %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); } static void d68000_bra_8(void) { - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "bra $%x", temp_pc + make_int_8(g_cpu_ir)); + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "bra $%x", temp_pc + make_int_8(g_cpu_ir)); } static void d68000_bra_16(void) { - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "bra $%x", temp_pc + make_int_16(read_imm_16())); + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "bra $%x", temp_pc + make_int_16(read_imm_16())); } static void d68020_bra_32(void) { - uint temp_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "bra $%x; (2+)", temp_pc + read_imm_32()); + uint temp_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "bra $%x; (2+)", temp_pc + read_imm_32()); } static void d68000_bset_r(void) { - sprintf(g_dasm_str, "bset D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "bset D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_bset_s(void) { - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "bset %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "bset %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_bsr_8(void) { - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "bsr $%x", temp_pc + make_int_8(g_cpu_ir)); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "bsr $%x", temp_pc + make_int_8(g_cpu_ir)); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68000_bsr_16(void) { - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "bsr $%x", temp_pc + make_int_16(read_imm_16())); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "bsr $%x", temp_pc + make_int_16(read_imm_16())); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68020_bsr_32(void) { - uint temp_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "bsr $%x; (2+)", temp_pc + read_imm_32()); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + uint temp_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "bsr $%x; (2+)", temp_pc + read_imm_32()); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68000_btst_r(void) { - sprintf(g_dasm_str, "btst D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "btst D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_btst_s(void) { - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "btst %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "btst %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68020_callm(void) { - char* str; - LIMIT_CPU_TYPES(M68020_ONLY); - str = get_imm_str_u8(); + char* str; + LIMIT_CPU_TYPES(M68020_ONLY); + str = get_imm_str_u8(); - sprintf(g_dasm_str, "callm %s, %s; (2)", str, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "callm %s, %s; (2)", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68020_cas_8(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "cas.b D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_8(g_cpu_ir)); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "cas.b D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68020_cas_16(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "cas.w D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_16(g_cpu_ir)); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "cas.w D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_16(g_cpu_ir)); } static void d68020_cas_32(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "cas.l D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_32(g_cpu_ir)); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "cas.l D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_32(g_cpu_ir)); } static void d68020_cas2_16(void) @@ -1277,1879 +1277,1879 @@ f e d c b a 9 8 7 6 5 4 3 2 1 0 DARn2 0 0 0 Du2 0 0 0 Dc2 */ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_32(); - sprintf(g_dasm_str, "cas2.w D%d:D%d, D%d:D%d, (%c%d):(%c%d); (2+)", - (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7, - BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7, - BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_32(); + sprintf(g_dasm_str, "cas2.w D%d:D%d, D%d:D%d, (%c%d):(%c%d); (2+)", + (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7, + BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7, + BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); } static void d68020_cas2_32(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_32(); - sprintf(g_dasm_str, "cas2.l D%d:D%d, D%d:D%d, (%c%d):(%c%d); (2+)", - (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7, - BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7, - BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_32(); + sprintf(g_dasm_str, "cas2.l D%d:D%d, D%d:D%d, (%c%d):(%c%d); (2+)", + (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7, + BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7, + BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); } static void d68000_chk_16(void) { - sprintf(g_dasm_str, "chk.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + sprintf(g_dasm_str, "chk.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68020_chk_32(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "chk.l %s, D%d; (2+)", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "chk.l %s, D%d; (2+)", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68020_chk2_cmp2_8(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "%s.b %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "%s.b %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); } static void d68020_chk2_cmp2_16(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "%s.w %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "%s.w %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); } static void d68020_chk2_cmp2_32(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "%s.l %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + sprintf(g_dasm_str, "%s.l %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); } static void d68040_cinv(void) { - LIMIT_CPU_TYPES(M68040_PLUS); - switch((g_cpu_ir>>3)&3) - { - case 0: - sprintf(g_dasm_str, "cinv (illegal scope); (4)"); - break; - case 1: - sprintf(g_dasm_str, "cinvl %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); - break; - case 2: - sprintf(g_dasm_str, "cinvp %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); - break; - case 3: - sprintf(g_dasm_str, "cinva %d; (4)", (g_cpu_ir>>6)&3); - break; - } + LIMIT_CPU_TYPES(M68040_PLUS); + switch((g_cpu_ir>>3)&3) + { + case 0: + sprintf(g_dasm_str, "cinv (illegal scope); (4)"); + break; + case 1: + sprintf(g_dasm_str, "cinvl %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); + break; + case 2: + sprintf(g_dasm_str, "cinvp %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); + break; + case 3: + sprintf(g_dasm_str, "cinva %d; (4)", (g_cpu_ir>>6)&3); + break; + } } static void d68000_clr_8(void) { - sprintf(g_dasm_str, "clr.b %s", get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "clr.b %s", get_ea_mode_str_8(g_cpu_ir)); } static void d68000_clr_16(void) { - sprintf(g_dasm_str, "clr.w %s", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "clr.w %s", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_clr_32(void) { - sprintf(g_dasm_str, "clr.l %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "clr.l %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_cmp_8(void) { - sprintf(g_dasm_str, "cmp.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "cmp.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_cmp_16(void) { - sprintf(g_dasm_str, "cmp.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "cmp.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_cmp_32(void) { - sprintf(g_dasm_str, "cmp.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "cmp.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_cmpa_16(void) { - sprintf(g_dasm_str, "cmpa.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "cmpa.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_cmpa_32(void) { - sprintf(g_dasm_str, "cmpa.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "cmpa.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_cmpi_8(void) { - char* str = get_imm_str_s8(); - sprintf(g_dasm_str, "cmpi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_s8(); + sprintf(g_dasm_str, "cmpi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68020_cmpi_pcdi_8(void) { - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s8(); - sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir)); + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s8(); + sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68020_cmpi_pcix_8(void) { - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s8(); - sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir)); + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s8(); + sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_cmpi_16(void) { - char* str; - str = get_imm_str_s16(); - sprintf(g_dasm_str, "cmpi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); + char* str; + str = get_imm_str_s16(); + sprintf(g_dasm_str, "cmpi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); } static void d68020_cmpi_pcdi_16(void) { - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s16(); - sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir)); + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s16(); + sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir)); } static void d68020_cmpi_pcix_16(void) { - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s16(); - sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir)); + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s16(); + sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_cmpi_32(void) { - char* str; - str = get_imm_str_s32(); - sprintf(g_dasm_str, "cmpi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); + char* str; + str = get_imm_str_s32(); + sprintf(g_dasm_str, "cmpi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); } static void d68020_cmpi_pcdi_32(void) { - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s32(); - sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir)); + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s32(); + sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir)); } static void d68020_cmpi_pcix_32(void) { - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s32(); - sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir)); + char* str; + LIMIT_CPU_TYPES(M68010_PLUS); + str = get_imm_str_s32(); + sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_cmpm_8(void) { - sprintf(g_dasm_str, "cmpm.b (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "cmpm.b (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_cmpm_16(void) { - sprintf(g_dasm_str, "cmpm.w (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "cmpm.w (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_cmpm_32(void) { - sprintf(g_dasm_str, "cmpm.l (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "cmpm.l (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68020_cpbcc_16(void) { - uint extension; - uint new_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - new_pc += make_int_16(read_imm_16()); - sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension); + uint extension; + uint new_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + new_pc += make_int_16(read_imm_16()); + sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension); } static void d68020_cpbcc_32(void) { - uint extension; - uint new_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - new_pc += read_imm_32(); - sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension); + uint extension; + uint new_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); + new_pc += read_imm_32(); + sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension); } static void d68020_cpdbcc(void) { - uint extension1; - uint extension2; - uint new_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - new_pc += make_int_16(read_imm_16()); - sprintf(g_dasm_str, "%ddb%-4s D%d,%s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], g_cpu_ir&7, get_imm_str_s16(), new_pc, extension2); + uint extension1; + uint extension2; + uint new_pc = g_cpu_pc; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + new_pc += make_int_16(read_imm_16()); + sprintf(g_dasm_str, "%ddb%-4s D%d,%s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], g_cpu_ir&7, get_imm_str_s16(), new_pc, extension2); } static void d68020_cpgen(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "%dgen %s; (2-3)", (g_cpu_ir>>9)&7, get_imm_str_u32()); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "%dgen %s; (2-3)", (g_cpu_ir>>9)&7, get_imm_str_u32()); } static void d68020_cprestore(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - if (((g_cpu_ir>>9)&7) == 1) - { - sprintf(g_dasm_str, "frestore %s", get_ea_mode_str_8(g_cpu_ir)); - } - else - { - sprintf(g_dasm_str, "%drestore %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); - } + LIMIT_CPU_TYPES(M68020_PLUS); + if (((g_cpu_ir>>9)&7) == 1) + { + sprintf(g_dasm_str, "frestore %s", get_ea_mode_str_8(g_cpu_ir)); + } + else + { + sprintf(g_dasm_str, "%drestore %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + } } static void d68020_cpsave(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - if (((g_cpu_ir>>9)&7) == 1) - { - sprintf(g_dasm_str, "fsave %s", get_ea_mode_str_8(g_cpu_ir)); - } - else - { - sprintf(g_dasm_str, "%dsave %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); - } + LIMIT_CPU_TYPES(M68020_PLUS); + if (((g_cpu_ir>>9)&7) == 1) + { + sprintf(g_dasm_str, "fsave %s", get_ea_mode_str_8(g_cpu_ir)); + } + else + { + sprintf(g_dasm_str, "%dsave %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + } } static void d68020_cpscc(void) { - uint extension1; - uint extension2; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - sprintf(g_dasm_str, "%ds%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_ea_mode_str_8(g_cpu_ir), extension2); + uint extension1; + uint extension2; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + sprintf(g_dasm_str, "%ds%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_ea_mode_str_8(g_cpu_ir), extension2); } static void d68020_cptrapcc_0(void) { - uint extension1; - uint extension2; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - sprintf(g_dasm_str, "%dtrap%-4s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], extension2); + uint extension1; + uint extension2; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + sprintf(g_dasm_str, "%dtrap%-4s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], extension2); } static void d68020_cptrapcc_16(void) { - uint extension1; - uint extension2; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u16(), extension2); + uint extension1; + uint extension2; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u16(), extension2); } static void d68020_cptrapcc_32(void) { - uint extension1; - uint extension2; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u32(), extension2); + uint extension1; + uint extension2; + LIMIT_CPU_TYPES(M68020_PLUS); + extension1 = read_imm_16(); + extension2 = read_imm_16(); + sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u32(), extension2); } static void d68040_cpush(void) { - LIMIT_CPU_TYPES(M68040_PLUS); - switch((g_cpu_ir>>3)&3) - { - case 0: - sprintf(g_dasm_str, "cpush (illegal scope); (4)"); - break; - case 1: - sprintf(g_dasm_str, "cpushl %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); - break; - case 2: - sprintf(g_dasm_str, "cpushp %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); - break; - case 3: - sprintf(g_dasm_str, "cpusha %d; (4)", (g_cpu_ir>>6)&3); - break; - } + LIMIT_CPU_TYPES(M68040_PLUS); + switch((g_cpu_ir>>3)&3) + { + case 0: + sprintf(g_dasm_str, "cpush (illegal scope); (4)"); + break; + case 1: + sprintf(g_dasm_str, "cpushl %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); + break; + case 2: + sprintf(g_dasm_str, "cpushp %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); + break; + case 3: + sprintf(g_dasm_str, "cpusha %d; (4)", (g_cpu_ir>>6)&3); + break; + } } static void d68000_dbra(void) { - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "dbra D%d, $%x", g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16())); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "dbra D%d, $%x", g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16())); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68000_dbcc(void) { - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "db%-2s D%d, $%x", g_cc[(g_cpu_ir>>8)&0xf], g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16())); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + uint temp_pc = g_cpu_pc; + sprintf(g_dasm_str, "db%-2s D%d, $%x", g_cc[(g_cpu_ir>>8)&0xf], g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16())); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68000_divs(void) { - sprintf(g_dasm_str, "divs.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "divs.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_divu(void) { - sprintf(g_dasm_str, "divu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "divu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68020_divl(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); - if(BIT_A(extension)) - sprintf(g_dasm_str, "div%c.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); - else if((extension&7) == ((extension>>12)&7)) - sprintf(g_dasm_str, "div%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7); - else - sprintf(g_dasm_str, "div%cl.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); + if(BIT_A(extension)) + sprintf(g_dasm_str, "div%c.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); + else if((extension&7) == ((extension>>12)&7)) + sprintf(g_dasm_str, "div%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7); + else + sprintf(g_dasm_str, "div%cl.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); } static void d68000_eor_8(void) { - sprintf(g_dasm_str, "eor.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "eor.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_eor_16(void) { - sprintf(g_dasm_str, "eor.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "eor.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_eor_32(void) { - sprintf(g_dasm_str, "eor.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "eor.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_eori_8(void) { - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "eori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "eori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_eori_16(void) { - char* str = get_imm_str_u16(); - sprintf(g_dasm_str, "eori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); + char* str = get_imm_str_u16(); + sprintf(g_dasm_str, "eori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_eori_32(void) { - char* str = get_imm_str_u32(); - sprintf(g_dasm_str, "eori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); + char* str = get_imm_str_u32(); + sprintf(g_dasm_str, "eori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_eori_to_ccr(void) { - sprintf(g_dasm_str, "eori %s, CCR", get_imm_str_u8()); + sprintf(g_dasm_str, "eori %s, CCR", get_imm_str_u8()); } static void d68000_eori_to_sr(void) { - sprintf(g_dasm_str, "eori %s, SR", get_imm_str_u16()); + sprintf(g_dasm_str, "eori %s, SR", get_imm_str_u16()); } static void d68000_exg_dd(void) { - sprintf(g_dasm_str, "exg D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "exg D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_exg_aa(void) { - sprintf(g_dasm_str, "exg A%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "exg A%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_exg_da(void) { - sprintf(g_dasm_str, "exg D%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "exg D%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_ext_16(void) { - sprintf(g_dasm_str, "ext.w D%d", g_cpu_ir&7); + sprintf(g_dasm_str, "ext.w D%d", g_cpu_ir&7); } static void d68000_ext_32(void) { - sprintf(g_dasm_str, "ext.l D%d", g_cpu_ir&7); + sprintf(g_dasm_str, "ext.l D%d", g_cpu_ir&7); } static void d68020_extb_32(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "extb.l D%d; (2+)", g_cpu_ir&7); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "extb.l D%d; (2+)", g_cpu_ir&7); } static void d68040_fpu(void) { - char float_data_format[8][3] = - { - ".l", ".s", ".x", ".p", ".w", ".d", ".b", ".p" - }; + char float_data_format[8][3] = + { + ".l", ".s", ".x", ".p", ".w", ".d", ".b", ".p" + }; - char mnemonic[40]; - uint32 w2, src, dst_reg; - LIMIT_CPU_TYPES(M68030_PLUS); - w2 = read_imm_16(); + char mnemonic[40]; + uint32 w2, src, dst_reg; + LIMIT_CPU_TYPES(M68030_PLUS); + w2 = read_imm_16(); - src = (w2 >> 10) & 0x7; - dst_reg = (w2 >> 7) & 0x7; + src = (w2 >> 10) & 0x7; + dst_reg = (w2 >> 7) & 0x7; - // special override for FMOVECR - if ((((w2 >> 13) & 0x7) == 2) && (((w2>>10)&0x7) == 7)) - { - sprintf(g_dasm_str, "fmovecr #$%0x, fp%d", (w2&0x7f), dst_reg); - return; - } + // special override for FMOVECR + if ((((w2 >> 13) & 0x7) == 2) && (((w2>>10)&0x7) == 7)) + { + sprintf(g_dasm_str, "fmovecr #$%0x, fp%d", (w2&0x7f), dst_reg); + return; + } - switch ((w2 >> 13) & 0x7) - { - case 0x0: - case 0x2: - { - switch(w2 & 0x7f) - { - case 0x00: sprintf(mnemonic, "fmove"); break; - case 0x01: sprintf(mnemonic, "fint"); break; - case 0x02: sprintf(mnemonic, "fsinh"); break; - case 0x03: sprintf(mnemonic, "fintrz"); break; - case 0x04: sprintf(mnemonic, "fsqrt"); break; - case 0x06: sprintf(mnemonic, "flognp1"); break; - case 0x08: sprintf(mnemonic, "fetoxm1"); break; - case 0x09: sprintf(mnemonic, "ftanh1"); break; - case 0x0a: sprintf(mnemonic, "fatan"); break; - case 0x0c: sprintf(mnemonic, "fasin"); break; - case 0x0d: sprintf(mnemonic, "fatanh"); break; - case 0x0e: sprintf(mnemonic, "fsin"); break; - case 0x0f: sprintf(mnemonic, "ftan"); break; - case 0x10: sprintf(mnemonic, "fetox"); break; - case 0x11: sprintf(mnemonic, "ftwotox"); break; - case 0x12: sprintf(mnemonic, "ftentox"); break; - case 0x14: sprintf(mnemonic, "flogn"); break; - case 0x15: sprintf(mnemonic, "flog10"); break; - case 0x16: sprintf(mnemonic, "flog2"); break; - case 0x18: sprintf(mnemonic, "fabs"); break; - case 0x19: sprintf(mnemonic, "fcosh"); break; - case 0x1a: sprintf(mnemonic, "fneg"); break; - case 0x1c: sprintf(mnemonic, "facos"); break; - case 0x1d: sprintf(mnemonic, "fcos"); break; - case 0x1e: sprintf(mnemonic, "fgetexp"); break; - case 0x1f: sprintf(mnemonic, "fgetman"); break; - case 0x20: sprintf(mnemonic, "fdiv"); break; - case 0x21: sprintf(mnemonic, "fmod"); break; - case 0x22: sprintf(mnemonic, "fadd"); break; - case 0x23: sprintf(mnemonic, "fmul"); break; - case 0x24: sprintf(mnemonic, "fsgldiv"); break; - case 0x25: sprintf(mnemonic, "frem"); break; - case 0x26: sprintf(mnemonic, "fscale"); break; - case 0x27: sprintf(mnemonic, "fsglmul"); break; - case 0x28: sprintf(mnemonic, "fsub"); break; - case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: - sprintf(mnemonic, "fsincos"); break; - case 0x38: sprintf(mnemonic, "fcmp"); break; - case 0x3a: sprintf(mnemonic, "ftst"); break; - case 0x41: sprintf(mnemonic, "fssqrt"); break; - case 0x45: sprintf(mnemonic, "fdsqrt"); break; - case 0x58: sprintf(mnemonic, "fsabs"); break; - case 0x5a: sprintf(mnemonic, "fsneg"); break; - case 0x5c: sprintf(mnemonic, "fdabs"); break; - case 0x5e: sprintf(mnemonic, "fdneg"); break; - case 0x60: sprintf(mnemonic, "fsdiv"); break; - case 0x62: sprintf(mnemonic, "fsadd"); break; - case 0x63: sprintf(mnemonic, "fsmul"); break; - case 0x64: sprintf(mnemonic, "fddiv"); break; - case 0x66: sprintf(mnemonic, "fdadd"); break; - case 0x67: sprintf(mnemonic, "fdmul"); break; - case 0x68: sprintf(mnemonic, "fssub"); break; - case 0x6c: sprintf(mnemonic, "fdsub"); break; + switch ((w2 >> 13) & 0x7) + { + case 0x0: + case 0x2: + { + switch(w2 & 0x7f) + { + case 0x00: sprintf(mnemonic, "fmove"); break; + case 0x01: sprintf(mnemonic, "fint"); break; + case 0x02: sprintf(mnemonic, "fsinh"); break; + case 0x03: sprintf(mnemonic, "fintrz"); break; + case 0x04: sprintf(mnemonic, "fsqrt"); break; + case 0x06: sprintf(mnemonic, "flognp1"); break; + case 0x08: sprintf(mnemonic, "fetoxm1"); break; + case 0x09: sprintf(mnemonic, "ftanh1"); break; + case 0x0a: sprintf(mnemonic, "fatan"); break; + case 0x0c: sprintf(mnemonic, "fasin"); break; + case 0x0d: sprintf(mnemonic, "fatanh"); break; + case 0x0e: sprintf(mnemonic, "fsin"); break; + case 0x0f: sprintf(mnemonic, "ftan"); break; + case 0x10: sprintf(mnemonic, "fetox"); break; + case 0x11: sprintf(mnemonic, "ftwotox"); break; + case 0x12: sprintf(mnemonic, "ftentox"); break; + case 0x14: sprintf(mnemonic, "flogn"); break; + case 0x15: sprintf(mnemonic, "flog10"); break; + case 0x16: sprintf(mnemonic, "flog2"); break; + case 0x18: sprintf(mnemonic, "fabs"); break; + case 0x19: sprintf(mnemonic, "fcosh"); break; + case 0x1a: sprintf(mnemonic, "fneg"); break; + case 0x1c: sprintf(mnemonic, "facos"); break; + case 0x1d: sprintf(mnemonic, "fcos"); break; + case 0x1e: sprintf(mnemonic, "fgetexp"); break; + case 0x1f: sprintf(mnemonic, "fgetman"); break; + case 0x20: sprintf(mnemonic, "fdiv"); break; + case 0x21: sprintf(mnemonic, "fmod"); break; + case 0x22: sprintf(mnemonic, "fadd"); break; + case 0x23: sprintf(mnemonic, "fmul"); break; + case 0x24: sprintf(mnemonic, "fsgldiv"); break; + case 0x25: sprintf(mnemonic, "frem"); break; + case 0x26: sprintf(mnemonic, "fscale"); break; + case 0x27: sprintf(mnemonic, "fsglmul"); break; + case 0x28: sprintf(mnemonic, "fsub"); break; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + sprintf(mnemonic, "fsincos"); break; + case 0x38: sprintf(mnemonic, "fcmp"); break; + case 0x3a: sprintf(mnemonic, "ftst"); break; + case 0x41: sprintf(mnemonic, "fssqrt"); break; + case 0x45: sprintf(mnemonic, "fdsqrt"); break; + case 0x58: sprintf(mnemonic, "fsabs"); break; + case 0x5a: sprintf(mnemonic, "fsneg"); break; + case 0x5c: sprintf(mnemonic, "fdabs"); break; + case 0x5e: sprintf(mnemonic, "fdneg"); break; + case 0x60: sprintf(mnemonic, "fsdiv"); break; + case 0x62: sprintf(mnemonic, "fsadd"); break; + case 0x63: sprintf(mnemonic, "fsmul"); break; + case 0x64: sprintf(mnemonic, "fddiv"); break; + case 0x66: sprintf(mnemonic, "fdadd"); break; + case 0x67: sprintf(mnemonic, "fdmul"); break; + case 0x68: sprintf(mnemonic, "fssub"); break; + case 0x6c: sprintf(mnemonic, "fdsub"); break; - default: sprintf(mnemonic, "FPU (?)"); break; - } + default: sprintf(mnemonic, "FPU (?)"); break; + } - if (w2 & 0x4000) - { - sprintf(g_dasm_str, "%s%s %s, FP%d", mnemonic, float_data_format[src], get_ea_mode_str_32(g_cpu_ir), dst_reg); - } - else - { - sprintf(g_dasm_str, "%s.x FP%d, FP%d", mnemonic, src, dst_reg); - } - break; - } + if (w2 & 0x4000) + { + sprintf(g_dasm_str, "%s%s %s, FP%d", mnemonic, float_data_format[src], get_ea_mode_str_32(g_cpu_ir), dst_reg); + } + else + { + sprintf(g_dasm_str, "%s.x FP%d, FP%d", mnemonic, src, dst_reg); + } + break; + } - case 0x3: - { - switch ((w2>>10)&7) - { - case 3: // packed decimal w/fixed k-factor - sprintf(g_dasm_str, "fmove%s FP%d, %s {#%d}", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir), sext_7bit_int(w2&0x7f)); - break; + case 0x3: + { + switch ((w2>>10)&7) + { + case 3: // packed decimal w/fixed k-factor + sprintf(g_dasm_str, "fmove%s FP%d, %s {#%d}", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir), sext_7bit_int(w2&0x7f)); + break; - case 7: // packed decimal w/dynamic k-factor (register) - sprintf(g_dasm_str, "fmove%s FP%d, %s {D%d}", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir), (w2>>4)&7); - break; + case 7: // packed decimal w/dynamic k-factor (register) + sprintf(g_dasm_str, "fmove%s FP%d, %s {D%d}", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir), (w2>>4)&7); + break; - default: - sprintf(g_dasm_str, "fmove%s FP%d, %s", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir)); - break; - } - break; - } + default: + sprintf(g_dasm_str, "fmove%s FP%d, %s", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir)); + break; + } + break; + } - case 0x4: // ea to control - { - sprintf(g_dasm_str, "fmovem.l %s, ", get_ea_mode_str_32(g_cpu_ir)); - if (w2 & 0x1000) strcat(g_dasm_str, "fpcr"); - if (w2 & 0x0800) strcat(g_dasm_str, "/fpsr"); - if (w2 & 0x0400) strcat(g_dasm_str, "/fpiar"); - break; - } + case 0x4: // ea to control + { + sprintf(g_dasm_str, "fmovem.l %s, ", get_ea_mode_str_32(g_cpu_ir)); + if (w2 & 0x1000) strcat(g_dasm_str, "fpcr"); + if (w2 & 0x0800) strcat(g_dasm_str, "/fpsr"); + if (w2 & 0x0400) strcat(g_dasm_str, "/fpiar"); + break; + } - case 0x5: // control to ea - { - - strcpy(g_dasm_str, "fmovem.l "); - if (w2 & 0x1000) strcat(g_dasm_str, "fpcr"); - if (w2 & 0x0800) strcat(g_dasm_str, "/fpsr"); - if (w2 & 0x0400) strcat(g_dasm_str, "/fpiar"); - strcat(g_dasm_str, ", "); - strcat(g_dasm_str, get_ea_mode_str_32(g_cpu_ir)); - break; - } + case 0x5: // control to ea + { + + strcpy(g_dasm_str, "fmovem.l "); + if (w2 & 0x1000) strcat(g_dasm_str, "fpcr"); + if (w2 & 0x0800) strcat(g_dasm_str, "/fpsr"); + if (w2 & 0x0400) strcat(g_dasm_str, "/fpiar"); + strcat(g_dasm_str, ", "); + strcat(g_dasm_str, get_ea_mode_str_32(g_cpu_ir)); + break; + } - case 0x6: // memory to FPU, list - { - char temp[32]; + case 0x6: // memory to FPU, list + { + char temp[32]; - if ((w2>>11) & 1) // dynamic register list - { - sprintf(g_dasm_str, "fmovem.x %s, D%d", get_ea_mode_str_32(g_cpu_ir), (w2>>4)&7); - } - else // static register list - { - int i; + if ((w2>>11) & 1) // dynamic register list + { + sprintf(g_dasm_str, "fmovem.x %s, D%d", get_ea_mode_str_32(g_cpu_ir), (w2>>4)&7); + } + else // static register list + { + int i; - sprintf(g_dasm_str, "fmovem.x %s, ", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "fmovem.x %s, ", get_ea_mode_str_32(g_cpu_ir)); - for (i = 0; i < 8; i++) - { - if (w2 & (1<>12) & 1) // postincrement or control - { - sprintf(temp, "FP%d ", 7-i); - } - else // predecrement - { - sprintf(temp, "FP%d ", i); - } - strcat(g_dasm_str, temp); - } - } - } - break; - } + for (i = 0; i < 8; i++) + { + if (w2 & (1<>12) & 1) // postincrement or control + { + sprintf(temp, "FP%d ", 7-i); + } + else // predecrement + { + sprintf(temp, "FP%d ", i); + } + strcat(g_dasm_str, temp); + } + } + } + break; + } - case 0x7: // FPU to memory, list - { - char temp[32]; + case 0x7: // FPU to memory, list + { + char temp[32]; - if ((w2>>11) & 1) // dynamic register list - { - sprintf(g_dasm_str, "fmovem.x D%d, %s", (w2>>4)&7, get_ea_mode_str_32(g_cpu_ir)); - } - else // static register list - { - int i; + if ((w2>>11) & 1) // dynamic register list + { + sprintf(g_dasm_str, "fmovem.x D%d, %s", (w2>>4)&7, get_ea_mode_str_32(g_cpu_ir)); + } + else // static register list + { + int i; - sprintf(g_dasm_str, "fmovem.x "); + sprintf(g_dasm_str, "fmovem.x "); - for (i = 0; i < 8; i++) - { - if (w2 & (1<>12) & 1) // postincrement or control - { - sprintf(temp, "FP%d ", 7-i); - } - else // predecrement - { - sprintf(temp, "FP%d ", i); - } - strcat(g_dasm_str, temp); - } - } + for (i = 0; i < 8; i++) + { + if (w2 & (1<>12) & 1) // postincrement or control + { + sprintf(temp, "FP%d ", 7-i); + } + else // predecrement + { + sprintf(temp, "FP%d ", i); + } + strcat(g_dasm_str, temp); + } + } - strcat(g_dasm_str, ", "); - strcat(g_dasm_str, get_ea_mode_str_32(g_cpu_ir)); - } - break; - } + strcat(g_dasm_str, ", "); + strcat(g_dasm_str, get_ea_mode_str_32(g_cpu_ir)); + } + break; + } - default: - { - sprintf(g_dasm_str, "FPU (?) "); - break; - } - } + default: + { + sprintf(g_dasm_str, "FPU (?) "); + break; + } + } } static void d68000_jmp(void) { - sprintf(g_dasm_str, "jmp %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "jmp %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_jsr(void) { - sprintf(g_dasm_str, "jsr %s", get_ea_mode_str_32(g_cpu_ir)); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + sprintf(g_dasm_str, "jsr %s", get_ea_mode_str_32(g_cpu_ir)); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68000_lea(void) { - sprintf(g_dasm_str, "lea %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "lea %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_link_16(void) { - sprintf(g_dasm_str, "link A%d, %s", g_cpu_ir&7, get_imm_str_s16()); + sprintf(g_dasm_str, "link A%d, %s", g_cpu_ir&7, get_imm_str_s16()); } static void d68020_link_32(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "link A%d, %s; (2+)", g_cpu_ir&7, get_imm_str_s32()); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "link A%d, %s; (2+)", g_cpu_ir&7, get_imm_str_s32()); } static void d68000_lsr_s_8(void) { - sprintf(g_dasm_str, "lsr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "lsr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_lsr_s_16(void) { - sprintf(g_dasm_str, "lsr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "lsr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_lsr_s_32(void) { - sprintf(g_dasm_str, "lsr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "lsr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_lsr_r_8(void) { - sprintf(g_dasm_str, "lsr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "lsr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_lsr_r_16(void) { - sprintf(g_dasm_str, "lsr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "lsr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_lsr_r_32(void) { - sprintf(g_dasm_str, "lsr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "lsr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_lsr_ea(void) { - sprintf(g_dasm_str, "lsr.w %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "lsr.w %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_lsl_s_8(void) { - sprintf(g_dasm_str, "lsl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "lsl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_lsl_s_16(void) { - sprintf(g_dasm_str, "lsl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "lsl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_lsl_s_32(void) { - sprintf(g_dasm_str, "lsl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "lsl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_lsl_r_8(void) { - sprintf(g_dasm_str, "lsl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "lsl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_lsl_r_16(void) { - sprintf(g_dasm_str, "lsl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "lsl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_lsl_r_32(void) { - sprintf(g_dasm_str, "lsl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "lsl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_lsl_ea(void) { - sprintf(g_dasm_str, "lsl.w %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "lsl.w %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_move_8(void) { - char* str = get_ea_mode_str_8(g_cpu_ir); - sprintf(g_dasm_str, "move.b %s, %s", str, get_ea_mode_str_8(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); + char* str = get_ea_mode_str_8(g_cpu_ir); + sprintf(g_dasm_str, "move.b %s, %s", str, get_ea_mode_str_8(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); } static void d68000_move_16(void) { - char* str = get_ea_mode_str_16(g_cpu_ir); - sprintf(g_dasm_str, "move.w %s, %s", str, get_ea_mode_str_16(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); + char* str = get_ea_mode_str_16(g_cpu_ir); + sprintf(g_dasm_str, "move.w %s, %s", str, get_ea_mode_str_16(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); } static void d68000_move_32(void) { - char* str = get_ea_mode_str_32(g_cpu_ir); - sprintf(g_dasm_str, "move.l %s, %s", str, get_ea_mode_str_32(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); + char* str = get_ea_mode_str_32(g_cpu_ir); + sprintf(g_dasm_str, "move.l %s, %s", str, get_ea_mode_str_32(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); } static void d68000_movea_16(void) { - sprintf(g_dasm_str, "movea.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "movea.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_movea_32(void) { - sprintf(g_dasm_str, "movea.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "movea.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_move_to_ccr(void) { - sprintf(g_dasm_str, "move %s, CCR", get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "move %s, CCR", get_ea_mode_str_8(g_cpu_ir)); } static void d68010_move_fr_ccr(void) { - LIMIT_CPU_TYPES(M68010_PLUS); - sprintf(g_dasm_str, "move CCR, %s; (1+)", get_ea_mode_str_8(g_cpu_ir)); + LIMIT_CPU_TYPES(M68010_PLUS); + sprintf(g_dasm_str, "move CCR, %s; (1+)", get_ea_mode_str_8(g_cpu_ir)); } static void d68000_move_fr_sr(void) { - sprintf(g_dasm_str, "move SR, %s", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "move SR, %s", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_move_to_sr(void) { - sprintf(g_dasm_str, "move %s, SR", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "move %s, SR", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_move_fr_usp(void) { - sprintf(g_dasm_str, "move USP, A%d", g_cpu_ir&7); + sprintf(g_dasm_str, "move USP, A%d", g_cpu_ir&7); } static void d68000_move_to_usp(void) { - sprintf(g_dasm_str, "move A%d, USP", g_cpu_ir&7); + sprintf(g_dasm_str, "move A%d, USP", g_cpu_ir&7); } static void d68010_movec(void) { - uint extension; - char* reg_name; - char* processor; - LIMIT_CPU_TYPES(M68010_PLUS); - extension = read_imm_16(); + uint extension; + char* reg_name; + char* processor; + LIMIT_CPU_TYPES(M68010_PLUS); + extension = read_imm_16(); - switch(extension & 0xfff) - { - case 0x000: - reg_name = "SFC"; - processor = "1+"; - break; - case 0x001: - reg_name = "DFC"; - processor = "1+"; - break; - case 0x800: - reg_name = "USP"; - processor = "1+"; - break; - case 0x801: - reg_name = "VBR"; - processor = "1+"; - break; - case 0x002: - reg_name = "CACR"; - processor = "2+"; - break; - case 0x802: - reg_name = "CAAR"; - processor = "2,3"; - break; - case 0x803: - reg_name = "MSP"; - processor = "2+"; - break; - case 0x804: - reg_name = "ISP"; - processor = "2+"; - break; - case 0x003: - reg_name = "TC"; - processor = "4+"; - break; - case 0x004: - reg_name = "ITT0"; - processor = "4+"; - break; - case 0x005: - reg_name = "ITT1"; - processor = "4+"; - break; - case 0x006: - reg_name = "DTT0"; - processor = "4+"; - break; - case 0x007: - reg_name = "DTT1"; - processor = "4+"; - break; - case 0x805: - reg_name = "MMUSR"; - processor = "4+"; - break; - case 0x806: - reg_name = "URP"; - processor = "4+"; - break; - case 0x807: - reg_name = "SRP"; - processor = "4+"; - break; - default: - reg_name = make_signed_hex_str_16(extension & 0xfff); - processor = "?"; - } + switch(extension & 0xfff) + { + case 0x000: + reg_name = "SFC"; + processor = "1+"; + break; + case 0x001: + reg_name = "DFC"; + processor = "1+"; + break; + case 0x800: + reg_name = "USP"; + processor = "1+"; + break; + case 0x801: + reg_name = "VBR"; + processor = "1+"; + break; + case 0x002: + reg_name = "CACR"; + processor = "2+"; + break; + case 0x802: + reg_name = "CAAR"; + processor = "2,3"; + break; + case 0x803: + reg_name = "MSP"; + processor = "2+"; + break; + case 0x804: + reg_name = "ISP"; + processor = "2+"; + break; + case 0x003: + reg_name = "TC"; + processor = "4+"; + break; + case 0x004: + reg_name = "ITT0"; + processor = "4+"; + break; + case 0x005: + reg_name = "ITT1"; + processor = "4+"; + break; + case 0x006: + reg_name = "DTT0"; + processor = "4+"; + break; + case 0x007: + reg_name = "DTT1"; + processor = "4+"; + break; + case 0x805: + reg_name = "MMUSR"; + processor = "4+"; + break; + case 0x806: + reg_name = "URP"; + processor = "4+"; + break; + case 0x807: + reg_name = "SRP"; + processor = "4+"; + break; + default: + reg_name = make_signed_hex_str_16(extension & 0xfff); + processor = "?"; + } - if(BIT_0(g_cpu_ir)) - sprintf(g_dasm_str, "movec %c%d, %s; (%s)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, reg_name, processor); - else - sprintf(g_dasm_str, "movec %s, %c%d; (%s)", reg_name, BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, processor); + if(BIT_0(g_cpu_ir)) + sprintf(g_dasm_str, "movec %c%d, %s; (%s)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, reg_name, processor); + else + sprintf(g_dasm_str, "movec %s, %c%d; (%s)", reg_name, BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, processor); } static void d68000_movem_pd_16(void) { - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1<<(15-i))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(15-(i+1))))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "D%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(7-i))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(7-(i+1))))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir)); + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1<<(15-i))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(15-(i+1))))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "D%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(7-i))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(7-(i+1))))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_movem_pd_32(void) { - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1<<(15-i))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(15-(i+1))))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "D%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(7-i))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(7-(i+1))))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir)); + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1<<(15-i))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(15-(i+1))))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "D%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(7-i))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(7-(i+1))))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_movem_er_16(void) { - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1< 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(i+8))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(i+8+1)))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.w %s, %s", get_ea_mode_str_16(g_cpu_ir), buffer); + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1< 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(i+8))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(i+8+1)))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.w %s, %s", get_ea_mode_str_16(g_cpu_ir), buffer); } static void d68000_movem_er_32(void) { - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1< 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(i+8))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(i+8+1)))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.l %s, %s", get_ea_mode_str_32(g_cpu_ir), buffer); + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1< 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(i+8))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(i+8+1)))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.l %s, %s", get_ea_mode_str_32(g_cpu_ir), buffer); } static void d68000_movem_re_16(void) { - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1< 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(i+8))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(i+8+1)))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir)); + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1< 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(i+8))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(i+8+1)))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_movem_re_32(void) { - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; + uint data = read_imm_16(); + char buffer[40]; + uint first; + uint run_length; + uint i; - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1< 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(i+8))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(i+8+1)))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir)); + buffer[0] = 0; + for(i=0;i<8;i++) + { + if(data&(1< 0) + sprintf(buffer+strlen(buffer), "-D%d", first + run_length); + } + } + for(i=0;i<8;i++) + { + if(data&(1<<(i+8))) + { + first = i; + run_length = 0; + while(i<7 && (data&(1<<(i+8+1)))) + { + i++; + run_length++; + } + if(buffer[0] != 0) + strcat(buffer, "/"); + sprintf(buffer+strlen(buffer), "A%d", first); + if(run_length > 0) + sprintf(buffer+strlen(buffer), "-A%d", first + run_length); + } + } + sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_movep_re_16(void) { - sprintf(g_dasm_str, "movep.w D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7); + sprintf(g_dasm_str, "movep.w D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7); } static void d68000_movep_re_32(void) { - sprintf(g_dasm_str, "movep.l D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7); + sprintf(g_dasm_str, "movep.l D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7); } static void d68000_movep_er_16(void) { - sprintf(g_dasm_str, "movep.w ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "movep.w ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_movep_er_32(void) { - sprintf(g_dasm_str, "movep.l ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "movep.l ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68010_moves_8(void) { - uint extension; - LIMIT_CPU_TYPES(M68010_PLUS); - extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(g_dasm_str, "moves.b %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir)); - else - sprintf(g_dasm_str, "moves.b %s, %c%d; (1+)", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); + uint extension; + LIMIT_CPU_TYPES(M68010_PLUS); + extension = read_imm_16(); + if(BIT_B(extension)) + sprintf(g_dasm_str, "moves.b %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir)); + else + sprintf(g_dasm_str, "moves.b %s, %c%d; (1+)", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); } static void d68010_moves_16(void) { - uint extension; - LIMIT_CPU_TYPES(M68010_PLUS); - extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(g_dasm_str, "moves.w %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_16(g_cpu_ir)); - else - sprintf(g_dasm_str, "moves.w %s, %c%d; (1+)", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); + uint extension; + LIMIT_CPU_TYPES(M68010_PLUS); + extension = read_imm_16(); + if(BIT_B(extension)) + sprintf(g_dasm_str, "moves.w %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_16(g_cpu_ir)); + else + sprintf(g_dasm_str, "moves.w %s, %c%d; (1+)", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); } static void d68010_moves_32(void) { - uint extension; - LIMIT_CPU_TYPES(M68010_PLUS); - extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(g_dasm_str, "moves.l %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_32(g_cpu_ir)); - else - sprintf(g_dasm_str, "moves.l %s, %c%d; (1+)", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); + uint extension; + LIMIT_CPU_TYPES(M68010_PLUS); + extension = read_imm_16(); + if(BIT_B(extension)) + sprintf(g_dasm_str, "moves.l %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_32(g_cpu_ir)); + else + sprintf(g_dasm_str, "moves.l %s, %c%d; (1+)", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); } static void d68000_moveq(void) { - sprintf(g_dasm_str, "moveq #%s, D%d", make_signed_hex_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "moveq #%s, D%d", make_signed_hex_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68040_move16_pi_pi(void) { - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 (A%d)+, (A%d)+; (4)", g_cpu_ir&7, (read_imm_16()>>12)&7); + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 (A%d)+, (A%d)+; (4)", g_cpu_ir&7, (read_imm_16()>>12)&7); } static void d68040_move16_pi_al(void) { - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 (A%d)+, %s; (4)", g_cpu_ir&7, get_imm_str_u32()); + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 (A%d)+, %s; (4)", g_cpu_ir&7, get_imm_str_u32()); } static void d68040_move16_al_pi(void) { - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 %s, (A%d)+; (4)", get_imm_str_u32(), g_cpu_ir&7); + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 %s, (A%d)+; (4)", get_imm_str_u32(), g_cpu_ir&7); } static void d68040_move16_ai_al(void) { - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 (A%d), %s; (4)", g_cpu_ir&7, get_imm_str_u32()); + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 (A%d), %s; (4)", g_cpu_ir&7, get_imm_str_u32()); } static void d68040_move16_al_ai(void) { - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 %s, (A%d); (4)", get_imm_str_u32(), g_cpu_ir&7); + LIMIT_CPU_TYPES(M68040_PLUS); + sprintf(g_dasm_str, "move16 %s, (A%d); (4)", get_imm_str_u32(), g_cpu_ir&7); } static void d68000_muls(void) { - sprintf(g_dasm_str, "muls.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "muls.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_mulu(void) { - sprintf(g_dasm_str, "mulu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "mulu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68020_mull(void) { - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); + uint extension; + LIMIT_CPU_TYPES(M68020_PLUS); + extension = read_imm_16(); - if(BIT_A(extension)) - sprintf(g_dasm_str, "mul%c.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); - else - sprintf(g_dasm_str, "mul%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7); + if(BIT_A(extension)) + sprintf(g_dasm_str, "mul%c.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); + else + sprintf(g_dasm_str, "mul%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7); } static void d68000_nbcd(void) { - sprintf(g_dasm_str, "nbcd %s", get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "nbcd %s", get_ea_mode_str_8(g_cpu_ir)); } static void d68000_neg_8(void) { - sprintf(g_dasm_str, "neg.b %s", get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "neg.b %s", get_ea_mode_str_8(g_cpu_ir)); } static void d68000_neg_16(void) { - sprintf(g_dasm_str, "neg.w %s", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "neg.w %s", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_neg_32(void) { - sprintf(g_dasm_str, "neg.l %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "neg.l %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_negx_8(void) { - sprintf(g_dasm_str, "negx.b %s", get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "negx.b %s", get_ea_mode_str_8(g_cpu_ir)); } static void d68000_negx_16(void) { - sprintf(g_dasm_str, "negx.w %s", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "negx.w %s", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_negx_32(void) { - sprintf(g_dasm_str, "negx.l %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "negx.l %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_nop(void) { - sprintf(g_dasm_str, "nop"); + sprintf(g_dasm_str, "nop"); } static void d68000_not_8(void) { - sprintf(g_dasm_str, "not.b %s", get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "not.b %s", get_ea_mode_str_8(g_cpu_ir)); } static void d68000_not_16(void) { - sprintf(g_dasm_str, "not.w %s", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "not.w %s", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_not_32(void) { - sprintf(g_dasm_str, "not.l %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "not.l %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_or_er_8(void) { - sprintf(g_dasm_str, "or.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "or.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_or_er_16(void) { - sprintf(g_dasm_str, "or.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "or.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_or_er_32(void) { - sprintf(g_dasm_str, "or.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "or.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_or_re_8(void) { - sprintf(g_dasm_str, "or.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "or.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_or_re_16(void) { - sprintf(g_dasm_str, "or.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "or.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_or_re_32(void) { - sprintf(g_dasm_str, "or.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "or.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_ori_8(void) { - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "ori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_u8(); + sprintf(g_dasm_str, "ori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_ori_16(void) { - char* str = get_imm_str_u16(); - sprintf(g_dasm_str, "ori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); + char* str = get_imm_str_u16(); + sprintf(g_dasm_str, "ori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_ori_32(void) { - char* str = get_imm_str_u32(); - sprintf(g_dasm_str, "ori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); + char* str = get_imm_str_u32(); + sprintf(g_dasm_str, "ori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_ori_to_ccr(void) { - sprintf(g_dasm_str, "ori %s, CCR", get_imm_str_u8()); + sprintf(g_dasm_str, "ori %s, CCR", get_imm_str_u8()); } static void d68000_ori_to_sr(void) { - sprintf(g_dasm_str, "ori %s, SR", get_imm_str_u16()); + sprintf(g_dasm_str, "ori %s, SR", get_imm_str_u16()); } static void d68020_pack_rr(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "pack D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "pack D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); } static void d68020_pack_mm(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "pack -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "pack -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); } static void d68000_pea(void) { - sprintf(g_dasm_str, "pea %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "pea %s", get_ea_mode_str_32(g_cpu_ir)); } // this is a 68040-specific form of PFLUSH static void d68040_pflush(void) { - LIMIT_CPU_TYPES(M68040_PLUS); + LIMIT_CPU_TYPES(M68040_PLUS); - if (g_cpu_ir & 0x10) - { - sprintf(g_dasm_str, "pflusha%s", (g_cpu_ir & 8) ? "" : "n"); - } - else - { - sprintf(g_dasm_str, "pflush%s(A%d)", (g_cpu_ir & 8) ? "" : "n", g_cpu_ir & 7); - } + if (g_cpu_ir & 0x10) + { + sprintf(g_dasm_str, "pflusha%s", (g_cpu_ir & 8) ? "" : "n"); + } + else + { + sprintf(g_dasm_str, "pflush%s(A%d)", (g_cpu_ir & 8) ? "" : "n", g_cpu_ir & 7); + } } static void d68000_reset(void) { - sprintf(g_dasm_str, "reset"); + sprintf(g_dasm_str, "reset"); } static void d68000_ror_s_8(void) { - sprintf(g_dasm_str, "ror.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "ror.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_ror_s_16(void) { - sprintf(g_dasm_str, "ror.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7],g_cpu_ir&7); + sprintf(g_dasm_str, "ror.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7],g_cpu_ir&7); } static void d68000_ror_s_32(void) { - sprintf(g_dasm_str, "ror.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "ror.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_ror_r_8(void) { - sprintf(g_dasm_str, "ror.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "ror.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_ror_r_16(void) { - sprintf(g_dasm_str, "ror.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "ror.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_ror_r_32(void) { - sprintf(g_dasm_str, "ror.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "ror.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_ror_ea(void) { - sprintf(g_dasm_str, "ror.w %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "ror.w %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_rol_s_8(void) { - sprintf(g_dasm_str, "rol.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "rol.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_rol_s_16(void) { - sprintf(g_dasm_str, "rol.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "rol.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_rol_s_32(void) { - sprintf(g_dasm_str, "rol.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "rol.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_rol_r_8(void) { - sprintf(g_dasm_str, "rol.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "rol.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_rol_r_16(void) { - sprintf(g_dasm_str, "rol.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "rol.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_rol_r_32(void) { - sprintf(g_dasm_str, "rol.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "rol.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_rol_ea(void) { - sprintf(g_dasm_str, "rol.w %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "rol.w %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_roxr_s_8(void) { - sprintf(g_dasm_str, "roxr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "roxr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_roxr_s_16(void) { - sprintf(g_dasm_str, "roxr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "roxr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_roxr_s_32(void) { - sprintf(g_dasm_str, "roxr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "roxr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_roxr_r_8(void) { - sprintf(g_dasm_str, "roxr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "roxr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_roxr_r_16(void) { - sprintf(g_dasm_str, "roxr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "roxr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_roxr_r_32(void) { - sprintf(g_dasm_str, "roxr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "roxr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_roxr_ea(void) { - sprintf(g_dasm_str, "roxr.w %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "roxr.w %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_roxl_s_8(void) { - sprintf(g_dasm_str, "roxl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "roxl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_roxl_s_16(void) { - sprintf(g_dasm_str, "roxl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "roxl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_roxl_s_32(void) { - sprintf(g_dasm_str, "roxl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); + sprintf(g_dasm_str, "roxl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); } static void d68000_roxl_r_8(void) { - sprintf(g_dasm_str, "roxl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "roxl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_roxl_r_16(void) { - sprintf(g_dasm_str, "roxl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "roxl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_roxl_r_32(void) { - sprintf(g_dasm_str, "roxl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); + sprintf(g_dasm_str, "roxl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); } static void d68000_roxl_ea(void) { - sprintf(g_dasm_str, "roxl.w %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "roxl.w %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68010_rtd(void) { - LIMIT_CPU_TYPES(M68010_PLUS); - sprintf(g_dasm_str, "rtd %s; (1+)", get_imm_str_s16()); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); + LIMIT_CPU_TYPES(M68010_PLUS); + sprintf(g_dasm_str, "rtd %s; (1+)", get_imm_str_s16()); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); } static void d68000_rte(void) { - sprintf(g_dasm_str, "rte"); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); + sprintf(g_dasm_str, "rte"); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); } static void d68020_rtm(void) { - LIMIT_CPU_TYPES(M68020_ONLY); - sprintf(g_dasm_str, "rtm %c%d; (2+)", BIT_3(g_cpu_ir) ? 'A' : 'D', g_cpu_ir&7); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); + LIMIT_CPU_TYPES(M68020_ONLY); + sprintf(g_dasm_str, "rtm %c%d; (2+)", BIT_3(g_cpu_ir) ? 'A' : 'D', g_cpu_ir&7); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); } static void d68000_rtr(void) { - sprintf(g_dasm_str, "rtr"); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); + sprintf(g_dasm_str, "rtr"); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); } static void d68000_rts(void) { - sprintf(g_dasm_str, "rts"); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); + sprintf(g_dasm_str, "rts"); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); } static void d68000_sbcd_rr(void) { - sprintf(g_dasm_str, "sbcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "sbcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_sbcd_mm(void) { - sprintf(g_dasm_str, "sbcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "sbcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_scc(void) { - sprintf(g_dasm_str, "s%-2s %s", g_cc[(g_cpu_ir>>8)&0xf], get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "s%-2s %s", g_cc[(g_cpu_ir>>8)&0xf], get_ea_mode_str_8(g_cpu_ir)); } static void d68000_stop(void) { - sprintf(g_dasm_str, "stop %s", get_imm_str_s16()); + sprintf(g_dasm_str, "stop %s", get_imm_str_s16()); } static void d68000_sub_er_8(void) { - sprintf(g_dasm_str, "sub.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "sub.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_sub_er_16(void) { - sprintf(g_dasm_str, "sub.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "sub.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_sub_er_32(void) { - sprintf(g_dasm_str, "sub.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "sub.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_sub_re_8(void) { - sprintf(g_dasm_str, "sub.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "sub.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_sub_re_16(void) { - sprintf(g_dasm_str, "sub.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "sub.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_sub_re_32(void) { - sprintf(g_dasm_str, "sub.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "sub.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_suba_16(void) { - sprintf(g_dasm_str, "suba.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "suba.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_suba_32(void) { - sprintf(g_dasm_str, "suba.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "suba.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); } static void d68000_subi_8(void) { - char* str = get_imm_str_s8(); - sprintf(g_dasm_str, "subi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); + char* str = get_imm_str_s8(); + sprintf(g_dasm_str, "subi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); } static void d68000_subi_16(void) { - char* str = get_imm_str_s16(); - sprintf(g_dasm_str, "subi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); + char* str = get_imm_str_s16(); + sprintf(g_dasm_str, "subi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); } static void d68000_subi_32(void) { - char* str = get_imm_str_s32(); - sprintf(g_dasm_str, "subi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); + char* str = get_imm_str_s32(); + sprintf(g_dasm_str, "subi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); } static void d68000_subq_8(void) { - sprintf(g_dasm_str, "subq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "subq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir)); } static void d68000_subq_16(void) { - sprintf(g_dasm_str, "subq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "subq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir)); } static void d68000_subq_32(void) { - sprintf(g_dasm_str, "subq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "subq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir)); } static void d68000_subx_rr_8(void) { - sprintf(g_dasm_str, "subx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "subx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_subx_rr_16(void) { - sprintf(g_dasm_str, "subx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "subx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_subx_rr_32(void) { - sprintf(g_dasm_str, "subx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "subx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_subx_mm_8(void) { - sprintf(g_dasm_str, "subx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "subx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_subx_mm_16(void) { - sprintf(g_dasm_str, "subx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "subx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_subx_mm_32(void) { - sprintf(g_dasm_str, "subx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); + sprintf(g_dasm_str, "subx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); } static void d68000_swap(void) { - sprintf(g_dasm_str, "swap D%d", g_cpu_ir&7); + sprintf(g_dasm_str, "swap D%d", g_cpu_ir&7); } static void d68000_tas(void) { - sprintf(g_dasm_str, "tas %s", get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "tas %s", get_ea_mode_str_8(g_cpu_ir)); } static void d68000_trap(void) { - sprintf(g_dasm_str, "trap #$%x", g_cpu_ir&0xf); + sprintf(g_dasm_str, "trap #$%x", g_cpu_ir&0xf); } static void d68020_trapcc_0(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "trap%-2s; (2+)", g_cc[(g_cpu_ir>>8)&0xf]); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "trap%-2s; (2+)", g_cc[(g_cpu_ir>>8)&0xf]); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68020_trapcc_16(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u16()); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u16()); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68020_trapcc_32(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u32()); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u32()); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68000_trapv(void) { - sprintf(g_dasm_str, "trapv"); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); + sprintf(g_dasm_str, "trapv"); + SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); } static void d68000_tst_8(void) { - sprintf(g_dasm_str, "tst.b %s", get_ea_mode_str_8(g_cpu_ir)); + sprintf(g_dasm_str, "tst.b %s", get_ea_mode_str_8(g_cpu_ir)); } static void d68020_tst_pcdi_8(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); } static void d68020_tst_pcix_8(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); } static void d68020_tst_i_8(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); } static void d68000_tst_16(void) { - sprintf(g_dasm_str, "tst.w %s", get_ea_mode_str_16(g_cpu_ir)); + sprintf(g_dasm_str, "tst.w %s", get_ea_mode_str_16(g_cpu_ir)); } static void d68020_tst_a_16(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); } static void d68020_tst_pcdi_16(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); } static void d68020_tst_pcix_16(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); } static void d68020_tst_i_16(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); } static void d68000_tst_32(void) { - sprintf(g_dasm_str, "tst.l %s", get_ea_mode_str_32(g_cpu_ir)); + sprintf(g_dasm_str, "tst.l %s", get_ea_mode_str_32(g_cpu_ir)); } static void d68020_tst_a_32(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); } static void d68020_tst_pcdi_32(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); } static void d68020_tst_pcix_32(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); } static void d68020_tst_i_32(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); } static void d68000_unlk(void) { - sprintf(g_dasm_str, "unlk A%d", g_cpu_ir&7); + sprintf(g_dasm_str, "unlk A%d", g_cpu_ir&7); } static void d68020_unpk_rr(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "unpk D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "unpk D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); } static void d68020_unpk_mm(void) { - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "unpk -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); + LIMIT_CPU_TYPES(M68020_PLUS); + sprintf(g_dasm_str, "unpk -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); } @@ -3164,125 +3164,125 @@ static void d68020_unpk_mm(void) // PFLUSHR: 1010000000000000 static void d68851_p000(void) { - char* str; - uint modes = read_imm_16(); + char* str; + uint modes = read_imm_16(); - // do this after fetching the second PMOVE word so we properly get the 3rd if necessary - str = get_ea_mode_str_32(g_cpu_ir); + // do this after fetching the second PMOVE word so we properly get the 3rd if necessary + str = get_ea_mode_str_32(g_cpu_ir); - if ((modes & 0xfde0) == 0x2000) // PLOAD - { - if (modes & 0x0200) - { - sprintf(g_dasm_str, "pload #%d, %s", (modes>>10)&7, str); - } - else - { - sprintf(g_dasm_str, "pload %s, #%d", str, (modes>>10)&7); - } - return; - } + if ((modes & 0xfde0) == 0x2000) // PLOAD + { + if (modes & 0x0200) + { + sprintf(g_dasm_str, "pload #%d, %s", (modes>>10)&7, str); + } + else + { + sprintf(g_dasm_str, "pload %s, #%d", str, (modes>>10)&7); + } + return; + } - if ((modes & 0xe200) == 0x2000) // PFLUSH - { - sprintf(g_dasm_str, "pflushr %x, %x, %s", modes & 0x1f, (modes>>5)&0xf, str); - return; - } + if ((modes & 0xe200) == 0x2000) // PFLUSH + { + sprintf(g_dasm_str, "pflushr %x, %x, %s", modes & 0x1f, (modes>>5)&0xf, str); + return; + } - if (modes == 0xa000) // PFLUSHR - { - sprintf(g_dasm_str, "pflushr %s", str); - } + if (modes == 0xa000) // PFLUSHR + { + sprintf(g_dasm_str, "pflushr %s", str); + } - if (modes == 0x2800) // PVALID (FORMAT 1) - { - sprintf(g_dasm_str, "pvalid VAL, %s", str); - return; - } + if (modes == 0x2800) // PVALID (FORMAT 1) + { + sprintf(g_dasm_str, "pvalid VAL, %s", str); + return; + } - if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2) - { - sprintf(g_dasm_str, "pvalid A%d, %s", modes & 0xf, str); - return; - } + if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2) + { + sprintf(g_dasm_str, "pvalid A%d, %s", modes & 0xf, str); + return; + } - if ((modes & 0xe000) == 0x8000) // PTEST - { - sprintf(g_dasm_str, "ptest #%d, %s", modes & 0x1f, str); - return; - } + if ((modes & 0xe000) == 0x8000) // PTEST + { + sprintf(g_dasm_str, "ptest #%d, %s", modes & 0x1f, str); + return; + } - switch ((modes>>13) & 0x7) - { - case 0: // MC68030/040 form with FD bit - case 2: // MC68881 form, FD never set - if (modes & 0x0100) - { - if (modes & 0x0200) - { - sprintf(g_dasm_str, "pmovefd %s, %s", g_mmuregs[(modes>>10)&7], str); - } - else - { - sprintf(g_dasm_str, "pmovefd %s, %s", str, g_mmuregs[(modes>>10)&7]); - } - } - else - { - if (modes & 0x0200) - { - sprintf(g_dasm_str, "pmove %s, %s", g_mmuregs[(modes>>10)&7], str); - } - else - { - sprintf(g_dasm_str, "pmove %s, %s", str, g_mmuregs[(modes>>10)&7]); - } - } - break; + switch ((modes>>13) & 0x7) + { + case 0: // MC68030/040 form with FD bit + case 2: // MC68881 form, FD never set + if (modes & 0x0100) + { + if (modes & 0x0200) + { + sprintf(g_dasm_str, "pmovefd %s, %s", g_mmuregs[(modes>>10)&7], str); + } + else + { + sprintf(g_dasm_str, "pmovefd %s, %s", str, g_mmuregs[(modes>>10)&7]); + } + } + else + { + if (modes & 0x0200) + { + sprintf(g_dasm_str, "pmove %s, %s", g_mmuregs[(modes>>10)&7], str); + } + else + { + sprintf(g_dasm_str, "pmove %s, %s", str, g_mmuregs[(modes>>10)&7]); + } + } + break; - case 3: // MC68030 to/from status reg - if (modes & 0x0200) - { - sprintf(g_dasm_str, "pmove mmusr, %s", str); - } - else - { - sprintf(g_dasm_str, "pmove %s, mmusr", str); - } - break; + case 3: // MC68030 to/from status reg + if (modes & 0x0200) + { + sprintf(g_dasm_str, "pmove mmusr, %s", str); + } + else + { + sprintf(g_dasm_str, "pmove %s, mmusr", str); + } + break; - default: - sprintf(g_dasm_str, "pmove [unknown form] %s", str); - break; - } + default: + sprintf(g_dasm_str, "pmove [unknown form] %s", str); + break; + } } static void d68851_pbcc16(void) { - uint32 temp_pc = g_cpu_pc; + uint32 temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_16(read_imm_16())); + sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_16(read_imm_16())); } static void d68851_pbcc32(void) { - uint32 temp_pc = g_cpu_pc; + uint32 temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_32(read_imm_32())); + sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_32(read_imm_32())); } static void d68851_pdbcc(void) { - uint32 temp_pc = g_cpu_pc; - uint16 modes = read_imm_16(); + uint32 temp_pc = g_cpu_pc; + uint16 modes = read_imm_16(); - sprintf(g_dasm_str, "pb%s %x", g_mmucond[modes&0xf], temp_pc + make_int_16(read_imm_16())); + sprintf(g_dasm_str, "pb%s %x", g_mmucond[modes&0xf], temp_pc + make_int_16(read_imm_16())); } // PScc: 0000000000xxxxxx static void d68851_p001(void) { - sprintf(g_dasm_str, "MMU 001 group"); + sprintf(g_dasm_str, "MMU 001 group"); } /* ======================================================================== */ @@ -3307,412 +3307,412 @@ static void d68851_p001(void) static const opcode_struct g_opcode_info[] = { /* opcode handler mask match ea mask */ - {d68000_1010 , 0xf000, 0xa000, 0x000}, - {d68000_1111 , 0xf000, 0xf000, 0x000}, - {d68000_abcd_rr , 0xf1f8, 0xc100, 0x000}, - {d68000_abcd_mm , 0xf1f8, 0xc108, 0x000}, - {d68000_add_er_8 , 0xf1c0, 0xd000, 0xbff}, - {d68000_add_er_16 , 0xf1c0, 0xd040, 0xfff}, - {d68000_add_er_32 , 0xf1c0, 0xd080, 0xfff}, - {d68000_add_re_8 , 0xf1c0, 0xd100, 0x3f8}, - {d68000_add_re_16 , 0xf1c0, 0xd140, 0x3f8}, - {d68000_add_re_32 , 0xf1c0, 0xd180, 0x3f8}, - {d68000_adda_16 , 0xf1c0, 0xd0c0, 0xfff}, - {d68000_adda_32 , 0xf1c0, 0xd1c0, 0xfff}, - {d68000_addi_8 , 0xffc0, 0x0600, 0xbf8}, - {d68000_addi_16 , 0xffc0, 0x0640, 0xbf8}, - {d68000_addi_32 , 0xffc0, 0x0680, 0xbf8}, - {d68000_addq_8 , 0xf1c0, 0x5000, 0xbf8}, - {d68000_addq_16 , 0xf1c0, 0x5040, 0xff8}, - {d68000_addq_32 , 0xf1c0, 0x5080, 0xff8}, - {d68000_addx_rr_8 , 0xf1f8, 0xd100, 0x000}, - {d68000_addx_rr_16 , 0xf1f8, 0xd140, 0x000}, - {d68000_addx_rr_32 , 0xf1f8, 0xd180, 0x000}, - {d68000_addx_mm_8 , 0xf1f8, 0xd108, 0x000}, - {d68000_addx_mm_16 , 0xf1f8, 0xd148, 0x000}, - {d68000_addx_mm_32 , 0xf1f8, 0xd188, 0x000}, - {d68000_and_er_8 , 0xf1c0, 0xc000, 0xbff}, - {d68000_and_er_16 , 0xf1c0, 0xc040, 0xbff}, - {d68000_and_er_32 , 0xf1c0, 0xc080, 0xbff}, - {d68000_and_re_8 , 0xf1c0, 0xc100, 0x3f8}, - {d68000_and_re_16 , 0xf1c0, 0xc140, 0x3f8}, - {d68000_and_re_32 , 0xf1c0, 0xc180, 0x3f8}, - {d68000_andi_to_ccr , 0xffff, 0x023c, 0x000}, - {d68000_andi_to_sr , 0xffff, 0x027c, 0x000}, - {d68000_andi_8 , 0xffc0, 0x0200, 0xbf8}, - {d68000_andi_16 , 0xffc0, 0x0240, 0xbf8}, - {d68000_andi_32 , 0xffc0, 0x0280, 0xbf8}, - {d68000_asr_s_8 , 0xf1f8, 0xe000, 0x000}, - {d68000_asr_s_16 , 0xf1f8, 0xe040, 0x000}, - {d68000_asr_s_32 , 0xf1f8, 0xe080, 0x000}, - {d68000_asr_r_8 , 0xf1f8, 0xe020, 0x000}, - {d68000_asr_r_16 , 0xf1f8, 0xe060, 0x000}, - {d68000_asr_r_32 , 0xf1f8, 0xe0a0, 0x000}, - {d68000_asr_ea , 0xffc0, 0xe0c0, 0x3f8}, - {d68000_asl_s_8 , 0xf1f8, 0xe100, 0x000}, - {d68000_asl_s_16 , 0xf1f8, 0xe140, 0x000}, - {d68000_asl_s_32 , 0xf1f8, 0xe180, 0x000}, - {d68000_asl_r_8 , 0xf1f8, 0xe120, 0x000}, - {d68000_asl_r_16 , 0xf1f8, 0xe160, 0x000}, - {d68000_asl_r_32 , 0xf1f8, 0xe1a0, 0x000}, - {d68000_asl_ea , 0xffc0, 0xe1c0, 0x3f8}, - {d68000_bcc_8 , 0xf000, 0x6000, 0x000}, - {d68000_bcc_16 , 0xf0ff, 0x6000, 0x000}, - {d68020_bcc_32 , 0xf0ff, 0x60ff, 0x000}, - {d68000_bchg_r , 0xf1c0, 0x0140, 0xbf8}, - {d68000_bchg_s , 0xffc0, 0x0840, 0xbf8}, - {d68000_bclr_r , 0xf1c0, 0x0180, 0xbf8}, - {d68000_bclr_s , 0xffc0, 0x0880, 0xbf8}, - {d68020_bfchg , 0xffc0, 0xeac0, 0xa78}, - {d68020_bfclr , 0xffc0, 0xecc0, 0xa78}, - {d68020_bfexts , 0xffc0, 0xebc0, 0xa7b}, - {d68020_bfextu , 0xffc0, 0xe9c0, 0xa7b}, - {d68020_bfffo , 0xffc0, 0xedc0, 0xa7b}, - {d68020_bfins , 0xffc0, 0xefc0, 0xa78}, - {d68020_bfset , 0xffc0, 0xeec0, 0xa78}, - {d68020_bftst , 0xffc0, 0xe8c0, 0xa7b}, - {d68010_bkpt , 0xfff8, 0x4848, 0x000}, - {d68000_bra_8 , 0xff00, 0x6000, 0x000}, - {d68000_bra_16 , 0xffff, 0x6000, 0x000}, - {d68020_bra_32 , 0xffff, 0x60ff, 0x000}, - {d68000_bset_r , 0xf1c0, 0x01c0, 0xbf8}, - {d68000_bset_s , 0xffc0, 0x08c0, 0xbf8}, - {d68000_bsr_8 , 0xff00, 0x6100, 0x000}, - {d68000_bsr_16 , 0xffff, 0x6100, 0x000}, - {d68020_bsr_32 , 0xffff, 0x61ff, 0x000}, - {d68000_btst_r , 0xf1c0, 0x0100, 0xbff}, - {d68000_btst_s , 0xffc0, 0x0800, 0xbfb}, - {d68020_callm , 0xffc0, 0x06c0, 0x27b}, - {d68020_cas_8 , 0xffc0, 0x0ac0, 0x3f8}, - {d68020_cas_16 , 0xffc0, 0x0cc0, 0x3f8}, - {d68020_cas_32 , 0xffc0, 0x0ec0, 0x3f8}, - {d68020_cas2_16 , 0xffff, 0x0cfc, 0x000}, - {d68020_cas2_32 , 0xffff, 0x0efc, 0x000}, - {d68000_chk_16 , 0xf1c0, 0x4180, 0xbff}, - {d68020_chk_32 , 0xf1c0, 0x4100, 0xbff}, - {d68020_chk2_cmp2_8 , 0xffc0, 0x00c0, 0x27b}, - {d68020_chk2_cmp2_16 , 0xffc0, 0x02c0, 0x27b}, - {d68020_chk2_cmp2_32 , 0xffc0, 0x04c0, 0x27b}, - {d68040_cinv , 0xff20, 0xf400, 0x000}, - {d68000_clr_8 , 0xffc0, 0x4200, 0xbf8}, - {d68000_clr_16 , 0xffc0, 0x4240, 0xbf8}, - {d68000_clr_32 , 0xffc0, 0x4280, 0xbf8}, - {d68000_cmp_8 , 0xf1c0, 0xb000, 0xbff}, - {d68000_cmp_16 , 0xf1c0, 0xb040, 0xfff}, - {d68000_cmp_32 , 0xf1c0, 0xb080, 0xfff}, - {d68000_cmpa_16 , 0xf1c0, 0xb0c0, 0xfff}, - {d68000_cmpa_32 , 0xf1c0, 0xb1c0, 0xfff}, - {d68000_cmpi_8 , 0xffc0, 0x0c00, 0xbf8}, - {d68020_cmpi_pcdi_8 , 0xffff, 0x0c3a, 0x000}, - {d68020_cmpi_pcix_8 , 0xffff, 0x0c3b, 0x000}, - {d68000_cmpi_16 , 0xffc0, 0x0c40, 0xbf8}, - {d68020_cmpi_pcdi_16 , 0xffff, 0x0c7a, 0x000}, - {d68020_cmpi_pcix_16 , 0xffff, 0x0c7b, 0x000}, - {d68000_cmpi_32 , 0xffc0, 0x0c80, 0xbf8}, - {d68020_cmpi_pcdi_32 , 0xffff, 0x0cba, 0x000}, - {d68020_cmpi_pcix_32 , 0xffff, 0x0cbb, 0x000}, - {d68000_cmpm_8 , 0xf1f8, 0xb108, 0x000}, - {d68000_cmpm_16 , 0xf1f8, 0xb148, 0x000}, - {d68000_cmpm_32 , 0xf1f8, 0xb188, 0x000}, - {d68020_cpbcc_16 , 0xf1c0, 0xf080, 0x000}, - {d68020_cpbcc_32 , 0xf1c0, 0xf0c0, 0x000}, - {d68020_cpdbcc , 0xf1f8, 0xf048, 0x000}, - {d68020_cpgen , 0xf1c0, 0xf000, 0x000}, - {d68020_cprestore , 0xf1c0, 0xf140, 0x37f}, - {d68020_cpsave , 0xf1c0, 0xf100, 0x2f8}, - {d68020_cpscc , 0xf1c0, 0xf040, 0xbf8}, - {d68020_cptrapcc_0 , 0xf1ff, 0xf07c, 0x000}, - {d68020_cptrapcc_16 , 0xf1ff, 0xf07a, 0x000}, - {d68020_cptrapcc_32 , 0xf1ff, 0xf07b, 0x000}, - {d68040_cpush , 0xff20, 0xf420, 0x000}, - {d68000_dbcc , 0xf0f8, 0x50c8, 0x000}, - {d68000_dbra , 0xfff8, 0x51c8, 0x000}, - {d68000_divs , 0xf1c0, 0x81c0, 0xbff}, - {d68000_divu , 0xf1c0, 0x80c0, 0xbff}, - {d68020_divl , 0xffc0, 0x4c40, 0xbff}, - {d68000_eor_8 , 0xf1c0, 0xb100, 0xbf8}, - {d68000_eor_16 , 0xf1c0, 0xb140, 0xbf8}, - {d68000_eor_32 , 0xf1c0, 0xb180, 0xbf8}, - {d68000_eori_to_ccr , 0xffff, 0x0a3c, 0x000}, - {d68000_eori_to_sr , 0xffff, 0x0a7c, 0x000}, - {d68000_eori_8 , 0xffc0, 0x0a00, 0xbf8}, - {d68000_eori_16 , 0xffc0, 0x0a40, 0xbf8}, - {d68000_eori_32 , 0xffc0, 0x0a80, 0xbf8}, - {d68000_exg_dd , 0xf1f8, 0xc140, 0x000}, - {d68000_exg_aa , 0xf1f8, 0xc148, 0x000}, - {d68000_exg_da , 0xf1f8, 0xc188, 0x000}, - {d68020_extb_32 , 0xfff8, 0x49c0, 0x000}, - {d68000_ext_16 , 0xfff8, 0x4880, 0x000}, - {d68000_ext_32 , 0xfff8, 0x48c0, 0x000}, - {d68040_fpu , 0xffc0, 0xf200, 0x000}, - {d68000_illegal , 0xffff, 0x4afc, 0x000}, - {d68000_jmp , 0xffc0, 0x4ec0, 0x27b}, - {d68000_jsr , 0xffc0, 0x4e80, 0x27b}, - {d68000_lea , 0xf1c0, 0x41c0, 0x27b}, - {d68000_link_16 , 0xfff8, 0x4e50, 0x000}, - {d68020_link_32 , 0xfff8, 0x4808, 0x000}, - {d68000_lsr_s_8 , 0xf1f8, 0xe008, 0x000}, - {d68000_lsr_s_16 , 0xf1f8, 0xe048, 0x000}, - {d68000_lsr_s_32 , 0xf1f8, 0xe088, 0x000}, - {d68000_lsr_r_8 , 0xf1f8, 0xe028, 0x000}, - {d68000_lsr_r_16 , 0xf1f8, 0xe068, 0x000}, - {d68000_lsr_r_32 , 0xf1f8, 0xe0a8, 0x000}, - {d68000_lsr_ea , 0xffc0, 0xe2c0, 0x3f8}, - {d68000_lsl_s_8 , 0xf1f8, 0xe108, 0x000}, - {d68000_lsl_s_16 , 0xf1f8, 0xe148, 0x000}, - {d68000_lsl_s_32 , 0xf1f8, 0xe188, 0x000}, - {d68000_lsl_r_8 , 0xf1f8, 0xe128, 0x000}, - {d68000_lsl_r_16 , 0xf1f8, 0xe168, 0x000}, - {d68000_lsl_r_32 , 0xf1f8, 0xe1a8, 0x000}, - {d68000_lsl_ea , 0xffc0, 0xe3c0, 0x3f8}, - {d68000_move_8 , 0xf000, 0x1000, 0xbff}, - {d68000_move_16 , 0xf000, 0x3000, 0xfff}, - {d68000_move_32 , 0xf000, 0x2000, 0xfff}, - {d68000_movea_16 , 0xf1c0, 0x3040, 0xfff}, - {d68000_movea_32 , 0xf1c0, 0x2040, 0xfff}, - {d68000_move_to_ccr , 0xffc0, 0x44c0, 0xbff}, - {d68010_move_fr_ccr , 0xffc0, 0x42c0, 0xbf8}, - {d68000_move_to_sr , 0xffc0, 0x46c0, 0xbff}, - {d68000_move_fr_sr , 0xffc0, 0x40c0, 0xbf8}, - {d68000_move_to_usp , 0xfff8, 0x4e60, 0x000}, - {d68000_move_fr_usp , 0xfff8, 0x4e68, 0x000}, - {d68010_movec , 0xfffe, 0x4e7a, 0x000}, - {d68000_movem_pd_16 , 0xfff8, 0x48a0, 0x000}, - {d68000_movem_pd_32 , 0xfff8, 0x48e0, 0x000}, - {d68000_movem_re_16 , 0xffc0, 0x4880, 0x2f8}, - {d68000_movem_re_32 , 0xffc0, 0x48c0, 0x2f8}, - {d68000_movem_er_16 , 0xffc0, 0x4c80, 0x37b}, - {d68000_movem_er_32 , 0xffc0, 0x4cc0, 0x37b}, - {d68000_movep_er_16 , 0xf1f8, 0x0108, 0x000}, - {d68000_movep_er_32 , 0xf1f8, 0x0148, 0x000}, - {d68000_movep_re_16 , 0xf1f8, 0x0188, 0x000}, - {d68000_movep_re_32 , 0xf1f8, 0x01c8, 0x000}, - {d68010_moves_8 , 0xffc0, 0x0e00, 0x3f8}, - {d68010_moves_16 , 0xffc0, 0x0e40, 0x3f8}, - {d68010_moves_32 , 0xffc0, 0x0e80, 0x3f8}, - {d68000_moveq , 0xf100, 0x7000, 0x000}, - {d68040_move16_pi_pi , 0xfff8, 0xf620, 0x000}, - {d68040_move16_pi_al , 0xfff8, 0xf600, 0x000}, - {d68040_move16_al_pi , 0xfff8, 0xf608, 0x000}, - {d68040_move16_ai_al , 0xfff8, 0xf610, 0x000}, - {d68040_move16_al_ai , 0xfff8, 0xf618, 0x000}, - {d68000_muls , 0xf1c0, 0xc1c0, 0xbff}, - {d68000_mulu , 0xf1c0, 0xc0c0, 0xbff}, - {d68020_mull , 0xffc0, 0x4c00, 0xbff}, - {d68000_nbcd , 0xffc0, 0x4800, 0xbf8}, - {d68000_neg_8 , 0xffc0, 0x4400, 0xbf8}, - {d68000_neg_16 , 0xffc0, 0x4440, 0xbf8}, - {d68000_neg_32 , 0xffc0, 0x4480, 0xbf8}, - {d68000_negx_8 , 0xffc0, 0x4000, 0xbf8}, - {d68000_negx_16 , 0xffc0, 0x4040, 0xbf8}, - {d68000_negx_32 , 0xffc0, 0x4080, 0xbf8}, - {d68000_nop , 0xffff, 0x4e71, 0x000}, - {d68000_not_8 , 0xffc0, 0x4600, 0xbf8}, - {d68000_not_16 , 0xffc0, 0x4640, 0xbf8}, - {d68000_not_32 , 0xffc0, 0x4680, 0xbf8}, - {d68000_or_er_8 , 0xf1c0, 0x8000, 0xbff}, - {d68000_or_er_16 , 0xf1c0, 0x8040, 0xbff}, - {d68000_or_er_32 , 0xf1c0, 0x8080, 0xbff}, - {d68000_or_re_8 , 0xf1c0, 0x8100, 0x3f8}, - {d68000_or_re_16 , 0xf1c0, 0x8140, 0x3f8}, - {d68000_or_re_32 , 0xf1c0, 0x8180, 0x3f8}, - {d68000_ori_to_ccr , 0xffff, 0x003c, 0x000}, - {d68000_ori_to_sr , 0xffff, 0x007c, 0x000}, - {d68000_ori_8 , 0xffc0, 0x0000, 0xbf8}, - {d68000_ori_16 , 0xffc0, 0x0040, 0xbf8}, - {d68000_ori_32 , 0xffc0, 0x0080, 0xbf8}, - {d68020_pack_rr , 0xf1f8, 0x8140, 0x000}, - {d68020_pack_mm , 0xf1f8, 0x8148, 0x000}, - {d68000_pea , 0xffc0, 0x4840, 0x27b}, - {d68040_pflush , 0xffe0, 0xf500, 0x000}, - {d68000_reset , 0xffff, 0x4e70, 0x000}, - {d68000_ror_s_8 , 0xf1f8, 0xe018, 0x000}, - {d68000_ror_s_16 , 0xf1f8, 0xe058, 0x000}, - {d68000_ror_s_32 , 0xf1f8, 0xe098, 0x000}, - {d68000_ror_r_8 , 0xf1f8, 0xe038, 0x000}, - {d68000_ror_r_16 , 0xf1f8, 0xe078, 0x000}, - {d68000_ror_r_32 , 0xf1f8, 0xe0b8, 0x000}, - {d68000_ror_ea , 0xffc0, 0xe6c0, 0x3f8}, - {d68000_rol_s_8 , 0xf1f8, 0xe118, 0x000}, - {d68000_rol_s_16 , 0xf1f8, 0xe158, 0x000}, - {d68000_rol_s_32 , 0xf1f8, 0xe198, 0x000}, - {d68000_rol_r_8 , 0xf1f8, 0xe138, 0x000}, - {d68000_rol_r_16 , 0xf1f8, 0xe178, 0x000}, - {d68000_rol_r_32 , 0xf1f8, 0xe1b8, 0x000}, - {d68000_rol_ea , 0xffc0, 0xe7c0, 0x3f8}, - {d68000_roxr_s_8 , 0xf1f8, 0xe010, 0x000}, - {d68000_roxr_s_16 , 0xf1f8, 0xe050, 0x000}, - {d68000_roxr_s_32 , 0xf1f8, 0xe090, 0x000}, - {d68000_roxr_r_8 , 0xf1f8, 0xe030, 0x000}, - {d68000_roxr_r_16 , 0xf1f8, 0xe070, 0x000}, - {d68000_roxr_r_32 , 0xf1f8, 0xe0b0, 0x000}, - {d68000_roxr_ea , 0xffc0, 0xe4c0, 0x3f8}, - {d68000_roxl_s_8 , 0xf1f8, 0xe110, 0x000}, - {d68000_roxl_s_16 , 0xf1f8, 0xe150, 0x000}, - {d68000_roxl_s_32 , 0xf1f8, 0xe190, 0x000}, - {d68000_roxl_r_8 , 0xf1f8, 0xe130, 0x000}, - {d68000_roxl_r_16 , 0xf1f8, 0xe170, 0x000}, - {d68000_roxl_r_32 , 0xf1f8, 0xe1b0, 0x000}, - {d68000_roxl_ea , 0xffc0, 0xe5c0, 0x3f8}, - {d68010_rtd , 0xffff, 0x4e74, 0x000}, - {d68000_rte , 0xffff, 0x4e73, 0x000}, - {d68020_rtm , 0xfff0, 0x06c0, 0x000}, - {d68000_rtr , 0xffff, 0x4e77, 0x000}, - {d68000_rts , 0xffff, 0x4e75, 0x000}, - {d68000_sbcd_rr , 0xf1f8, 0x8100, 0x000}, - {d68000_sbcd_mm , 0xf1f8, 0x8108, 0x000}, - {d68000_scc , 0xf0c0, 0x50c0, 0xbf8}, - {d68000_stop , 0xffff, 0x4e72, 0x000}, - {d68000_sub_er_8 , 0xf1c0, 0x9000, 0xbff}, - {d68000_sub_er_16 , 0xf1c0, 0x9040, 0xfff}, - {d68000_sub_er_32 , 0xf1c0, 0x9080, 0xfff}, - {d68000_sub_re_8 , 0xf1c0, 0x9100, 0x3f8}, - {d68000_sub_re_16 , 0xf1c0, 0x9140, 0x3f8}, - {d68000_sub_re_32 , 0xf1c0, 0x9180, 0x3f8}, - {d68000_suba_16 , 0xf1c0, 0x90c0, 0xfff}, - {d68000_suba_32 , 0xf1c0, 0x91c0, 0xfff}, - {d68000_subi_8 , 0xffc0, 0x0400, 0xbf8}, - {d68000_subi_16 , 0xffc0, 0x0440, 0xbf8}, - {d68000_subi_32 , 0xffc0, 0x0480, 0xbf8}, - {d68000_subq_8 , 0xf1c0, 0x5100, 0xbf8}, - {d68000_subq_16 , 0xf1c0, 0x5140, 0xff8}, - {d68000_subq_32 , 0xf1c0, 0x5180, 0xff8}, - {d68000_subx_rr_8 , 0xf1f8, 0x9100, 0x000}, - {d68000_subx_rr_16 , 0xf1f8, 0x9140, 0x000}, - {d68000_subx_rr_32 , 0xf1f8, 0x9180, 0x000}, - {d68000_subx_mm_8 , 0xf1f8, 0x9108, 0x000}, - {d68000_subx_mm_16 , 0xf1f8, 0x9148, 0x000}, - {d68000_subx_mm_32 , 0xf1f8, 0x9188, 0x000}, - {d68000_swap , 0xfff8, 0x4840, 0x000}, - {d68000_tas , 0xffc0, 0x4ac0, 0xbf8}, - {d68000_trap , 0xfff0, 0x4e40, 0x000}, - {d68020_trapcc_0 , 0xf0ff, 0x50fc, 0x000}, - {d68020_trapcc_16 , 0xf0ff, 0x50fa, 0x000}, - {d68020_trapcc_32 , 0xf0ff, 0x50fb, 0x000}, - {d68000_trapv , 0xffff, 0x4e76, 0x000}, - {d68000_tst_8 , 0xffc0, 0x4a00, 0xbf8}, - {d68020_tst_pcdi_8 , 0xffff, 0x4a3a, 0x000}, - {d68020_tst_pcix_8 , 0xffff, 0x4a3b, 0x000}, - {d68020_tst_i_8 , 0xffff, 0x4a3c, 0x000}, - {d68000_tst_16 , 0xffc0, 0x4a40, 0xbf8}, - {d68020_tst_a_16 , 0xfff8, 0x4a48, 0x000}, - {d68020_tst_pcdi_16 , 0xffff, 0x4a7a, 0x000}, - {d68020_tst_pcix_16 , 0xffff, 0x4a7b, 0x000}, - {d68020_tst_i_16 , 0xffff, 0x4a7c, 0x000}, - {d68000_tst_32 , 0xffc0, 0x4a80, 0xbf8}, - {d68020_tst_a_32 , 0xfff8, 0x4a88, 0x000}, - {d68020_tst_pcdi_32 , 0xffff, 0x4aba, 0x000}, - {d68020_tst_pcix_32 , 0xffff, 0x4abb, 0x000}, - {d68020_tst_i_32 , 0xffff, 0x4abc, 0x000}, - {d68000_unlk , 0xfff8, 0x4e58, 0x000}, - {d68020_unpk_rr , 0xf1f8, 0x8180, 0x000}, - {d68020_unpk_mm , 0xf1f8, 0x8188, 0x000}, - {d68851_p000 , 0xffc0, 0xf000, 0x000}, - {d68851_pbcc16 , 0xffc0, 0xf080, 0x000}, - {d68851_pbcc32 , 0xffc0, 0xf0c0, 0x000}, - {d68851_pdbcc , 0xfff8, 0xf048, 0x000}, - {d68851_p001 , 0xffc0, 0xf040, 0x000}, - {0, 0, 0, 0} + {d68000_1010 , 0xf000, 0xa000, 0x000}, + {d68000_1111 , 0xf000, 0xf000, 0x000}, + {d68000_abcd_rr , 0xf1f8, 0xc100, 0x000}, + {d68000_abcd_mm , 0xf1f8, 0xc108, 0x000}, + {d68000_add_er_8 , 0xf1c0, 0xd000, 0xbff}, + {d68000_add_er_16 , 0xf1c0, 0xd040, 0xfff}, + {d68000_add_er_32 , 0xf1c0, 0xd080, 0xfff}, + {d68000_add_re_8 , 0xf1c0, 0xd100, 0x3f8}, + {d68000_add_re_16 , 0xf1c0, 0xd140, 0x3f8}, + {d68000_add_re_32 , 0xf1c0, 0xd180, 0x3f8}, + {d68000_adda_16 , 0xf1c0, 0xd0c0, 0xfff}, + {d68000_adda_32 , 0xf1c0, 0xd1c0, 0xfff}, + {d68000_addi_8 , 0xffc0, 0x0600, 0xbf8}, + {d68000_addi_16 , 0xffc0, 0x0640, 0xbf8}, + {d68000_addi_32 , 0xffc0, 0x0680, 0xbf8}, + {d68000_addq_8 , 0xf1c0, 0x5000, 0xbf8}, + {d68000_addq_16 , 0xf1c0, 0x5040, 0xff8}, + {d68000_addq_32 , 0xf1c0, 0x5080, 0xff8}, + {d68000_addx_rr_8 , 0xf1f8, 0xd100, 0x000}, + {d68000_addx_rr_16 , 0xf1f8, 0xd140, 0x000}, + {d68000_addx_rr_32 , 0xf1f8, 0xd180, 0x000}, + {d68000_addx_mm_8 , 0xf1f8, 0xd108, 0x000}, + {d68000_addx_mm_16 , 0xf1f8, 0xd148, 0x000}, + {d68000_addx_mm_32 , 0xf1f8, 0xd188, 0x000}, + {d68000_and_er_8 , 0xf1c0, 0xc000, 0xbff}, + {d68000_and_er_16 , 0xf1c0, 0xc040, 0xbff}, + {d68000_and_er_32 , 0xf1c0, 0xc080, 0xbff}, + {d68000_and_re_8 , 0xf1c0, 0xc100, 0x3f8}, + {d68000_and_re_16 , 0xf1c0, 0xc140, 0x3f8}, + {d68000_and_re_32 , 0xf1c0, 0xc180, 0x3f8}, + {d68000_andi_to_ccr , 0xffff, 0x023c, 0x000}, + {d68000_andi_to_sr , 0xffff, 0x027c, 0x000}, + {d68000_andi_8 , 0xffc0, 0x0200, 0xbf8}, + {d68000_andi_16 , 0xffc0, 0x0240, 0xbf8}, + {d68000_andi_32 , 0xffc0, 0x0280, 0xbf8}, + {d68000_asr_s_8 , 0xf1f8, 0xe000, 0x000}, + {d68000_asr_s_16 , 0xf1f8, 0xe040, 0x000}, + {d68000_asr_s_32 , 0xf1f8, 0xe080, 0x000}, + {d68000_asr_r_8 , 0xf1f8, 0xe020, 0x000}, + {d68000_asr_r_16 , 0xf1f8, 0xe060, 0x000}, + {d68000_asr_r_32 , 0xf1f8, 0xe0a0, 0x000}, + {d68000_asr_ea , 0xffc0, 0xe0c0, 0x3f8}, + {d68000_asl_s_8 , 0xf1f8, 0xe100, 0x000}, + {d68000_asl_s_16 , 0xf1f8, 0xe140, 0x000}, + {d68000_asl_s_32 , 0xf1f8, 0xe180, 0x000}, + {d68000_asl_r_8 , 0xf1f8, 0xe120, 0x000}, + {d68000_asl_r_16 , 0xf1f8, 0xe160, 0x000}, + {d68000_asl_r_32 , 0xf1f8, 0xe1a0, 0x000}, + {d68000_asl_ea , 0xffc0, 0xe1c0, 0x3f8}, + {d68000_bcc_8 , 0xf000, 0x6000, 0x000}, + {d68000_bcc_16 , 0xf0ff, 0x6000, 0x000}, + {d68020_bcc_32 , 0xf0ff, 0x60ff, 0x000}, + {d68000_bchg_r , 0xf1c0, 0x0140, 0xbf8}, + {d68000_bchg_s , 0xffc0, 0x0840, 0xbf8}, + {d68000_bclr_r , 0xf1c0, 0x0180, 0xbf8}, + {d68000_bclr_s , 0xffc0, 0x0880, 0xbf8}, + {d68020_bfchg , 0xffc0, 0xeac0, 0xa78}, + {d68020_bfclr , 0xffc0, 0xecc0, 0xa78}, + {d68020_bfexts , 0xffc0, 0xebc0, 0xa7b}, + {d68020_bfextu , 0xffc0, 0xe9c0, 0xa7b}, + {d68020_bfffo , 0xffc0, 0xedc0, 0xa7b}, + {d68020_bfins , 0xffc0, 0xefc0, 0xa78}, + {d68020_bfset , 0xffc0, 0xeec0, 0xa78}, + {d68020_bftst , 0xffc0, 0xe8c0, 0xa7b}, + {d68010_bkpt , 0xfff8, 0x4848, 0x000}, + {d68000_bra_8 , 0xff00, 0x6000, 0x000}, + {d68000_bra_16 , 0xffff, 0x6000, 0x000}, + {d68020_bra_32 , 0xffff, 0x60ff, 0x000}, + {d68000_bset_r , 0xf1c0, 0x01c0, 0xbf8}, + {d68000_bset_s , 0xffc0, 0x08c0, 0xbf8}, + {d68000_bsr_8 , 0xff00, 0x6100, 0x000}, + {d68000_bsr_16 , 0xffff, 0x6100, 0x000}, + {d68020_bsr_32 , 0xffff, 0x61ff, 0x000}, + {d68000_btst_r , 0xf1c0, 0x0100, 0xbff}, + {d68000_btst_s , 0xffc0, 0x0800, 0xbfb}, + {d68020_callm , 0xffc0, 0x06c0, 0x27b}, + {d68020_cas_8 , 0xffc0, 0x0ac0, 0x3f8}, + {d68020_cas_16 , 0xffc0, 0x0cc0, 0x3f8}, + {d68020_cas_32 , 0xffc0, 0x0ec0, 0x3f8}, + {d68020_cas2_16 , 0xffff, 0x0cfc, 0x000}, + {d68020_cas2_32 , 0xffff, 0x0efc, 0x000}, + {d68000_chk_16 , 0xf1c0, 0x4180, 0xbff}, + {d68020_chk_32 , 0xf1c0, 0x4100, 0xbff}, + {d68020_chk2_cmp2_8 , 0xffc0, 0x00c0, 0x27b}, + {d68020_chk2_cmp2_16 , 0xffc0, 0x02c0, 0x27b}, + {d68020_chk2_cmp2_32 , 0xffc0, 0x04c0, 0x27b}, + {d68040_cinv , 0xff20, 0xf400, 0x000}, + {d68000_clr_8 , 0xffc0, 0x4200, 0xbf8}, + {d68000_clr_16 , 0xffc0, 0x4240, 0xbf8}, + {d68000_clr_32 , 0xffc0, 0x4280, 0xbf8}, + {d68000_cmp_8 , 0xf1c0, 0xb000, 0xbff}, + {d68000_cmp_16 , 0xf1c0, 0xb040, 0xfff}, + {d68000_cmp_32 , 0xf1c0, 0xb080, 0xfff}, + {d68000_cmpa_16 , 0xf1c0, 0xb0c0, 0xfff}, + {d68000_cmpa_32 , 0xf1c0, 0xb1c0, 0xfff}, + {d68000_cmpi_8 , 0xffc0, 0x0c00, 0xbf8}, + {d68020_cmpi_pcdi_8 , 0xffff, 0x0c3a, 0x000}, + {d68020_cmpi_pcix_8 , 0xffff, 0x0c3b, 0x000}, + {d68000_cmpi_16 , 0xffc0, 0x0c40, 0xbf8}, + {d68020_cmpi_pcdi_16 , 0xffff, 0x0c7a, 0x000}, + {d68020_cmpi_pcix_16 , 0xffff, 0x0c7b, 0x000}, + {d68000_cmpi_32 , 0xffc0, 0x0c80, 0xbf8}, + {d68020_cmpi_pcdi_32 , 0xffff, 0x0cba, 0x000}, + {d68020_cmpi_pcix_32 , 0xffff, 0x0cbb, 0x000}, + {d68000_cmpm_8 , 0xf1f8, 0xb108, 0x000}, + {d68000_cmpm_16 , 0xf1f8, 0xb148, 0x000}, + {d68000_cmpm_32 , 0xf1f8, 0xb188, 0x000}, + {d68020_cpbcc_16 , 0xf1c0, 0xf080, 0x000}, + {d68020_cpbcc_32 , 0xf1c0, 0xf0c0, 0x000}, + {d68020_cpdbcc , 0xf1f8, 0xf048, 0x000}, + {d68020_cpgen , 0xf1c0, 0xf000, 0x000}, + {d68020_cprestore , 0xf1c0, 0xf140, 0x37f}, + {d68020_cpsave , 0xf1c0, 0xf100, 0x2f8}, + {d68020_cpscc , 0xf1c0, 0xf040, 0xbf8}, + {d68020_cptrapcc_0 , 0xf1ff, 0xf07c, 0x000}, + {d68020_cptrapcc_16 , 0xf1ff, 0xf07a, 0x000}, + {d68020_cptrapcc_32 , 0xf1ff, 0xf07b, 0x000}, + {d68040_cpush , 0xff20, 0xf420, 0x000}, + {d68000_dbcc , 0xf0f8, 0x50c8, 0x000}, + {d68000_dbra , 0xfff8, 0x51c8, 0x000}, + {d68000_divs , 0xf1c0, 0x81c0, 0xbff}, + {d68000_divu , 0xf1c0, 0x80c0, 0xbff}, + {d68020_divl , 0xffc0, 0x4c40, 0xbff}, + {d68000_eor_8 , 0xf1c0, 0xb100, 0xbf8}, + {d68000_eor_16 , 0xf1c0, 0xb140, 0xbf8}, + {d68000_eor_32 , 0xf1c0, 0xb180, 0xbf8}, + {d68000_eori_to_ccr , 0xffff, 0x0a3c, 0x000}, + {d68000_eori_to_sr , 0xffff, 0x0a7c, 0x000}, + {d68000_eori_8 , 0xffc0, 0x0a00, 0xbf8}, + {d68000_eori_16 , 0xffc0, 0x0a40, 0xbf8}, + {d68000_eori_32 , 0xffc0, 0x0a80, 0xbf8}, + {d68000_exg_dd , 0xf1f8, 0xc140, 0x000}, + {d68000_exg_aa , 0xf1f8, 0xc148, 0x000}, + {d68000_exg_da , 0xf1f8, 0xc188, 0x000}, + {d68020_extb_32 , 0xfff8, 0x49c0, 0x000}, + {d68000_ext_16 , 0xfff8, 0x4880, 0x000}, + {d68000_ext_32 , 0xfff8, 0x48c0, 0x000}, + {d68040_fpu , 0xffc0, 0xf200, 0x000}, + {d68000_illegal , 0xffff, 0x4afc, 0x000}, + {d68000_jmp , 0xffc0, 0x4ec0, 0x27b}, + {d68000_jsr , 0xffc0, 0x4e80, 0x27b}, + {d68000_lea , 0xf1c0, 0x41c0, 0x27b}, + {d68000_link_16 , 0xfff8, 0x4e50, 0x000}, + {d68020_link_32 , 0xfff8, 0x4808, 0x000}, + {d68000_lsr_s_8 , 0xf1f8, 0xe008, 0x000}, + {d68000_lsr_s_16 , 0xf1f8, 0xe048, 0x000}, + {d68000_lsr_s_32 , 0xf1f8, 0xe088, 0x000}, + {d68000_lsr_r_8 , 0xf1f8, 0xe028, 0x000}, + {d68000_lsr_r_16 , 0xf1f8, 0xe068, 0x000}, + {d68000_lsr_r_32 , 0xf1f8, 0xe0a8, 0x000}, + {d68000_lsr_ea , 0xffc0, 0xe2c0, 0x3f8}, + {d68000_lsl_s_8 , 0xf1f8, 0xe108, 0x000}, + {d68000_lsl_s_16 , 0xf1f8, 0xe148, 0x000}, + {d68000_lsl_s_32 , 0xf1f8, 0xe188, 0x000}, + {d68000_lsl_r_8 , 0xf1f8, 0xe128, 0x000}, + {d68000_lsl_r_16 , 0xf1f8, 0xe168, 0x000}, + {d68000_lsl_r_32 , 0xf1f8, 0xe1a8, 0x000}, + {d68000_lsl_ea , 0xffc0, 0xe3c0, 0x3f8}, + {d68000_move_8 , 0xf000, 0x1000, 0xbff}, + {d68000_move_16 , 0xf000, 0x3000, 0xfff}, + {d68000_move_32 , 0xf000, 0x2000, 0xfff}, + {d68000_movea_16 , 0xf1c0, 0x3040, 0xfff}, + {d68000_movea_32 , 0xf1c0, 0x2040, 0xfff}, + {d68000_move_to_ccr , 0xffc0, 0x44c0, 0xbff}, + {d68010_move_fr_ccr , 0xffc0, 0x42c0, 0xbf8}, + {d68000_move_to_sr , 0xffc0, 0x46c0, 0xbff}, + {d68000_move_fr_sr , 0xffc0, 0x40c0, 0xbf8}, + {d68000_move_to_usp , 0xfff8, 0x4e60, 0x000}, + {d68000_move_fr_usp , 0xfff8, 0x4e68, 0x000}, + {d68010_movec , 0xfffe, 0x4e7a, 0x000}, + {d68000_movem_pd_16 , 0xfff8, 0x48a0, 0x000}, + {d68000_movem_pd_32 , 0xfff8, 0x48e0, 0x000}, + {d68000_movem_re_16 , 0xffc0, 0x4880, 0x2f8}, + {d68000_movem_re_32 , 0xffc0, 0x48c0, 0x2f8}, + {d68000_movem_er_16 , 0xffc0, 0x4c80, 0x37b}, + {d68000_movem_er_32 , 0xffc0, 0x4cc0, 0x37b}, + {d68000_movep_er_16 , 0xf1f8, 0x0108, 0x000}, + {d68000_movep_er_32 , 0xf1f8, 0x0148, 0x000}, + {d68000_movep_re_16 , 0xf1f8, 0x0188, 0x000}, + {d68000_movep_re_32 , 0xf1f8, 0x01c8, 0x000}, + {d68010_moves_8 , 0xffc0, 0x0e00, 0x3f8}, + {d68010_moves_16 , 0xffc0, 0x0e40, 0x3f8}, + {d68010_moves_32 , 0xffc0, 0x0e80, 0x3f8}, + {d68000_moveq , 0xf100, 0x7000, 0x000}, + {d68040_move16_pi_pi , 0xfff8, 0xf620, 0x000}, + {d68040_move16_pi_al , 0xfff8, 0xf600, 0x000}, + {d68040_move16_al_pi , 0xfff8, 0xf608, 0x000}, + {d68040_move16_ai_al , 0xfff8, 0xf610, 0x000}, + {d68040_move16_al_ai , 0xfff8, 0xf618, 0x000}, + {d68000_muls , 0xf1c0, 0xc1c0, 0xbff}, + {d68000_mulu , 0xf1c0, 0xc0c0, 0xbff}, + {d68020_mull , 0xffc0, 0x4c00, 0xbff}, + {d68000_nbcd , 0xffc0, 0x4800, 0xbf8}, + {d68000_neg_8 , 0xffc0, 0x4400, 0xbf8}, + {d68000_neg_16 , 0xffc0, 0x4440, 0xbf8}, + {d68000_neg_32 , 0xffc0, 0x4480, 0xbf8}, + {d68000_negx_8 , 0xffc0, 0x4000, 0xbf8}, + {d68000_negx_16 , 0xffc0, 0x4040, 0xbf8}, + {d68000_negx_32 , 0xffc0, 0x4080, 0xbf8}, + {d68000_nop , 0xffff, 0x4e71, 0x000}, + {d68000_not_8 , 0xffc0, 0x4600, 0xbf8}, + {d68000_not_16 , 0xffc0, 0x4640, 0xbf8}, + {d68000_not_32 , 0xffc0, 0x4680, 0xbf8}, + {d68000_or_er_8 , 0xf1c0, 0x8000, 0xbff}, + {d68000_or_er_16 , 0xf1c0, 0x8040, 0xbff}, + {d68000_or_er_32 , 0xf1c0, 0x8080, 0xbff}, + {d68000_or_re_8 , 0xf1c0, 0x8100, 0x3f8}, + {d68000_or_re_16 , 0xf1c0, 0x8140, 0x3f8}, + {d68000_or_re_32 , 0xf1c0, 0x8180, 0x3f8}, + {d68000_ori_to_ccr , 0xffff, 0x003c, 0x000}, + {d68000_ori_to_sr , 0xffff, 0x007c, 0x000}, + {d68000_ori_8 , 0xffc0, 0x0000, 0xbf8}, + {d68000_ori_16 , 0xffc0, 0x0040, 0xbf8}, + {d68000_ori_32 , 0xffc0, 0x0080, 0xbf8}, + {d68020_pack_rr , 0xf1f8, 0x8140, 0x000}, + {d68020_pack_mm , 0xf1f8, 0x8148, 0x000}, + {d68000_pea , 0xffc0, 0x4840, 0x27b}, + {d68040_pflush , 0xffe0, 0xf500, 0x000}, + {d68000_reset , 0xffff, 0x4e70, 0x000}, + {d68000_ror_s_8 , 0xf1f8, 0xe018, 0x000}, + {d68000_ror_s_16 , 0xf1f8, 0xe058, 0x000}, + {d68000_ror_s_32 , 0xf1f8, 0xe098, 0x000}, + {d68000_ror_r_8 , 0xf1f8, 0xe038, 0x000}, + {d68000_ror_r_16 , 0xf1f8, 0xe078, 0x000}, + {d68000_ror_r_32 , 0xf1f8, 0xe0b8, 0x000}, + {d68000_ror_ea , 0xffc0, 0xe6c0, 0x3f8}, + {d68000_rol_s_8 , 0xf1f8, 0xe118, 0x000}, + {d68000_rol_s_16 , 0xf1f8, 0xe158, 0x000}, + {d68000_rol_s_32 , 0xf1f8, 0xe198, 0x000}, + {d68000_rol_r_8 , 0xf1f8, 0xe138, 0x000}, + {d68000_rol_r_16 , 0xf1f8, 0xe178, 0x000}, + {d68000_rol_r_32 , 0xf1f8, 0xe1b8, 0x000}, + {d68000_rol_ea , 0xffc0, 0xe7c0, 0x3f8}, + {d68000_roxr_s_8 , 0xf1f8, 0xe010, 0x000}, + {d68000_roxr_s_16 , 0xf1f8, 0xe050, 0x000}, + {d68000_roxr_s_32 , 0xf1f8, 0xe090, 0x000}, + {d68000_roxr_r_8 , 0xf1f8, 0xe030, 0x000}, + {d68000_roxr_r_16 , 0xf1f8, 0xe070, 0x000}, + {d68000_roxr_r_32 , 0xf1f8, 0xe0b0, 0x000}, + {d68000_roxr_ea , 0xffc0, 0xe4c0, 0x3f8}, + {d68000_roxl_s_8 , 0xf1f8, 0xe110, 0x000}, + {d68000_roxl_s_16 , 0xf1f8, 0xe150, 0x000}, + {d68000_roxl_s_32 , 0xf1f8, 0xe190, 0x000}, + {d68000_roxl_r_8 , 0xf1f8, 0xe130, 0x000}, + {d68000_roxl_r_16 , 0xf1f8, 0xe170, 0x000}, + {d68000_roxl_r_32 , 0xf1f8, 0xe1b0, 0x000}, + {d68000_roxl_ea , 0xffc0, 0xe5c0, 0x3f8}, + {d68010_rtd , 0xffff, 0x4e74, 0x000}, + {d68000_rte , 0xffff, 0x4e73, 0x000}, + {d68020_rtm , 0xfff0, 0x06c0, 0x000}, + {d68000_rtr , 0xffff, 0x4e77, 0x000}, + {d68000_rts , 0xffff, 0x4e75, 0x000}, + {d68000_sbcd_rr , 0xf1f8, 0x8100, 0x000}, + {d68000_sbcd_mm , 0xf1f8, 0x8108, 0x000}, + {d68000_scc , 0xf0c0, 0x50c0, 0xbf8}, + {d68000_stop , 0xffff, 0x4e72, 0x000}, + {d68000_sub_er_8 , 0xf1c0, 0x9000, 0xbff}, + {d68000_sub_er_16 , 0xf1c0, 0x9040, 0xfff}, + {d68000_sub_er_32 , 0xf1c0, 0x9080, 0xfff}, + {d68000_sub_re_8 , 0xf1c0, 0x9100, 0x3f8}, + {d68000_sub_re_16 , 0xf1c0, 0x9140, 0x3f8}, + {d68000_sub_re_32 , 0xf1c0, 0x9180, 0x3f8}, + {d68000_suba_16 , 0xf1c0, 0x90c0, 0xfff}, + {d68000_suba_32 , 0xf1c0, 0x91c0, 0xfff}, + {d68000_subi_8 , 0xffc0, 0x0400, 0xbf8}, + {d68000_subi_16 , 0xffc0, 0x0440, 0xbf8}, + {d68000_subi_32 , 0xffc0, 0x0480, 0xbf8}, + {d68000_subq_8 , 0xf1c0, 0x5100, 0xbf8}, + {d68000_subq_16 , 0xf1c0, 0x5140, 0xff8}, + {d68000_subq_32 , 0xf1c0, 0x5180, 0xff8}, + {d68000_subx_rr_8 , 0xf1f8, 0x9100, 0x000}, + {d68000_subx_rr_16 , 0xf1f8, 0x9140, 0x000}, + {d68000_subx_rr_32 , 0xf1f8, 0x9180, 0x000}, + {d68000_subx_mm_8 , 0xf1f8, 0x9108, 0x000}, + {d68000_subx_mm_16 , 0xf1f8, 0x9148, 0x000}, + {d68000_subx_mm_32 , 0xf1f8, 0x9188, 0x000}, + {d68000_swap , 0xfff8, 0x4840, 0x000}, + {d68000_tas , 0xffc0, 0x4ac0, 0xbf8}, + {d68000_trap , 0xfff0, 0x4e40, 0x000}, + {d68020_trapcc_0 , 0xf0ff, 0x50fc, 0x000}, + {d68020_trapcc_16 , 0xf0ff, 0x50fa, 0x000}, + {d68020_trapcc_32 , 0xf0ff, 0x50fb, 0x000}, + {d68000_trapv , 0xffff, 0x4e76, 0x000}, + {d68000_tst_8 , 0xffc0, 0x4a00, 0xbf8}, + {d68020_tst_pcdi_8 , 0xffff, 0x4a3a, 0x000}, + {d68020_tst_pcix_8 , 0xffff, 0x4a3b, 0x000}, + {d68020_tst_i_8 , 0xffff, 0x4a3c, 0x000}, + {d68000_tst_16 , 0xffc0, 0x4a40, 0xbf8}, + {d68020_tst_a_16 , 0xfff8, 0x4a48, 0x000}, + {d68020_tst_pcdi_16 , 0xffff, 0x4a7a, 0x000}, + {d68020_tst_pcix_16 , 0xffff, 0x4a7b, 0x000}, + {d68020_tst_i_16 , 0xffff, 0x4a7c, 0x000}, + {d68000_tst_32 , 0xffc0, 0x4a80, 0xbf8}, + {d68020_tst_a_32 , 0xfff8, 0x4a88, 0x000}, + {d68020_tst_pcdi_32 , 0xffff, 0x4aba, 0x000}, + {d68020_tst_pcix_32 , 0xffff, 0x4abb, 0x000}, + {d68020_tst_i_32 , 0xffff, 0x4abc, 0x000}, + {d68000_unlk , 0xfff8, 0x4e58, 0x000}, + {d68020_unpk_rr , 0xf1f8, 0x8180, 0x000}, + {d68020_unpk_mm , 0xf1f8, 0x8188, 0x000}, + {d68851_p000 , 0xffc0, 0xf000, 0x000}, + {d68851_pbcc16 , 0xffc0, 0xf080, 0x000}, + {d68851_pbcc32 , 0xffc0, 0xf0c0, 0x000}, + {d68851_pdbcc , 0xfff8, 0xf048, 0x000}, + {d68851_p001 , 0xffc0, 0xf040, 0x000}, + {0, 0, 0, 0} }; /* Check if opcode is using a valid ea mode */ static int valid_ea(uint opcode, uint mask) { - if(mask == 0) - return 1; + if(mask == 0) + return 1; - switch(opcode & 0x3f) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - return (mask & 0x800) != 0; - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - return (mask & 0x400) != 0; - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x14: case 0x15: case 0x16: case 0x17: - return (mask & 0x200) != 0; - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - return (mask & 0x100) != 0; - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - return (mask & 0x080) != 0; - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - return (mask & 0x040) != 0; - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: - return (mask & 0x020) != 0; - case 0x38: - return (mask & 0x010) != 0; - case 0x39: - return (mask & 0x008) != 0; - case 0x3a: - return (mask & 0x002) != 0; - case 0x3b: - return (mask & 0x001) != 0; - case 0x3c: - return (mask & 0x004) != 0; - } - return 0; + switch(opcode & 0x3f) + { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + return (mask & 0x800) != 0; + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + return (mask & 0x400) != 0; + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + return (mask & 0x200) != 0; + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + return (mask & 0x100) != 0; + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + return (mask & 0x080) != 0; + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + return (mask & 0x040) != 0; + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + return (mask & 0x020) != 0; + case 0x38: + return (mask & 0x010) != 0; + case 0x39: + return (mask & 0x008) != 0; + case 0x3a: + return (mask & 0x002) != 0; + case 0x3b: + return (mask & 0x001) != 0; + case 0x3c: + return (mask & 0x004) != 0; + } + return 0; } /* Used by qsort */ static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr) { - uint a = ((const opcode_struct*)aptr)->mask; - uint b = ((const opcode_struct*)bptr)->mask; + uint a = ((const opcode_struct*)aptr)->mask; + uint b = ((const opcode_struct*)bptr)->mask; - a = ((a & 0xAAAA) >> 1) + (a & 0x5555); - a = ((a & 0xCCCC) >> 2) + (a & 0x3333); - a = ((a & 0xF0F0) >> 4) + (a & 0x0F0F); - a = ((a & 0xFF00) >> 8) + (a & 0x00FF); + a = ((a & 0xAAAA) >> 1) + (a & 0x5555); + a = ((a & 0xCCCC) >> 2) + (a & 0x3333); + a = ((a & 0xF0F0) >> 4) + (a & 0x0F0F); + a = ((a & 0xFF00) >> 8) + (a & 0x00FF); - b = ((b & 0xAAAA) >> 1) + (b & 0x5555); - b = ((b & 0xCCCC) >> 2) + (b & 0x3333); - b = ((b & 0xF0F0) >> 4) + (b & 0x0F0F); - b = ((b & 0xFF00) >> 8) + (b & 0x00FF); + b = ((b & 0xAAAA) >> 1) + (b & 0x5555); + b = ((b & 0xCCCC) >> 2) + (b & 0x3333); + b = ((b & 0xF0F0) >> 4) + (b & 0x0F0F); + b = ((b & 0xFF00) >> 8) + (b & 0x00FF); - return b - a; /* reversed to get greatest to least sorting */ + return b - a; /* reversed to get greatest to least sorting */ } /* build the opcode handler jump table */ static void build_opcode_table(void) { - uint i; - uint opcode; - opcode_struct* ostruct; - opcode_struct opcode_info[ARRAY_LENGTH(g_opcode_info)]; + uint i; + uint opcode; + opcode_struct* ostruct; + opcode_struct opcode_info[ARRAY_LENGTH(g_opcode_info)]; - memcpy(opcode_info, g_opcode_info, sizeof(g_opcode_info)); - qsort((void *)opcode_info, ARRAY_LENGTH(opcode_info)-1, sizeof(opcode_info[0]), compare_nof_true_bits); + memcpy(opcode_info, g_opcode_info, sizeof(g_opcode_info)); + qsort((void *)opcode_info, ARRAY_LENGTH(opcode_info)-1, sizeof(opcode_info[0]), compare_nof_true_bits); - for(i=0;i<0x10000;i++) - { - g_instruction_table[i] = d68000_illegal; /* default to illegal */ - opcode = i; - /* search through opcode info for a match */ - for(ostruct = opcode_info;ostruct->opcode_handler != 0;ostruct++) - { - /* match opcode mask and allowed ea modes */ - if((opcode & ostruct->mask) == ostruct->match) - { - /* Handle destination ea for move instructions */ - if((ostruct->opcode_handler == d68000_move_8 || - ostruct->opcode_handler == d68000_move_16 || - ostruct->opcode_handler == d68000_move_32) && - !valid_ea(((opcode>>9)&7) | ((opcode>>3)&0x38), 0xbf8)) - continue; - if(valid_ea(opcode, ostruct->ea_mask)) - { - g_instruction_table[i] = ostruct->opcode_handler; - break; - } - } - } - } + for(i=0;i<0x10000;i++) + { + g_instruction_table[i] = d68000_illegal; /* default to illegal */ + opcode = i; + /* search through opcode info for a match */ + for(ostruct = opcode_info;ostruct->opcode_handler != 0;ostruct++) + { + /* match opcode mask and allowed ea modes */ + if((opcode & ostruct->mask) == ostruct->match) + { + /* Handle destination ea for move instructions */ + if((ostruct->opcode_handler == d68000_move_8 || + ostruct->opcode_handler == d68000_move_16 || + ostruct->opcode_handler == d68000_move_32) && + !valid_ea(((opcode>>9)&7) | ((opcode>>3)&0x38), 0xbf8)) + continue; + if(valid_ea(opcode, ostruct->ea_mask)) + { + g_instruction_table[i] = ostruct->opcode_handler; + break; + } + } + } + } } @@ -3724,277 +3724,277 @@ static void build_opcode_table(void) /* Disasemble one instruction at pc and store in str_buff */ unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type) { - if(!g_initialized) - { - build_opcode_table(); - g_initialized = 1; - } - switch(cpu_type) - { - case M68K_CPU_TYPE_68000: - g_cpu_type = TYPE_68000; - g_address_mask = 0x00ffffff; - break; - case M68K_CPU_TYPE_68010: - g_cpu_type = TYPE_68010; - g_address_mask = 0x00ffffff; - break; - case M68K_CPU_TYPE_68EC020: - g_cpu_type = TYPE_68020; - g_address_mask = 0x00ffffff; - break; - case M68K_CPU_TYPE_68020: - g_cpu_type = TYPE_68020; - g_address_mask = 0xffffffff; - break; - case M68K_CPU_TYPE_68EC030: - case M68K_CPU_TYPE_68030: - g_cpu_type = TYPE_68030; - g_address_mask = 0xffffffff; - break; - case M68K_CPU_TYPE_68040: - case M68K_CPU_TYPE_68EC040: - case M68K_CPU_TYPE_68LC040: - g_cpu_type = TYPE_68040; - g_address_mask = 0xffffffff; - break; - default: - return 0; - } + if(!g_initialized) + { + build_opcode_table(); + g_initialized = 1; + } + switch(cpu_type) + { + case M68K_CPU_TYPE_68000: + g_cpu_type = TYPE_68000; + g_address_mask = 0x00ffffff; + break; + case M68K_CPU_TYPE_68010: + g_cpu_type = TYPE_68010; + g_address_mask = 0x00ffffff; + break; + case M68K_CPU_TYPE_68EC020: + g_cpu_type = TYPE_68020; + g_address_mask = 0x00ffffff; + break; + case M68K_CPU_TYPE_68020: + g_cpu_type = TYPE_68020; + g_address_mask = 0xffffffff; + break; + case M68K_CPU_TYPE_68EC030: + case M68K_CPU_TYPE_68030: + g_cpu_type = TYPE_68030; + g_address_mask = 0xffffffff; + break; + case M68K_CPU_TYPE_68040: + case M68K_CPU_TYPE_68EC040: + case M68K_CPU_TYPE_68LC040: + g_cpu_type = TYPE_68040; + g_address_mask = 0xffffffff; + break; + default: + return 0; + } - g_cpu_pc = pc; - g_helper_str[0] = 0; - g_cpu_ir = read_imm_16(); - g_opcode_type = 0; - g_instruction_table[g_cpu_ir](); - sprintf(str_buff, "%s%s", g_dasm_str, g_helper_str); - return COMBINE_OPCODE_FLAGS(g_cpu_pc - pc); + g_cpu_pc = pc; + g_helper_str[0] = 0; + g_cpu_ir = read_imm_16(); + g_opcode_type = 0; + g_instruction_table[g_cpu_ir](); + sprintf(str_buff, "%s%s", g_dasm_str, g_helper_str); + return COMBINE_OPCODE_FLAGS(g_cpu_pc - pc); } char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type) { - static char buff[100]; - buff[0] = 0; - m68k_disassemble(buff, pc, cpu_type); - return buff; + static char buff[100]; + buff[0] = 0; + m68k_disassemble(buff, pc, cpu_type); + return buff; } unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type) { - unsigned int result; - (void)argdata; + unsigned int result; + (void)argdata; - g_rawop = opdata; - g_rawbasepc = pc; - result = m68k_disassemble(str_buff, pc, cpu_type); - g_rawop = NULL; - return result; + g_rawop = opdata; + g_rawbasepc = pc; + result = m68k_disassemble(str_buff, pc, cpu_type); + g_rawop = NULL; + return result; } /* Check if the instruction is a valid one */ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type) { - if(!g_initialized) - { - build_opcode_table(); - g_initialized = 1; - } + if(!g_initialized) + { + build_opcode_table(); + g_initialized = 1; + } - instruction &= 0xffff; - if(g_instruction_table[instruction] == d68000_illegal) - return 0; + instruction &= 0xffff; + if(g_instruction_table[instruction] == d68000_illegal) + return 0; - switch(cpu_type) - { - case M68K_CPU_TYPE_68000: - if(g_instruction_table[instruction] == d68010_bkpt) - return 0; - if(g_instruction_table[instruction] == d68010_move_fr_ccr) - return 0; - if(g_instruction_table[instruction] == d68010_movec) - return 0; - if(g_instruction_table[instruction] == d68010_moves_8) - return 0; - if(g_instruction_table[instruction] == d68010_moves_16) - return 0; - if(g_instruction_table[instruction] == d68010_moves_32) - return 0; - if(g_instruction_table[instruction] == d68010_rtd) - return 0; - // Fallthrough - case M68K_CPU_TYPE_68010: - if(g_instruction_table[instruction] == d68020_bcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_bfchg) - return 0; - if(g_instruction_table[instruction] == d68020_bfclr) - return 0; - if(g_instruction_table[instruction] == d68020_bfexts) - return 0; - if(g_instruction_table[instruction] == d68020_bfextu) - return 0; - if(g_instruction_table[instruction] == d68020_bfffo) - return 0; - if(g_instruction_table[instruction] == d68020_bfins) - return 0; - if(g_instruction_table[instruction] == d68020_bfset) - return 0; - if(g_instruction_table[instruction] == d68020_bftst) - return 0; - if(g_instruction_table[instruction] == d68020_bra_32) - return 0; - if(g_instruction_table[instruction] == d68020_bsr_32) - return 0; - if(g_instruction_table[instruction] == d68020_callm) - return 0; - if(g_instruction_table[instruction] == d68020_cas_8) - return 0; - if(g_instruction_table[instruction] == d68020_cas_16) - return 0; - if(g_instruction_table[instruction] == d68020_cas_32) - return 0; - if(g_instruction_table[instruction] == d68020_cas2_16) - return 0; - if(g_instruction_table[instruction] == d68020_cas2_32) - return 0; - if(g_instruction_table[instruction] == d68020_chk_32) - return 0; - if(g_instruction_table[instruction] == d68020_chk2_cmp2_8) - return 0; - if(g_instruction_table[instruction] == d68020_chk2_cmp2_16) - return 0; - if(g_instruction_table[instruction] == d68020_chk2_cmp2_32) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcdi_8) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcix_8) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcdi_16) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcix_16) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcdi_32) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcix_32) - return 0; - if(g_instruction_table[instruction] == d68020_cpbcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_cpbcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_cpdbcc) - return 0; - if(g_instruction_table[instruction] == d68020_cpgen) - return 0; - if(g_instruction_table[instruction] == d68020_cprestore) - return 0; - if(g_instruction_table[instruction] == d68020_cpsave) - return 0; - if(g_instruction_table[instruction] == d68020_cpscc) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_0) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_divl) - return 0; - if(g_instruction_table[instruction] == d68020_extb_32) - return 0; - if(g_instruction_table[instruction] == d68020_link_32) - return 0; - if(g_instruction_table[instruction] == d68020_mull) - return 0; - if(g_instruction_table[instruction] == d68020_pack_rr) - return 0; - if(g_instruction_table[instruction] == d68020_pack_mm) - return 0; - if(g_instruction_table[instruction] == d68020_rtm) - return 0; - if(g_instruction_table[instruction] == d68020_trapcc_0) - return 0; - if(g_instruction_table[instruction] == d68020_trapcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_trapcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcdi_8) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcix_8) - return 0; - if(g_instruction_table[instruction] == d68020_tst_i_8) - return 0; - if(g_instruction_table[instruction] == d68020_tst_a_16) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcdi_16) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcix_16) - return 0; - if(g_instruction_table[instruction] == d68020_tst_i_16) - return 0; - if(g_instruction_table[instruction] == d68020_tst_a_32) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcdi_32) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcix_32) - return 0; - if(g_instruction_table[instruction] == d68020_tst_i_32) - return 0; - if(g_instruction_table[instruction] == d68020_unpk_rr) - return 0; - if(g_instruction_table[instruction] == d68020_unpk_mm) - return 0; - // Fallthrough - case M68K_CPU_TYPE_68EC020: - case M68K_CPU_TYPE_68020: - case M68K_CPU_TYPE_68030: - case M68K_CPU_TYPE_68EC030: - if(g_instruction_table[instruction] == d68040_cinv) - return 0; - if(g_instruction_table[instruction] == d68040_cpush) - return 0; - if(g_instruction_table[instruction] == d68040_move16_pi_pi) - return 0; - if(g_instruction_table[instruction] == d68040_move16_pi_al) - return 0; - if(g_instruction_table[instruction] == d68040_move16_al_pi) - return 0; - if(g_instruction_table[instruction] == d68040_move16_ai_al) - return 0; - if(g_instruction_table[instruction] == d68040_move16_al_ai) - return 0; - // Fallthrough - case M68K_CPU_TYPE_68040: - case M68K_CPU_TYPE_68EC040: - case M68K_CPU_TYPE_68LC040: - if(g_instruction_table[instruction] == d68020_cpbcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_cpbcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_cpdbcc) - return 0; - if(g_instruction_table[instruction] == d68020_cpgen) - return 0; - if(g_instruction_table[instruction] == d68020_cprestore) - return 0; - if(g_instruction_table[instruction] == d68020_cpsave) - return 0; - if(g_instruction_table[instruction] == d68020_cpscc) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_0) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_32) - return 0; - if(g_instruction_table[instruction] == d68040_pflush) - return 0; - } - if(cpu_type != M68K_CPU_TYPE_68020 && cpu_type != M68K_CPU_TYPE_68EC020 && - (g_instruction_table[instruction] == d68020_callm || - g_instruction_table[instruction] == d68020_rtm)) - return 0; + switch(cpu_type) + { + case M68K_CPU_TYPE_68000: + if(g_instruction_table[instruction] == d68010_bkpt) + return 0; + if(g_instruction_table[instruction] == d68010_move_fr_ccr) + return 0; + if(g_instruction_table[instruction] == d68010_movec) + return 0; + if(g_instruction_table[instruction] == d68010_moves_8) + return 0; + if(g_instruction_table[instruction] == d68010_moves_16) + return 0; + if(g_instruction_table[instruction] == d68010_moves_32) + return 0; + if(g_instruction_table[instruction] == d68010_rtd) + return 0; + // Fallthrough + case M68K_CPU_TYPE_68010: + if(g_instruction_table[instruction] == d68020_bcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_bfchg) + return 0; + if(g_instruction_table[instruction] == d68020_bfclr) + return 0; + if(g_instruction_table[instruction] == d68020_bfexts) + return 0; + if(g_instruction_table[instruction] == d68020_bfextu) + return 0; + if(g_instruction_table[instruction] == d68020_bfffo) + return 0; + if(g_instruction_table[instruction] == d68020_bfins) + return 0; + if(g_instruction_table[instruction] == d68020_bfset) + return 0; + if(g_instruction_table[instruction] == d68020_bftst) + return 0; + if(g_instruction_table[instruction] == d68020_bra_32) + return 0; + if(g_instruction_table[instruction] == d68020_bsr_32) + return 0; + if(g_instruction_table[instruction] == d68020_callm) + return 0; + if(g_instruction_table[instruction] == d68020_cas_8) + return 0; + if(g_instruction_table[instruction] == d68020_cas_16) + return 0; + if(g_instruction_table[instruction] == d68020_cas_32) + return 0; + if(g_instruction_table[instruction] == d68020_cas2_16) + return 0; + if(g_instruction_table[instruction] == d68020_cas2_32) + return 0; + if(g_instruction_table[instruction] == d68020_chk_32) + return 0; + if(g_instruction_table[instruction] == d68020_chk2_cmp2_8) + return 0; + if(g_instruction_table[instruction] == d68020_chk2_cmp2_16) + return 0; + if(g_instruction_table[instruction] == d68020_chk2_cmp2_32) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcdi_8) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcix_8) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcdi_16) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcix_16) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcdi_32) + return 0; + if(g_instruction_table[instruction] == d68020_cmpi_pcix_32) + return 0; + if(g_instruction_table[instruction] == d68020_cpbcc_16) + return 0; + if(g_instruction_table[instruction] == d68020_cpbcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_cpdbcc) + return 0; + if(g_instruction_table[instruction] == d68020_cpgen) + return 0; + if(g_instruction_table[instruction] == d68020_cprestore) + return 0; + if(g_instruction_table[instruction] == d68020_cpsave) + return 0; + if(g_instruction_table[instruction] == d68020_cpscc) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_0) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_16) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_divl) + return 0; + if(g_instruction_table[instruction] == d68020_extb_32) + return 0; + if(g_instruction_table[instruction] == d68020_link_32) + return 0; + if(g_instruction_table[instruction] == d68020_mull) + return 0; + if(g_instruction_table[instruction] == d68020_pack_rr) + return 0; + if(g_instruction_table[instruction] == d68020_pack_mm) + return 0; + if(g_instruction_table[instruction] == d68020_rtm) + return 0; + if(g_instruction_table[instruction] == d68020_trapcc_0) + return 0; + if(g_instruction_table[instruction] == d68020_trapcc_16) + return 0; + if(g_instruction_table[instruction] == d68020_trapcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcdi_8) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcix_8) + return 0; + if(g_instruction_table[instruction] == d68020_tst_i_8) + return 0; + if(g_instruction_table[instruction] == d68020_tst_a_16) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcdi_16) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcix_16) + return 0; + if(g_instruction_table[instruction] == d68020_tst_i_16) + return 0; + if(g_instruction_table[instruction] == d68020_tst_a_32) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcdi_32) + return 0; + if(g_instruction_table[instruction] == d68020_tst_pcix_32) + return 0; + if(g_instruction_table[instruction] == d68020_tst_i_32) + return 0; + if(g_instruction_table[instruction] == d68020_unpk_rr) + return 0; + if(g_instruction_table[instruction] == d68020_unpk_mm) + return 0; + // Fallthrough + case M68K_CPU_TYPE_68EC020: + case M68K_CPU_TYPE_68020: + case M68K_CPU_TYPE_68030: + case M68K_CPU_TYPE_68EC030: + if(g_instruction_table[instruction] == d68040_cinv) + return 0; + if(g_instruction_table[instruction] == d68040_cpush) + return 0; + if(g_instruction_table[instruction] == d68040_move16_pi_pi) + return 0; + if(g_instruction_table[instruction] == d68040_move16_pi_al) + return 0; + if(g_instruction_table[instruction] == d68040_move16_al_pi) + return 0; + if(g_instruction_table[instruction] == d68040_move16_ai_al) + return 0; + if(g_instruction_table[instruction] == d68040_move16_al_ai) + return 0; + // Fallthrough + case M68K_CPU_TYPE_68040: + case M68K_CPU_TYPE_68EC040: + case M68K_CPU_TYPE_68LC040: + if(g_instruction_table[instruction] == d68020_cpbcc_16) + return 0; + if(g_instruction_table[instruction] == d68020_cpbcc_32) + return 0; + if(g_instruction_table[instruction] == d68020_cpdbcc) + return 0; + if(g_instruction_table[instruction] == d68020_cpgen) + return 0; + if(g_instruction_table[instruction] == d68020_cprestore) + return 0; + if(g_instruction_table[instruction] == d68020_cpsave) + return 0; + if(g_instruction_table[instruction] == d68020_cpscc) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_0) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_16) + return 0; + if(g_instruction_table[instruction] == d68020_cptrapcc_32) + return 0; + if(g_instruction_table[instruction] == d68040_pflush) + return 0; + } + if(cpu_type != M68K_CPU_TYPE_68020 && cpu_type != M68K_CPU_TYPE_68EC020 && + (g_instruction_table[instruction] == d68020_callm || + g_instruction_table[instruction] == d68020_rtm)) + return 0; - return 1; + return 1; } // f028 2215 0008 diff --git a/AltairZ80/m68k/m68kfpu.c b/AltairZ80/m68k/m68kfpu.c index dd39aa8a..0d0973e0 100644 --- a/AltairZ80/m68k/m68kfpu.c +++ b/AltairZ80/m68k/m68kfpu.c @@ -1,1769 +1,1769 @@ -#include -#include -#include - -extern void exit(int); - -static void fatalerror(const char *format, ...) { - va_list ap; - va_start(ap,format); - vfprintf(stderr,format,ap); // JFF: fixed. Was using fprintf and arguments were wrong - va_end(ap); - exit(1); -} - -#define FPCC_N 0x08000000 -#define FPCC_Z 0x04000000 -#define FPCC_I 0x02000000 -#define FPCC_NAN 0x01000000 - -#define DOUBLE_INFINITY (unsigned long long)(0x7ff0000000000000) -#define DOUBLE_EXPONENT (unsigned long long)(0x7ff0000000000000) -#define DOUBLE_MANTISSA (unsigned long long)(0x000fffffffffffff) - -extern flag floatx80_is_nan( floatx80 a ); - -// masks for packed dwords, positive k-factor -static uint32 pkmask2[18] = -{ - 0xffffffff, 0, 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, - 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff -}; - -static uint32 pkmask3[18] = -{ - 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, - 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, -}; - -static inline double fx80_to_double(floatx80 fx) -{ - uint64 d; - double *foo; - - foo = (double *)&d; - - d = floatx80_to_float64(fx); - - return *foo; -} - -static inline floatx80 double_to_fx80(double in) -{ - uint64 *d; - - d = (uint64 *)∈ - - return float64_to_floatx80(*d); -} - -static inline floatx80 load_extended_float80(uint32 ea) -{ - uint32 d1,d2; - uint16 d3; - floatx80 fp; - - d3 = m68ki_read_16(ea); - d1 = m68ki_read_32(ea+4); - d2 = m68ki_read_32(ea+8); - - fp.high = d3; - fp.low = ((uint64)d1<<32) | (d2 & 0xffffffff); - - return fp; -} - -static inline void store_extended_float80(uint32 ea, floatx80 fpr) -{ - m68ki_write_16(ea+0, fpr.high); - m68ki_write_16(ea+2, 0); - m68ki_write_32(ea+4, (fpr.low>>32)&0xffffffff); - m68ki_write_32(ea+8, fpr.low&0xffffffff); -} - -static inline floatx80 load_pack_float80(uint32 ea) -{ - uint32 dw1, dw2, dw3; - floatx80 result; - double tmp; - char str[128], *ch; - - dw1 = m68ki_read_32(ea); - dw2 = m68ki_read_32(ea+4); - dw3 = m68ki_read_32(ea+8); - - ch = &str[0]; - if (dw1 & 0x80000000) // mantissa sign - { - *ch++ = '-'; - } - *ch++ = (char)((dw1 & 0xf) + '0'); - *ch++ = '.'; - *ch++ = (char)(((dw2 >> 28) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 24) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 20) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 16) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 12) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 8) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 4) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 0) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 28) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 24) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 20) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 16) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 12) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 8) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 4) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 0) & 0xf) + '0'); - *ch++ = 'E'; - if (dw1 & 0x40000000) // exponent sign - { - *ch++ = '-'; - } - *ch++ = (char)(((dw1 >> 24) & 0xf) + '0'); - *ch++ = (char)(((dw1 >> 20) & 0xf) + '0'); - *ch++ = (char)(((dw1 >> 16) & 0xf) + '0'); - *ch = '\0'; - - sscanf(str, "%le", &tmp); - - result = double_to_fx80(tmp); - - return result; -} - -static inline void store_pack_float80(uint32 ea, int k, floatx80 fpr) -{ - uint32 dw1, dw2, dw3; - char str[128], *ch; - int i, j, exp; - - dw1 = dw2 = dw3 = 0; - ch = &str[0]; - - sprintf(str, "%.16e", fx80_to_double(fpr)); - - if (*ch == '-') - { - ch++; - dw1 = 0x80000000; - } - - if (*ch == '+') - { - ch++; - } - - dw1 |= (*ch++ - '0'); - - if (*ch == '.') - { - ch++; - } - - // handle negative k-factor here - if ((k <= 0) && (k >= -13)) - { - exp = 0; - for (i = 0; i < 3; i++) - { - if (ch[18+i] >= '0' && ch[18+i] <= '9') - { - exp = (exp << 4) | (ch[18+i] - '0'); - } - } - - if (ch[17] == '-') - { - exp = -exp; - } - - k = -k; - // last digit is (k + exponent - 1) - k += (exp - 1); - - // round up the last significant mantissa digit - if (ch[k+1] >= '5') - { - ch[k]++; - } - - // zero out the rest of the mantissa digits - for (j = (k+1); j < 16; j++) - { - ch[j] = '0'; - } - - // now zero out K to avoid tripping the positive K detection below - k = 0; - } - - // crack 8 digits of the mantissa - for (i = 0; i < 8; i++) - { - dw2 <<= 4; - if (*ch >= '0' && *ch <= '9') - { - dw2 |= *ch++ - '0'; - } - } - - // next 8 digits of the mantissa - for (i = 0; i < 8; i++) - { - dw3 <<= 4; - if (*ch >= '0' && *ch <= '9') - dw3 |= *ch++ - '0'; - } - - // handle masking if k is positive - if (k >= 1) - { - if (k <= 17) - { - dw2 &= pkmask2[k]; - dw3 &= pkmask3[k]; - } - else - { - dw2 &= pkmask2[17]; - dw3 &= pkmask3[17]; -// m68ki_cpu.fpcr |= (need to set OPERR bit) - } - } - - // finally, crack the exponent - if (*ch == 'e' || *ch == 'E') - { - ch++; - if (*ch == '-') - { - ch++; - dw1 |= 0x40000000; - } - - if (*ch == '+') - { - ch++; - } - - j = 0; - for (i = 0; i < 3; i++) - { - if (*ch >= '0' && *ch <= '9') - { - j = (j << 4) | (*ch++ - '0'); - } - } - - dw1 |= (j << 16); - } - - m68ki_write_32(ea, dw1); - m68ki_write_32(ea+4, dw2); - m68ki_write_32(ea+8, dw3); -} - -static inline void SET_CONDITION_CODES(floatx80 reg) -{ - REG_FPSR &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN); - - // sign flag - if (reg.high & 0x8000) - { - REG_FPSR |= FPCC_N; - } - - // zero flag - if (((reg.high & 0x7fff) == 0) && ((reg.low<<1) == 0)) - { - REG_FPSR |= FPCC_Z; - } - - // infinity flag - if (((reg.high & 0x7fff) == 0x7fff) && ((reg.low<<1) == 0)) - { - REG_FPSR |= FPCC_I; - } - - // NaN flag - if (floatx80_is_nan(reg)) - { - REG_FPSR |= FPCC_NAN; - } -} - -static inline int TEST_CONDITION(int condition) -{ - int n = (REG_FPSR & FPCC_N) != 0; - int z = (REG_FPSR & FPCC_Z) != 0; - int nan = (REG_FPSR & FPCC_NAN) != 0; - int r = 0; - switch (condition) - { - case 0x10: - case 0x00: return 0; // False - - case 0x11: - case 0x01: return (z); // Equal - - case 0x12: - case 0x02: return (!(nan || z || n)); // Greater Than - - case 0x13: - case 0x03: return (z || !(nan || n)); // Greater or Equal - - case 0x14: - case 0x04: return (n && !(nan || z)); // Less Than - - case 0x15: - case 0x05: return (z || (n && !nan)); // Less Than or Equal - - case 0x16: - case 0x06: return !nan && !z; - - case 0x17: - case 0x07: return !nan; - - case 0x18: - case 0x08: return nan; - - case 0x19: - case 0x09: return nan || z; - - case 0x1a: - case 0x0a: return (nan || !(n || z)); // Not Less Than or Equal - - case 0x1b: - case 0x0b: return (nan || z || !n); // Not Less Than - - case 0x1c: - case 0x0c: return (nan || (n && !z)); // Not Greater or Equal Than - - case 0x1d: - case 0x0d: return (nan || z || n); // Not Greater Than - - case 0x1e: - case 0x0e: return (!z); // Not Equal - - case 0x1f: - case 0x0f: return 1; // True - - default: fatalerror("M68kFPU: test_condition: unhandled condition %02X\n", condition); - } - - return r; -} - -static uint8 READ_EA_8(int ea) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - return REG_D[reg]; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - return m68ki_read_8(ea); - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_8(); - return m68ki_read_8(ea); - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_8(); - return m68ki_read_8(ea); - } - case 7: - { - switch (reg) - { - case 0: // (xxx).W - { - uint32 ea = (uint32)OPER_I_16(); - return m68ki_read_8(ea); - } - case 1: // (xxx).L - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - return m68ki_read_8(ea); - } - case 4: // # - { - return OPER_I_8(); - } - default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - - return 0; -} - -static uint16 READ_EA_16(int ea) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - return (uint16)(REG_D[reg]); - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - return m68ki_read_16(ea); - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_16(); - return m68ki_read_16(ea); - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_16(); - return m68ki_read_16(ea); - } - case 7: - { - switch (reg) - { - case 0: // (xxx).W - { - uint32 ea = (uint32)OPER_I_16(); - return m68ki_read_16(ea); - } - case 1: // (xxx).L - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - return m68ki_read_16(ea); - } - case 4: // # - { - return OPER_I_16(); - } - - default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - - return 0; -} - -static uint32 READ_EA_32(int ea) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - return REG_D[reg]; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - return m68ki_read_32(ea); - } - case 3: // (An)+ - { - uint32 ea = EA_AY_PI_32(); - return m68ki_read_32(ea); - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_32(); - return m68ki_read_32(ea); - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_32(); - return m68ki_read_32(ea); - } - case 7: - { - switch (reg) - { - case 0: // (xxx).W - { - uint32 ea = (uint32)OPER_I_16(); - return m68ki_read_32(ea); - } - case 1: // (xxx).L - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - return m68ki_read_32(ea); - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_32(); - return m68ki_read_32(ea); - } - case 4: // # - { - return OPER_I_32(); - } - default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - return 0; -} - -static uint64 READ_EA_64(int ea) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - uint32 h1, h2; - - switch (mode) - { - case 2: // (An) - { - uint32 ea = REG_A[reg]; - h1 = m68ki_read_32(ea+0); - h2 = m68ki_read_32(ea+4); - return (uint64)(h1) << 32 | (uint64)(h2); - } - case 3: // (An)+ - { - uint32 ea = REG_A[reg]; - REG_A[reg] += 8; - h1 = m68ki_read_32(ea+0); - h2 = m68ki_read_32(ea+4); - return (uint64)(h1) << 32 | (uint64)(h2); - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_32(); - h1 = m68ki_read_32(ea+0); - h2 = m68ki_read_32(ea+4); - return (uint64)(h1) << 32 | (uint64)(h2); - } - case 7: - { - switch (reg) - { - case 4: // # - { - h1 = OPER_I_32(); - h2 = OPER_I_32(); - return (uint64)(h1) << 32 | (uint64)(h2); - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_32(); - h1 = m68ki_read_32(ea+0); - h2 = m68ki_read_32(ea+4); - return (uint64)(h1) << 32 | (uint64)(h2); - } - default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - - return 0; -} - - -static floatx80 READ_EA_FPE(int mode, int reg, uint32 di_mode_ea) -{ - floatx80 fpr; - - switch (mode) - { - case 2: // (An) - { - uint32 ea = REG_A[reg]; - fpr = load_extended_float80(ea); - break; - } - - case 3: // (An)+ - { - uint32 ea = REG_A[reg]; - REG_A[reg] += 12; - fpr = load_extended_float80(ea); - break; - } - case 5: // (d16, An) (added by JFF) - { - fpr = load_extended_float80(di_mode_ea); - break; - - } - case 7: // extended modes - { - switch (reg) - { - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_32(); - fpr = load_extended_float80(ea); - } - break; - - case 3: // (d16,PC,Dx.w) - { - uint32 ea = EA_PCIX_32(); - fpr = load_extended_float80(ea); - } - break; - case 4: // immediate (JFF) - { - uint32 ea = REG_PC; - fpr = load_extended_float80(ea); - REG_PC += 12; - } - break; - default: - fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - break; - } - } - break; - - default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break; - } - - return fpr; -} - -static floatx80 READ_EA_PACK(int ea) -{ - floatx80 fpr; - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 2: // (An) - { - uint32 ea = REG_A[reg]; - fpr = load_pack_float80(ea); - break; - } - - case 3: // (An)+ - { - uint32 ea = REG_A[reg]; - REG_A[reg] += 12; - fpr = load_pack_float80(ea); - break; - } - - case 7: // extended modes - { - switch (reg) - { - case 3: // (d16,PC,Dx.w) - { - uint32 ea = EA_PCIX_32(); - fpr = load_pack_float80(ea); - } - break; - - default: - fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - break; - } - } - break; - - default: fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break; - } - - return fpr; -} - -static void WRITE_EA_8(int ea, uint8 data) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - REG_D[reg] = data; - break; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - m68ki_write_8(ea, data); - break; - } - case 3: // (An)+ - { - uint32 ea = EA_AY_PI_8(); - m68ki_write_8(ea, data); - break; - } - case 4: // -(An) - { - uint32 ea = EA_AY_PD_8(); - m68ki_write_8(ea, data); - break; - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_8(); - m68ki_write_8(ea, data); - break; - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_8(); - m68ki_write_8(ea, data); - break; - } - case 7: - { - switch (reg) - { - case 1: // (xxx).B - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - m68ki_write_8(ea, data); - break; - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_16(); - m68ki_write_8(ea, data); - break; - } - default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); - } -} - -static void WRITE_EA_16(int ea, uint16 data) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - REG_D[reg] = data; - break; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - m68ki_write_16(ea, data); - break; - } - case 3: // (An)+ - { - uint32 ea = EA_AY_PI_16(); - m68ki_write_16(ea, data); - break; - } - case 4: // -(An) - { - uint32 ea = EA_AY_PD_16(); - m68ki_write_16(ea, data); - break; - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_16(); - m68ki_write_16(ea, data); - break; - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_16(); - m68ki_write_16(ea, data); - break; - } - case 7: - { - switch (reg) - { - case 1: // (xxx).W - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - m68ki_write_16(ea, data); - break; - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_16(); - m68ki_write_16(ea, data); - break; - } - default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); - } -} - -static void WRITE_EA_32(int ea, uint32 data) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - REG_D[reg] = data; - break; - } - case 1: // An - { - REG_A[reg] = data; - break; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - m68ki_write_32(ea, data); - break; - } - case 3: // (An)+ - { - uint32 ea = EA_AY_PI_32(); - m68ki_write_32(ea, data); - break; - } - case 4: // -(An) - { - uint32 ea = EA_AY_PD_32(); - m68ki_write_32(ea, data); - break; - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_32(); - m68ki_write_32(ea, data); - break; - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_32(); - m68ki_write_32(ea, data); - break; - } - case 7: - { - switch (reg) - { - case 1: // (xxx).L - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - m68ki_write_32(ea, data); - break; - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_32(); - m68ki_write_32(ea, data); - break; - } - default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); - } -} - -static void WRITE_EA_64(int ea, uint64 data) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 2: // (An) - { - uint32 ea = REG_A[reg]; - m68ki_write_32(ea, (uint32)(data >> 32)); - m68ki_write_32(ea+4, (uint32)(data)); - break; - } - case 4: // -(An) - { - uint32 ea; - REG_A[reg] -= 8; - ea = REG_A[reg]; - m68ki_write_32(ea+0, (uint32)(data >> 32)); - m68ki_write_32(ea+4, (uint32)(data)); - break; - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_32(); - m68ki_write_32(ea+0, (uint32)(data >> 32)); - m68ki_write_32(ea+4, (uint32)(data)); - break; - } - default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (uint32)(data >> 32), (uint32)(data), REG_PC); - } -} - -static void WRITE_EA_FPE(int mode, int reg, floatx80 fpr, uint32 di_mode_ea) -{ - - - switch (mode) - { - case 2: // (An) - { - uint32 ea; - ea = REG_A[reg]; - store_extended_float80(ea, fpr); - break; - } - - case 3: // (An)+ - { - uint32 ea; - ea = REG_A[reg]; - store_extended_float80(ea, fpr); - REG_A[reg] += 12; - break; - } - - case 4: // -(An) - { - uint32 ea; - REG_A[reg] -= 12; - ea = REG_A[reg]; - store_extended_float80(ea, fpr); - break; - } - case 5: // (d16, An) (added by JFF) - { - // EA_AY_DI_32() should not be done here because fmovem would increase - // PC each time, reading incorrect displacement & advancing PC too much - // uint32 ea = EA_AY_DI_32(); - store_extended_float80(di_mode_ea, fpr); - break; - - } - case 7: - { - switch (reg) - { - default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - } -} - -static void WRITE_EA_PACK(int ea, int k, floatx80 fpr) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 2: // (An) - { - uint32 ea; - ea = REG_A[reg]; - store_pack_float80(ea, k, fpr); - break; - } - - case 3: // (An)+ - { - uint32 ea; - ea = REG_A[reg]; - store_pack_float80(ea, k, fpr); - REG_A[reg] += 12; - break; - } - - case 4: // -(An) - { - uint32 ea; - REG_A[reg] -= 12; - ea = REG_A[reg]; - store_pack_float80(ea, k, fpr); - break; - } - - case 7: - { - switch (reg) - { - default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - } - } - break; - default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - } -} - - -static void fpgen_rm_reg(uint16 w2) -{ - int ea = REG_IR & 0x3f; - int rm = (w2 >> 14) & 0x1; - int src = (w2 >> 10) & 0x7; - int dst = (w2 >> 7) & 0x7; - int opmode = w2 & 0x7f; - floatx80 source; - - // fmovecr #$f, fp0 f200 5c0f - - if (rm) - { - switch (src) - { - case 0: // Long-Word Integer - { - sint32 d = READ_EA_32(ea); - source = int32_to_floatx80(d); - break; - } - case 1: // Single-precision Real - { - uint32 d = READ_EA_32(ea); - source = float32_to_floatx80(d); - break; - } - case 2: // Extended-precision Real - { - int imode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - uint32 di_mode_ea = imode == 5 ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - source = READ_EA_FPE(imode,reg,di_mode_ea); - break; - } - case 3: // Packed-decimal Real - { - source = READ_EA_PACK(ea); - break; - } - case 4: // Word Integer - { - sint16 d = READ_EA_16(ea); - source = int32_to_floatx80((sint32)d); - break; - } - case 5: // Double-precision Real - { - uint64 d = READ_EA_64(ea); - - source = float64_to_floatx80(d); - break; - } - case 6: // Byte Integer - { - sint8 d = READ_EA_8(ea); - source = int32_to_floatx80((sint32)d); - break; - } - case 7: // FMOVECR load from constant ROM - { - switch (w2 & 0x7f) - { - case 0x0: // Pi - source.high = 0x4000; - source.low = U64(0xc90fdaa22168c235); - break; - - case 0xb: // log10(2) - source.high = 0x3ffd; - source.low = U64(0x9a209a84fbcff798); - break; - - case 0xc: // e - source.high = 0x4000; - source.low = U64(0xadf85458a2bb4a9b); - break; - - case 0xd: // log2(e) - source.high = 0x3fff; - source.low = U64(0xb8aa3b295c17f0bc); - break; - - case 0xe: // log10(e) - source.high = 0x3ffd; - source.low = U64(0xde5bd8a937287195); - break; - - case 0xf: // 0.0 - source = int32_to_floatx80((sint32)0); - break; - - case 0x30: // ln(2) - source.high = 0x3ffe; - source.low = U64(0xb17217f7d1cf79ac); - break; - - case 0x31: // ln(10) - source.high = 0x4000; - source.low = U64(0x935d8dddaaa8ac17); - break; - - case 0x32: // 1 (or 100? manuals are unclear, but 1 would make more sense) - source = int32_to_floatx80((sint32)1); - break; - - case 0x33: // 10^1 - source = int32_to_floatx80((sint32)10); - break; - - case 0x34: // 10^2 - source = int32_to_floatx80((sint32)10*10); - break; - - default: - fatalerror("fmove_rm_reg: unknown constant ROM offset %x at %08x\n", w2&0x7f, REG_PC-4); - break; - } - - // handle it right here, the usual opmode bits aren't valid in the FMOVECR case - REG_FP[dst] = source; - SET_CONDITION_CODES(REG_FP[dst]); // JFF when destination is a register, we HAVE to update FPCR - USE_CYCLES(4); - return; - } - default: fatalerror("fmove_rm_reg: invalid source specifier %x at %08X\n", src, REG_PC-4); - } - } - else - { - source = REG_FP[src]; - } - - - - switch (opmode) - { - case 0x00: // FMOVE - { - REG_FP[dst] = source; - SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes - USE_CYCLES(4); - break; - } - case 0x01: // Fsint - { - sint32 temp; - temp = floatx80_to_int32(source); - REG_FP[dst] = int32_to_floatx80(temp); - SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes - break; - } - case 0x03: // FsintRZ - { - sint32 temp; - temp = floatx80_to_int32_round_to_zero(source); - REG_FP[dst] = int32_to_floatx80(temp); - SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes - break; - } - case 0x04: // FSQRT - { - REG_FP[dst] = floatx80_sqrt(source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(109); - break; - } - case 0x18: // FABS - { - REG_FP[dst] = source; - REG_FP[dst].high &= 0x7fff; - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(3); - break; - } - case 0x1a: // FNEG - { - REG_FP[dst] = source; - REG_FP[dst].high ^= 0x8000; - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(3); - break; - } - case 0x1e: // FGETEXP - { - sint16 temp; - temp = source.high; // get the exponent - temp -= 0x3fff; // take off the bias - REG_FP[dst] = double_to_fx80((double)temp); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(6); - break; - } - case 0x60: // FSDIVS (JFF) (source has already been converted to floatx80) - case 0x20: // FDIV - { - REG_FP[dst] = floatx80_div(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); // JFF - USE_CYCLES(43); - break; - } - case 0x22: // FADD - { - REG_FP[dst] = floatx80_add(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(9); - break; - } - case 0x63: // FSMULS (JFF) (source has already been converted to floatx80) - case 0x23: // FMUL - { - REG_FP[dst] = floatx80_mul(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(11); - break; - } - case 0x25: // FREM - { - REG_FP[dst] = floatx80_rem(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(43); // guess - break; - } - case 0x28: // FSUB - { - REG_FP[dst] = floatx80_sub(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(9); - break; - } - case 0x38: // FCMP - { - floatx80 res; - res = floatx80_sub(REG_FP[dst], source); - SET_CONDITION_CODES(res); - USE_CYCLES(7); - break; - } - case 0x3a: // FTST - { - floatx80 res; - res = source; - SET_CONDITION_CODES(res); - USE_CYCLES(7); - break; - } - - default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4); - } -} - -static void fmove_reg_mem(uint16 w2) -{ - int ea = REG_IR & 0x3f; - int src = (w2 >> 7) & 0x7; - int dst = (w2 >> 10) & 0x7; - int k = (w2 & 0x7f); - - switch (dst) - { - case 0: // Long-Word Integer - { - sint32 d = (sint32)floatx80_to_int32(REG_FP[src]); - WRITE_EA_32(ea, d); - break; - } - case 1: // Single-precision Real - { - uint32 d = floatx80_to_float32(REG_FP[src]); - WRITE_EA_32(ea, d); - break; - } - case 2: // Extended-precision Real - { - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - uint32 di_mode_ea = mode == 5 ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - WRITE_EA_FPE(mode, reg, REG_FP[src], di_mode_ea); - break; - } - case 3: // Packed-decimal Real with Static K-factor - { - // sign-extend k - k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f); - WRITE_EA_PACK(ea, k, REG_FP[src]); - break; - } - case 4: // Word Integer - { - WRITE_EA_16(ea, (sint16)floatx80_to_int32(REG_FP[src])); - break; - } - case 5: // Double-precision Real - { - uint64 d; - - d = floatx80_to_float64(REG_FP[src]); - - WRITE_EA_64(ea, d); - break; - } - case 6: // Byte Integer - { - WRITE_EA_8(ea, (sint8)floatx80_to_int32(REG_FP[src])); - break; - } - case 7: // Packed-decimal Real with Dynamic K-factor - { - WRITE_EA_PACK(ea, REG_D[k>>4], REG_FP[src]); - break; - } - } - - USE_CYCLES(12); -} - -static void fmove_fpcr(uint16 w2) -{ - int ea = REG_IR & 0x3f; - int dir = (w2 >> 13) & 0x1; - int reg = (w2 >> 10) & 0x7; - - if (dir) // From system control reg to - { - if (reg & 4) WRITE_EA_32(ea, REG_FPCR); - if (reg & 2) WRITE_EA_32(ea, REG_FPSR); - if (reg & 1) WRITE_EA_32(ea, REG_FPIAR); - } - else // From to system control reg - { - if (reg & 4) - { - REG_FPCR = READ_EA_32(ea); - // JFF: need to update rounding mode from softfloat module - float_rounding_mode = (REG_FPCR >> 4) & 0x3; - } - if (reg & 2) REG_FPSR = READ_EA_32(ea); - if (reg & 1) REG_FPIAR = READ_EA_32(ea); - } - - USE_CYCLES(10); -} - -static void fmovem(uint16 w2) -{ - int i; - int ea = REG_IR & 0x3f; - int dir = (w2 >> 13) & 0x1; - int mode = (w2 >> 11) & 0x3; - int reglist = w2 & 0xff; - - if (dir) // From FP regs to mem - { - switch (mode) - { - case 2: // (JFF): Static register list, postincrement or control addressing mode. - { - int imode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - int di_mode = imode == 5; - uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - for (i=0; i < 8; i++) - { - if (reglist & (1 << i)) - { - WRITE_EA_FPE(imode,reg, REG_FP[7-i],di_mode_ea); - USE_CYCLES(2); - if (di_mode) - { - di_mode_ea += 12; - } - } - } - break; - } - case 0: // Static register list, predecrement addressing mode - { - int imode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - // the "di_mode_ea" parameter kludge is required here else WRITE_EA_FPE would have - // to call EA_AY_DI_32() (that advances PC & reads displacement) each time - // when the proper behaviour is 1) read once, 2) increment ea for each matching register - // this forces to pre-read the mode (named "imode") so we can decide to read displacement, only once - int di_mode = imode == 5; - uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - for (i=0; i < 8; i++) - { - if (reglist & (1 << i)) - { - WRITE_EA_FPE(imode,reg, REG_FP[i],di_mode_ea); - USE_CYCLES(2); - if (di_mode) - { - di_mode_ea += 12; - } - } - } - break; - } - - default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); - } - } - else // From mem to FP regs - { - switch (mode) - { - case 2: // Static register list, postincrement addressing mode - { - int imode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - int di_mode = imode == 5; - uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - for (i=0; i < 8; i++) - { - if (reglist & (1 << i)) - { - REG_FP[7-i] = READ_EA_FPE(imode,reg,di_mode_ea); - USE_CYCLES(2); - if (di_mode) - { - di_mode_ea += 12; - } - } - } - break; - } - - default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); - } - } -} - -static void fscc() -{ - // added by JFF, this seems to work properly now - int condition = OPER_I_16() & 0x3f; - - int cc = TEST_CONDITION(condition); - int mode = (REG_IR & 0x38) >> 3; - int v = (cc ? 0xff : 0x00); - - switch (mode) - { - case 0: // fscc Dx - { - // If the specified floating-point condition is true, sets the byte integer operand at - // the destination to TRUE (all ones); otherwise, sets the byte to FALSE (all zeros). - - REG_D[REG_IR & 7] = (REG_D[REG_IR & 7] & 0xFFFFFF00) | v; - break; - } - case 5: // (disp,Ax) - { - int reg = REG_IR & 7; - uint32 ea = REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16()); - m68ki_write_8(ea,v); - break; - } - - default: - { - // unimplemented see fpu_uae.cpp around line 1300 - fatalerror("040fpu0: fscc: mode %d not implemented at %08X\n", mode, REG_PC-4); - } - } - USE_CYCLES(7); // JFF unsure of the number of cycles!! -} -static void fbcc16(void) -{ - sint32 offset; - int condition = REG_IR & 0x3f; - - offset = (sint16)(OPER_I_16()); - - // TODO: condition and jump!!! - if (TEST_CONDITION(condition)) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset-2); - } - - USE_CYCLES(7); - } - -static void fbcc32(void) -{ - sint32 offset; - int condition = REG_IR & 0x3f; - - offset = OPER_I_32(); - - // TODO: condition and jump!!! - if (TEST_CONDITION(condition)) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_32(offset-4); - } - - USE_CYCLES(7); -} - - -void m68040_fpu_op0() -{ - m68ki_cpu.fpu_just_reset = 0; - - switch ((REG_IR >> 6) & 0x3) - { - case 0: - { - uint16 w2 = OPER_I_16(); - switch ((w2 >> 13) & 0x7) - { - case 0x0: // FPU ALU FP, FP - case 0x2: // FPU ALU ea, FP - { - fpgen_rm_reg(w2); - break; - } - - case 0x3: // FMOVE FP, ea - { - fmove_reg_mem(w2); - break; - } - - case 0x4: // FMOVEM ea, FPCR - case 0x5: // FMOVEM FPCR, ea - { - fmove_fpcr(w2); - break; - } - - case 0x6: // FMOVEM ea, list - case 0x7: // FMOVEM list, ea - { - fmovem(w2); - break; - } - - default: fatalerror("M68kFPU: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC-4); - } - break; - } - - case 1: // FScc (JFF) - { - fscc(); - break; - } - case 2: // FBcc disp16 - { - fbcc16(); - break; - } - case 3: // FBcc disp32 - { - fbcc32(); - break; - } - - default: fatalerror("M68kFPU: unimplemented main op %d at %08X\n", (m68ki_cpu.ir >> 6) & 0x3, REG_PC-4); - } -} - -static void perform_fsave(uint32 addr, int inc) -{ - if (inc) - { - // 68881 IDLE, version 0x1f - m68ki_write_32(addr, 0x1f180000); - m68ki_write_32(addr+4, 0); - m68ki_write_32(addr+8, 0); - m68ki_write_32(addr+12, 0); - m68ki_write_32(addr+16, 0); - m68ki_write_32(addr+20, 0); - m68ki_write_32(addr+24, 0x70000000); - } - else - { - m68ki_write_32(addr, 0x70000000); - m68ki_write_32(addr-4, 0); - m68ki_write_32(addr-8, 0); - m68ki_write_32(addr-12, 0); - m68ki_write_32(addr-16, 0); - m68ki_write_32(addr-20, 0); - m68ki_write_32(addr-24, 0x1f180000); - } -} - -// FRESTORE on a NULL frame reboots the FPU - all registers to NaN, the 3 status regs to 0 -static void do_frestore_null() -{ - int i; - - REG_FPCR = 0; - REG_FPSR = 0; - REG_FPIAR = 0; - for (i = 0; i < 8; i++) - { - REG_FP[i].high = 0x7fff; - REG_FP[i].low = U64(0xffffffffffffffff); - } - - // Mac IIci at 408458e6 wants an FSAVE of a just-restored NULL frame to also be NULL - // The PRM says it's possible to generate a NULL frame, but not how/when/why. (need the 68881/68882 manual!) - m68ki_cpu.fpu_just_reset = 1; -} - -void m68040_fpu_op1() -{ - int ea = REG_IR & 0x3f; - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - uint32 addr, temp; - - switch ((REG_IR >> 6) & 0x3) - { - case 0: // FSAVE - { - switch (mode) - { - case 3: // (An)+ - addr = EA_AY_PI_32(); - - if (m68ki_cpu.fpu_just_reset) - { - m68ki_write_32(addr, 0); - } - else - { - // we normally generate an IDLE frame - REG_A[reg] += 6*4; - perform_fsave(addr, 1); - } - break; - - case 4: // -(An) - addr = EA_AY_PD_32(); - - if (m68ki_cpu.fpu_just_reset) - { - m68ki_write_32(addr, 0); - } - else - { - // we normally generate an IDLE frame - REG_A[reg] -= 6*4; - perform_fsave(addr, 0); - } - break; - - default: - fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC); - } - break; - } - break; - - case 1: // FRESTORE - { - switch (mode) - { - case 2: // (An) - addr = REG_A[reg]; - temp = m68ki_read_32(addr); - - // check for NULL frame - if (temp & 0xff000000) - { - // we don't handle non-NULL frames and there's no pre/post inc/dec to do here - m68ki_cpu.fpu_just_reset = 0; - } - else - { - do_frestore_null(); - } - break; - - case 3: // (An)+ - addr = EA_AY_PI_32(); - temp = m68ki_read_32(addr); - - // check for NULL frame - if (temp & 0xff000000) - { - m68ki_cpu.fpu_just_reset = 0; - - // how about an IDLE frame? - if ((temp & 0x00ff0000) == 0x00180000) - { - REG_A[reg] += 6*4; - } // check UNIMP - else if ((temp & 0x00ff0000) == 0x00380000) - { - REG_A[reg] += 14*4; - } // check BUSY - else if ((temp & 0x00ff0000) == 0x00b40000) - { - REG_A[reg] += 45*4; - } - } - else - { - do_frestore_null(); - } - break; - - default: - fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC); - } - break; - } - break; - - default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (REG_IR >> 6) & 0x3, REG_PC-2); - } -} - - - +#include +#include +#include + +extern void exit(int); + +static void fatalerror(const char *format, ...) { + va_list ap; + va_start(ap,format); + vfprintf(stderr,format,ap); // JFF: fixed. Was using fprintf and arguments were wrong + va_end(ap); + exit(1); +} + +#define FPCC_N 0x08000000 +#define FPCC_Z 0x04000000 +#define FPCC_I 0x02000000 +#define FPCC_NAN 0x01000000 + +#define DOUBLE_INFINITY (unsigned long long)(0x7ff0000000000000) +#define DOUBLE_EXPONENT (unsigned long long)(0x7ff0000000000000) +#define DOUBLE_MANTISSA (unsigned long long)(0x000fffffffffffff) + +extern flag floatx80_is_nan( floatx80 a ); + +// masks for packed dwords, positive k-factor +static uint32 pkmask2[18] = +{ + 0xffffffff, 0, 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, + 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff +}; + +static uint32 pkmask3[18] = +{ + 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, + 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, +}; + +static inline double fx80_to_double(floatx80 fx) +{ + uint64 d; + double *foo; + + foo = (double *)&d; + + d = floatx80_to_float64(fx); + + return *foo; +} + +static inline floatx80 double_to_fx80(double in) +{ + uint64 *d; + + d = (uint64 *)∈ + + return float64_to_floatx80(*d); +} + +static inline floatx80 load_extended_float80(uint32 ea) +{ + uint32 d1,d2; + uint16 d3; + floatx80 fp; + + d3 = m68ki_read_16(ea); + d1 = m68ki_read_32(ea+4); + d2 = m68ki_read_32(ea+8); + + fp.high = d3; + fp.low = ((uint64)d1<<32) | (d2 & 0xffffffff); + + return fp; +} + +static inline void store_extended_float80(uint32 ea, floatx80 fpr) +{ + m68ki_write_16(ea+0, fpr.high); + m68ki_write_16(ea+2, 0); + m68ki_write_32(ea+4, (fpr.low>>32)&0xffffffff); + m68ki_write_32(ea+8, fpr.low&0xffffffff); +} + +static inline floatx80 load_pack_float80(uint32 ea) +{ + uint32 dw1, dw2, dw3; + floatx80 result; + double tmp; + char str[128], *ch; + + dw1 = m68ki_read_32(ea); + dw2 = m68ki_read_32(ea+4); + dw3 = m68ki_read_32(ea+8); + + ch = &str[0]; + if (dw1 & 0x80000000) // mantissa sign + { + *ch++ = '-'; + } + *ch++ = (char)((dw1 & 0xf) + '0'); + *ch++ = '.'; + *ch++ = (char)(((dw2 >> 28) & 0xf) + '0'); + *ch++ = (char)(((dw2 >> 24) & 0xf) + '0'); + *ch++ = (char)(((dw2 >> 20) & 0xf) + '0'); + *ch++ = (char)(((dw2 >> 16) & 0xf) + '0'); + *ch++ = (char)(((dw2 >> 12) & 0xf) + '0'); + *ch++ = (char)(((dw2 >> 8) & 0xf) + '0'); + *ch++ = (char)(((dw2 >> 4) & 0xf) + '0'); + *ch++ = (char)(((dw2 >> 0) & 0xf) + '0'); + *ch++ = (char)(((dw3 >> 28) & 0xf) + '0'); + *ch++ = (char)(((dw3 >> 24) & 0xf) + '0'); + *ch++ = (char)(((dw3 >> 20) & 0xf) + '0'); + *ch++ = (char)(((dw3 >> 16) & 0xf) + '0'); + *ch++ = (char)(((dw3 >> 12) & 0xf) + '0'); + *ch++ = (char)(((dw3 >> 8) & 0xf) + '0'); + *ch++ = (char)(((dw3 >> 4) & 0xf) + '0'); + *ch++ = (char)(((dw3 >> 0) & 0xf) + '0'); + *ch++ = 'E'; + if (dw1 & 0x40000000) // exponent sign + { + *ch++ = '-'; + } + *ch++ = (char)(((dw1 >> 24) & 0xf) + '0'); + *ch++ = (char)(((dw1 >> 20) & 0xf) + '0'); + *ch++ = (char)(((dw1 >> 16) & 0xf) + '0'); + *ch = '\0'; + + sscanf(str, "%le", &tmp); + + result = double_to_fx80(tmp); + + return result; +} + +static inline void store_pack_float80(uint32 ea, int k, floatx80 fpr) +{ + uint32 dw1, dw2, dw3; + char str[128], *ch; + int i, j, exp; + + dw1 = dw2 = dw3 = 0; + ch = &str[0]; + + sprintf(str, "%.16e", fx80_to_double(fpr)); + + if (*ch == '-') + { + ch++; + dw1 = 0x80000000; + } + + if (*ch == '+') + { + ch++; + } + + dw1 |= (*ch++ - '0'); + + if (*ch == '.') + { + ch++; + } + + // handle negative k-factor here + if ((k <= 0) && (k >= -13)) + { + exp = 0; + for (i = 0; i < 3; i++) + { + if (ch[18+i] >= '0' && ch[18+i] <= '9') + { + exp = (exp << 4) | (ch[18+i] - '0'); + } + } + + if (ch[17] == '-') + { + exp = -exp; + } + + k = -k; + // last digit is (k + exponent - 1) + k += (exp - 1); + + // round up the last significant mantissa digit + if (ch[k+1] >= '5') + { + ch[k]++; + } + + // zero out the rest of the mantissa digits + for (j = (k+1); j < 16; j++) + { + ch[j] = '0'; + } + + // now zero out K to avoid tripping the positive K detection below + k = 0; + } + + // crack 8 digits of the mantissa + for (i = 0; i < 8; i++) + { + dw2 <<= 4; + if (*ch >= '0' && *ch <= '9') + { + dw2 |= *ch++ - '0'; + } + } + + // next 8 digits of the mantissa + for (i = 0; i < 8; i++) + { + dw3 <<= 4; + if (*ch >= '0' && *ch <= '9') + dw3 |= *ch++ - '0'; + } + + // handle masking if k is positive + if (k >= 1) + { + if (k <= 17) + { + dw2 &= pkmask2[k]; + dw3 &= pkmask3[k]; + } + else + { + dw2 &= pkmask2[17]; + dw3 &= pkmask3[17]; +// m68ki_cpu.fpcr |= (need to set OPERR bit) + } + } + + // finally, crack the exponent + if (*ch == 'e' || *ch == 'E') + { + ch++; + if (*ch == '-') + { + ch++; + dw1 |= 0x40000000; + } + + if (*ch == '+') + { + ch++; + } + + j = 0; + for (i = 0; i < 3; i++) + { + if (*ch >= '0' && *ch <= '9') + { + j = (j << 4) | (*ch++ - '0'); + } + } + + dw1 |= (j << 16); + } + + m68ki_write_32(ea, dw1); + m68ki_write_32(ea+4, dw2); + m68ki_write_32(ea+8, dw3); +} + +static inline void SET_CONDITION_CODES(floatx80 reg) +{ + REG_FPSR &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN); + + // sign flag + if (reg.high & 0x8000) + { + REG_FPSR |= FPCC_N; + } + + // zero flag + if (((reg.high & 0x7fff) == 0) && ((reg.low<<1) == 0)) + { + REG_FPSR |= FPCC_Z; + } + + // infinity flag + if (((reg.high & 0x7fff) == 0x7fff) && ((reg.low<<1) == 0)) + { + REG_FPSR |= FPCC_I; + } + + // NaN flag + if (floatx80_is_nan(reg)) + { + REG_FPSR |= FPCC_NAN; + } +} + +static inline int TEST_CONDITION(int condition) +{ + int n = (REG_FPSR & FPCC_N) != 0; + int z = (REG_FPSR & FPCC_Z) != 0; + int nan = (REG_FPSR & FPCC_NAN) != 0; + int r = 0; + switch (condition) + { + case 0x10: + case 0x00: return 0; // False + + case 0x11: + case 0x01: return (z); // Equal + + case 0x12: + case 0x02: return (!(nan || z || n)); // Greater Than + + case 0x13: + case 0x03: return (z || !(nan || n)); // Greater or Equal + + case 0x14: + case 0x04: return (n && !(nan || z)); // Less Than + + case 0x15: + case 0x05: return (z || (n && !nan)); // Less Than or Equal + + case 0x16: + case 0x06: return !nan && !z; + + case 0x17: + case 0x07: return !nan; + + case 0x18: + case 0x08: return nan; + + case 0x19: + case 0x09: return nan || z; + + case 0x1a: + case 0x0a: return (nan || !(n || z)); // Not Less Than or Equal + + case 0x1b: + case 0x0b: return (nan || z || !n); // Not Less Than + + case 0x1c: + case 0x0c: return (nan || (n && !z)); // Not Greater or Equal Than + + case 0x1d: + case 0x0d: return (nan || z || n); // Not Greater Than + + case 0x1e: + case 0x0e: return (!z); // Not Equal + + case 0x1f: + case 0x0f: return 1; // True + + default: fatalerror("M68kFPU: test_condition: unhandled condition %02X\n", condition); + } + + return r; +} + +static uint8 READ_EA_8(int ea) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 0: // Dn + { + return REG_D[reg]; + } + case 2: // (An) + { + uint32 ea = REG_A[reg]; + return m68ki_read_8(ea); + } + case 5: // (d16, An) + { + uint32 ea = EA_AY_DI_8(); + return m68ki_read_8(ea); + } + case 6: // (An) + (Xn) + d8 + { + uint32 ea = EA_AY_IX_8(); + return m68ki_read_8(ea); + } + case 7: + { + switch (reg) + { + case 0: // (xxx).W + { + uint32 ea = (uint32)OPER_I_16(); + return m68ki_read_8(ea); + } + case 1: // (xxx).L + { + uint32 d1 = OPER_I_16(); + uint32 d2 = OPER_I_16(); + uint32 ea = (d1 << 16) | d2; + return m68ki_read_8(ea); + } + case 4: // # + { + return OPER_I_8(); + } + default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + break; + } + default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + + return 0; +} + +static uint16 READ_EA_16(int ea) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 0: // Dn + { + return (uint16)(REG_D[reg]); + } + case 2: // (An) + { + uint32 ea = REG_A[reg]; + return m68ki_read_16(ea); + } + case 5: // (d16, An) + { + uint32 ea = EA_AY_DI_16(); + return m68ki_read_16(ea); + } + case 6: // (An) + (Xn) + d8 + { + uint32 ea = EA_AY_IX_16(); + return m68ki_read_16(ea); + } + case 7: + { + switch (reg) + { + case 0: // (xxx).W + { + uint32 ea = (uint32)OPER_I_16(); + return m68ki_read_16(ea); + } + case 1: // (xxx).L + { + uint32 d1 = OPER_I_16(); + uint32 d2 = OPER_I_16(); + uint32 ea = (d1 << 16) | d2; + return m68ki_read_16(ea); + } + case 4: // # + { + return OPER_I_16(); + } + + default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + break; + } + default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + + return 0; +} + +static uint32 READ_EA_32(int ea) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 0: // Dn + { + return REG_D[reg]; + } + case 2: // (An) + { + uint32 ea = REG_A[reg]; + return m68ki_read_32(ea); + } + case 3: // (An)+ + { + uint32 ea = EA_AY_PI_32(); + return m68ki_read_32(ea); + } + case 5: // (d16, An) + { + uint32 ea = EA_AY_DI_32(); + return m68ki_read_32(ea); + } + case 6: // (An) + (Xn) + d8 + { + uint32 ea = EA_AY_IX_32(); + return m68ki_read_32(ea); + } + case 7: + { + switch (reg) + { + case 0: // (xxx).W + { + uint32 ea = (uint32)OPER_I_16(); + return m68ki_read_32(ea); + } + case 1: // (xxx).L + { + uint32 d1 = OPER_I_16(); + uint32 d2 = OPER_I_16(); + uint32 ea = (d1 << 16) | d2; + return m68ki_read_32(ea); + } + case 2: // (d16, PC) + { + uint32 ea = EA_PCDI_32(); + return m68ki_read_32(ea); + } + case 4: // # + { + return OPER_I_32(); + } + default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + break; + } + default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + return 0; +} + +static uint64 READ_EA_64(int ea) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + uint32 h1, h2; + + switch (mode) + { + case 2: // (An) + { + uint32 ea = REG_A[reg]; + h1 = m68ki_read_32(ea+0); + h2 = m68ki_read_32(ea+4); + return (uint64)(h1) << 32 | (uint64)(h2); + } + case 3: // (An)+ + { + uint32 ea = REG_A[reg]; + REG_A[reg] += 8; + h1 = m68ki_read_32(ea+0); + h2 = m68ki_read_32(ea+4); + return (uint64)(h1) << 32 | (uint64)(h2); + } + case 5: // (d16, An) + { + uint32 ea = EA_AY_DI_32(); + h1 = m68ki_read_32(ea+0); + h2 = m68ki_read_32(ea+4); + return (uint64)(h1) << 32 | (uint64)(h2); + } + case 7: + { + switch (reg) + { + case 4: // # + { + h1 = OPER_I_32(); + h2 = OPER_I_32(); + return (uint64)(h1) << 32 | (uint64)(h2); + } + case 2: // (d16, PC) + { + uint32 ea = EA_PCDI_32(); + h1 = m68ki_read_32(ea+0); + h2 = m68ki_read_32(ea+4); + return (uint64)(h1) << 32 | (uint64)(h2); + } + default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + break; + } + default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + + return 0; +} + + +static floatx80 READ_EA_FPE(int mode, int reg, uint32 di_mode_ea) +{ + floatx80 fpr; + + switch (mode) + { + case 2: // (An) + { + uint32 ea = REG_A[reg]; + fpr = load_extended_float80(ea); + break; + } + + case 3: // (An)+ + { + uint32 ea = REG_A[reg]; + REG_A[reg] += 12; + fpr = load_extended_float80(ea); + break; + } + case 5: // (d16, An) (added by JFF) + { + fpr = load_extended_float80(di_mode_ea); + break; + + } + case 7: // extended modes + { + switch (reg) + { + case 2: // (d16, PC) + { + uint32 ea = EA_PCDI_32(); + fpr = load_extended_float80(ea); + } + break; + + case 3: // (d16,PC,Dx.w) + { + uint32 ea = EA_PCIX_32(); + fpr = load_extended_float80(ea); + } + break; + case 4: // immediate (JFF) + { + uint32 ea = REG_PC; + fpr = load_extended_float80(ea); + REG_PC += 12; + } + break; + default: + fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); + break; + } + } + break; + + default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break; + } + + return fpr; +} + +static floatx80 READ_EA_PACK(int ea) +{ + floatx80 fpr; + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 2: // (An) + { + uint32 ea = REG_A[reg]; + fpr = load_pack_float80(ea); + break; + } + + case 3: // (An)+ + { + uint32 ea = REG_A[reg]; + REG_A[reg] += 12; + fpr = load_pack_float80(ea); + break; + } + + case 7: // extended modes + { + switch (reg) + { + case 3: // (d16,PC,Dx.w) + { + uint32 ea = EA_PCIX_32(); + fpr = load_pack_float80(ea); + } + break; + + default: + fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); + break; + } + } + break; + + default: fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break; + } + + return fpr; +} + +static void WRITE_EA_8(int ea, uint8 data) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 0: // Dn + { + REG_D[reg] = data; + break; + } + case 2: // (An) + { + uint32 ea = REG_A[reg]; + m68ki_write_8(ea, data); + break; + } + case 3: // (An)+ + { + uint32 ea = EA_AY_PI_8(); + m68ki_write_8(ea, data); + break; + } + case 4: // -(An) + { + uint32 ea = EA_AY_PD_8(); + m68ki_write_8(ea, data); + break; + } + case 5: // (d16, An) + { + uint32 ea = EA_AY_DI_8(); + m68ki_write_8(ea, data); + break; + } + case 6: // (An) + (Xn) + d8 + { + uint32 ea = EA_AY_IX_8(); + m68ki_write_8(ea, data); + break; + } + case 7: + { + switch (reg) + { + case 1: // (xxx).B + { + uint32 d1 = OPER_I_16(); + uint32 d2 = OPER_I_16(); + uint32 ea = (d1 << 16) | d2; + m68ki_write_8(ea, data); + break; + } + case 2: // (d16, PC) + { + uint32 ea = EA_PCDI_16(); + m68ki_write_8(ea, data); + break; + } + default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + break; + } + default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); + } +} + +static void WRITE_EA_16(int ea, uint16 data) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 0: // Dn + { + REG_D[reg] = data; + break; + } + case 2: // (An) + { + uint32 ea = REG_A[reg]; + m68ki_write_16(ea, data); + break; + } + case 3: // (An)+ + { + uint32 ea = EA_AY_PI_16(); + m68ki_write_16(ea, data); + break; + } + case 4: // -(An) + { + uint32 ea = EA_AY_PD_16(); + m68ki_write_16(ea, data); + break; + } + case 5: // (d16, An) + { + uint32 ea = EA_AY_DI_16(); + m68ki_write_16(ea, data); + break; + } + case 6: // (An) + (Xn) + d8 + { + uint32 ea = EA_AY_IX_16(); + m68ki_write_16(ea, data); + break; + } + case 7: + { + switch (reg) + { + case 1: // (xxx).W + { + uint32 d1 = OPER_I_16(); + uint32 d2 = OPER_I_16(); + uint32 ea = (d1 << 16) | d2; + m68ki_write_16(ea, data); + break; + } + case 2: // (d16, PC) + { + uint32 ea = EA_PCDI_16(); + m68ki_write_16(ea, data); + break; + } + default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + break; + } + default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); + } +} + +static void WRITE_EA_32(int ea, uint32 data) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 0: // Dn + { + REG_D[reg] = data; + break; + } + case 1: // An + { + REG_A[reg] = data; + break; + } + case 2: // (An) + { + uint32 ea = REG_A[reg]; + m68ki_write_32(ea, data); + break; + } + case 3: // (An)+ + { + uint32 ea = EA_AY_PI_32(); + m68ki_write_32(ea, data); + break; + } + case 4: // -(An) + { + uint32 ea = EA_AY_PD_32(); + m68ki_write_32(ea, data); + break; + } + case 5: // (d16, An) + { + uint32 ea = EA_AY_DI_32(); + m68ki_write_32(ea, data); + break; + } + case 6: // (An) + (Xn) + d8 + { + uint32 ea = EA_AY_IX_32(); + m68ki_write_32(ea, data); + break; + } + case 7: + { + switch (reg) + { + case 1: // (xxx).L + { + uint32 d1 = OPER_I_16(); + uint32 d2 = OPER_I_16(); + uint32 ea = (d1 << 16) | d2; + m68ki_write_32(ea, data); + break; + } + case 2: // (d16, PC) + { + uint32 ea = EA_PCDI_32(); + m68ki_write_32(ea, data); + break; + } + default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); + } + break; + } + default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); + } +} + +static void WRITE_EA_64(int ea, uint64 data) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 2: // (An) + { + uint32 ea = REG_A[reg]; + m68ki_write_32(ea, (uint32)(data >> 32)); + m68ki_write_32(ea+4, (uint32)(data)); + break; + } + case 4: // -(An) + { + uint32 ea; + REG_A[reg] -= 8; + ea = REG_A[reg]; + m68ki_write_32(ea+0, (uint32)(data >> 32)); + m68ki_write_32(ea+4, (uint32)(data)); + break; + } + case 5: // (d16, An) + { + uint32 ea = EA_AY_DI_32(); + m68ki_write_32(ea+0, (uint32)(data >> 32)); + m68ki_write_32(ea+4, (uint32)(data)); + break; + } + default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (uint32)(data >> 32), (uint32)(data), REG_PC); + } +} + +static void WRITE_EA_FPE(int mode, int reg, floatx80 fpr, uint32 di_mode_ea) +{ + + + switch (mode) + { + case 2: // (An) + { + uint32 ea; + ea = REG_A[reg]; + store_extended_float80(ea, fpr); + break; + } + + case 3: // (An)+ + { + uint32 ea; + ea = REG_A[reg]; + store_extended_float80(ea, fpr); + REG_A[reg] += 12; + break; + } + + case 4: // -(An) + { + uint32 ea; + REG_A[reg] -= 12; + ea = REG_A[reg]; + store_extended_float80(ea, fpr); + break; + } + case 5: // (d16, An) (added by JFF) + { + // EA_AY_DI_32() should not be done here because fmovem would increase + // PC each time, reading incorrect displacement & advancing PC too much + // uint32 ea = EA_AY_DI_32(); + store_extended_float80(di_mode_ea, fpr); + break; + + } + case 7: + { + switch (reg) + { + default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); + } + break; + } + default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); + } +} + +static void WRITE_EA_PACK(int ea, int k, floatx80 fpr) +{ + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + + switch (mode) + { + case 2: // (An) + { + uint32 ea; + ea = REG_A[reg]; + store_pack_float80(ea, k, fpr); + break; + } + + case 3: // (An)+ + { + uint32 ea; + ea = REG_A[reg]; + store_pack_float80(ea, k, fpr); + REG_A[reg] += 12; + break; + } + + case 4: // -(An) + { + uint32 ea; + REG_A[reg] -= 12; + ea = REG_A[reg]; + store_pack_float80(ea, k, fpr); + break; + } + + case 7: + { + switch (reg) + { + default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); + } + } + break; + default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); + } +} + + +static void fpgen_rm_reg(uint16 w2) +{ + int ea = REG_IR & 0x3f; + int rm = (w2 >> 14) & 0x1; + int src = (w2 >> 10) & 0x7; + int dst = (w2 >> 7) & 0x7; + int opmode = w2 & 0x7f; + floatx80 source; + + // fmovecr #$f, fp0 f200 5c0f + + if (rm) + { + switch (src) + { + case 0: // Long-Word Integer + { + sint32 d = READ_EA_32(ea); + source = int32_to_floatx80(d); + break; + } + case 1: // Single-precision Real + { + uint32 d = READ_EA_32(ea); + source = float32_to_floatx80(d); + break; + } + case 2: // Extended-precision Real + { + int imode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + uint32 di_mode_ea = imode == 5 ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; + source = READ_EA_FPE(imode,reg,di_mode_ea); + break; + } + case 3: // Packed-decimal Real + { + source = READ_EA_PACK(ea); + break; + } + case 4: // Word Integer + { + sint16 d = READ_EA_16(ea); + source = int32_to_floatx80((sint32)d); + break; + } + case 5: // Double-precision Real + { + uint64 d = READ_EA_64(ea); + + source = float64_to_floatx80(d); + break; + } + case 6: // Byte Integer + { + sint8 d = READ_EA_8(ea); + source = int32_to_floatx80((sint32)d); + break; + } + case 7: // FMOVECR load from constant ROM + { + switch (w2 & 0x7f) + { + case 0x0: // Pi + source.high = 0x4000; + source.low = U64(0xc90fdaa22168c235); + break; + + case 0xb: // log10(2) + source.high = 0x3ffd; + source.low = U64(0x9a209a84fbcff798); + break; + + case 0xc: // e + source.high = 0x4000; + source.low = U64(0xadf85458a2bb4a9b); + break; + + case 0xd: // log2(e) + source.high = 0x3fff; + source.low = U64(0xb8aa3b295c17f0bc); + break; + + case 0xe: // log10(e) + source.high = 0x3ffd; + source.low = U64(0xde5bd8a937287195); + break; + + case 0xf: // 0.0 + source = int32_to_floatx80((sint32)0); + break; + + case 0x30: // ln(2) + source.high = 0x3ffe; + source.low = U64(0xb17217f7d1cf79ac); + break; + + case 0x31: // ln(10) + source.high = 0x4000; + source.low = U64(0x935d8dddaaa8ac17); + break; + + case 0x32: // 1 (or 100? manuals are unclear, but 1 would make more sense) + source = int32_to_floatx80((sint32)1); + break; + + case 0x33: // 10^1 + source = int32_to_floatx80((sint32)10); + break; + + case 0x34: // 10^2 + source = int32_to_floatx80((sint32)10*10); + break; + + default: + fatalerror("fmove_rm_reg: unknown constant ROM offset %x at %08x\n", w2&0x7f, REG_PC-4); + break; + } + + // handle it right here, the usual opmode bits aren't valid in the FMOVECR case + REG_FP[dst] = source; + SET_CONDITION_CODES(REG_FP[dst]); // JFF when destination is a register, we HAVE to update FPCR + USE_CYCLES(4); + return; + } + default: fatalerror("fmove_rm_reg: invalid source specifier %x at %08X\n", src, REG_PC-4); + } + } + else + { + source = REG_FP[src]; + } + + + + switch (opmode) + { + case 0x00: // FMOVE + { + REG_FP[dst] = source; + SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes + USE_CYCLES(4); + break; + } + case 0x01: // Fsint + { + sint32 temp; + temp = floatx80_to_int32(source); + REG_FP[dst] = int32_to_floatx80(temp); + SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes + break; + } + case 0x03: // FsintRZ + { + sint32 temp; + temp = floatx80_to_int32_round_to_zero(source); + REG_FP[dst] = int32_to_floatx80(temp); + SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes + break; + } + case 0x04: // FSQRT + { + REG_FP[dst] = floatx80_sqrt(source); + SET_CONDITION_CODES(REG_FP[dst]); + USE_CYCLES(109); + break; + } + case 0x18: // FABS + { + REG_FP[dst] = source; + REG_FP[dst].high &= 0x7fff; + SET_CONDITION_CODES(REG_FP[dst]); + USE_CYCLES(3); + break; + } + case 0x1a: // FNEG + { + REG_FP[dst] = source; + REG_FP[dst].high ^= 0x8000; + SET_CONDITION_CODES(REG_FP[dst]); + USE_CYCLES(3); + break; + } + case 0x1e: // FGETEXP + { + sint16 temp; + temp = source.high; // get the exponent + temp -= 0x3fff; // take off the bias + REG_FP[dst] = double_to_fx80((double)temp); + SET_CONDITION_CODES(REG_FP[dst]); + USE_CYCLES(6); + break; + } + case 0x60: // FSDIVS (JFF) (source has already been converted to floatx80) + case 0x20: // FDIV + { + REG_FP[dst] = floatx80_div(REG_FP[dst], source); + SET_CONDITION_CODES(REG_FP[dst]); // JFF + USE_CYCLES(43); + break; + } + case 0x22: // FADD + { + REG_FP[dst] = floatx80_add(REG_FP[dst], source); + SET_CONDITION_CODES(REG_FP[dst]); + USE_CYCLES(9); + break; + } + case 0x63: // FSMULS (JFF) (source has already been converted to floatx80) + case 0x23: // FMUL + { + REG_FP[dst] = floatx80_mul(REG_FP[dst], source); + SET_CONDITION_CODES(REG_FP[dst]); + USE_CYCLES(11); + break; + } + case 0x25: // FREM + { + REG_FP[dst] = floatx80_rem(REG_FP[dst], source); + SET_CONDITION_CODES(REG_FP[dst]); + USE_CYCLES(43); // guess + break; + } + case 0x28: // FSUB + { + REG_FP[dst] = floatx80_sub(REG_FP[dst], source); + SET_CONDITION_CODES(REG_FP[dst]); + USE_CYCLES(9); + break; + } + case 0x38: // FCMP + { + floatx80 res; + res = floatx80_sub(REG_FP[dst], source); + SET_CONDITION_CODES(res); + USE_CYCLES(7); + break; + } + case 0x3a: // FTST + { + floatx80 res; + res = source; + SET_CONDITION_CODES(res); + USE_CYCLES(7); + break; + } + + default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4); + } +} + +static void fmove_reg_mem(uint16 w2) +{ + int ea = REG_IR & 0x3f; + int src = (w2 >> 7) & 0x7; + int dst = (w2 >> 10) & 0x7; + int k = (w2 & 0x7f); + + switch (dst) + { + case 0: // Long-Word Integer + { + sint32 d = (sint32)floatx80_to_int32(REG_FP[src]); + WRITE_EA_32(ea, d); + break; + } + case 1: // Single-precision Real + { + uint32 d = floatx80_to_float32(REG_FP[src]); + WRITE_EA_32(ea, d); + break; + } + case 2: // Extended-precision Real + { + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + uint32 di_mode_ea = mode == 5 ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; + WRITE_EA_FPE(mode, reg, REG_FP[src], di_mode_ea); + break; + } + case 3: // Packed-decimal Real with Static K-factor + { + // sign-extend k + k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f); + WRITE_EA_PACK(ea, k, REG_FP[src]); + break; + } + case 4: // Word Integer + { + WRITE_EA_16(ea, (sint16)floatx80_to_int32(REG_FP[src])); + break; + } + case 5: // Double-precision Real + { + uint64 d; + + d = floatx80_to_float64(REG_FP[src]); + + WRITE_EA_64(ea, d); + break; + } + case 6: // Byte Integer + { + WRITE_EA_8(ea, (sint8)floatx80_to_int32(REG_FP[src])); + break; + } + case 7: // Packed-decimal Real with Dynamic K-factor + { + WRITE_EA_PACK(ea, REG_D[k>>4], REG_FP[src]); + break; + } + } + + USE_CYCLES(12); +} + +static void fmove_fpcr(uint16 w2) +{ + int ea = REG_IR & 0x3f; + int dir = (w2 >> 13) & 0x1; + int reg = (w2 >> 10) & 0x7; + + if (dir) // From system control reg to + { + if (reg & 4) WRITE_EA_32(ea, REG_FPCR); + if (reg & 2) WRITE_EA_32(ea, REG_FPSR); + if (reg & 1) WRITE_EA_32(ea, REG_FPIAR); + } + else // From to system control reg + { + if (reg & 4) + { + REG_FPCR = READ_EA_32(ea); + // JFF: need to update rounding mode from softfloat module + float_rounding_mode = (REG_FPCR >> 4) & 0x3; + } + if (reg & 2) REG_FPSR = READ_EA_32(ea); + if (reg & 1) REG_FPIAR = READ_EA_32(ea); + } + + USE_CYCLES(10); +} + +static void fmovem(uint16 w2) +{ + int i; + int ea = REG_IR & 0x3f; + int dir = (w2 >> 13) & 0x1; + int mode = (w2 >> 11) & 0x3; + int reglist = w2 & 0xff; + + if (dir) // From FP regs to mem + { + switch (mode) + { + case 2: // (JFF): Static register list, postincrement or control addressing mode. + { + int imode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + int di_mode = imode == 5; + uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; + for (i=0; i < 8; i++) + { + if (reglist & (1 << i)) + { + WRITE_EA_FPE(imode,reg, REG_FP[7-i],di_mode_ea); + USE_CYCLES(2); + if (di_mode) + { + di_mode_ea += 12; + } + } + } + break; + } + case 0: // Static register list, predecrement addressing mode + { + int imode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + // the "di_mode_ea" parameter kludge is required here else WRITE_EA_FPE would have + // to call EA_AY_DI_32() (that advances PC & reads displacement) each time + // when the proper behaviour is 1) read once, 2) increment ea for each matching register + // this forces to pre-read the mode (named "imode") so we can decide to read displacement, only once + int di_mode = imode == 5; + uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; + for (i=0; i < 8; i++) + { + if (reglist & (1 << i)) + { + WRITE_EA_FPE(imode,reg, REG_FP[i],di_mode_ea); + USE_CYCLES(2); + if (di_mode) + { + di_mode_ea += 12; + } + } + } + break; + } + + default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); + } + } + else // From mem to FP regs + { + switch (mode) + { + case 2: // Static register list, postincrement addressing mode + { + int imode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + int di_mode = imode == 5; + uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; + for (i=0; i < 8; i++) + { + if (reglist & (1 << i)) + { + REG_FP[7-i] = READ_EA_FPE(imode,reg,di_mode_ea); + USE_CYCLES(2); + if (di_mode) + { + di_mode_ea += 12; + } + } + } + break; + } + + default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); + } + } +} + +static void fscc() +{ + // added by JFF, this seems to work properly now + int condition = OPER_I_16() & 0x3f; + + int cc = TEST_CONDITION(condition); + int mode = (REG_IR & 0x38) >> 3; + int v = (cc ? 0xff : 0x00); + + switch (mode) + { + case 0: // fscc Dx + { + // If the specified floating-point condition is true, sets the byte integer operand at + // the destination to TRUE (all ones); otherwise, sets the byte to FALSE (all zeros). + + REG_D[REG_IR & 7] = (REG_D[REG_IR & 7] & 0xFFFFFF00) | v; + break; + } + case 5: // (disp,Ax) + { + int reg = REG_IR & 7; + uint32 ea = REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16()); + m68ki_write_8(ea,v); + break; + } + + default: + { + // unimplemented see fpu_uae.cpp around line 1300 + fatalerror("040fpu0: fscc: mode %d not implemented at %08X\n", mode, REG_PC-4); + } + } + USE_CYCLES(7); // JFF unsure of the number of cycles!! +} +static void fbcc16(void) +{ + sint32 offset; + int condition = REG_IR & 0x3f; + + offset = (sint16)(OPER_I_16()); + + // TODO: condition and jump!!! + if (TEST_CONDITION(condition)) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_16(offset-2); + } + + USE_CYCLES(7); + } + +static void fbcc32(void) +{ + sint32 offset; + int condition = REG_IR & 0x3f; + + offset = OPER_I_32(); + + // TODO: condition and jump!!! + if (TEST_CONDITION(condition)) + { + m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ + m68ki_branch_32(offset-4); + } + + USE_CYCLES(7); +} + + +void m68040_fpu_op0() +{ + m68ki_cpu.fpu_just_reset = 0; + + switch ((REG_IR >> 6) & 0x3) + { + case 0: + { + uint16 w2 = OPER_I_16(); + switch ((w2 >> 13) & 0x7) + { + case 0x0: // FPU ALU FP, FP + case 0x2: // FPU ALU ea, FP + { + fpgen_rm_reg(w2); + break; + } + + case 0x3: // FMOVE FP, ea + { + fmove_reg_mem(w2); + break; + } + + case 0x4: // FMOVEM ea, FPCR + case 0x5: // FMOVEM FPCR, ea + { + fmove_fpcr(w2); + break; + } + + case 0x6: // FMOVEM ea, list + case 0x7: // FMOVEM list, ea + { + fmovem(w2); + break; + } + + default: fatalerror("M68kFPU: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC-4); + } + break; + } + + case 1: // FScc (JFF) + { + fscc(); + break; + } + case 2: // FBcc disp16 + { + fbcc16(); + break; + } + case 3: // FBcc disp32 + { + fbcc32(); + break; + } + + default: fatalerror("M68kFPU: unimplemented main op %d at %08X\n", (m68ki_cpu.ir >> 6) & 0x3, REG_PC-4); + } +} + +static void perform_fsave(uint32 addr, int inc) +{ + if (inc) + { + // 68881 IDLE, version 0x1f + m68ki_write_32(addr, 0x1f180000); + m68ki_write_32(addr+4, 0); + m68ki_write_32(addr+8, 0); + m68ki_write_32(addr+12, 0); + m68ki_write_32(addr+16, 0); + m68ki_write_32(addr+20, 0); + m68ki_write_32(addr+24, 0x70000000); + } + else + { + m68ki_write_32(addr, 0x70000000); + m68ki_write_32(addr-4, 0); + m68ki_write_32(addr-8, 0); + m68ki_write_32(addr-12, 0); + m68ki_write_32(addr-16, 0); + m68ki_write_32(addr-20, 0); + m68ki_write_32(addr-24, 0x1f180000); + } +} + +// FRESTORE on a NULL frame reboots the FPU - all registers to NaN, the 3 status regs to 0 +static void do_frestore_null() +{ + int i; + + REG_FPCR = 0; + REG_FPSR = 0; + REG_FPIAR = 0; + for (i = 0; i < 8; i++) + { + REG_FP[i].high = 0x7fff; + REG_FP[i].low = U64(0xffffffffffffffff); + } + + // Mac IIci at 408458e6 wants an FSAVE of a just-restored NULL frame to also be NULL + // The PRM says it's possible to generate a NULL frame, but not how/when/why. (need the 68881/68882 manual!) + m68ki_cpu.fpu_just_reset = 1; +} + +void m68040_fpu_op1() +{ + int ea = REG_IR & 0x3f; + int mode = (ea >> 3) & 0x7; + int reg = (ea & 0x7); + uint32 addr, temp; + + switch ((REG_IR >> 6) & 0x3) + { + case 0: // FSAVE + { + switch (mode) + { + case 3: // (An)+ + addr = EA_AY_PI_32(); + + if (m68ki_cpu.fpu_just_reset) + { + m68ki_write_32(addr, 0); + } + else + { + // we normally generate an IDLE frame + REG_A[reg] += 6*4; + perform_fsave(addr, 1); + } + break; + + case 4: // -(An) + addr = EA_AY_PD_32(); + + if (m68ki_cpu.fpu_just_reset) + { + m68ki_write_32(addr, 0); + } + else + { + // we normally generate an IDLE frame + REG_A[reg] -= 6*4; + perform_fsave(addr, 0); + } + break; + + default: + fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC); + } + break; + } + break; + + case 1: // FRESTORE + { + switch (mode) + { + case 2: // (An) + addr = REG_A[reg]; + temp = m68ki_read_32(addr); + + // check for NULL frame + if (temp & 0xff000000) + { + // we don't handle non-NULL frames and there's no pre/post inc/dec to do here + m68ki_cpu.fpu_just_reset = 0; + } + else + { + do_frestore_null(); + } + break; + + case 3: // (An)+ + addr = EA_AY_PI_32(); + temp = m68ki_read_32(addr); + + // check for NULL frame + if (temp & 0xff000000) + { + m68ki_cpu.fpu_just_reset = 0; + + // how about an IDLE frame? + if ((temp & 0x00ff0000) == 0x00180000) + { + REG_A[reg] += 6*4; + } // check UNIMP + else if ((temp & 0x00ff0000) == 0x00380000) + { + REG_A[reg] += 14*4; + } // check BUSY + else if ((temp & 0x00ff0000) == 0x00b40000) + { + REG_A[reg] += 45*4; + } + } + else + { + do_frestore_null(); + } + break; + + default: + fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC); + } + break; + } + break; + + default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (REG_IR >> 6) & 0x3, REG_PC-2); + } +} + + + diff --git a/AltairZ80/m68k/m68kmake.c b/AltairZ80/m68k/m68kmake.c index 928ebd2c..af482ced 100644 --- a/AltairZ80/m68k/m68kmake.c +++ b/AltairZ80/m68k/m68kmake.c @@ -1,1408 +1,1408 @@ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 4.60 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * FPU and MMU by R. Belmont. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - - -/* ======================================================================== */ -/* ============================ CODE GENERATOR ============================ */ -/* ======================================================================== */ -/* - * This is the code generator program which will generate the opcode table - * and the final opcode handlers. - * - * It requires an input file to function (default m68k_in.c), but you can - * specify your own like so: - * - * m68kmake - * - * where output path is the path where the output files should be placed, and - * input file is the file to use for input. - * - * If you modify the input file greatly from its released form, you may have - * to tweak the configuration section a bit since I'm using static allocation - * to keep things simple. - * - * - * TODO: - build a better code generator for the move instruction. - * - Add callm and rtm instructions - * - Fix RTE to handle other format words - * - Add address error (and bus error?) handling - */ - - -static const char g_version[] = "4.60"; - -/* ======================================================================== */ -/* =============================== INCLUDES =============================== */ -/* ======================================================================== */ - -#include -#include -#include -#include -#include - - - -/* ======================================================================== */ -/* ============================= CONFIGURATION ============================ */ -/* ======================================================================== */ - -#define M68K_MAX_PATH 1024 -#define M68K_MAX_DIR 1024 - -#define MAX_LINE_LENGTH 200 /* length of 1 line */ -#define MAX_BODY_LENGTH 300 /* Number of lines in 1 function */ -#define MAX_REPLACE_LENGTH 30 /* Max number of replace strings */ -#define MAX_INSERT_LENGTH 5000 /* Max size of insert piece */ -#define MAX_NAME_LENGTH 30 /* Max length of ophandler name */ -#define MAX_SPEC_PROC_LENGTH 4 /* Max length of special processing str */ -#define MAX_SPEC_EA_LENGTH 5 /* Max length of specified EA str */ -#define EA_ALLOWED_LENGTH 11 /* Max length of ea allowed str */ -#define MAX_OPCODE_INPUT_TABLE_LENGTH 1000 /* Max length of opcode handler tbl */ -#define MAX_OPCODE_OUTPUT_TABLE_LENGTH 3000 /* Max length of opcode handler tbl */ - -/* Default filenames */ -#define FILENAME_INPUT "m68k_in.c" -#define FILENAME_PROTOTYPE "m68kops.h" -#define FILENAME_TABLE "m68kops.c" - - -/* Identifier sequences recognized by this program */ - -#define ID_INPUT_SEPARATOR "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - -#define ID_BASE "M68KMAKE" -#define ID_PROTOTYPE_HEADER ID_BASE "_PROTOTYPE_HEADER" -#define ID_PROTOTYPE_FOOTER ID_BASE "_PROTOTYPE_FOOTER" -#define ID_TABLE_HEADER ID_BASE "_TABLE_HEADER" -#define ID_TABLE_FOOTER ID_BASE "_TABLE_FOOTER" -#define ID_TABLE_BODY ID_BASE "_TABLE_BODY" -#define ID_TABLE_START ID_BASE "_TABLE_START" -#define ID_OPHANDLER_HEADER ID_BASE "_OPCODE_HANDLER_HEADER" -#define ID_OPHANDLER_FOOTER ID_BASE "_OPCODE_HANDLER_FOOTER" -#define ID_OPHANDLER_BODY ID_BASE "_OPCODE_HANDLER_BODY" -#define ID_END ID_BASE "_END" - -#define ID_OPHANDLER_NAME ID_BASE "_OP" -#define ID_OPHANDLER_EA_AY_8 ID_BASE "_GET_EA_AY_8" -#define ID_OPHANDLER_EA_AY_16 ID_BASE "_GET_EA_AY_16" -#define ID_OPHANDLER_EA_AY_32 ID_BASE "_GET_EA_AY_32" -#define ID_OPHANDLER_OPER_AY_8 ID_BASE "_GET_OPER_AY_8" -#define ID_OPHANDLER_OPER_AY_16 ID_BASE "_GET_OPER_AY_16" -#define ID_OPHANDLER_OPER_AY_32 ID_BASE "_GET_OPER_AY_32" -#define ID_OPHANDLER_CC ID_BASE "_CC" -#define ID_OPHANDLER_NOT_CC ID_BASE "_NOT_CC" - - -#ifndef DECL_SPEC -#define DECL_SPEC -#endif /* DECL_SPEC */ - - - -/* ======================================================================== */ -/* ============================== PROTOTYPES ============================== */ -/* ======================================================================== */ - -enum { - CPU_TYPE_000=0, - CPU_TYPE_010, - CPU_TYPE_020, - CPU_TYPE_030, - CPU_TYPE_040, - NUM_CPUS -}; - -#define UNSPECIFIED "." -#define UNSPECIFIED_CH '.' - -#define HAS_NO_EA_MODE(A) (strcmp(A, "..........") == 0) -#define HAS_EA_AI(A) ((A)[0] == 'A') -#define HAS_EA_PI(A) ((A)[1] == '+') -#define HAS_EA_PD(A) ((A)[2] == '-') -#define HAS_EA_DI(A) ((A)[3] == 'D') -#define HAS_EA_IX(A) ((A)[4] == 'X') -#define HAS_EA_AW(A) ((A)[5] == 'W') -#define HAS_EA_AL(A) ((A)[6] == 'L') -#define HAS_EA_PCDI(A) ((A)[7] == 'd') -#define HAS_EA_PCIX(A) ((A)[8] == 'x') -#define HAS_EA_I(A) ((A)[9] == 'I') - -enum -{ - EA_MODE_NONE, /* No special addressing mode */ - EA_MODE_AI, /* Address register indirect */ - EA_MODE_PI, /* Address register indirect with postincrement */ - EA_MODE_PI7, /* Address register 7 indirect with postincrement */ - EA_MODE_PD, /* Address register indirect with predecrement */ - EA_MODE_PD7, /* Address register 7 indirect with predecrement */ - EA_MODE_DI, /* Address register indirect with displacement */ - EA_MODE_IX, /* Address register indirect with index */ - EA_MODE_AW, /* Absolute word */ - EA_MODE_AL, /* Absolute long */ - EA_MODE_PCDI, /* Program counter indirect with displacement */ - EA_MODE_PCIX, /* Program counter indirect with index */ - EA_MODE_I /* Immediate */ -}; - - -/* Everything we need to know about an opcode */ -typedef struct -{ - char name[MAX_NAME_LENGTH]; /* opcode handler name */ - unsigned char size; /* Size of operation */ - char spec_proc[MAX_SPEC_PROC_LENGTH]; /* Special processing mode */ - char spec_ea[MAX_SPEC_EA_LENGTH]; /* Specified effective addressing mode */ - unsigned char bits; /* Number of significant bits (used for sorting the table) */ - unsigned short op_mask; /* Mask to apply for matching an opcode to a handler */ - unsigned short op_match; /* Value to match after masking */ - char ea_allowed[EA_ALLOWED_LENGTH]; /* Effective addressing modes allowed */ - char cpu_mode[NUM_CPUS]; /* User or supervisor mode */ - char cpus[NUM_CPUS+1]; /* Allowed CPUs */ - unsigned char cycles[NUM_CPUS]; /* cycles for 000, 010, 020, 030, 040 */ -} opcode_struct; - - -/* All modifications necessary for a specific EA mode of an instruction */ -typedef struct -{ - char* fname_add; - char* ea_add; - unsigned int mask_add; - unsigned int match_add; -} ea_info_struct; - - -/* Holds the body of a function */ -typedef struct -{ - char body[MAX_BODY_LENGTH][MAX_LINE_LENGTH+1]; - int length; -} body_struct; - - -/* Holds a sequence of search / replace strings */ -typedef struct -{ - char replace[MAX_REPLACE_LENGTH][2][MAX_LINE_LENGTH+1]; - int length; -} replace_struct; - - -/* Function Prototypes */ -void error_exit(const char* fmt, ...); -void perror_exit(const char* fmt, ...); -int check_strsncpy(char* dst, char* src, int maxlength); -int check_atoi(char* str, int *result); -int skip_spaces(char* str); -int num_bits(int value); -int atoh(char* buff); -int fgetline(char* buff, int nchars, FILE* file); -int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type); -opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea); -opcode_struct* find_illegal_opcode(void); -int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea); -void add_replace_string(replace_struct* replace, char* search_str, char* replace_str); -void write_body(FILE* filep, body_struct* body, replace_struct* replace); -void get_base_name(char* base_name, opcode_struct* op); -void write_function_name(FILE* filep, char* base_name); -void add_opcode_output_table_entry(opcode_struct* op, char* name); -static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr); -void print_opcode_output_table(FILE* filep); -void write_table_entry(FILE* filep, opcode_struct* op); -void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode); -void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode); -void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op); -void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset); -void process_opcode_handlers(FILE* filep); -void populate_table(void); -void read_insert(char* insert); - - - -/* ======================================================================== */ -/* ================================= DATA ================================= */ -/* ======================================================================== */ - -/* Name of the input file */ -char g_input_filename[M68K_MAX_PATH] = FILENAME_INPUT; - -/* File handles */ -FILE* g_input_file = NULL; -FILE* g_prototype_file = NULL; -FILE* g_table_file = NULL; - -int g_num_functions = 0; /* Number of functions processed */ -int g_num_primitives = 0; /* Number of function primitives read */ -int g_line_number = 1; /* Current line number */ - -/* Opcode handler table */ -opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH]; - -opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH]; -int g_opcode_output_table_length = 0; - -const ea_info_struct g_ea_info_table[13] = -{/* fname ea mask match */ - {"", "", 0x00, 0x00}, /* EA_MODE_NONE */ - {"ai", "AY_AI", 0x38, 0x10}, /* EA_MODE_AI */ - {"pi", "AY_PI", 0x38, 0x18}, /* EA_MODE_PI */ - {"pi7", "A7_PI", 0x3f, 0x1f}, /* EA_MODE_PI7 */ - {"pd", "AY_PD", 0x38, 0x20}, /* EA_MODE_PD */ - {"pd7", "A7_PD", 0x3f, 0x27}, /* EA_MODE_PD7 */ - {"di", "AY_DI", 0x38, 0x28}, /* EA_MODE_DI */ - {"ix", "AY_IX", 0x38, 0x30}, /* EA_MODE_IX */ - {"aw", "AW", 0x3f, 0x38}, /* EA_MODE_AW */ - {"al", "AL", 0x3f, 0x39}, /* EA_MODE_AL */ - {"pcdi", "PCDI", 0x3f, 0x3a}, /* EA_MODE_PCDI */ - {"pcix", "PCIX", 0x3f, 0x3b}, /* EA_MODE_PCIX */ - {"i", "I", 0x3f, 0x3c}, /* EA_MODE_I */ -}; - - -const char *const g_cc_table[16][2] = -{ - { "t", "T"}, /* 0000 */ - { "f", "F"}, /* 0001 */ - {"hi", "HI"}, /* 0010 */ - {"ls", "LS"}, /* 0011 */ - {"cc", "CC"}, /* 0100 */ - {"cs", "CS"}, /* 0101 */ - {"ne", "NE"}, /* 0110 */ - {"eq", "EQ"}, /* 0111 */ - {"vc", "VC"}, /* 1000 */ - {"vs", "VS"}, /* 1001 */ - {"pl", "PL"}, /* 1010 */ - {"mi", "MI"}, /* 1011 */ - {"ge", "GE"}, /* 1100 */ - {"lt", "LT"}, /* 1101 */ - {"gt", "GT"}, /* 1110 */ - {"le", "LE"}, /* 1111 */ -}; - -/* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */ -const int g_size_select_table[33] = -{ - 0, /* unsized */ - 0, 0, 0, 0, 0, 0, 0, 1, /* 8 */ - 0, 0, 0, 0, 0, 0, 0, 1, /* 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* 32 */ -}; - -/* Extra cycles required for certain EA modes */ -/* TODO: correct timings for 030, 040 */ -const int g_ea_cycle_table[13][NUM_CPUS][3] = -{/* 000 010 020 030 040 */ - {{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */ - {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AI */ - {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI */ - {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI7 */ - {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD */ - {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD7 */ - {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_DI */ - {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_IX */ - {{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AW */ - {{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AL */ - {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PCDI */ - {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_PCIX */ - {{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}, { 0, 2, 4}, { 0, 2, 4}}, /* EA_MODE_I */ -}; - -/* Extra cycles for JMP instruction (000, 010) */ -const int g_jmp_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 4, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 6, /* EA_MODE_DI */ - 10, /* EA_MODE_IX */ - 6, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 6, /* EA_MODE_PCDI */ - 10, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for JSR instruction (000, 010) */ -const int g_jsr_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 4, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 6, /* EA_MODE_DI */ - 10, /* EA_MODE_IX */ - 6, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 6, /* EA_MODE_PCDI */ - 10, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for LEA instruction (000, 010) */ -const int g_lea_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 4, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 8, /* EA_MODE_DI */ - 12, /* EA_MODE_IX */ - 8, /* EA_MODE_AW */ - 12, /* EA_MODE_AL */ - 8, /* EA_MODE_PCDI */ - 12, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for PEA instruction (000, 010) */ -const int g_pea_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 6, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 10, /* EA_MODE_DI */ - 14, /* EA_MODE_IX */ - 10, /* EA_MODE_AW */ - 14, /* EA_MODE_AL */ - 10, /* EA_MODE_PCDI */ - 14, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for MOVEM instruction (000, 010) */ -const int g_movem_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 0, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 4, /* EA_MODE_DI */ - 6, /* EA_MODE_IX */ - 4, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 0, /* EA_MODE_PCDI */ - 0, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for MOVES instruction (010) */ -const int g_moves_cycle_table[13][3] = -{ - { 0, 0, 0}, /* EA_MODE_NONE */ - { 0, 4, 6}, /* EA_MODE_AI */ - { 0, 4, 6}, /* EA_MODE_PI */ - { 0, 4, 6}, /* EA_MODE_PI7 */ - { 0, 6, 12}, /* EA_MODE_PD */ - { 0, 6, 12}, /* EA_MODE_PD7 */ - { 0, 12, 16}, /* EA_MODE_DI */ - { 0, 16, 20}, /* EA_MODE_IX */ - { 0, 12, 16}, /* EA_MODE_AW */ - { 0, 16, 20}, /* EA_MODE_AL */ - { 0, 0, 0}, /* EA_MODE_PCDI */ - { 0, 0, 0}, /* EA_MODE_PCIX */ - { 0, 0, 0}, /* EA_MODE_I */ -}; - -/* Extra cycles for CLR instruction (010) */ -const int g_clr_cycle_table[13][3] = -{ - { 0, 0, 0}, /* EA_MODE_NONE */ - { 0, 4, 6}, /* EA_MODE_AI */ - { 0, 4, 6}, /* EA_MODE_PI */ - { 0, 4, 6}, /* EA_MODE_PI7 */ - { 0, 6, 8}, /* EA_MODE_PD */ - { 0, 6, 8}, /* EA_MODE_PD7 */ - { 0, 8, 10}, /* EA_MODE_DI */ - { 0, 10, 14}, /* EA_MODE_IX */ - { 0, 8, 10}, /* EA_MODE_AW */ - { 0, 10, 14}, /* EA_MODE_AL */ - { 0, 0, 0}, /* EA_MODE_PCDI */ - { 0, 0, 0}, /* EA_MODE_PCIX */ - { 0, 0, 0}, /* EA_MODE_I */ -}; - - - -/* ======================================================================== */ -/* =========================== UTILITY FUNCTIONS ========================== */ -/* ======================================================================== */ - -/* Print an error message and exit with status error */ -void error_exit(const char* fmt, ...) -{ - va_list args; - fprintf(stderr, "In %s, near or on line %d:\n\t", g_input_filename, g_line_number); - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - fprintf(stderr, "\n"); - - if(g_prototype_file) fclose(g_prototype_file); - if(g_table_file) fclose(g_table_file); - if(g_input_file) fclose(g_input_file); - - exit(EXIT_FAILURE); -} - -/* Print an error message, call perror(), and exit with status error */ -void perror_exit(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - perror(""); - - if(g_prototype_file) fclose(g_prototype_file); - if(g_table_file) fclose(g_table_file); - if(g_input_file) fclose(g_input_file); - - exit(EXIT_FAILURE); -} - - -/* copy until 0 or space and exit with error if we read too far */ -int check_strsncpy(char* dst, char* src, int maxlength) -{ - char* p = dst; - while(*src && *src != ' ') - { - *p++ = *src++; - if(p - dst > maxlength) - error_exit("Field too long"); - } - *p = 0; - return p - dst; -} - -/* copy until 0 or specified character and exit with error if we read too far */ -int check_strcncpy(char* dst, char* src, char delim, int maxlength) -{ - char* p = dst; - while(*src && *src != delim) - { - *p++ = *src++; - if(p - dst > maxlength) - error_exit("Field too long"); - } - *p = 0; - return p - dst; -} - -/* convert ascii to integer and exit with error if we find invalid data */ -int check_atoi(char* str, int *result) -{ - int accum = 0; - char* p = str; - while(*p >= '0' && *p <= '9') - { - accum *= 10; - accum += *p++ - '0'; - } - if(*p != ' ' && *p != 0) - error_exit("Malformed integer value (%c)", *p); - *result = accum; - return p - str; -} - -/* Skip past spaces in a string */ -int skip_spaces(char* str) -{ - char* p = str; - - while(*p == ' ') - p++; - - return p - str; -} - -/* Count the number of set bits in a value */ -int num_bits(int value) -{ - value = ((value & 0xaaaa) >> 1) + (value & 0x5555); - value = ((value & 0xcccc) >> 2) + (value & 0x3333); - value = ((value & 0xf0f0) >> 4) + (value & 0x0f0f); - value = ((value & 0xff00) >> 8) + (value & 0x00ff); - return value; -} - -/* Convert a hex value written in ASCII */ -int atoh(char* buff) -{ - int accum = 0; - - for(;;buff++) - { - if(*buff >= '0' && *buff <= '9') - { - accum <<= 4; - accum += *buff - '0'; - } - else if(*buff >= 'a' && *buff <= 'f') - { - accum <<= 4; - accum += *buff - 'a' + 10; - } - else break; - } - return accum; -} - -/* Get a line of text from a file, discarding any end-of-line characters */ -int fgetline(char* buff, int nchars, FILE* file) -{ - int length; - - if(fgets(buff, nchars, file) == NULL) - return -1; - if(buff[0] == '\r') - memmove(buff, buff + 1, nchars - 1); - - length = strlen(buff); - while(length && (buff[length-1] == '\r' || buff[length-1] == '\n')) - length--; - buff[length] = 0; - g_line_number++; - - return length; -} - - - -/* ======================================================================== */ -/* =========================== HELPER FUNCTIONS =========================== */ -/* ======================================================================== */ - -/* Calculate the number of cycles an opcode requires */ -int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type) -{ - int size = g_size_select_table[op->size]; - - if(op->cpus[cpu_type] == '.') - return 0; - - if(cpu_type < CPU_TYPE_020) - { - if(cpu_type == CPU_TYPE_010) - { - if(strcmp(op->name, "moves") == 0) - return op->cycles[cpu_type] + g_moves_cycle_table[ea_mode][size]; - if(strcmp(op->name, "clr") == 0) - return op->cycles[cpu_type] + g_clr_cycle_table[ea_mode][size]; - } - - /* ASG: added these cases -- immediate modes take 2 extra cycles here */ - if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I && - ((strcmp(op->name, "add") == 0 && strcmp(op->spec_proc, "er") == 0) || - strcmp(op->name, "adda") == 0 || - (strcmp(op->name, "and") == 0 && strcmp(op->spec_proc, "er") == 0) || - (strcmp(op->name, "or") == 0 && strcmp(op->spec_proc, "er") == 0) || - (strcmp(op->name, "sub") == 0 && strcmp(op->spec_proc, "er") == 0) || - strcmp(op->name, "suba") == 0)) - return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2; - - if(strcmp(op->name, "jmp") == 0) - return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode]; - if(strcmp(op->name, "jsr") == 0) - return op->cycles[cpu_type] + g_jsr_cycle_table[ea_mode]; - if(strcmp(op->name, "lea") == 0) - return op->cycles[cpu_type] + g_lea_cycle_table[ea_mode]; - if(strcmp(op->name, "pea") == 0) - return op->cycles[cpu_type] + g_pea_cycle_table[ea_mode]; - if(strcmp(op->name, "movem") == 0) - return op->cycles[cpu_type] + g_movem_cycle_table[ea_mode]; - } - return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size]; -} - -/* Find an opcode in the opcode handler list */ -opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea) -{ - opcode_struct* op; - - - for(op = g_opcode_input_table;op < &g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];op++) - { - if( strcmp(name, op->name) == 0 && - (size == op->size) && - strcmp(spec_proc, op->spec_proc) == 0 && - strcmp(spec_ea, op->spec_ea) == 0) - return op; - } - return NULL; -} - -/* Specifically find the illegal opcode in the list */ -opcode_struct* find_illegal_opcode(void) -{ - opcode_struct* op; - - for(op = g_opcode_input_table;op < &g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];op++) - { - if(strcmp(op->name, "illegal") == 0) - return op; - } - return NULL; -} - -/* Parse an opcode handler name */ -int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea) -{ - char* ptr = strstr(src, ID_OPHANDLER_NAME); - - if(ptr == NULL) - return 0; - - ptr += strlen(ID_OPHANDLER_NAME) + 1; - - ptr += check_strcncpy(name, ptr, ',', MAX_NAME_LENGTH); - if(*ptr != ',') return 0; - ptr++; - ptr += skip_spaces(ptr); - - *size = atoi(ptr); - ptr = strstr(ptr, ","); - if(ptr == NULL) return 0; - ptr++; - ptr += skip_spaces(ptr); - - ptr += check_strcncpy(spec_proc, ptr, ',', MAX_SPEC_PROC_LENGTH); - if(*ptr != ',') return 0; - ptr++; - ptr += skip_spaces(ptr); - - ptr += check_strcncpy(spec_ea, ptr, ')', MAX_SPEC_EA_LENGTH); - if(*ptr != ')') return 0; - ptr++; - ptr += skip_spaces(ptr); - - return 1; -} - - -/* Add a search/replace pair to a replace structure */ -void add_replace_string(replace_struct* replace, char* search_str, char* replace_str) -{ - if(replace->length >= MAX_REPLACE_LENGTH) - error_exit("overflow in replace structure"); - - strcpy(replace->replace[replace->length][0], search_str); - strcpy(replace->replace[replace->length++][1], replace_str); -} - -/* Write a function body while replacing any selected strings */ -void write_body(FILE* filep, body_struct* body, replace_struct* replace) -{ - int i; - int j; - char* ptr; - char output[MAX_LINE_LENGTH+1]; - char temp_buff[MAX_LINE_LENGTH+1]; - int found; - - for(i=0;ilength;i++) - { - strcpy(output, body->body[i]); - /* Check for the base directive header */ - if(strstr(output, ID_BASE) != NULL) - { - /* Search for any text we need to replace */ - found = 0; - for(j=0;jlength;j++) - { - ptr = strstr(output, replace->replace[j][0]); - if(ptr) - { - /* We found something to replace */ - found = 1; - strcpy(temp_buff, ptr+strlen(replace->replace[j][0])); - strcpy(ptr, replace->replace[j][1]); - strcat(ptr, temp_buff); - } - } - /* Found a directive with no matching replace string */ - if(!found) - error_exit("Unknown " ID_BASE " directive [%s]", output); - } - fprintf(filep, "%s\n", output); - } - fprintf(filep, "\n\n"); -} - -/* Generate a base function name from an opcode struct */ -void get_base_name(char* base_name, opcode_struct* op) -{ - sprintf(base_name, "m68k_op_%s", op->name); - if(op->size > 0) - sprintf(base_name+strlen(base_name), "_%d", op->size); - if(strcmp(op->spec_proc, UNSPECIFIED) != 0) - sprintf(base_name+strlen(base_name), "_%s", op->spec_proc); - if(strcmp(op->spec_ea, UNSPECIFIED) != 0) - sprintf(base_name+strlen(base_name), "_%s", op->spec_ea); -} - -/* Write the name of an opcode handler function */ -void write_function_name(FILE* filep, char* base_name) -{ - fprintf(filep, "static void %s(void)\n", base_name); -} - -void add_opcode_output_table_entry(opcode_struct* op, char* name) -{ - opcode_struct* ptr; - if(g_opcode_output_table_length > MAX_OPCODE_OUTPUT_TABLE_LENGTH) - error_exit("Opcode output table overflow"); - - ptr = g_opcode_output_table + g_opcode_output_table_length++; - - *ptr = *op; - strcpy(ptr->name, name); - ptr->bits = num_bits(ptr->op_mask); -} - -/* - * Comparison function for qsort() - * For entries with an equal number of set bits in - * the mask compare the match values - */ -static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr) -{ - const opcode_struct *a = aptr, *b = bptr; - if(a->bits != b->bits) - return a->bits - b->bits; - if(a->op_mask != b->op_mask) - return a->op_mask - b->op_mask; - return a->op_match - b->op_match; -} - -void print_opcode_output_table(FILE* filep) -{ - int i; - qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits); - - for(i=0;iname, op->op_mask, op->op_match); - - for(i=0;icycles[i]); - if(i < NUM_CPUS-1) - fprintf(filep, ", "); - } - - fprintf(filep, "}},\n"); -} - -/* Fill out an opcode struct with a specific addressing mode of the source opcode struct */ -void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode) -{ - int i; - - *dst = *src; - - for(i=0;icycles[i] = get_oper_cycles(dst, ea_mode, i); - if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE) - sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add); - dst->op_mask |= g_ea_info_table[ea_mode].mask_add; - dst->op_match |= g_ea_info_table[ea_mode].match_add; -} - - -/* Generate a final opcode handler from the provided data */ -void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode) -{ - char str[MAX_LINE_LENGTH+1]; - opcode_struct* op = malloc(sizeof(opcode_struct)); - - /* Set the opcode structure and write the tables, prototypes, etc */ - set_opcode_struct(opinfo, op, ea_mode); - get_base_name(str, op); - add_opcode_output_table_entry(op, str); - write_function_name(filep, str); - - /* Add any replace strings needed */ - if(ea_mode != EA_MODE_NONE) - { - sprintf(str, "EA_%s_8()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str); - sprintf(str, "EA_%s_16()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str); - sprintf(str, "EA_%s_32()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str); - sprintf(str, "OPER_%s_8()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str); - sprintf(str, "OPER_%s_16()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str); - sprintf(str, "OPER_%s_32()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str); - } - - /* Now write the function body with the selected replace strings */ - write_body(filep, body, replace); - g_num_functions++; - free(op); -} - -/* Generate opcode variants based on available addressing modes */ -void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op) -{ - int old_length = replace->length; - - /* No ea modes available for this opcode */ - if(HAS_NO_EA_MODE(op->ea_allowed)) - { - generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE); - return; - } - - /* Check for and create specific opcodes for each available addressing mode */ - if(HAS_EA_AI(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_AI); - replace->length = old_length; - if(HAS_EA_PI(op->ea_allowed)) - { - generate_opcode_handler(filep, body, replace, op, EA_MODE_PI); - replace->length = old_length; - if(op->size == 8) - generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7); - } - replace->length = old_length; - if(HAS_EA_PD(op->ea_allowed)) - { - generate_opcode_handler(filep, body, replace, op, EA_MODE_PD); - replace->length = old_length; - if(op->size == 8) - generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7); - } - replace->length = old_length; - if(HAS_EA_DI(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_DI); - replace->length = old_length; - if(HAS_EA_IX(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_IX); - replace->length = old_length; - if(HAS_EA_AW(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_AW); - replace->length = old_length; - if(HAS_EA_AL(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_AL); - replace->length = old_length; - if(HAS_EA_PCDI(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI); - replace->length = old_length; - if(HAS_EA_PCIX(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX); - replace->length = old_length; - if(HAS_EA_I(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_I); - replace->length = old_length; -} - -/* Generate variants of condition code opcodes */ -void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset) -{ - char repl[20]; - char replnot[20]; - int i; - int old_length = replace->length; - opcode_struct* op = malloc(sizeof(opcode_struct)); - - *op = *op_in; - - op->op_mask |= 0x0f00; - - /* Do all condition codes except t and f */ - for(i=2;i<16;i++) - { - /* Add replace strings for this condition code */ - sprintf(repl, "COND_%s()", g_cc_table[i][1]); - sprintf(replnot, "COND_NOT_%s()", g_cc_table[i][1]); - - add_replace_string(replace, ID_OPHANDLER_CC, repl); - add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot); - - /* Set the new opcode info */ - strcpy(op->name+offset, g_cc_table[i][0]); - - op->op_match = (op->op_match & 0xf0ff) | (i<<8); - - /* Generate all opcode variants for this modified opcode */ - generate_opcode_ea_variants(filep, body, replace, op); - /* Remove the above replace strings */ - replace->length = old_length; - } - free(op); -} - -/* Process the opcode handlers section of the input file */ -void process_opcode_handlers(FILE* filep) -{ - FILE* input_file = g_input_file; - char func_name[MAX_LINE_LENGTH+1]; - char oper_name[MAX_LINE_LENGTH+1]; - int oper_size; - char oper_spec_proc[MAX_LINE_LENGTH+1]; - char oper_spec_ea[MAX_LINE_LENGTH+1]; - opcode_struct* opinfo; - replace_struct* replace = malloc(sizeof(replace_struct)); - body_struct* body = malloc(sizeof(body_struct)); - - for(;;) - { - /* Find the first line of the function */ - func_name[0] = 0; - while(strstr(func_name, ID_OPHANDLER_NAME) == NULL) - { - if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0) - { - free(replace); - free(body); - return; /* all done */ - } - if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0) - error_exit("Premature end of file when getting function name"); - } - /* Get the rest of the function */ - for(body->length=0;;body->length++) - { - if(body->length > MAX_BODY_LENGTH) - error_exit("Function too long"); - - if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0) - error_exit("Premature end of file when getting function body"); - - if(body->body[body->length][0] == '}') - { - body->length++; - break; - } - } - - g_num_primitives++; - - /* Extract the function name information */ - if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea)) - error_exit("Invalid " ID_OPHANDLER_NAME " format"); - - /* Find the corresponding table entry */ - opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea); - if(opinfo == NULL) - error_exit("Unable to find matching table entry for %s", func_name); - - replace->length = 0; - - /* Generate opcode variants */ - if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0) - generate_opcode_cc_variants(filep, body, replace, opinfo, 1); - else if(strcmp(opinfo->name, "dbcc") == 0) - generate_opcode_cc_variants(filep, body, replace, opinfo, 2); - else if(strcmp(opinfo->name, "trapcc") == 0) - generate_opcode_cc_variants(filep, body, replace, opinfo, 4); - else - generate_opcode_ea_variants(filep, body, replace, opinfo); - } - - free(replace); - free(body); -} - - -/* Populate the opcode handler table from the input file */ -void populate_table(void) -{ - char* ptr; - char bitpattern[17]; - opcode_struct* op; - char buff[MAX_LINE_LENGTH]; - int i; - int temp; - - buff[0] = 0; - - /* Find the start of the table */ - while(strcmp(buff, ID_TABLE_START) != 0) - if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) - error_exit("(table_start) Premature EOF while reading table"); - - /* Process the entire table */ - for(op = g_opcode_input_table;;op++) - { - if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) - error_exit("(inline) Premature EOF while reading table"); - if(strlen(buff) == 0) - continue; - /* We finish when we find an input separator */ - if(strcmp(buff, ID_INPUT_SEPARATOR) == 0) - break; - - /* Extract the info from the table */ - ptr = buff; - - /* Name */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH); - - /* Size */ - ptr += skip_spaces(ptr); - ptr += check_atoi(ptr, &temp); - op->size = (unsigned char)temp; - - /* Special processing */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH); - - /* Specified EA Mode */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH); - - /* Bit Pattern (more processing later) */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(bitpattern, ptr, 17); - - /* Allowed Addressing Mode List */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH); - - /* CPU operating mode (U = user or supervisor, S = supervisor only */ - ptr += skip_spaces(ptr); - for(i=0;icpu_mode[i] = *ptr++; - ptr += skip_spaces(ptr); - } - - /* Allowed CPUs for this instruction */ - for(i=0;icpus[i] = UNSPECIFIED_CH; - op->cycles[i] = 0; - ptr++; - } - else - { - op->cpus[i] = '0' + i; - ptr += check_atoi(ptr, &temp); - op->cycles[i] = (unsigned char)temp; - } - } - - /* generate mask and match from bitpattern */ - op->op_mask = 0; - op->op_match = 0; - for(i=0;i<16;i++) - { - op->op_mask |= (bitpattern[i] != '.') << (15-i); - op->op_match |= (bitpattern[i] == '1') << (15-i); - } - } - /* Terminate the list */ - op->name[0] = 0; -} - -/* Read a header or footer insert from the input file */ -void read_insert(char* insert) -{ - char* ptr = insert; - char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH; - int length; - char* first_blank = NULL; - - first_blank = NULL; - - /* Skip any leading blank lines */ - for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) - if(ptr >= overflow) - error_exit("Buffer overflow reading inserts"); - if(length < 0) - error_exit("Premature EOF while reading inserts"); - - /* Advance and append newline */ - ptr += length; - strcpy(ptr++, "\n"); - - /* Read until next separator */ - for(;;) - { - /* Read a new line */ - if(ptr >= overflow) - error_exit("Buffer overflow reading inserts"); - if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0) - error_exit("Premature EOF while reading inserts"); - - /* Stop if we read a separator */ - if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0) - break; - - /* keep track in case there are trailing blanks */ - if(length == 0) - { - if(first_blank == NULL) - first_blank = ptr; - } - else - first_blank = NULL; - - /* Advance and append newline */ - ptr += length; - strcpy(ptr++, "\n"); - } - - /* kill any trailing blank lines */ - if(first_blank) - ptr = first_blank; - *ptr++ = 0; -} - - - -/* ======================================================================== */ -/* ============================= MAIN FUNCTION ============================ */ -/* ======================================================================== */ - -int main(int argc, char **argv) -{ - /* File stuff */ - char output_path[M68K_MAX_DIR] = ""; - char filename[M68K_MAX_PATH*2]; - /* Section identifier */ - char section_id[MAX_LINE_LENGTH+1]; - /* Inserts */ - char temp_insert[MAX_INSERT_LENGTH+1]; - char prototype_footer_insert[MAX_INSERT_LENGTH+1]; - char table_header_insert[MAX_INSERT_LENGTH+1]; - char table_footer_insert[MAX_INSERT_LENGTH+1]; - char ophandler_header_insert[MAX_INSERT_LENGTH+1]; - char ophandler_footer_insert[MAX_INSERT_LENGTH+1]; - /* Flags if we've processed certain parts already */ - int prototype_header_read = 0; - int prototype_footer_read = 0; - int table_header_read = 0; - int table_footer_read = 0; - int ophandler_header_read = 0; - int ophandler_footer_read = 0; - int table_body_read = 0; - int ophandler_body_read = 0; - - printf("\n\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, 68040 emulator\n", g_version); - printf("\t\tCopyright Karl Stenerud (kstenerud@gmail.com)\n\n"); - - /* Check if output path and source for the input file are given */ - if(argc > 1) - { - char *ptr; - strcpy(output_path, argv[1]); - - for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\')) - *ptr = '/'; - if(output_path[strlen(output_path)-1] != '/') - strcat(output_path, "/"); - if(argc > 2) - strcpy(g_input_filename, argv[2]); - } - - - /* Open the files we need */ - sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE); - if((g_prototype_file = fopen(filename, "wt")) == NULL) - perror_exit("Unable to create prototype file (%s)\n", filename); - - sprintf(filename, "%s%s", output_path, FILENAME_TABLE); - if((g_table_file = fopen(filename, "wt")) == NULL) - perror_exit("Unable to create table file (%s)\n", filename); - - if((g_input_file=fopen(g_input_filename, "rt")) == NULL) - perror_exit("can't open %s for input", g_input_filename); - - - /* Get to the first section of the input file */ - section_id[0] = 0; - while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0) - if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) - error_exit("Premature EOF while reading input file"); - - /* Now process all sections */ - for(;;) - { - if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) - error_exit("Premature EOF while reading input file"); - if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0) - { - if(prototype_header_read) - error_exit("Duplicate prototype header"); - read_insert(temp_insert); - fprintf(g_prototype_file, "%s\n\n", temp_insert); - prototype_header_read = 1; - } - else if(strcmp(section_id, ID_TABLE_HEADER) == 0) - { - if(table_header_read) - error_exit("Duplicate table header"); - read_insert(table_header_insert); - table_header_read = 1; - } - else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0) - { - if(ophandler_header_read) - error_exit("Duplicate opcode handler header"); - read_insert(ophandler_header_insert); - ophandler_header_read = 1; - } - else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0) - { - if(prototype_footer_read) - error_exit("Duplicate prototype footer"); - read_insert(prototype_footer_insert); - prototype_footer_read = 1; - } - else if(strcmp(section_id, ID_TABLE_FOOTER) == 0) - { - if(table_footer_read) - error_exit("Duplicate table footer"); - read_insert(table_footer_insert); - table_footer_read = 1; - } - else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0) - { - if(ophandler_footer_read) - error_exit("Duplicate opcode handler footer"); - read_insert(ophandler_footer_insert); - ophandler_footer_read = 1; - } - else if(strcmp(section_id, ID_TABLE_BODY) == 0) - { - if(!prototype_header_read) - error_exit("Table body encountered before prototype header"); - if(!table_header_read) - error_exit("Table body encountered before table header"); - if(!ophandler_header_read) - error_exit("Table body encountered before opcode handler header"); - - if(table_body_read) - error_exit("Duplicate table body"); - - populate_table(); - table_body_read = 1; - } - else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0) - { - if(!prototype_header_read) - error_exit("Opcode handlers encountered before prototype header"); - if(!table_header_read) - error_exit("Opcode handlers encountered before table header"); - if(!ophandler_header_read) - error_exit("Opcode handlers encountered before opcode handler header"); - if(!table_body_read) - error_exit("Opcode handlers encountered before table body"); - - if(ophandler_body_read) - error_exit("Duplicate opcode handler section"); - - fprintf(g_table_file, "%s\n\n", ophandler_header_insert); - process_opcode_handlers(g_table_file); - fprintf(g_table_file, "%s\n\n", ophandler_footer_insert); - - ophandler_body_read = 1; - } - else if(strcmp(section_id, ID_END) == 0) - { - /* End of input file. Do a sanity check and then write footers */ - if(!prototype_header_read) - error_exit("Missing prototype header"); - if(!prototype_footer_read) - error_exit("Missing prototype footer"); - if(!table_header_read) - error_exit("Missing table header"); - if(!table_footer_read) - error_exit("Missing table footer"); - if(!table_body_read) - error_exit("Missing table body"); - if(!ophandler_header_read) - error_exit("Missing opcode handler header"); - if(!ophandler_footer_read) - error_exit("Missing opcode handler footer"); - if(!ophandler_body_read) - error_exit("Missing opcode handler body"); - - fprintf(g_table_file, "%s\n\n", table_header_insert); - print_opcode_output_table(g_table_file); - fprintf(g_table_file, "%s\n\n", table_footer_insert); - - fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert); - - break; - } - else - { - error_exit("Unknown section identifier: %s", section_id); - } - } - - /* Close all files and exit */ - fclose(g_prototype_file); - fclose(g_table_file); - fclose(g_input_file); - - printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives); - - return 0; -} - - - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ +/* ======================================================================== */ +/* ========================= LICENSING & COPYRIGHT ======================== */ +/* ======================================================================== */ +/* + * MUSASHI + * Version 4.60 + * + * A portable Motorola M680x0 processor emulation engine. + * Copyright Karl Stenerud. All rights reserved. + * FPU and MMU by R. Belmont. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + + +/* ======================================================================== */ +/* ============================ CODE GENERATOR ============================ */ +/* ======================================================================== */ +/* + * This is the code generator program which will generate the opcode table + * and the final opcode handlers. + * + * It requires an input file to function (default m68k_in.c), but you can + * specify your own like so: + * + * m68kmake + * + * where output path is the path where the output files should be placed, and + * input file is the file to use for input. + * + * If you modify the input file greatly from its released form, you may have + * to tweak the configuration section a bit since I'm using static allocation + * to keep things simple. + * + * + * TODO: - build a better code generator for the move instruction. + * - Add callm and rtm instructions + * - Fix RTE to handle other format words + * - Add address error (and bus error?) handling + */ + + +static const char g_version[] = "4.60"; + +/* ======================================================================== */ +/* =============================== INCLUDES =============================== */ +/* ======================================================================== */ + +#include +#include +#include +#include +#include + + + +/* ======================================================================== */ +/* ============================= CONFIGURATION ============================ */ +/* ======================================================================== */ + +#define M68K_MAX_PATH 1024 +#define M68K_MAX_DIR 1024 + +#define MAX_LINE_LENGTH 200 /* length of 1 line */ +#define MAX_BODY_LENGTH 300 /* Number of lines in 1 function */ +#define MAX_REPLACE_LENGTH 30 /* Max number of replace strings */ +#define MAX_INSERT_LENGTH 5000 /* Max size of insert piece */ +#define MAX_NAME_LENGTH 30 /* Max length of ophandler name */ +#define MAX_SPEC_PROC_LENGTH 4 /* Max length of special processing str */ +#define MAX_SPEC_EA_LENGTH 5 /* Max length of specified EA str */ +#define EA_ALLOWED_LENGTH 11 /* Max length of ea allowed str */ +#define MAX_OPCODE_INPUT_TABLE_LENGTH 1000 /* Max length of opcode handler tbl */ +#define MAX_OPCODE_OUTPUT_TABLE_LENGTH 3000 /* Max length of opcode handler tbl */ + +/* Default filenames */ +#define FILENAME_INPUT "m68k_in.c" +#define FILENAME_PROTOTYPE "m68kops.h" +#define FILENAME_TABLE "m68kops.c" + + +/* Identifier sequences recognized by this program */ + +#define ID_INPUT_SEPARATOR "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + +#define ID_BASE "M68KMAKE" +#define ID_PROTOTYPE_HEADER ID_BASE "_PROTOTYPE_HEADER" +#define ID_PROTOTYPE_FOOTER ID_BASE "_PROTOTYPE_FOOTER" +#define ID_TABLE_HEADER ID_BASE "_TABLE_HEADER" +#define ID_TABLE_FOOTER ID_BASE "_TABLE_FOOTER" +#define ID_TABLE_BODY ID_BASE "_TABLE_BODY" +#define ID_TABLE_START ID_BASE "_TABLE_START" +#define ID_OPHANDLER_HEADER ID_BASE "_OPCODE_HANDLER_HEADER" +#define ID_OPHANDLER_FOOTER ID_BASE "_OPCODE_HANDLER_FOOTER" +#define ID_OPHANDLER_BODY ID_BASE "_OPCODE_HANDLER_BODY" +#define ID_END ID_BASE "_END" + +#define ID_OPHANDLER_NAME ID_BASE "_OP" +#define ID_OPHANDLER_EA_AY_8 ID_BASE "_GET_EA_AY_8" +#define ID_OPHANDLER_EA_AY_16 ID_BASE "_GET_EA_AY_16" +#define ID_OPHANDLER_EA_AY_32 ID_BASE "_GET_EA_AY_32" +#define ID_OPHANDLER_OPER_AY_8 ID_BASE "_GET_OPER_AY_8" +#define ID_OPHANDLER_OPER_AY_16 ID_BASE "_GET_OPER_AY_16" +#define ID_OPHANDLER_OPER_AY_32 ID_BASE "_GET_OPER_AY_32" +#define ID_OPHANDLER_CC ID_BASE "_CC" +#define ID_OPHANDLER_NOT_CC ID_BASE "_NOT_CC" + + +#ifndef DECL_SPEC +#define DECL_SPEC +#endif /* DECL_SPEC */ + + + +/* ======================================================================== */ +/* ============================== PROTOTYPES ============================== */ +/* ======================================================================== */ + +enum { + CPU_TYPE_000=0, + CPU_TYPE_010, + CPU_TYPE_020, + CPU_TYPE_030, + CPU_TYPE_040, + NUM_CPUS +}; + +#define UNSPECIFIED "." +#define UNSPECIFIED_CH '.' + +#define HAS_NO_EA_MODE(A) (strcmp(A, "..........") == 0) +#define HAS_EA_AI(A) ((A)[0] == 'A') +#define HAS_EA_PI(A) ((A)[1] == '+') +#define HAS_EA_PD(A) ((A)[2] == '-') +#define HAS_EA_DI(A) ((A)[3] == 'D') +#define HAS_EA_IX(A) ((A)[4] == 'X') +#define HAS_EA_AW(A) ((A)[5] == 'W') +#define HAS_EA_AL(A) ((A)[6] == 'L') +#define HAS_EA_PCDI(A) ((A)[7] == 'd') +#define HAS_EA_PCIX(A) ((A)[8] == 'x') +#define HAS_EA_I(A) ((A)[9] == 'I') + +enum +{ + EA_MODE_NONE, /* No special addressing mode */ + EA_MODE_AI, /* Address register indirect */ + EA_MODE_PI, /* Address register indirect with postincrement */ + EA_MODE_PI7, /* Address register 7 indirect with postincrement */ + EA_MODE_PD, /* Address register indirect with predecrement */ + EA_MODE_PD7, /* Address register 7 indirect with predecrement */ + EA_MODE_DI, /* Address register indirect with displacement */ + EA_MODE_IX, /* Address register indirect with index */ + EA_MODE_AW, /* Absolute word */ + EA_MODE_AL, /* Absolute long */ + EA_MODE_PCDI, /* Program counter indirect with displacement */ + EA_MODE_PCIX, /* Program counter indirect with index */ + EA_MODE_I /* Immediate */ +}; + + +/* Everything we need to know about an opcode */ +typedef struct +{ + char name[MAX_NAME_LENGTH]; /* opcode handler name */ + unsigned char size; /* Size of operation */ + char spec_proc[MAX_SPEC_PROC_LENGTH]; /* Special processing mode */ + char spec_ea[MAX_SPEC_EA_LENGTH]; /* Specified effective addressing mode */ + unsigned char bits; /* Number of significant bits (used for sorting the table) */ + unsigned short op_mask; /* Mask to apply for matching an opcode to a handler */ + unsigned short op_match; /* Value to match after masking */ + char ea_allowed[EA_ALLOWED_LENGTH]; /* Effective addressing modes allowed */ + char cpu_mode[NUM_CPUS]; /* User or supervisor mode */ + char cpus[NUM_CPUS+1]; /* Allowed CPUs */ + unsigned char cycles[NUM_CPUS]; /* cycles for 000, 010, 020, 030, 040 */ +} opcode_struct; + + +/* All modifications necessary for a specific EA mode of an instruction */ +typedef struct +{ + char* fname_add; + char* ea_add; + unsigned int mask_add; + unsigned int match_add; +} ea_info_struct; + + +/* Holds the body of a function */ +typedef struct +{ + char body[MAX_BODY_LENGTH][MAX_LINE_LENGTH+1]; + int length; +} body_struct; + + +/* Holds a sequence of search / replace strings */ +typedef struct +{ + char replace[MAX_REPLACE_LENGTH][2][MAX_LINE_LENGTH+1]; + int length; +} replace_struct; + + +/* Function Prototypes */ +void error_exit(const char* fmt, ...); +void perror_exit(const char* fmt, ...); +int check_strsncpy(char* dst, char* src, int maxlength); +int check_atoi(char* str, int *result); +int skip_spaces(char* str); +int num_bits(int value); +int atoh(char* buff); +int fgetline(char* buff, int nchars, FILE* file); +int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type); +opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea); +opcode_struct* find_illegal_opcode(void); +int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea); +void add_replace_string(replace_struct* replace, char* search_str, char* replace_str); +void write_body(FILE* filep, body_struct* body, replace_struct* replace); +void get_base_name(char* base_name, opcode_struct* op); +void write_function_name(FILE* filep, char* base_name); +void add_opcode_output_table_entry(opcode_struct* op, char* name); +static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr); +void print_opcode_output_table(FILE* filep); +void write_table_entry(FILE* filep, opcode_struct* op); +void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode); +void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode); +void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op); +void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset); +void process_opcode_handlers(FILE* filep); +void populate_table(void); +void read_insert(char* insert); + + + +/* ======================================================================== */ +/* ================================= DATA ================================= */ +/* ======================================================================== */ + +/* Name of the input file */ +char g_input_filename[M68K_MAX_PATH] = FILENAME_INPUT; + +/* File handles */ +FILE* g_input_file = NULL; +FILE* g_prototype_file = NULL; +FILE* g_table_file = NULL; + +int g_num_functions = 0; /* Number of functions processed */ +int g_num_primitives = 0; /* Number of function primitives read */ +int g_line_number = 1; /* Current line number */ + +/* Opcode handler table */ +opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH]; + +opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH]; +int g_opcode_output_table_length = 0; + +const ea_info_struct g_ea_info_table[13] = +{/* fname ea mask match */ + {"", "", 0x00, 0x00}, /* EA_MODE_NONE */ + {"ai", "AY_AI", 0x38, 0x10}, /* EA_MODE_AI */ + {"pi", "AY_PI", 0x38, 0x18}, /* EA_MODE_PI */ + {"pi7", "A7_PI", 0x3f, 0x1f}, /* EA_MODE_PI7 */ + {"pd", "AY_PD", 0x38, 0x20}, /* EA_MODE_PD */ + {"pd7", "A7_PD", 0x3f, 0x27}, /* EA_MODE_PD7 */ + {"di", "AY_DI", 0x38, 0x28}, /* EA_MODE_DI */ + {"ix", "AY_IX", 0x38, 0x30}, /* EA_MODE_IX */ + {"aw", "AW", 0x3f, 0x38}, /* EA_MODE_AW */ + {"al", "AL", 0x3f, 0x39}, /* EA_MODE_AL */ + {"pcdi", "PCDI", 0x3f, 0x3a}, /* EA_MODE_PCDI */ + {"pcix", "PCIX", 0x3f, 0x3b}, /* EA_MODE_PCIX */ + {"i", "I", 0x3f, 0x3c}, /* EA_MODE_I */ +}; + + +const char *const g_cc_table[16][2] = +{ + { "t", "T"}, /* 0000 */ + { "f", "F"}, /* 0001 */ + {"hi", "HI"}, /* 0010 */ + {"ls", "LS"}, /* 0011 */ + {"cc", "CC"}, /* 0100 */ + {"cs", "CS"}, /* 0101 */ + {"ne", "NE"}, /* 0110 */ + {"eq", "EQ"}, /* 0111 */ + {"vc", "VC"}, /* 1000 */ + {"vs", "VS"}, /* 1001 */ + {"pl", "PL"}, /* 1010 */ + {"mi", "MI"}, /* 1011 */ + {"ge", "GE"}, /* 1100 */ + {"lt", "LT"}, /* 1101 */ + {"gt", "GT"}, /* 1110 */ + {"le", "LE"}, /* 1111 */ +}; + +/* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */ +const int g_size_select_table[33] = +{ + 0, /* unsized */ + 0, 0, 0, 0, 0, 0, 0, 1, /* 8 */ + 0, 0, 0, 0, 0, 0, 0, 1, /* 16 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* 32 */ +}; + +/* Extra cycles required for certain EA modes */ +/* TODO: correct timings for 030, 040 */ +const int g_ea_cycle_table[13][NUM_CPUS][3] = +{/* 000 010 020 030 040 */ + {{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AI */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI7 */ + {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD */ + {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD7 */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_DI */ + {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_IX */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AW */ + {{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AL */ + {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PCDI */ + {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_PCIX */ + {{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}, { 0, 2, 4}, { 0, 2, 4}}, /* EA_MODE_I */ +}; + +/* Extra cycles for JMP instruction (000, 010) */ +const int g_jmp_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 6, /* EA_MODE_DI */ + 10, /* EA_MODE_IX */ + 6, /* EA_MODE_AW */ + 8, /* EA_MODE_AL */ + 6, /* EA_MODE_PCDI */ + 10, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for JSR instruction (000, 010) */ +const int g_jsr_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 6, /* EA_MODE_DI */ + 10, /* EA_MODE_IX */ + 6, /* EA_MODE_AW */ + 8, /* EA_MODE_AL */ + 6, /* EA_MODE_PCDI */ + 10, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for LEA instruction (000, 010) */ +const int g_lea_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 4, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 8, /* EA_MODE_DI */ + 12, /* EA_MODE_IX */ + 8, /* EA_MODE_AW */ + 12, /* EA_MODE_AL */ + 8, /* EA_MODE_PCDI */ + 12, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for PEA instruction (000, 010) */ +const int g_pea_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 6, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 10, /* EA_MODE_DI */ + 14, /* EA_MODE_IX */ + 10, /* EA_MODE_AW */ + 14, /* EA_MODE_AL */ + 10, /* EA_MODE_PCDI */ + 14, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for MOVEM instruction (000, 010) */ +const int g_movem_cycle_table[13] = +{ + 0, /* EA_MODE_NONE */ + 0, /* EA_MODE_AI */ + 0, /* EA_MODE_PI */ + 0, /* EA_MODE_PI7 */ + 0, /* EA_MODE_PD */ + 0, /* EA_MODE_PD7 */ + 4, /* EA_MODE_DI */ + 6, /* EA_MODE_IX */ + 4, /* EA_MODE_AW */ + 8, /* EA_MODE_AL */ + 0, /* EA_MODE_PCDI */ + 0, /* EA_MODE_PCIX */ + 0, /* EA_MODE_I */ +}; + +/* Extra cycles for MOVES instruction (010) */ +const int g_moves_cycle_table[13][3] = +{ + { 0, 0, 0}, /* EA_MODE_NONE */ + { 0, 4, 6}, /* EA_MODE_AI */ + { 0, 4, 6}, /* EA_MODE_PI */ + { 0, 4, 6}, /* EA_MODE_PI7 */ + { 0, 6, 12}, /* EA_MODE_PD */ + { 0, 6, 12}, /* EA_MODE_PD7 */ + { 0, 12, 16}, /* EA_MODE_DI */ + { 0, 16, 20}, /* EA_MODE_IX */ + { 0, 12, 16}, /* EA_MODE_AW */ + { 0, 16, 20}, /* EA_MODE_AL */ + { 0, 0, 0}, /* EA_MODE_PCDI */ + { 0, 0, 0}, /* EA_MODE_PCIX */ + { 0, 0, 0}, /* EA_MODE_I */ +}; + +/* Extra cycles for CLR instruction (010) */ +const int g_clr_cycle_table[13][3] = +{ + { 0, 0, 0}, /* EA_MODE_NONE */ + { 0, 4, 6}, /* EA_MODE_AI */ + { 0, 4, 6}, /* EA_MODE_PI */ + { 0, 4, 6}, /* EA_MODE_PI7 */ + { 0, 6, 8}, /* EA_MODE_PD */ + { 0, 6, 8}, /* EA_MODE_PD7 */ + { 0, 8, 10}, /* EA_MODE_DI */ + { 0, 10, 14}, /* EA_MODE_IX */ + { 0, 8, 10}, /* EA_MODE_AW */ + { 0, 10, 14}, /* EA_MODE_AL */ + { 0, 0, 0}, /* EA_MODE_PCDI */ + { 0, 0, 0}, /* EA_MODE_PCIX */ + { 0, 0, 0}, /* EA_MODE_I */ +}; + + + +/* ======================================================================== */ +/* =========================== UTILITY FUNCTIONS ========================== */ +/* ======================================================================== */ + +/* Print an error message and exit with status error */ +void error_exit(const char* fmt, ...) +{ + va_list args; + fprintf(stderr, "In %s, near or on line %d:\n\t", g_input_filename, g_line_number); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + + if(g_prototype_file) fclose(g_prototype_file); + if(g_table_file) fclose(g_table_file); + if(g_input_file) fclose(g_input_file); + + exit(EXIT_FAILURE); +} + +/* Print an error message, call perror(), and exit with status error */ +void perror_exit(const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + perror(""); + + if(g_prototype_file) fclose(g_prototype_file); + if(g_table_file) fclose(g_table_file); + if(g_input_file) fclose(g_input_file); + + exit(EXIT_FAILURE); +} + + +/* copy until 0 or space and exit with error if we read too far */ +int check_strsncpy(char* dst, char* src, int maxlength) +{ + char* p = dst; + while(*src && *src != ' ') + { + *p++ = *src++; + if(p - dst > maxlength) + error_exit("Field too long"); + } + *p = 0; + return p - dst; +} + +/* copy until 0 or specified character and exit with error if we read too far */ +int check_strcncpy(char* dst, char* src, char delim, int maxlength) +{ + char* p = dst; + while(*src && *src != delim) + { + *p++ = *src++; + if(p - dst > maxlength) + error_exit("Field too long"); + } + *p = 0; + return p - dst; +} + +/* convert ascii to integer and exit with error if we find invalid data */ +int check_atoi(char* str, int *result) +{ + int accum = 0; + char* p = str; + while(*p >= '0' && *p <= '9') + { + accum *= 10; + accum += *p++ - '0'; + } + if(*p != ' ' && *p != 0) + error_exit("Malformed integer value (%c)", *p); + *result = accum; + return p - str; +} + +/* Skip past spaces in a string */ +int skip_spaces(char* str) +{ + char* p = str; + + while(*p == ' ') + p++; + + return p - str; +} + +/* Count the number of set bits in a value */ +int num_bits(int value) +{ + value = ((value & 0xaaaa) >> 1) + (value & 0x5555); + value = ((value & 0xcccc) >> 2) + (value & 0x3333); + value = ((value & 0xf0f0) >> 4) + (value & 0x0f0f); + value = ((value & 0xff00) >> 8) + (value & 0x00ff); + return value; +} + +/* Convert a hex value written in ASCII */ +int atoh(char* buff) +{ + int accum = 0; + + for(;;buff++) + { + if(*buff >= '0' && *buff <= '9') + { + accum <<= 4; + accum += *buff - '0'; + } + else if(*buff >= 'a' && *buff <= 'f') + { + accum <<= 4; + accum += *buff - 'a' + 10; + } + else break; + } + return accum; +} + +/* Get a line of text from a file, discarding any end-of-line characters */ +int fgetline(char* buff, int nchars, FILE* file) +{ + int length; + + if(fgets(buff, nchars, file) == NULL) + return -1; + if(buff[0] == '\r') + memmove(buff, buff + 1, nchars - 1); + + length = strlen(buff); + while(length && (buff[length-1] == '\r' || buff[length-1] == '\n')) + length--; + buff[length] = 0; + g_line_number++; + + return length; +} + + + +/* ======================================================================== */ +/* =========================== HELPER FUNCTIONS =========================== */ +/* ======================================================================== */ + +/* Calculate the number of cycles an opcode requires */ +int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type) +{ + int size = g_size_select_table[op->size]; + + if(op->cpus[cpu_type] == '.') + return 0; + + if(cpu_type < CPU_TYPE_020) + { + if(cpu_type == CPU_TYPE_010) + { + if(strcmp(op->name, "moves") == 0) + return op->cycles[cpu_type] + g_moves_cycle_table[ea_mode][size]; + if(strcmp(op->name, "clr") == 0) + return op->cycles[cpu_type] + g_clr_cycle_table[ea_mode][size]; + } + + /* ASG: added these cases -- immediate modes take 2 extra cycles here */ + if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I && + ((strcmp(op->name, "add") == 0 && strcmp(op->spec_proc, "er") == 0) || + strcmp(op->name, "adda") == 0 || + (strcmp(op->name, "and") == 0 && strcmp(op->spec_proc, "er") == 0) || + (strcmp(op->name, "or") == 0 && strcmp(op->spec_proc, "er") == 0) || + (strcmp(op->name, "sub") == 0 && strcmp(op->spec_proc, "er") == 0) || + strcmp(op->name, "suba") == 0)) + return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2; + + if(strcmp(op->name, "jmp") == 0) + return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode]; + if(strcmp(op->name, "jsr") == 0) + return op->cycles[cpu_type] + g_jsr_cycle_table[ea_mode]; + if(strcmp(op->name, "lea") == 0) + return op->cycles[cpu_type] + g_lea_cycle_table[ea_mode]; + if(strcmp(op->name, "pea") == 0) + return op->cycles[cpu_type] + g_pea_cycle_table[ea_mode]; + if(strcmp(op->name, "movem") == 0) + return op->cycles[cpu_type] + g_movem_cycle_table[ea_mode]; + } + return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size]; +} + +/* Find an opcode in the opcode handler list */ +opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea) +{ + opcode_struct* op; + + + for(op = g_opcode_input_table;op < &g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];op++) + { + if( strcmp(name, op->name) == 0 && + (size == op->size) && + strcmp(spec_proc, op->spec_proc) == 0 && + strcmp(spec_ea, op->spec_ea) == 0) + return op; + } + return NULL; +} + +/* Specifically find the illegal opcode in the list */ +opcode_struct* find_illegal_opcode(void) +{ + opcode_struct* op; + + for(op = g_opcode_input_table;op < &g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];op++) + { + if(strcmp(op->name, "illegal") == 0) + return op; + } + return NULL; +} + +/* Parse an opcode handler name */ +int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea) +{ + char* ptr = strstr(src, ID_OPHANDLER_NAME); + + if(ptr == NULL) + return 0; + + ptr += strlen(ID_OPHANDLER_NAME) + 1; + + ptr += check_strcncpy(name, ptr, ',', MAX_NAME_LENGTH); + if(*ptr != ',') return 0; + ptr++; + ptr += skip_spaces(ptr); + + *size = atoi(ptr); + ptr = strstr(ptr, ","); + if(ptr == NULL) return 0; + ptr++; + ptr += skip_spaces(ptr); + + ptr += check_strcncpy(spec_proc, ptr, ',', MAX_SPEC_PROC_LENGTH); + if(*ptr != ',') return 0; + ptr++; + ptr += skip_spaces(ptr); + + ptr += check_strcncpy(spec_ea, ptr, ')', MAX_SPEC_EA_LENGTH); + if(*ptr != ')') return 0; + ptr++; + ptr += skip_spaces(ptr); + + return 1; +} + + +/* Add a search/replace pair to a replace structure */ +void add_replace_string(replace_struct* replace, char* search_str, char* replace_str) +{ + if(replace->length >= MAX_REPLACE_LENGTH) + error_exit("overflow in replace structure"); + + strcpy(replace->replace[replace->length][0], search_str); + strcpy(replace->replace[replace->length++][1], replace_str); +} + +/* Write a function body while replacing any selected strings */ +void write_body(FILE* filep, body_struct* body, replace_struct* replace) +{ + int i; + int j; + char* ptr; + char output[MAX_LINE_LENGTH+1]; + char temp_buff[MAX_LINE_LENGTH+1]; + int found; + + for(i=0;ilength;i++) + { + strcpy(output, body->body[i]); + /* Check for the base directive header */ + if(strstr(output, ID_BASE) != NULL) + { + /* Search for any text we need to replace */ + found = 0; + for(j=0;jlength;j++) + { + ptr = strstr(output, replace->replace[j][0]); + if(ptr) + { + /* We found something to replace */ + found = 1; + strcpy(temp_buff, ptr+strlen(replace->replace[j][0])); + strcpy(ptr, replace->replace[j][1]); + strcat(ptr, temp_buff); + } + } + /* Found a directive with no matching replace string */ + if(!found) + error_exit("Unknown " ID_BASE " directive [%s]", output); + } + fprintf(filep, "%s\n", output); + } + fprintf(filep, "\n\n"); +} + +/* Generate a base function name from an opcode struct */ +void get_base_name(char* base_name, opcode_struct* op) +{ + sprintf(base_name, "m68k_op_%s", op->name); + if(op->size > 0) + sprintf(base_name+strlen(base_name), "_%d", op->size); + if(strcmp(op->spec_proc, UNSPECIFIED) != 0) + sprintf(base_name+strlen(base_name), "_%s", op->spec_proc); + if(strcmp(op->spec_ea, UNSPECIFIED) != 0) + sprintf(base_name+strlen(base_name), "_%s", op->spec_ea); +} + +/* Write the name of an opcode handler function */ +void write_function_name(FILE* filep, char* base_name) +{ + fprintf(filep, "static void %s(void)\n", base_name); +} + +void add_opcode_output_table_entry(opcode_struct* op, char* name) +{ + opcode_struct* ptr; + if(g_opcode_output_table_length > MAX_OPCODE_OUTPUT_TABLE_LENGTH) + error_exit("Opcode output table overflow"); + + ptr = g_opcode_output_table + g_opcode_output_table_length++; + + *ptr = *op; + strcpy(ptr->name, name); + ptr->bits = num_bits(ptr->op_mask); +} + +/* + * Comparison function for qsort() + * For entries with an equal number of set bits in + * the mask compare the match values + */ +static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr) +{ + const opcode_struct *a = aptr, *b = bptr; + if(a->bits != b->bits) + return a->bits - b->bits; + if(a->op_mask != b->op_mask) + return a->op_mask - b->op_mask; + return a->op_match - b->op_match; +} + +void print_opcode_output_table(FILE* filep) +{ + int i; + qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits); + + for(i=0;iname, op->op_mask, op->op_match); + + for(i=0;icycles[i]); + if(i < NUM_CPUS-1) + fprintf(filep, ", "); + } + + fprintf(filep, "}},\n"); +} + +/* Fill out an opcode struct with a specific addressing mode of the source opcode struct */ +void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode) +{ + int i; + + *dst = *src; + + for(i=0;icycles[i] = get_oper_cycles(dst, ea_mode, i); + if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE) + sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add); + dst->op_mask |= g_ea_info_table[ea_mode].mask_add; + dst->op_match |= g_ea_info_table[ea_mode].match_add; +} + + +/* Generate a final opcode handler from the provided data */ +void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode) +{ + char str[MAX_LINE_LENGTH+1]; + opcode_struct* op = malloc(sizeof(opcode_struct)); + + /* Set the opcode structure and write the tables, prototypes, etc */ + set_opcode_struct(opinfo, op, ea_mode); + get_base_name(str, op); + add_opcode_output_table_entry(op, str); + write_function_name(filep, str); + + /* Add any replace strings needed */ + if(ea_mode != EA_MODE_NONE) + { + sprintf(str, "EA_%s_8()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str); + sprintf(str, "EA_%s_16()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str); + sprintf(str, "EA_%s_32()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str); + sprintf(str, "OPER_%s_8()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str); + sprintf(str, "OPER_%s_16()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str); + sprintf(str, "OPER_%s_32()", g_ea_info_table[ea_mode].ea_add); + add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str); + } + + /* Now write the function body with the selected replace strings */ + write_body(filep, body, replace); + g_num_functions++; + free(op); +} + +/* Generate opcode variants based on available addressing modes */ +void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op) +{ + int old_length = replace->length; + + /* No ea modes available for this opcode */ + if(HAS_NO_EA_MODE(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE); + return; + } + + /* Check for and create specific opcodes for each available addressing mode */ + if(HAS_EA_AI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AI); + replace->length = old_length; + if(HAS_EA_PI(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_PI); + replace->length = old_length; + if(op->size == 8) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7); + } + replace->length = old_length; + if(HAS_EA_PD(op->ea_allowed)) + { + generate_opcode_handler(filep, body, replace, op, EA_MODE_PD); + replace->length = old_length; + if(op->size == 8) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7); + } + replace->length = old_length; + if(HAS_EA_DI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_DI); + replace->length = old_length; + if(HAS_EA_IX(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_IX); + replace->length = old_length; + if(HAS_EA_AW(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AW); + replace->length = old_length; + if(HAS_EA_AL(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_AL); + replace->length = old_length; + if(HAS_EA_PCDI(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI); + replace->length = old_length; + if(HAS_EA_PCIX(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX); + replace->length = old_length; + if(HAS_EA_I(op->ea_allowed)) + generate_opcode_handler(filep, body, replace, op, EA_MODE_I); + replace->length = old_length; +} + +/* Generate variants of condition code opcodes */ +void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset) +{ + char repl[20]; + char replnot[20]; + int i; + int old_length = replace->length; + opcode_struct* op = malloc(sizeof(opcode_struct)); + + *op = *op_in; + + op->op_mask |= 0x0f00; + + /* Do all condition codes except t and f */ + for(i=2;i<16;i++) + { + /* Add replace strings for this condition code */ + sprintf(repl, "COND_%s()", g_cc_table[i][1]); + sprintf(replnot, "COND_NOT_%s()", g_cc_table[i][1]); + + add_replace_string(replace, ID_OPHANDLER_CC, repl); + add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot); + + /* Set the new opcode info */ + strcpy(op->name+offset, g_cc_table[i][0]); + + op->op_match = (op->op_match & 0xf0ff) | (i<<8); + + /* Generate all opcode variants for this modified opcode */ + generate_opcode_ea_variants(filep, body, replace, op); + /* Remove the above replace strings */ + replace->length = old_length; + } + free(op); +} + +/* Process the opcode handlers section of the input file */ +void process_opcode_handlers(FILE* filep) +{ + FILE* input_file = g_input_file; + char func_name[MAX_LINE_LENGTH+1]; + char oper_name[MAX_LINE_LENGTH+1]; + int oper_size; + char oper_spec_proc[MAX_LINE_LENGTH+1]; + char oper_spec_ea[MAX_LINE_LENGTH+1]; + opcode_struct* opinfo; + replace_struct* replace = malloc(sizeof(replace_struct)); + body_struct* body = malloc(sizeof(body_struct)); + + for(;;) + { + /* Find the first line of the function */ + func_name[0] = 0; + while(strstr(func_name, ID_OPHANDLER_NAME) == NULL) + { + if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0) + { + free(replace); + free(body); + return; /* all done */ + } + if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0) + error_exit("Premature end of file when getting function name"); + } + /* Get the rest of the function */ + for(body->length=0;;body->length++) + { + if(body->length > MAX_BODY_LENGTH) + error_exit("Function too long"); + + if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0) + error_exit("Premature end of file when getting function body"); + + if(body->body[body->length][0] == '}') + { + body->length++; + break; + } + } + + g_num_primitives++; + + /* Extract the function name information */ + if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea)) + error_exit("Invalid " ID_OPHANDLER_NAME " format"); + + /* Find the corresponding table entry */ + opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea); + if(opinfo == NULL) + error_exit("Unable to find matching table entry for %s", func_name); + + replace->length = 0; + + /* Generate opcode variants */ + if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0) + generate_opcode_cc_variants(filep, body, replace, opinfo, 1); + else if(strcmp(opinfo->name, "dbcc") == 0) + generate_opcode_cc_variants(filep, body, replace, opinfo, 2); + else if(strcmp(opinfo->name, "trapcc") == 0) + generate_opcode_cc_variants(filep, body, replace, opinfo, 4); + else + generate_opcode_ea_variants(filep, body, replace, opinfo); + } + + free(replace); + free(body); +} + + +/* Populate the opcode handler table from the input file */ +void populate_table(void) +{ + char* ptr; + char bitpattern[17]; + opcode_struct* op; + char buff[MAX_LINE_LENGTH]; + int i; + int temp; + + buff[0] = 0; + + /* Find the start of the table */ + while(strcmp(buff, ID_TABLE_START) != 0) + if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("(table_start) Premature EOF while reading table"); + + /* Process the entire table */ + for(op = g_opcode_input_table;;op++) + { + if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("(inline) Premature EOF while reading table"); + if(strlen(buff) == 0) + continue; + /* We finish when we find an input separator */ + if(strcmp(buff, ID_INPUT_SEPARATOR) == 0) + break; + + /* Extract the info from the table */ + ptr = buff; + + /* Name */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH); + + /* Size */ + ptr += skip_spaces(ptr); + ptr += check_atoi(ptr, &temp); + op->size = (unsigned char)temp; + + /* Special processing */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH); + + /* Specified EA Mode */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH); + + /* Bit Pattern (more processing later) */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(bitpattern, ptr, 17); + + /* Allowed Addressing Mode List */ + ptr += skip_spaces(ptr); + ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH); + + /* CPU operating mode (U = user or supervisor, S = supervisor only */ + ptr += skip_spaces(ptr); + for(i=0;icpu_mode[i] = *ptr++; + ptr += skip_spaces(ptr); + } + + /* Allowed CPUs for this instruction */ + for(i=0;icpus[i] = UNSPECIFIED_CH; + op->cycles[i] = 0; + ptr++; + } + else + { + op->cpus[i] = '0' + i; + ptr += check_atoi(ptr, &temp); + op->cycles[i] = (unsigned char)temp; + } + } + + /* generate mask and match from bitpattern */ + op->op_mask = 0; + op->op_match = 0; + for(i=0;i<16;i++) + { + op->op_mask |= (bitpattern[i] != '.') << (15-i); + op->op_match |= (bitpattern[i] == '1') << (15-i); + } + } + /* Terminate the list */ + op->name[0] = 0; +} + +/* Read a header or footer insert from the input file */ +void read_insert(char* insert) +{ + char* ptr = insert; + char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH; + int length; + char* first_blank = NULL; + + first_blank = NULL; + + /* Skip any leading blank lines */ + for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) + if(ptr >= overflow) + error_exit("Buffer overflow reading inserts"); + if(length < 0) + error_exit("Premature EOF while reading inserts"); + + /* Advance and append newline */ + ptr += length; + strcpy(ptr++, "\n"); + + /* Read until next separator */ + for(;;) + { + /* Read a new line */ + if(ptr >= overflow) + error_exit("Buffer overflow reading inserts"); + if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0) + error_exit("Premature EOF while reading inserts"); + + /* Stop if we read a separator */ + if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0) + break; + + /* keep track in case there are trailing blanks */ + if(length == 0) + { + if(first_blank == NULL) + first_blank = ptr; + } + else + first_blank = NULL; + + /* Advance and append newline */ + ptr += length; + strcpy(ptr++, "\n"); + } + + /* kill any trailing blank lines */ + if(first_blank) + ptr = first_blank; + *ptr++ = 0; +} + + + +/* ======================================================================== */ +/* ============================= MAIN FUNCTION ============================ */ +/* ======================================================================== */ + +int main(int argc, char **argv) +{ + /* File stuff */ + char output_path[M68K_MAX_DIR] = ""; + char filename[M68K_MAX_PATH*2]; + /* Section identifier */ + char section_id[MAX_LINE_LENGTH+1]; + /* Inserts */ + char temp_insert[MAX_INSERT_LENGTH+1]; + char prototype_footer_insert[MAX_INSERT_LENGTH+1]; + char table_header_insert[MAX_INSERT_LENGTH+1]; + char table_footer_insert[MAX_INSERT_LENGTH+1]; + char ophandler_header_insert[MAX_INSERT_LENGTH+1]; + char ophandler_footer_insert[MAX_INSERT_LENGTH+1]; + /* Flags if we've processed certain parts already */ + int prototype_header_read = 0; + int prototype_footer_read = 0; + int table_header_read = 0; + int table_footer_read = 0; + int ophandler_header_read = 0; + int ophandler_footer_read = 0; + int table_body_read = 0; + int ophandler_body_read = 0; + + printf("\n\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, 68040 emulator\n", g_version); + printf("\t\tCopyright Karl Stenerud (kstenerud@gmail.com)\n\n"); + + /* Check if output path and source for the input file are given */ + if(argc > 1) + { + char *ptr; + strcpy(output_path, argv[1]); + + for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\')) + *ptr = '/'; + if(output_path[strlen(output_path)-1] != '/') + strcat(output_path, "/"); + if(argc > 2) + strcpy(g_input_filename, argv[2]); + } + + + /* Open the files we need */ + sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE); + if((g_prototype_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create prototype file (%s)\n", filename); + + sprintf(filename, "%s%s", output_path, FILENAME_TABLE); + if((g_table_file = fopen(filename, "wt")) == NULL) + perror_exit("Unable to create table file (%s)\n", filename); + + if((g_input_file=fopen(g_input_filename, "rt")) == NULL) + perror_exit("can't open %s for input", g_input_filename); + + + /* Get to the first section of the input file */ + section_id[0] = 0; + while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0) + if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading input file"); + + /* Now process all sections */ + for(;;) + { + if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) + error_exit("Premature EOF while reading input file"); + if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0) + { + if(prototype_header_read) + error_exit("Duplicate prototype header"); + read_insert(temp_insert); + fprintf(g_prototype_file, "%s\n\n", temp_insert); + prototype_header_read = 1; + } + else if(strcmp(section_id, ID_TABLE_HEADER) == 0) + { + if(table_header_read) + error_exit("Duplicate table header"); + read_insert(table_header_insert); + table_header_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0) + { + if(ophandler_header_read) + error_exit("Duplicate opcode handler header"); + read_insert(ophandler_header_insert); + ophandler_header_read = 1; + } + else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0) + { + if(prototype_footer_read) + error_exit("Duplicate prototype footer"); + read_insert(prototype_footer_insert); + prototype_footer_read = 1; + } + else if(strcmp(section_id, ID_TABLE_FOOTER) == 0) + { + if(table_footer_read) + error_exit("Duplicate table footer"); + read_insert(table_footer_insert); + table_footer_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0) + { + if(ophandler_footer_read) + error_exit("Duplicate opcode handler footer"); + read_insert(ophandler_footer_insert); + ophandler_footer_read = 1; + } + else if(strcmp(section_id, ID_TABLE_BODY) == 0) + { + if(!prototype_header_read) + error_exit("Table body encountered before prototype header"); + if(!table_header_read) + error_exit("Table body encountered before table header"); + if(!ophandler_header_read) + error_exit("Table body encountered before opcode handler header"); + + if(table_body_read) + error_exit("Duplicate table body"); + + populate_table(); + table_body_read = 1; + } + else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0) + { + if(!prototype_header_read) + error_exit("Opcode handlers encountered before prototype header"); + if(!table_header_read) + error_exit("Opcode handlers encountered before table header"); + if(!ophandler_header_read) + error_exit("Opcode handlers encountered before opcode handler header"); + if(!table_body_read) + error_exit("Opcode handlers encountered before table body"); + + if(ophandler_body_read) + error_exit("Duplicate opcode handler section"); + + fprintf(g_table_file, "%s\n\n", ophandler_header_insert); + process_opcode_handlers(g_table_file); + fprintf(g_table_file, "%s\n\n", ophandler_footer_insert); + + ophandler_body_read = 1; + } + else if(strcmp(section_id, ID_END) == 0) + { + /* End of input file. Do a sanity check and then write footers */ + if(!prototype_header_read) + error_exit("Missing prototype header"); + if(!prototype_footer_read) + error_exit("Missing prototype footer"); + if(!table_header_read) + error_exit("Missing table header"); + if(!table_footer_read) + error_exit("Missing table footer"); + if(!table_body_read) + error_exit("Missing table body"); + if(!ophandler_header_read) + error_exit("Missing opcode handler header"); + if(!ophandler_footer_read) + error_exit("Missing opcode handler footer"); + if(!ophandler_body_read) + error_exit("Missing opcode handler body"); + + fprintf(g_table_file, "%s\n\n", table_header_insert); + print_opcode_output_table(g_table_file); + fprintf(g_table_file, "%s\n\n", table_footer_insert); + + fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert); + + break; + } + else + { + error_exit("Unknown section identifier: %s", section_id); + } + } + + /* Close all files and exit */ + fclose(g_prototype_file); + fclose(g_table_file); + fclose(g_input_file); + + printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives); + + return 0; +} + + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ diff --git a/AltairZ80/m68k/m68kmmu.h b/AltairZ80/m68k/m68kmmu.h index b6d90986..164e9a94 100644 --- a/AltairZ80/m68k/m68kmmu.h +++ b/AltairZ80/m68k/m68kmmu.h @@ -1,321 +1,321 @@ -/* - m68kmmu.h - PMMU implementation for 68851/68030/68040 - - By R. Belmont - - Copyright Nicola Salmoria and the MAME Team. - Visit http://mamedev.org for licensing and usage restrictions. -*/ - -/* - pmmu_translate_addr: perform 68851/68030-style PMMU address translation -*/ -uint pmmu_translate_addr(uint addr_in) -{ - uint32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0, tcmode = 0; - uint root_aptr, root_limit, tofs, is, abits, bbits, cbits; - uint resolved, tptr, shift; - - resolved = 0; - addr_out = addr_in; - - // if SRP is enabled and we're in supervisor mode, use it - if ((m68ki_cpu.mmu_tc & 0x02000000) && (m68ki_get_sr() & 0x2000)) - { - root_aptr = m68ki_cpu.mmu_srp_aptr; - root_limit = m68ki_cpu.mmu_srp_limit; - } - else // else use the CRP - { - root_aptr = m68ki_cpu.mmu_crp_aptr; - root_limit = m68ki_cpu.mmu_crp_limit; - } - - // get initial shift (# of top bits to ignore) - is = (m68ki_cpu.mmu_tc>>16) & 0xf; - abits = (m68ki_cpu.mmu_tc>>12)&0xf; - bbits = (m68ki_cpu.mmu_tc>>8)&0xf; - cbits = (m68ki_cpu.mmu_tc>>4)&0xf; - -// fprintf(stderr,"PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68ki_cpu.mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits); - - // get table A offset - tofs = (addr_in<>(32-abits); - - // find out what format table A is - switch (root_limit & 3) - { - case 0: // invalid, should cause MMU exception - case 1: // page descriptor, should cause direct mapping - fatalerror("680x0 PMMU: Unhandled root mode\n"); - break; - - case 2: // valid 4 byte descriptors - tofs *= 4; -// fprintf(stderr,"PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc)); - tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)); - tamode = tbl_entry & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs); - break; - - case 3: // valid 8 byte descriptors - tofs *= 8; -// fprintf(stderr,"PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc)); - tbl_entry2 = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)); - tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)+4); - tamode = tbl_entry2 & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); - break; - } - - // get table B offset and pointer - tofs = (addr_in<<(is+abits))>>(32-bbits); - tptr = tbl_entry & 0xfffffff0; - - // find out what format table B is, if any - switch (tamode) - { - case 0: // invalid, should cause MMU exception - fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in); - break; - - case 2: // 4-byte table B descriptor - tofs *= 4; -// fprintf(stderr,"PMMU: reading table B entry at %08x\n", tofs + tptr); - tbl_entry = m68k_read_memory_32( tofs + tptr); - tbmode = tbl_entry & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); - break; - - case 3: // 8-byte table B descriptor - tofs *= 8; -// fprintf(stderr,"PMMU: reading table B entries at %08x\n", tofs + tptr); - tbl_entry2 = m68k_read_memory_32( tofs + tptr); - tbl_entry = m68k_read_memory_32( tofs + tptr + 4); - tbmode = tbl_entry2 & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); - break; - - case 1: // early termination descriptor - tbl_entry &= 0xffffff00; - - shift = is+abits; - addr_out = ((addr_in<>shift) + tbl_entry; - resolved = 1; - break; - } - - // if table A wasn't early-out, continue to process table B - if (!resolved) - { - // get table C offset and pointer - tofs = (addr_in<<(is+abits+bbits))>>(32-cbits); - tptr = tbl_entry & 0xfffffff0; - - switch (tbmode) - { - case 0: // invalid, should cause MMU exception - fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC); - break; - - case 2: // 4-byte table C descriptor - tofs *= 4; -// fprintf(stderr,"PMMU: reading table C entry at %08x\n", tofs + tptr); - tbl_entry = m68k_read_memory_32(tofs + tptr); - tcmode = tbl_entry & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); - break; - - case 3: // 8-byte table C descriptor - tofs *= 8; -// fprintf(stderr,"PMMU: reading table C entries at %08x\n", tofs + tptr); - tbl_entry2 = m68k_read_memory_32(tofs + tptr); - tbl_entry = m68k_read_memory_32(tofs + tptr + 4); - tcmode = tbl_entry2 & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); - break; - - case 1: // termination descriptor - tbl_entry &= 0xffffff00; - - shift = is+abits+bbits; - addr_out = ((addr_in<>shift) + tbl_entry; - resolved = 1; - break; - } - } - - if (!resolved) - { - switch (tcmode) - { - case 0: // invalid, should cause MMU exception - case 2: // 4-byte ??? descriptor - case 3: // 8-byte ??? descriptor - fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC); - break; - - case 1: // termination descriptor - tbl_entry &= 0xffffff00; - - shift = is+abits+bbits+cbits; - addr_out = ((addr_in<>shift) + tbl_entry; - resolved = 1; - break; - } - } - - -// fprintf(stderr,"PMMU: [%08x] => [%08x]\n", addr_in, addr_out); - - return addr_out; -} - -/* - - m68881_mmu_ops: COP 0 MMU opcode handling - -*/ - -void m68881_mmu_ops(void) -{ - uint16 modes; - uint32 ea = m68ki_cpu.ir & 0x3f; - uint64 temp64; - - // catch the 2 "weird" encodings up front (PBcc) - if ((m68ki_cpu.ir & 0xffc0) == 0xf0c0) - { - fprintf(stderr,"680x0: unhandled PBcc\n"); - return; - } - else if ((m68ki_cpu.ir & 0xffc0) == 0xf080) - { - fprintf(stderr,"680x0: unhandled PBcc\n"); - return; - } - else // the rest are 1111000xxxXXXXXX where xxx is the instruction family - { - switch ((m68ki_cpu.ir>>9) & 0x7) - { - case 0: - modes = OPER_I_16(); - - if ((modes & 0xfde0) == 0x2000) // PLOAD - { - fprintf(stderr,"680x0: unhandled PLOAD\n"); - return; - } - else if ((modes & 0xe200) == 0x2000) // PFLUSH - { - fprintf(stderr,"680x0: unhandled PFLUSH PC=%x\n", REG_PC); - return; - } - else if (modes == 0xa000) // PFLUSHR - { - fprintf(stderr,"680x0: unhandled PFLUSHR\n"); - return; - } - else if (modes == 0x2800) // PVALID (FORMAT 1) - { - fprintf(stderr,"680x0: unhandled PVALID1\n"); - return; - } - else if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2) - { - fprintf(stderr,"680x0: unhandled PVALID2\n"); - return; - } - else if ((modes & 0xe000) == 0x8000) // PTEST - { - fprintf(stderr,"680x0: unhandled PTEST\n"); - return; - } - else - { - switch ((modes>>13) & 0x7) - { - case 0: // MC68030/040 form with FD bit - case 2: // MC68881 form, FD never set - if (modes & 0x200) - { - switch ((modes>>10) & 7) - { - case 0: // translation control register - WRITE_EA_32(ea, m68ki_cpu.mmu_tc); - break; - - case 2: // supervisor root pointer - WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_srp_limit<<32 | (uint64)m68ki_cpu.mmu_srp_aptr); - break; - - case 3: // CPU root pointer - WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_crp_limit<<32 | (uint64)m68ki_cpu.mmu_crp_aptr); - break; - - default: - fprintf(stderr,"680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC); - break; - } - } - else - { - switch ((modes>>10) & 7) - { - case 0: // translation control register - m68ki_cpu.mmu_tc = READ_EA_32(ea); - - if (m68ki_cpu.mmu_tc & 0x80000000) - { - m68ki_cpu.pmmu_enabled = 1; - } - else - { - m68ki_cpu.pmmu_enabled = 0; - } - break; - - case 2: // supervisor root pointer - temp64 = READ_EA_64(ea); - m68ki_cpu.mmu_srp_limit = (temp64>>32) & 0xffffffff; - m68ki_cpu.mmu_srp_aptr = temp64 & 0xffffffff; - break; - - case 3: // CPU root pointer - temp64 = READ_EA_64(ea); - m68ki_cpu.mmu_crp_limit = (temp64>>32) & 0xffffffff; - m68ki_cpu.mmu_crp_aptr = temp64 & 0xffffffff; - break; - - default: - fprintf(stderr,"680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC); - break; - } - } - break; - - case 3: // MC68030 to/from status reg - if (modes & 0x200) - { - WRITE_EA_32(ea, m68ki_cpu.mmu_sr); - } - else - { - m68ki_cpu.mmu_sr = READ_EA_32(ea); - } - break; - - default: - fprintf(stderr,"680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, REG_PC); - break; - } - } - break; - - default: - fprintf(stderr,"680x0: unknown PMMU instruction group %d\n", (m68ki_cpu.ir>>9) & 0x7); - break; - } - } -} - +/* + m68kmmu.h - PMMU implementation for 68851/68030/68040 + + By R. Belmont + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. +*/ + +/* + pmmu_translate_addr: perform 68851/68030-style PMMU address translation +*/ +uint pmmu_translate_addr(uint addr_in) +{ + uint32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0, tcmode = 0; + uint root_aptr, root_limit, tofs, is, abits, bbits, cbits; + uint resolved, tptr, shift; + + resolved = 0; + addr_out = addr_in; + + // if SRP is enabled and we're in supervisor mode, use it + if ((m68ki_cpu.mmu_tc & 0x02000000) && (m68ki_get_sr() & 0x2000)) + { + root_aptr = m68ki_cpu.mmu_srp_aptr; + root_limit = m68ki_cpu.mmu_srp_limit; + } + else // else use the CRP + { + root_aptr = m68ki_cpu.mmu_crp_aptr; + root_limit = m68ki_cpu.mmu_crp_limit; + } + + // get initial shift (# of top bits to ignore) + is = (m68ki_cpu.mmu_tc>>16) & 0xf; + abits = (m68ki_cpu.mmu_tc>>12)&0xf; + bbits = (m68ki_cpu.mmu_tc>>8)&0xf; + cbits = (m68ki_cpu.mmu_tc>>4)&0xf; + +// fprintf(stderr,"PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68ki_cpu.mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits); + + // get table A offset + tofs = (addr_in<>(32-abits); + + // find out what format table A is + switch (root_limit & 3) + { + case 0: // invalid, should cause MMU exception + case 1: // page descriptor, should cause direct mapping + fatalerror("680x0 PMMU: Unhandled root mode\n"); + break; + + case 2: // valid 4 byte descriptors + tofs *= 4; +// fprintf(stderr,"PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc)); + tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)); + tamode = tbl_entry & 3; +// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs); + break; + + case 3: // valid 8 byte descriptors + tofs *= 8; +// fprintf(stderr,"PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc)); + tbl_entry2 = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)); + tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)+4); + tamode = tbl_entry2 & 3; +// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); + break; + } + + // get table B offset and pointer + tofs = (addr_in<<(is+abits))>>(32-bbits); + tptr = tbl_entry & 0xfffffff0; + + // find out what format table B is, if any + switch (tamode) + { + case 0: // invalid, should cause MMU exception + fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in); + break; + + case 2: // 4-byte table B descriptor + tofs *= 4; +// fprintf(stderr,"PMMU: reading table B entry at %08x\n", tofs + tptr); + tbl_entry = m68k_read_memory_32( tofs + tptr); + tbmode = tbl_entry & 3; +// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); + break; + + case 3: // 8-byte table B descriptor + tofs *= 8; +// fprintf(stderr,"PMMU: reading table B entries at %08x\n", tofs + tptr); + tbl_entry2 = m68k_read_memory_32( tofs + tptr); + tbl_entry = m68k_read_memory_32( tofs + tptr + 4); + tbmode = tbl_entry2 & 3; +// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); + break; + + case 1: // early termination descriptor + tbl_entry &= 0xffffff00; + + shift = is+abits; + addr_out = ((addr_in<>shift) + tbl_entry; + resolved = 1; + break; + } + + // if table A wasn't early-out, continue to process table B + if (!resolved) + { + // get table C offset and pointer + tofs = (addr_in<<(is+abits+bbits))>>(32-cbits); + tptr = tbl_entry & 0xfffffff0; + + switch (tbmode) + { + case 0: // invalid, should cause MMU exception + fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC); + break; + + case 2: // 4-byte table C descriptor + tofs *= 4; +// fprintf(stderr,"PMMU: reading table C entry at %08x\n", tofs + tptr); + tbl_entry = m68k_read_memory_32(tofs + tptr); + tcmode = tbl_entry & 3; +// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); + break; + + case 3: // 8-byte table C descriptor + tofs *= 8; +// fprintf(stderr,"PMMU: reading table C entries at %08x\n", tofs + tptr); + tbl_entry2 = m68k_read_memory_32(tofs + tptr); + tbl_entry = m68k_read_memory_32(tofs + tptr + 4); + tcmode = tbl_entry2 & 3; +// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); + break; + + case 1: // termination descriptor + tbl_entry &= 0xffffff00; + + shift = is+abits+bbits; + addr_out = ((addr_in<>shift) + tbl_entry; + resolved = 1; + break; + } + } + + if (!resolved) + { + switch (tcmode) + { + case 0: // invalid, should cause MMU exception + case 2: // 4-byte ??? descriptor + case 3: // 8-byte ??? descriptor + fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC); + break; + + case 1: // termination descriptor + tbl_entry &= 0xffffff00; + + shift = is+abits+bbits+cbits; + addr_out = ((addr_in<>shift) + tbl_entry; + resolved = 1; + break; + } + } + + +// fprintf(stderr,"PMMU: [%08x] => [%08x]\n", addr_in, addr_out); + + return addr_out; +} + +/* + + m68881_mmu_ops: COP 0 MMU opcode handling + +*/ + +void m68881_mmu_ops(void) +{ + uint16 modes; + uint32 ea = m68ki_cpu.ir & 0x3f; + uint64 temp64; + + // catch the 2 "weird" encodings up front (PBcc) + if ((m68ki_cpu.ir & 0xffc0) == 0xf0c0) + { + fprintf(stderr,"680x0: unhandled PBcc\n"); + return; + } + else if ((m68ki_cpu.ir & 0xffc0) == 0xf080) + { + fprintf(stderr,"680x0: unhandled PBcc\n"); + return; + } + else // the rest are 1111000xxxXXXXXX where xxx is the instruction family + { + switch ((m68ki_cpu.ir>>9) & 0x7) + { + case 0: + modes = OPER_I_16(); + + if ((modes & 0xfde0) == 0x2000) // PLOAD + { + fprintf(stderr,"680x0: unhandled PLOAD\n"); + return; + } + else if ((modes & 0xe200) == 0x2000) // PFLUSH + { + fprintf(stderr,"680x0: unhandled PFLUSH PC=%x\n", REG_PC); + return; + } + else if (modes == 0xa000) // PFLUSHR + { + fprintf(stderr,"680x0: unhandled PFLUSHR\n"); + return; + } + else if (modes == 0x2800) // PVALID (FORMAT 1) + { + fprintf(stderr,"680x0: unhandled PVALID1\n"); + return; + } + else if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2) + { + fprintf(stderr,"680x0: unhandled PVALID2\n"); + return; + } + else if ((modes & 0xe000) == 0x8000) // PTEST + { + fprintf(stderr,"680x0: unhandled PTEST\n"); + return; + } + else + { + switch ((modes>>13) & 0x7) + { + case 0: // MC68030/040 form with FD bit + case 2: // MC68881 form, FD never set + if (modes & 0x200) + { + switch ((modes>>10) & 7) + { + case 0: // translation control register + WRITE_EA_32(ea, m68ki_cpu.mmu_tc); + break; + + case 2: // supervisor root pointer + WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_srp_limit<<32 | (uint64)m68ki_cpu.mmu_srp_aptr); + break; + + case 3: // CPU root pointer + WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_crp_limit<<32 | (uint64)m68ki_cpu.mmu_crp_aptr); + break; + + default: + fprintf(stderr,"680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC); + break; + } + } + else + { + switch ((modes>>10) & 7) + { + case 0: // translation control register + m68ki_cpu.mmu_tc = READ_EA_32(ea); + + if (m68ki_cpu.mmu_tc & 0x80000000) + { + m68ki_cpu.pmmu_enabled = 1; + } + else + { + m68ki_cpu.pmmu_enabled = 0; + } + break; + + case 2: // supervisor root pointer + temp64 = READ_EA_64(ea); + m68ki_cpu.mmu_srp_limit = (temp64>>32) & 0xffffffff; + m68ki_cpu.mmu_srp_aptr = temp64 & 0xffffffff; + break; + + case 3: // CPU root pointer + temp64 = READ_EA_64(ea); + m68ki_cpu.mmu_crp_limit = (temp64>>32) & 0xffffffff; + m68ki_cpu.mmu_crp_aptr = temp64 & 0xffffffff; + break; + + default: + fprintf(stderr,"680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC); + break; + } + } + break; + + case 3: // MC68030 to/from status reg + if (modes & 0x200) + { + WRITE_EA_32(ea, m68ki_cpu.mmu_sr); + } + else + { + m68ki_cpu.mmu_sr = READ_EA_32(ea); + } + break; + + default: + fprintf(stderr,"680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, REG_PC); + break; + } + } + break; + + default: + fprintf(stderr,"680x0: unknown PMMU instruction group %d\n", (m68ki_cpu.ir>>9) & 0x7); + break; + } + } +} + diff --git a/AltairZ80/m68k/softfloat/softfloat.c b/AltairZ80/m68k/softfloat/softfloat.c index fd65afa4..b71900fd 100644 --- a/AltairZ80/m68k/softfloat/softfloat.c +++ b/AltairZ80/m68k/softfloat/softfloat.c @@ -1,4940 +1,4940 @@ - -/*============================================================================ - -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "../m68kcpu.h" // which includes softfloat.h after defining the basic types - -/*---------------------------------------------------------------------------- -| Floating-point rounding mode, extended double-precision rounding precision, -| and exception flags. -*----------------------------------------------------------------------------*/ -int8 float_exception_flags = 0; -#ifdef FLOATX80 -int8 floatx80_rounding_precision = 80; -#endif - -int8 float_rounding_mode = float_round_nearest_even; - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) -{ - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int32 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - roundIncrement = 0x40; - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if ( zSign ) { - if ( roundingMode == float_round_up ) roundIncrement = 0; - } - else { - if ( roundingMode == float_round_down ) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = ( absZ + roundIncrement )>>7; - absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - z = (int32)absZ; - if ( zSign ) z = - z; - if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_raise( float_flag_invalid ); - return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( roundBits ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest positive or negative integer is -| returned. -*----------------------------------------------------------------------------*/ - -static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) -{ - int8 roundingMode; - flag roundNearestEven, increment; - int64 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) absZ1 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && absZ1; - } - else { - increment = ( roundingMode == float_round_up ) && absZ1; - } - } - } - if ( increment ) { - ++absZ0; - if ( absZ0 == 0 ) goto overflow; - absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); - } - z = absZ0; - if ( zSign ) z = - z; - if ( z && ( ( z < 0 ) ^ zSign ) ) { - overflow: - float_raise( float_flag_invalid ); - return - zSign ? (sbits64) LIT64( 0x8000000000000000 ) - : (sbits64) LIT64( 0x7FFFFFFFFFFFFFFF ); - } - if ( absZ1 ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline bits32 extractFloat32Frac( float32 a ) -{ - return a & 0x007FFFFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline int16 extractFloat32Exp( float32 a ) -{ - return ( a>>23 ) & 0xFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat32Sign( float32 a ) -{ - return a>>31; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( aSig ) - 8; - *zSigPtr = aSig<>7; - zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat64Sign( float64 a ) -{ - return a>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ) - 11; - *zSigPtr = aSig<>10; - zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>48 ) & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat128Sign( float128 a ) -{ - return a.high>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat128Subnormal( - bits64 aSig0, - bits64 aSig1, - int32 *zExpPtr, - bits64 *zSig0Ptr, - bits64 *zSig1Ptr - ) -{ - int8 shiftCount; - - if ( aSig0 == 0 ) { - shiftCount = countLeadingZeros64( aSig1 ) - 15; - if ( shiftCount < 0 ) { - *zSig0Ptr = aSig1>>( - shiftCount ); - *zSig1Ptr = aSig1<<( shiftCount & 63 ); - } - else { - *zSig0Ptr = aSig1<>( - shiftCount ); - if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64, aSigExtra; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = 0xBE - aExp; - if ( shiftCount < 0 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - if ( aExp ) aSig |= 0x00800000; - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); - return roundAndPackInt64( aSign, aSig64, aSigExtra ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64_round_to_zero( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64; - int64 z; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0xBE; - if ( 0 <= shiftCount ) { - if ( a != 0xDF000000 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>( - shiftCount ); - if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); - return packFloat64( aSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float32_to_floatx80( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - aSig |= 0x00800000; - return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float32_to_float128( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 lastBitMask, roundBitsMask; - int8 roundingMode; - float32 z; - - aExp = extractFloat32Exp( a ); - if ( 0x96 <= aExp ) { - if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { - return propagateFloat32NaN( a, a ); - } - return a; - } - if ( aExp <= 0x7E ) { - if ( (bits32) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat32Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { - return packFloat32( aSign, 0x7F, 0 ); - } - break; - case float_round_down: - return aSign ? 0xBF800000 : 0; - case float_round_up: - return aSign ? 0x80000000 : 0x3F800000; - } - return packFloat32( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - if ( 0 < expDiff ) { - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x20000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x20000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); - zSig = 0x40000000 + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= 0x20000000; - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits32) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign ^ 1, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x40000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x40000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return addFloat32Sigs( a, b, aSign ); - } - else { - return subFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return subFloat32Sigs( a, b, aSign ); - } - else { - return addFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig; - bits64 zSig64; - bits32 zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x7F; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); - zSig = (bits32)zSig64; - if ( 0 <= (sbits32) ( zSig<<1 ) ) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat32( zSign, 0xFF, 0 ); - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x7D; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = ( ( (bits64) aSig )<<32 ) / bSig; - if ( ( zSig & 0x3F ) == 0 ) { - zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the single-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_rem( float32 a, float32 b ) -{ - flag aSign, zSign; - int16 aExp, bExp, expDiff; - bits32 aSig, bSig; - bits32 q; - bits64 aSig64, bSig64, q64; - bits32 alternateASig; - sbits32 sigMean; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); -// bSign = extractFloat32Sign( b ); - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig |= 0x00800000; - bSig |= 0x00800000; - if ( expDiff < 32 ) { - aSig <<= 8; - bSig <<= 8; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - if ( 0 < expDiff ) { - q = ( ( (bits64) aSig )<<32 ) / bSig; - q >>= 32 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - } - else { - if ( bSig <= aSig ) aSig -= bSig; - aSig64 = ( (bits64) aSig )<<40; - bSig64 = ( (bits64) bSig )<<40; - expDiff -= 64; - while ( 0 < expDiff ) { - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - aSig64 = - ( ( bSig * q64 )<<38 ); - expDiff -= 62; - } - expDiff += 64; - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - q = (bits32)(q64>>( 64 - expDiff )); - bSig <<= 6; - aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits32) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits32) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt( float32 a ) -{ - flag aSign; - int16 aExp, zExp; - bits32 aSig, zSig; - bits64 rem, term; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, 0 ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; - aSig = ( aSig | 0x00800000 )<<8; - zSig = estimateSqrt32( aExp, aSig ) + 2; - if ( ( zSig & 0x7F ) <= 5 ) { - if ( zSig < 2 ) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ( (bits64) zSig ) * zSig; - rem = ( ( (bits64) aSig )<<32 ) - term; - while ( (sbits64) rem < 0 ) { - --zSig; - rem += ( ( (bits64) zSig )<<1 ) | 1; - } - zSig |= ( rem != 0 ); - } - shift32RightJamming( zSig, 1, &zSig ); - roundAndPack: - return roundAndPackFloat32( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq( float32 a, float32 b ) -{ - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq_signaling( float32 a, float32 b ) -{ - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; -// int16 aExp, bExp; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x42C - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32_round_to_zero( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( 0x41E < aExp ) { - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = (int32)aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - bits32 zSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 22, &aSig ); - zSig = (bits32)aSig; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float64_to_floatx80( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - return - packFloatx80( - aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the quadruple-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float64_to_float128( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float64 z; - - aExp = extractFloat64Exp( a ); - if ( 0x433 <= aExp ) { - if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { - return propagateFloat64NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FF ) { - if ( (bits64) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat64Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { - return packFloat64( aSign, 0x3FF, 0 ); - } - break; - case float_round_down: - return aSign ? LIT64( 0xBFF0000000000000 ) : 0; - case float_round_up: - return - aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); - } - return packFloat64( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if ( 0 < expDiff ) { - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); - zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= LIT64( 0x2000000000000000 ); - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits64) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign ^ 1, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - bSig |= LIT64( 0x4000000000000000 ); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - aSig |= LIT64( 0x4000000000000000 ); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return addFloat64Sigs( a, b, aSign ); - } - else { - return subFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return subFloat64Sigs( a, b, aSign ); - } - else { - return addFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FF; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - zSig0 |= ( zSig1 != 0 ); - if ( 0 <= (sbits64) ( zSig0<<1 ) ) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64( zSign, zExp, zSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - bits64 rem0, rem1; - bits64 term0, term1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat64( zSign, 0x7FF, 0 ); - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FD; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64( aSig, 0, bSig ); - if ( ( zSig & 0x1FF ) <= 2 ) { - mul64To128( bSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig |= ( rem1 != 0 ); - } - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the double-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_rem( float64 a, float64 b ) -{ - flag aSign, zSign; - int16 aExp, bExp, expDiff; - bits64 aSig, bSig; - bits64 q, alternateASig; - sbits64 sigMean; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); -// bSign = extractFloat64Sign( b ); - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - aSig = - ( ( bSig>>2 ) * q ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits64) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits64) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt( float64 a ) -{ - flag aSign; - int16 aExp, zExp; - bits64 aSig, zSig, doubleZSig; - bits64 rem0, rem1, term0, term1; -// float64 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, a ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; - aSig |= LIT64( 0x0010000000000000 ); - zSig = estimateSqrt32( aExp, (bits32)(aSig>>21) ); - aSig <<= 9 - ( aExp & 1 ); - zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); - if ( ( zSig & 0x1FF ) <= 5 ) { - doubleZSig = zSig<<1; - mul64To128( zSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - doubleZSig -= 2; - add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); - } - zSig |= ( ( rem0 | rem1 ) != 0 ); - } - return roundAndPackFloat64( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq( float64 a, float64 b ) -{ - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The invalid exception is raised -| if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq_signaling( float64 a, float64 b ) -{ - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; -// int16 aExp, bExp; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic---which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN, the -| largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - shiftCount = 0x4037 - aExp; - if ( shiftCount <= 0 ) shiftCount = 1; - shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN, the largest positive integer is returned. -| Otherwise, if the conversion overflows, the largest integer with the same -| sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32_round_to_zero( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = (int32)aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 33, &aSig ); - if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, (bits32)aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig, zSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shift64RightJamming( aSig, 1, &zSig ); - if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); - -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128( floatx80 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); - } - shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended quadruple-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - floatx80 z; - - aExp = extractFloatx80Exp( a ); - if ( 0x403E <= aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { - return propagateFloatx80NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FFF ) { - if ( ( aExp == 0 ) - && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { - return a; - } - float_exception_flags |= float_flag_inexact; - aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) - ) { - return - packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - break; - case float_round_down: - return - aSign ? - packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) - : packFloatx80( 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloatx80( 1, 0, 0 ) - : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - return packFloatx80( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.low += lastBitMask>>1; - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z.low += roundBitsMask; - } - } - z.low &= ~ roundBitsMask; - if ( z.low == 0 ) { - ++z.high; - z.low = LIT64( 0x8000000000000000 ); - } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if ( aExp == 0 ) { - normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ( (sbits64) zSig0 < 0 ) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); - ++zExp; - roundAndPack: - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - bBigger: - sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - aBigger: - sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); - } - else { - return subFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); - } - else { - return addFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) goto invalid; - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - if ( 0 < (sbits64) zSig0 ) { - shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); - --zExp; - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - bits64 rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - goto invalid; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if ( bSig <= aSig ) { - shift128Right( aSig, 0, 1, &aSig, &rem1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig, rem1, bSig ); - mul64To128( bSig, zSig0, &term0, &term1 ); - sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, bSig ); - if ( (bits64) ( zSig1<<1 ) <= 8 ) { - mul64To128( bSig, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); - } - zSig1 |= ( ( rem1 | rem2 ) != 0 ); - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_rem( floatx80 a, floatx80 b ) -{ - flag aSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig; - bits64 q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); -// bSign = extractFloatx80Sign( b ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( (bits64) ( aSig0<<1 ) == 0 ) return a; - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - bSig |= LIT64( 0x8000000000000000 ); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); - expDiff = 0; - } - q = ( bSig <= aSig0 ); - if ( q ) aSig0 -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - mul64To128( bSig, q, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); - while ( le128( term0, term1, aSig0, aSig1 ) ) { - ++q; - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - } - } - else { - term1 = 0; - term0 = bSig; - } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt( floatx80 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; - zSig0 = estimateSqrt32( aExp, aSig0>>32 ); - shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq( floatx80 a, floatx80 b ) -{ - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq_signaling( floatx80 a, floatx80 b ) -{ - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - aSig0 |= ( aSig1 != 0 ); - shiftCount = 0x4028 - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); - return roundAndPackInt32( aSign, aSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32_round_to_zero( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1, savedASig; - int32 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - aSig0 |= ( aSig1 != 0 ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = (int32)aSig0; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); - if ( (bits64) ( aSig1<>( - shiftCount ); - if ( aSig1 - || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - bits32 zSig; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - aSig0 |= ( aSig1 != 0 ); - shift64RightJamming( aSig0, 18, &aSig0 ); - zSig = (bits32)aSig0; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - aSig0 |= ( aSig1 != 0 ); - if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); - aExp -= 0x3C01; - } - return roundAndPackFloat64( aSign, aExp, aSig0 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a ) ); - } - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); - return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, and -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float128 z; - - aExp = extractFloat128Exp( a ); - if ( 0x402F <= aExp ) { - if ( 0x406F <= aExp ) { - if ( ( aExp == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) - ) { - return propagateFloat128NaN( a, a ); - } - return a; - } - lastBitMask = 1; - lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else { - if ( (sbits64) z.low < 0 ) { - ++z.high; - if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; - } - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); - } - } - z.low &= ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat128Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.high += lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { - z.high &= ~ lastBitMask; - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - z.high |= ( a.low != 0 ); - z.high += roundBitsMask; - } - } - z.high &= ~ roundBitsMask; - } - if ( ( z.low != a.low ) || ( z.high != a.high ) ) { - float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32 expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32 expDiff; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs( a, b, aSign ); - } - else { - return subFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs( a, b, aSign ); - } - else { - return addFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the quadruple-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_rem( float128 a, float128 b ) -{ - flag aSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; - bits64 allZero, alternateASig0, alternateASig1, sigMean1; - sbits64 sigMean0; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); -// bSign = extractFloat128Sign( b ); - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return a; - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - expDiff = aExp - bExp; - if ( expDiff < -1 ) return a; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), - aSig1, - 15 - ( expDiff < 0 ), - &aSig0, - &aSig1 - ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - q = le128( bSig0, bSig1, aSig0, aSig1 ); - if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); - shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); - sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); - expDiff -= 61; - } - if ( -64 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - q >>= - expDiff; - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - expDiff += 52; - if ( expDiff < 0 ) { - shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - } - else { - shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); - } - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); - } - else { - shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - } - do { - alternateASig0 = aSig0; - alternateASig1 = aSig1; - ++q; - sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - } while ( 0 <= (sbits64) aSig0 ); - add128( - aSig0, aSig1, alternateASig0, alternateASig1, (bits64 *)&sigMean0, &sigMean1 ); - if ( ( sigMean0 < 0 ) - || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - } - zSign = ( (sbits64) aSig0 < 0 ); - if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); - return - normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt( float128 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); - zSig0 = estimateSqrt32( aExp, (bits32)(aSig0>>17 )); - shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & 0x1FFF ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq( float128 a, float128 b ) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq_signaling( float128 a, float128 b ) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif + +/*============================================================================ + +This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +#include "../m68kcpu.h" // which includes softfloat.h after defining the basic types + +/*---------------------------------------------------------------------------- +| Floating-point rounding mode, extended double-precision rounding precision, +| and exception flags. +*----------------------------------------------------------------------------*/ +int8 float_exception_flags = 0; +#ifdef FLOATX80 +int8 floatx80_rounding_precision = 80; +#endif + +int8 float_rounding_mode = float_round_nearest_even; + +/*---------------------------------------------------------------------------- +| Functions and definitions to determine: (1) whether tininess for underflow +| is detected before or after rounding by default, (2) what (if anything) +| happens when exceptions are raised, (3) how signaling NaNs are distinguished +| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs +| are propagated from function inputs to output. These details are target- +| specific. +*----------------------------------------------------------------------------*/ +#include "softfloat-specialize" + +/*---------------------------------------------------------------------------- +| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 +| and 7, and returns the properly rounded 32-bit integer corresponding to the +| input. If `zSign' is 1, the input is negated before being converted to an +| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input +| is simply rounded to an integer, with the inexact exception raised if the +| input cannot be represented exactly as an integer. However, if the fixed- +| point input is too large, the invalid exception is raised and the largest +| positive or negative integer is returned. +*----------------------------------------------------------------------------*/ + +static int32 roundAndPackInt32( flag zSign, bits64 absZ ) +{ + int8 roundingMode; + flag roundNearestEven; + int8 roundIncrement, roundBits; + int32 z; + + roundingMode = float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + roundIncrement = 0x40; + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + roundIncrement = 0; + } + else { + roundIncrement = 0x7F; + if ( zSign ) { + if ( roundingMode == float_round_up ) roundIncrement = 0; + } + else { + if ( roundingMode == float_round_down ) roundIncrement = 0; + } + } + } + roundBits = absZ & 0x7F; + absZ = ( absZ + roundIncrement )>>7; + absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + z = (int32)absZ; + if ( zSign ) z = - z; + if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { + float_raise( float_flag_invalid ); + return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( roundBits ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and +| `absZ1', with binary point between bits 63 and 64 (between the input words), +| and returns the properly rounded 64-bit integer corresponding to the input. +| If `zSign' is 1, the input is negated before being converted to an integer. +| Ordinarily, the fixed-point input is simply rounded to an integer, with +| the inexact exception raised if the input cannot be represented exactly as +| an integer. However, if the fixed-point input is too large, the invalid +| exception is raised and the largest positive or negative integer is +| returned. +*----------------------------------------------------------------------------*/ + +static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) +{ + int8 roundingMode; + flag roundNearestEven, increment; + int64 z; + + roundingMode = float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + increment = ( (sbits64) absZ1 < 0 ); + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + increment = 0; + } + else { + if ( zSign ) { + increment = ( roundingMode == float_round_down ) && absZ1; + } + else { + increment = ( roundingMode == float_round_up ) && absZ1; + } + } + } + if ( increment ) { + ++absZ0; + if ( absZ0 == 0 ) goto overflow; + absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); + } + z = absZ0; + if ( zSign ) z = - z; + if ( z && ( ( z < 0 ) ^ zSign ) ) { + overflow: + float_raise( float_flag_invalid ); + return + zSign ? (sbits64) LIT64( 0x8000000000000000 ) + : (sbits64) LIT64( 0x7FFFFFFFFFFFFFFF ); + } + if ( absZ1 ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the fraction bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline bits32 extractFloat32Frac( float32 a ) +{ + return a & 0x007FFFFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the exponent bits of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline int16 extractFloat32Exp( float32 a ) +{ + return ( a>>23 ) & 0xFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the single-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline flag extractFloat32Sign( float32 a ) +{ + return a>>31; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal single-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros32( aSig ) - 8; + *zSigPtr = aSig<>7; + zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); + if ( zSig == 0 ) zExp = 0; + return packFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper single-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat32' except that `zSig' does not have to be normalized. +| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +static float32 + normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros32( zSig ) - 1; + return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the double-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline flag extractFloat64Sign( float64 a ) +{ + return a>>63; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal double-precision floating-point value represented +| by the denormalized significand `aSig'. The normalized exponent and +| significand are stored at the locations pointed to by `zExpPtr' and +| `zSigPtr', respectively. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64( aSig ) - 11; + *zSigPtr = aSig<>10; + zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); + if ( zSig == 0 ) zExp = 0; + return packFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Takes an abstract floating-point value having sign `zSign', exponent `zExp', +| and significand `zSig', and returns the proper double-precision floating- +| point value corresponding to the abstract input. This routine is just like +| `roundAndPackFloat64' except that `zSig' does not have to be normalized. +| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' +| floating-point exponent. +*----------------------------------------------------------------------------*/ + +static float64 + normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64( zSig ) - 1; + return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>48 ) & 0x7FFF; + +} + +/*---------------------------------------------------------------------------- +| Returns the sign bit of the quadruple-precision floating-point value `a'. +*----------------------------------------------------------------------------*/ + +static inline flag extractFloat128Sign( float128 a ) +{ + return a.high>>63; + +} + +/*---------------------------------------------------------------------------- +| Normalizes the subnormal quadruple-precision floating-point value +| represented by the denormalized significand formed by the concatenation of +| `aSig0' and `aSig1'. The normalized exponent is stored at the location +| pointed to by `zExpPtr'. The most significant 49 bits of the normalized +| significand are stored at the location pointed to by `zSig0Ptr', and the +| least significant 64 bits of the normalized significand are stored at the +| location pointed to by `zSig1Ptr'. +*----------------------------------------------------------------------------*/ + +static void + normalizeFloat128Subnormal( + bits64 aSig0, + bits64 aSig1, + int32 *zExpPtr, + bits64 *zSig0Ptr, + bits64 *zSig1Ptr + ) +{ + int8 shiftCount; + + if ( aSig0 == 0 ) { + shiftCount = countLeadingZeros64( aSig1 ) - 15; + if ( shiftCount < 0 ) { + *zSig0Ptr = aSig1>>( - shiftCount ); + *zSig1Ptr = aSig1<<( shiftCount & 63 ); + } + else { + *zSig0Ptr = aSig1<>( - shiftCount ); + if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. Otherwise, if the conversion overflows, the +| largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int64 float32_to_int64( float32 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits32 aSig; + bits64 aSig64, aSigExtra; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + shiftCount = 0xBE - aExp; + if ( shiftCount < 0 ) { + float_raise( float_flag_invalid ); + if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + if ( aExp ) aSig |= 0x00800000; + aSig64 = aSig; + aSig64 <<= 40; + shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); + return roundAndPackInt64( aSign, aSig64, aSigExtra ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the 64-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. If +| `a' is a NaN, the largest positive integer is returned. Otherwise, if the +| conversion overflows, the largest integer with the same sign as `a' is +| returned. +*----------------------------------------------------------------------------*/ + +int64 float32_to_int64_round_to_zero( float32 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits32 aSig; + bits64 aSig64; + int64 z; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + shiftCount = aExp - 0xBE; + if ( 0 <= shiftCount ) { + if ( a != 0xDF000000 ) { + float_raise( float_flag_invalid ); + if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { + return LIT64( 0x7FFFFFFFFFFFFFFF ); + } + } + return (sbits64) LIT64( 0x8000000000000000 ); + } + else if ( aExp <= 0x7E ) { + if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig64 = aSig | 0x00800000; + aSig64 <<= 40; + z = aSig64>>( - shiftCount ); + if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the double-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float32_to_float64( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); + return packFloat64( aSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the extended double-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float32_to_floatx80( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + aSig |= 0x00800000; + return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the single-precision floating-point value +| `a' to the double-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float32_to_float128( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 aSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); + return packFloat128( aSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the single-precision floating-point value `a' to an integer, and +| returns the result as a single-precision floating-point value. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_round_to_int( float32 a ) +{ + flag aSign; + int16 aExp; + bits32 lastBitMask, roundBitsMask; + int8 roundingMode; + float32 z; + + aExp = extractFloat32Exp( a ); + if ( 0x96 <= aExp ) { + if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { + return propagateFloat32NaN( a, a ); + } + return a; + } + if ( aExp <= 0x7E ) { + if ( (bits32) ( a<<1 ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat32Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { + return packFloat32( aSign, 0x7F, 0 ); + } + break; + case float_round_down: + return aSign ? 0xBF800000 : 0; + case float_round_up: + return aSign ? 0x80000000 : 0x3F800000; + } + return packFloat32( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x96 - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z += lastBitMask>>1; + if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z += roundBitsMask; + } + } + z &= ~ roundBitsMask; + if ( z != a ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the single-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + expDiff = aExp - bExp; + aSig <<= 6; + bSig <<= 6; + if ( 0 < expDiff ) { + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= 0x20000000; + } + shift32RightJamming( bSig, expDiff, &bSig ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign, 0xFF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= 0x20000000; + } + shift32RightJamming( aSig, - expDiff, &aSig ); + zExp = bExp; + } + else { + if ( aExp == 0xFF ) { + if ( aSig | bSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); + zSig = 0x40000000 + aSig + bSig; + zExp = aExp; + goto roundAndPack; + } + aSig |= 0x20000000; + zSig = ( aSig + bSig )<<1; + --zExp; + if ( (sbits32) zSig < 0 ) { + zSig = aSig + bSig; + ++zExp; + } + roundAndPack: + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the single- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + expDiff = aExp - bExp; + aSig <<= 7; + bSig <<= 7; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0xFF ) { + if ( aSig | bSig ) return propagateFloat32NaN( a, b ); + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign ^ 1, 0xFF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= 0x40000000; + } + shift32RightJamming( aSig, - expDiff, &aSig ); + bSig |= 0x40000000; + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= 0x40000000; + } + shift32RightJamming( bSig, expDiff, &bSig ); + aSig |= 0x40000000; + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the single-precision floating-point values `a' +| and `b'. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_add( float32 a, float32 b ) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign == bSign ) { + return addFloat32Sigs( a, b, aSign ); + } + else { + return subFloat32Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_sub( float32 a, float32 b ) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign == bSign ) { + return subFloat32Sigs( a, b, aSign ); + } + else { + return addFloat32Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the single-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_mul( float32 a, float32 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits32 aSig, bSig; + bits64 zSig64; + bits32 zSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + bSign = extractFloat32Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0xFF ) { + if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { + return propagateFloat32NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x7F; + aSig = ( aSig | 0x00800000 )<<7; + bSig = ( bSig | 0x00800000 )<<8; + shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); + zSig = (bits32)zSig64; + if ( 0 <= (sbits32) ( zSig<<1 ) ) { + zSig <<= 1; + --zExp; + } + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the single-precision floating-point value `a' +| by the corresponding value `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_div( float32 a, float32 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); + bSign = extractFloat32Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, b ); + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + float_raise( float_flag_invalid ); + return float32_default_nan; + } + return packFloat32( zSign, 0xFF, 0 ); + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return packFloat32( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + float_raise( float_flag_divbyzero ); + return packFloat32( zSign, 0xFF, 0 ); + } + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x7D; + aSig = ( aSig | 0x00800000 )<<7; + bSig = ( bSig | 0x00800000 )<<8; + if ( bSig <= ( aSig + aSig ) ) { + aSig >>= 1; + ++zExp; + } + zSig = ( ( (bits64) aSig )<<32 ) / bSig; + if ( ( zSig & 0x3F ) == 0 ) { + zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); + } + return roundAndPackFloat32( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the single-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_rem( float32 a, float32 b ) +{ + flag aSign, zSign; + int16 aExp, bExp, expDiff; + bits32 aSig, bSig; + bits32 q; + bits64 aSig64, bSig64, q64; + bits32 alternateASig; + sbits32 sigMean; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + bSig = extractFloat32Frac( b ); + bExp = extractFloat32Exp( b ); +// bSign = extractFloat32Sign( b ); + if ( aExp == 0xFF ) { + if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { + return propagateFloat32NaN( a, b ); + } + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( bExp == 0xFF ) { + if ( bSig ) return propagateFloat32NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + float_raise( float_flag_invalid ); + return float32_default_nan; + } + normalizeFloat32Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return a; + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + expDiff = aExp - bExp; + aSig |= 0x00800000; + bSig |= 0x00800000; + if ( expDiff < 32 ) { + aSig <<= 8; + bSig <<= 8; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + aSig >>= 1; + } + q = ( bSig <= aSig ); + if ( q ) aSig -= bSig; + if ( 0 < expDiff ) { + q = ( ( (bits64) aSig )<<32 ) / bSig; + q >>= 32 - expDiff; + bSig >>= 2; + aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; + } + else { + aSig >>= 2; + bSig >>= 2; + } + } + else { + if ( bSig <= aSig ) aSig -= bSig; + aSig64 = ( (bits64) aSig )<<40; + bSig64 = ( (bits64) bSig )<<40; + expDiff -= 64; + while ( 0 < expDiff ) { + q64 = estimateDiv128To64( aSig64, 0, bSig64 ); + q64 = ( 2 < q64 ) ? q64 - 2 : 0; + aSig64 = - ( ( bSig * q64 )<<38 ); + expDiff -= 62; + } + expDiff += 64; + q64 = estimateDiv128To64( aSig64, 0, bSig64 ); + q64 = ( 2 < q64 ) ? q64 - 2 : 0; + q = (bits32)(q64>>( 64 - expDiff )); + bSig <<= 6; + aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; + } + do { + alternateASig = aSig; + ++q; + aSig -= bSig; + } while ( 0 <= (sbits32) aSig ); + sigMean = aSig + alternateASig; + if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { + aSig = alternateASig; + } + zSign = ( (sbits32) aSig < 0 ); + if ( zSign ) aSig = - aSig; + return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the single-precision floating-point value `a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float32_sqrt( float32 a ) +{ + flag aSign; + int16 aExp, zExp; + bits32 aSig, zSig; + bits64 rem, term; + + aSig = extractFloat32Frac( a ); + aExp = extractFloat32Exp( a ); + aSign = extractFloat32Sign( a ); + if ( aExp == 0xFF ) { + if ( aSig ) return propagateFloat32NaN( a, 0 ); + if ( ! aSign ) return a; + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aSign ) { + if ( ( aExp | aSig ) == 0 ) return a; + float_raise( float_flag_invalid ); + return float32_default_nan; + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return 0; + normalizeFloat32Subnormal( aSig, &aExp, &aSig ); + } + zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; + aSig = ( aSig | 0x00800000 )<<8; + zSig = estimateSqrt32( aExp, aSig ) + 2; + if ( ( zSig & 0x7F ) <= 5 ) { + if ( zSig < 2 ) { + zSig = 0x7FFFFFFF; + goto roundAndPack; + } + aSig >>= aExp & 1; + term = ( (bits64) zSig ) * zSig; + rem = ( ( (bits64) aSig )<<32 ) - term; + while ( (sbits64) rem < 0 ) { + --zSig; + rem += ( ( (bits64) zSig )<<1 ) | 1; + } + zSig |= ( rem != 0 ); + } + shift32RightJamming( zSig, 1, &zSig ); + roundAndPack: + return roundAndPackFloat32( 0, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_eq( float32 a, float32 b ) +{ + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. The comparison +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_le( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_lt( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_eq_signaling( float32 a, float32 b ) +{ + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_le_quiet( float32 a, float32 b ) +{ + flag aSign, bSign; +// int16 aExp, bExp; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the single-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float32_lt_quiet( float32 a, float32 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) + || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + ) { + if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat32Sign( a ); + bSign = extractFloat32Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. Otherwise, if the conversion overflows, the +| largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 float64_to_int32( float64 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits64 aSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; + if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); + shiftCount = 0x42C - aExp; + if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); + return roundAndPackInt32( aSign, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the 32-bit two's complement integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. +| If `a' is a NaN, the largest positive integer is returned. Otherwise, if +| the conversion overflows, the largest integer with the same sign as `a' is +| returned. +*----------------------------------------------------------------------------*/ + +int32 float64_to_int32_round_to_zero( float64 a ) +{ + flag aSign; + int16 aExp, shiftCount; + bits64 aSig, savedASig; + int32 z; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( 0x41E < aExp ) { + if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FF ) { + if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig |= LIT64( 0x0010000000000000 ); + shiftCount = 0x433 - aExp; + savedASig = aSig; + aSig >>= shiftCount; + z = (int32)aSig; + if ( aSign ) z = - z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig<>( - shiftCount ); + if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the single-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float64_to_float32( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig; + bits32 zSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); + return packFloat32( aSign, 0xFF, 0 ); + } + shift64RightJamming( aSig, 22, &aSig ); + zSig = (bits32)aSig; + if ( aExp || zSig ) { + zSig |= 0x40000000; + aExp -= 0x381; + } + return roundAndPackFloat32( aSign, aExp, zSig ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the extended double-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float64_to_floatx80( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + return + packFloatx80( + aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the double-precision floating-point value +| `a' to the quadruple-precision floating-point format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float64_to_float128( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig, zSig0, zSig1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); + return packFloat128( aSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + --aExp; + } + shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); + return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the double-precision floating-point value `a' to an integer, and +| returns the result as a double-precision floating-point value. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_round_to_int( float64 a ) +{ + flag aSign; + int16 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + float64 z; + + aExp = extractFloat64Exp( a ); + if ( 0x433 <= aExp ) { + if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { + return propagateFloat64NaN( a, a ); + } + return a; + } + if ( aExp < 0x3FF ) { + if ( (bits64) ( a<<1 ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat64Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { + return packFloat64( aSign, 0x3FF, 0 ); + } + break; + case float_round_down: + return aSign ? LIT64( 0xBFF0000000000000 ) : 0; + case float_round_up: + return + aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); + } + return packFloat64( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x433 - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z += lastBitMask>>1; + if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z += roundBitsMask; + } + } + z &= ~ roundBitsMask; + if ( z != a ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the double-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + expDiff = aExp - bExp; + aSig <<= 9; + bSig <<= 9; + if ( 0 < expDiff ) { + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= LIT64( 0x2000000000000000 ); + } + shift64RightJamming( bSig, expDiff, &bSig ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= LIT64( 0x2000000000000000 ); + } + shift64RightJamming( aSig, - expDiff, &aSig ); + zExp = bExp; + } + else { + if ( aExp == 0x7FF ) { + if ( aSig | bSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); + zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; + zExp = aExp; + goto roundAndPack; + } + aSig |= LIT64( 0x2000000000000000 ); + zSig = ( aSig + bSig )<<1; + --zExp; + if ( (sbits64) zSig < 0 ) { + zSig = aSig + bSig; + ++zExp; + } + roundAndPack: + return roundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the double- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) +{ + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + expDiff = aExp - bExp; + aSig <<= 10; + bSig <<= 10; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FF ) { + if ( aSig | bSig ) return propagateFloat64NaN( a, b ); + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign ^ 1, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig |= LIT64( 0x4000000000000000 ); + } + shift64RightJamming( aSig, - expDiff, &aSig ); + bSig |= LIT64( 0x4000000000000000 ); + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig |= LIT64( 0x4000000000000000 ); + } + shift64RightJamming( bSig, expDiff, &bSig ); + aSig |= LIT64( 0x4000000000000000 ); + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the double-precision floating-point values `a' +| and `b'. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_add( float64 a, float64 b ) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign == bSign ) { + return addFloat64Sigs( a, b, aSign ); + } + else { + return subFloat64Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_sub( float64 a, float64 b ) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign == bSign ) { + return subFloat64Sigs( a, b, aSign ); + } + else { + return addFloat64Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the double-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_mul( float64 a, float64 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + bSign = extractFloat64Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FF ) { + if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { + return propagateFloat64NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x3FF; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + mul64To128( aSig, bSig, &zSig0, &zSig1 ); + zSig0 |= ( zSig1 != 0 ); + if ( 0 <= (sbits64) ( zSig0<<1 ) ) { + zSig0 <<= 1; + --zExp; + } + return roundAndPackFloat64( zSign, zExp, zSig0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the double-precision floating-point value `a' +| by the corresponding value `b'. The operation is performed according to +| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_div( float64 a, float64 b ) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + bits64 rem0, rem1; + bits64 term0, term1; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); + bSign = extractFloat64Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, b ); + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + float_raise( float_flag_invalid ); + return float64_default_nan; + } + return packFloat64( zSign, 0x7FF, 0 ); + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return packFloat64( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + float_raise( float_flag_divbyzero ); + return packFloat64( zSign, 0x7FF, 0 ); + } + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x3FD; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + if ( bSig <= ( aSig + aSig ) ) { + aSig >>= 1; + ++zExp; + } + zSig = estimateDiv128To64( aSig, 0, bSig ); + if ( ( zSig & 0x1FF ) <= 2 ) { + mul64To128( bSig, zSig, &term0, &term1 ); + sub128( aSig, 0, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig; + add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); + } + zSig |= ( rem1 != 0 ); + } + return roundAndPackFloat64( zSign, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the double-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_rem( float64 a, float64 b ) +{ + flag aSign, zSign; + int16 aExp, bExp, expDiff; + bits64 aSig, bSig; + bits64 q, alternateASig; + sbits64 sigMean; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + bSig = extractFloat64Frac( b ); + bExp = extractFloat64Exp( b ); +// bSign = extractFloat64Sign( b ); + if ( aExp == 0x7FF ) { + if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { + return propagateFloat64NaN( a, b ); + } + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( bExp == 0x7FF ) { + if ( bSig ) return propagateFloat64NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + float_raise( float_flag_invalid ); + return float64_default_nan; + } + normalizeFloat64Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return a; + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + expDiff = aExp - bExp; + aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; + bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + aSig >>= 1; + } + q = ( bSig <= aSig ); + if ( q ) aSig -= bSig; + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig, 0, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + aSig = - ( ( bSig>>2 ) * q ); + expDiff -= 62; + } + expDiff += 64; + if ( 0 < expDiff ) { + q = estimateDiv128To64( aSig, 0, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + q >>= 64 - expDiff; + bSig >>= 2; + aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; + } + else { + aSig >>= 2; + bSig >>= 2; + } + do { + alternateASig = aSig; + ++q; + aSig -= bSig; + } while ( 0 <= (sbits64) aSig ); + sigMean = aSig + alternateASig; + if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { + aSig = alternateASig; + } + zSign = ( (sbits64) aSig < 0 ); + if ( zSign ) aSig = - aSig; + return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the double-precision floating-point value `a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float64_sqrt( float64 a ) +{ + flag aSign; + int16 aExp, zExp; + bits64 aSig, zSig, doubleZSig; + bits64 rem0, rem1, term0, term1; +// float64 z; + + aSig = extractFloat64Frac( a ); + aExp = extractFloat64Exp( a ); + aSign = extractFloat64Sign( a ); + if ( aExp == 0x7FF ) { + if ( aSig ) return propagateFloat64NaN( a, a ); + if ( ! aSign ) return a; + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aSign ) { + if ( ( aExp | aSig ) == 0 ) return a; + float_raise( float_flag_invalid ); + return float64_default_nan; + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return 0; + normalizeFloat64Subnormal( aSig, &aExp, &aSig ); + } + zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; + aSig |= LIT64( 0x0010000000000000 ); + zSig = estimateSqrt32( aExp, (bits32)(aSig>>21) ); + aSig <<= 9 - ( aExp & 1 ); + zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); + if ( ( zSig & 0x1FF ) <= 5 ) { + doubleZSig = zSig<<1; + mul64To128( zSig, zSig, &term0, &term1 ); + sub128( aSig, 0, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig; + doubleZSig -= 2; + add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); + } + zSig |= ( ( rem0 | rem1 ) != 0 ); + } + return roundAndPackFloat64( 0, zExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is equal to the +| corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_eq( float64 a, float64 b ) +{ + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_le( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_lt( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is equal to the +| corresponding value `b', and 0 otherwise. The invalid exception is raised +| if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_eq_signaling( float64 a, float64 b ) +{ + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than or +| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_le_quiet( float64 a, float64 b ) +{ + flag aSign, bSign; +// int16 aExp, bExp; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); + return ( a == b ) || ( aSign ^ ( a < b ) ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the double-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float64_lt_quiet( float64 a, float64 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) + || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + ) { + if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat64Sign( a ); + bSign = extractFloat64Sign( b ); + if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); + return ( a != b ) && ( aSign ^ ( a < b ) ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the 32-bit two's complement integer format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic---which means in particular that the conversion +| is rounded according to the current rounding mode. If `a' is a NaN, the +| largest positive integer is returned. Otherwise, if the conversion +| overflows, the largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 floatx80_to_int32( floatx80 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; + shiftCount = 0x4037 - aExp; + if ( shiftCount <= 0 ) shiftCount = 1; + shift64RightJamming( aSig, shiftCount, &aSig ); + return roundAndPackInt32( aSign, aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the 32-bit two's complement integer format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic, except that the conversion is always rounded +| toward zero. If `a' is a NaN, the largest positive integer is returned. +| Otherwise, if the conversion overflows, the largest integer with the same +| sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 floatx80_to_int32_round_to_zero( floatx80 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig, savedASig; + int32 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( 0x401E < aExp ) { + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FFF ) { + if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; + return 0; + } + shiftCount = 0x403E - aExp; + savedASig = aSig; + aSig >>= shiftCount; + z = (int32)aSig; + if ( aSign ) z = - z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig<>( - shiftCount ); + if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { + float_exception_flags |= float_flag_inexact; + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the single-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 floatx80_to_float32( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); + } + return packFloat32( aSign, 0xFF, 0 ); + } + shift64RightJamming( aSig, 33, &aSig ); + if ( aExp || aSig ) aExp -= 0x3F81; + return roundAndPackFloat32( aSign, aExp, (bits32)aSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the double-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 floatx80_to_float64( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig, zSig; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); + } + return packFloat64( aSign, 0x7FF, 0 ); + } + shift64RightJamming( aSig, 1, &zSig ); + if ( aExp || aSig ) aExp -= 0x3C01; + return roundAndPackFloat64( aSign, aExp, zSig ); + +} + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the extended double-precision floating- +| point value `a' to the quadruple-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 floatx80_to_float128( floatx80 a ) +{ + flag aSign; + int16 aExp; + bits64 aSig, zSig0, zSig1; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { + return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); + } + shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); + return packFloat128( aSign, aExp, zSig0, zSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the extended double-precision floating-point value `a' to an integer, +| and returns the result as an extended quadruple-precision floating-point +| value. The operation is performed according to the IEC/IEEE Standard for +| Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_round_to_int( floatx80 a ) +{ + flag aSign; + int32 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + floatx80 z; + + aExp = extractFloatx80Exp( a ); + if ( 0x403E <= aExp ) { + if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { + return propagateFloatx80NaN( a, a ); + } + return a; + } + if ( aExp < 0x3FFF ) { + if ( ( aExp == 0 ) + && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { + return a; + } + float_exception_flags |= float_flag_inexact; + aSign = extractFloatx80Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) + ) { + return + packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); + } + break; + case float_round_down: + return + aSign ? + packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) + : packFloatx80( 0, 0, 0 ); + case float_round_up: + return + aSign ? packFloatx80( 1, 0, 0 ) + : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); + } + return packFloatx80( aSign, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x403E - aExp; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z.low += lastBitMask>>1; + if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { + z.low += roundBitsMask; + } + } + z.low &= ~ roundBitsMask; + if ( z.low == 0 ) { + ++z.high; + z.low = LIT64( 0x8000000000000000 ); + } + if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the extended double- +| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is +| negated before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + int32 expDiff; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) { + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) --expDiff; + shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) ++expDiff; + shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); + zExp = bExp; + } + else { + if ( aExp == 0x7FFF ) { + if ( (bits64) ( ( aSig | bSig )<<1 ) ) { + return propagateFloatx80NaN( a, b ); + } + return a; + } + zSig1 = 0; + zSig0 = aSig + bSig; + if ( aExp == 0 ) { + normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); + goto roundAndPack; + } + zExp = aExp; + goto shiftRight1; + } + zSig0 = aSig + bSig; + if ( (sbits64) zSig0 < 0 ) goto roundAndPack; + shiftRight1: + shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); + zSig0 |= LIT64( 0x8000000000000000 ); + ++zExp; + roundAndPack: + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the extended +| double-precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + int32 expDiff; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( ( aSig | bSig )<<1 ) ) { + return propagateFloatx80NaN( a, b ); + } + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + zSig1 = 0; + if ( bSig < aSig ) goto aBigger; + if ( aSig < bSig ) goto bBigger; + return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) ++expDiff; + shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); + bBigger: + sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) --expDiff; + shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); + aBigger: + sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); + zExp = aExp; + normalizeRoundAndPack: + return + normalizeRoundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the extended double-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_add( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign == bSign ) { + return addFloatx80Sigs( a, b, aSign ); + } + else { + return subFloatx80Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the extended double-precision floating- +| point values `a' and `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_sub( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign == bSign ) { + return subFloatx80Sigs( a, b, aSign ); + } + else { + return addFloatx80Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the extended double-precision floating- +| point values `a' and `b'. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_mul( floatx80 a, floatx80 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + bSign = extractFloatx80Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) + || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { + return propagateFloatx80NaN( a, b ); + } + if ( ( bExp | bSig ) == 0 ) goto invalid; + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + if ( ( aExp | aSig ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + zExp = aExp + bExp - 0x3FFE; + mul64To128( aSig, bSig, &zSig0, &zSig1 ); + if ( 0 < (sbits64) zSig0 ) { + shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); + --zExp; + } + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the extended double-precision floating-point +| value `a' by the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_div( floatx80 a, floatx80 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig, bSig, zSig0, zSig1; + bits64 rem0, rem1, rem2, term0, term1, term2; + floatx80 z; + + aSig = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); + bSign = extractFloatx80Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + goto invalid; + } + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return packFloatx80( zSign, 0, 0 ); + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + if ( ( aExp | aSig ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + float_raise( float_flag_divbyzero ); + return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); + normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); + } + zExp = aExp - bExp + 0x3FFE; + rem1 = 0; + if ( bSig <= aSig ) { + shift128Right( aSig, 0, 1, &aSig, &rem1 ); + ++zExp; + } + zSig0 = estimateDiv128To64( aSig, rem1, bSig ); + mul64To128( bSig, zSig0, &term0, &term1 ); + sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, bSig ); + if ( (bits64) ( zSig1<<1 ) <= 8 ) { + mul64To128( bSig, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); + } + zSig1 |= ( ( rem1 | rem2 ) != 0 ); + } + return + roundAndPackFloatx80( + floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the extended double-precision floating-point value +| `a' with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_rem( floatx80 a, floatx80 b ) +{ + flag aSign, zSign; + int32 aExp, bExp, expDiff; + bits64 aSig0, aSig1, bSig; + bits64 q, term0, term1, alternateASig0, alternateASig1; + floatx80 z; + + aSig0 = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + bSig = extractFloatx80Frac( b ); + bExp = extractFloatx80Exp( b ); +// bSign = extractFloatx80Sign( b ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig0<<1 ) + || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { + return propagateFloatx80NaN( a, b ); + } + goto invalid; + } + if ( bExp == 0x7FFF ) { + if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( bSig == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); + } + if ( aExp == 0 ) { + if ( (bits64) ( aSig0<<1 ) == 0 ) return a; + normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); + } + bSig |= LIT64( 0x8000000000000000 ); + zSign = aSign; + expDiff = aExp - bExp; + aSig1 = 0; + if ( expDiff < 0 ) { + if ( expDiff < -1 ) return a; + shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); + expDiff = 0; + } + q = ( bSig <= aSig0 ); + if ( q ) aSig0 -= bSig; + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + mul64To128( bSig, q, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); + expDiff -= 62; + } + expDiff += 64; + if ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig ); + q = ( 2 < q ) ? q - 2 : 0; + q >>= 64 - expDiff; + mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); + while ( le128( term0, term1, aSig0, aSig1 ) ) { + ++q; + sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); + } + } + else { + term1 = 0; + term0 = bSig; + } + sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); + if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) + || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) + && ( q & 1 ) ) + ) { + aSig0 = alternateASig0; + aSig1 = alternateASig1; + zSign = ! zSign; + } + return + normalizeRoundAndPackFloatx80( + 80, zSign, bExp + expDiff, aSig0, aSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the extended double-precision floating-point +| value `a'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 floatx80_sqrt( floatx80 a ) +{ + flag aSign; + int32 aExp, zExp; + bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + floatx80 z; + + aSig0 = extractFloatx80Frac( a ); + aExp = extractFloatx80Exp( a ); + aSign = extractFloatx80Sign( a ); + if ( aExp == 0x7FFF ) { + if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); + if ( ! aSign ) return a; + goto invalid; + } + if ( aSign ) { + if ( ( aExp | aSig0 ) == 0 ) return a; + invalid: + float_raise( float_flag_invalid ); + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; + return z; + } + if ( aExp == 0 ) { + if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); + normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); + } + zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; + zSig0 = estimateSqrt32( aExp, aSig0>>32 ); + shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); + zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); + doubleZSig0 = zSig0<<1; + mul64To128( zSig0, zSig0, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + doubleZSig0 -= 2; + add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); + if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { + if ( zSig1 == 0 ) zSig1 = 1; + mul64To128( doubleZSig0, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + mul64To128( zSig1, zSig1, &term2, &term3 ); + sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + shortShift128Left( 0, zSig1, 1, &term2, &term3 ); + term3 |= 1; + term2 |= doubleZSig0; + add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); + zSig0 |= doubleZSig0; + return + roundAndPackFloatx80( + floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| equal to the corresponding value `b', and 0 otherwise. The comparison is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_eq( floatx80 a, floatx80 b ) +{ + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| less than or equal to the corresponding value `b', and 0 otherwise. The +| comparison is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_le( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is +| less than the corresponding value `b', and 0 otherwise. The comparison +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_lt( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is equal +| to the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_eq_signaling( floatx80 a, floatx80 b ) +{ + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is less +| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs +| do not cause an exception. Otherwise, the comparison is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_le_quiet( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the extended double-precision floating-point value `a' is less +| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause +| an exception. Otherwise, the comparison is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag floatx80_lt_quiet( floatx80 a, floatx80 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( a )<<1 ) ) + || ( ( extractFloatx80Exp( b ) == 0x7FFF ) + && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + ) { + if ( floatx80_is_signaling_nan( a ) + || floatx80_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloatx80Sign( a ); + bSign = extractFloatx80Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the 32-bit two's complement integer format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. Otherwise, if the conversion overflows, the +| largest integer with the same sign as `a' is returned. +*----------------------------------------------------------------------------*/ + +int32 float128_to_int32( float128 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; + if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); + aSig0 |= ( aSig1 != 0 ); + shiftCount = 0x4028 - aExp; + if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); + return roundAndPackInt32( aSign, aSig0 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the 32-bit two's complement integer format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic, except that the conversion is always rounded toward zero. If +| `a' is a NaN, the largest positive integer is returned. Otherwise, if the +| conversion overflows, the largest integer with the same sign as `a' is +| returned. +*----------------------------------------------------------------------------*/ + +int32 float128_to_int32_round_to_zero( float128 a ) +{ + flag aSign; + int32 aExp, shiftCount; + bits64 aSig0, aSig1, savedASig; + int32 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + aSig0 |= ( aSig1 != 0 ); + if ( 0x401E < aExp ) { + if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; + goto invalid; + } + else if ( aExp < 0x3FFF ) { + if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; + return 0; + } + aSig0 |= LIT64( 0x0001000000000000 ); + shiftCount = 0x402F - aExp; + savedASig = aSig0; + aSig0 >>= shiftCount; + z = (int32)aSig0; + if ( aSign ) z = - z; + if ( ( z < 0 ) ^ aSign ) { + invalid: + float_raise( float_flag_invalid ); + return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); + if ( (bits64) ( aSig1<>( - shiftCount ); + if ( aSig1 + || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { + float_exception_flags |= float_flag_inexact; + } + } + if ( aSign ) z = - z; + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the single-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 float128_to_float32( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + bits32 zSig; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloat32( float128ToCommonNaN( a ) ); + } + return packFloat32( aSign, 0xFF, 0 ); + } + aSig0 |= ( aSig1 != 0 ); + shift64RightJamming( aSig0, 18, &aSig0 ); + zSig = (bits32)aSig0; + if ( aExp || zSig ) { + zSig |= 0x40000000; + aExp -= 0x3F81; + } + return roundAndPackFloat32( aSign, aExp, zSig ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the double-precision floating-point format. The conversion +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 float128_to_float64( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloat64( float128ToCommonNaN( a ) ); + } + return packFloat64( aSign, 0x7FF, 0 ); + } + shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); + aSig0 |= ( aSig1 != 0 ); + if ( aExp || aSig0 ) { + aSig0 |= LIT64( 0x4000000000000000 ); + aExp -= 0x3C01; + } + return roundAndPackFloat64( aSign, aExp, aSig0 ); + +} + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point +| value `a' to the extended double-precision floating-point format. The +| conversion is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +floatx80 float128_to_floatx80( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 aSig0, aSig1; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) { + return commonNaNToFloatx80( float128ToCommonNaN( a ) ); + } + return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + else { + aSig0 |= LIT64( 0x0001000000000000 ); + } + shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); + return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); + +} + +#endif + +/*---------------------------------------------------------------------------- +| Rounds the quadruple-precision floating-point value `a' to an integer, and +| returns the result as a quadruple-precision floating-point value. The +| operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_round_to_int( float128 a ) +{ + flag aSign; + int32 aExp; + bits64 lastBitMask, roundBitsMask; + int8 roundingMode; + float128 z; + + aExp = extractFloat128Exp( a ); + if ( 0x402F <= aExp ) { + if ( 0x406F <= aExp ) { + if ( ( aExp == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) + ) { + return propagateFloat128NaN( a, a ); + } + return a; + } + lastBitMask = 1; + lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; + roundBitsMask = lastBitMask - 1; + z = a; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + if ( lastBitMask ) { + add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); + if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; + } + else { + if ( (sbits64) z.low < 0 ) { + ++z.high; + if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; + } + } + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat128Sign( z ) + ^ ( roundingMode == float_round_up ) ) { + add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); + } + } + z.low &= ~ roundBitsMask; + } + else { + if ( aExp < 0x3FFF ) { + if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; + float_exception_flags |= float_flag_inexact; + aSign = extractFloat128Sign( a ); + switch ( float_rounding_mode ) { + case float_round_nearest_even: + if ( ( aExp == 0x3FFE ) + && ( extractFloat128Frac0( a ) + | extractFloat128Frac1( a ) ) + ) { + return packFloat128( aSign, 0x3FFF, 0, 0 ); + } + break; + case float_round_down: + return + aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) + : packFloat128( 0, 0, 0, 0 ); + case float_round_up: + return + aSign ? packFloat128( 1, 0, 0, 0 ) + : packFloat128( 0, 0x3FFF, 0, 0 ); + } + return packFloat128( aSign, 0, 0, 0 ); + } + lastBitMask = 1; + lastBitMask <<= 0x402F - aExp; + roundBitsMask = lastBitMask - 1; + z.low = 0; + z.high = a.high; + roundingMode = float_rounding_mode; + if ( roundingMode == float_round_nearest_even ) { + z.high += lastBitMask>>1; + if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { + z.high &= ~ lastBitMask; + } + } + else if ( roundingMode != float_round_to_zero ) { + if ( extractFloat128Sign( z ) + ^ ( roundingMode == float_round_up ) ) { + z.high |= ( a.low != 0 ); + z.high += roundBitsMask; + } + } + z.high &= ~ roundBitsMask; + } + if ( ( z.low != a.low ) || ( z.high != a.high ) ) { + float_exception_flags |= float_flag_inexact; + } + return z; + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the absolute values of the quadruple-precision +| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated +| before being returned. `zSign' is ignored if the result is a NaN. +| The addition is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + int32 expDiff; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + expDiff = aExp - bExp; + if ( 0 < expDiff ) { + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig0 |= LIT64( 0x0001000000000000 ); + } + shift128ExtraRightJamming( + bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); + zExp = aExp; + } + else if ( expDiff < 0 ) { + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig0 |= LIT64( 0x0001000000000000 ); + } + shift128ExtraRightJamming( + aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); + zExp = bExp; + } + else { + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 | bSig0 | bSig1 ) { + return propagateFloat128NaN( a, b ); + } + return a; + } + add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); + zSig2 = 0; + zSig0 |= LIT64( 0x0002000000000000 ); + zExp = aExp; + goto shiftRight1; + } + aSig0 |= LIT64( 0x0001000000000000 ); + add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + --zExp; + if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; + ++zExp; + shiftRight1: + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); + roundAndPack: + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the absolute values of the quadruple- +| precision floating-point values `a' and `b'. If `zSign' is 1, the +| difference is negated before being returned. `zSign' is ignored if the +| result is a NaN. The subtraction is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) +{ + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; + int32 expDiff; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + expDiff = aExp - bExp; + shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); + shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); + if ( 0 < expDiff ) goto aExpBigger; + if ( expDiff < 0 ) goto bExpBigger; + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 | bSig0 | bSig1 ) { + return propagateFloat128NaN( a, b ); + } + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + if ( aExp == 0 ) { + aExp = 1; + bExp = 1; + } + if ( bSig0 < aSig0 ) goto aBigger; + if ( aSig0 < bSig0 ) goto bBigger; + if ( bSig1 < aSig1 ) goto aBigger; + if ( aSig1 < bSig1 ) goto bBigger; + return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); + bExpBigger: + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + ++expDiff; + } + else { + aSig0 |= LIT64( 0x4000000000000000 ); + } + shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); + bSig0 |= LIT64( 0x4000000000000000 ); + bBigger: + sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + --expDiff; + } + else { + bSig0 |= LIT64( 0x4000000000000000 ); + } + shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); + aSig0 |= LIT64( 0x4000000000000000 ); + aBigger: + sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of adding the quadruple-precision floating-point values +| `a' and `b'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_add( float128 a, float128 b ) +{ + flag aSign, bSign; + + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign == bSign ) { + return addFloat128Sigs( a, b, aSign ); + } + else { + return subFloat128Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of subtracting the quadruple-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_sub( float128 a, float128 b ) +{ + flag aSign, bSign; + + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign == bSign ) { + return subFloat128Sigs( a, b, aSign ); + } + else { + return addFloat128Sigs( a, b, aSign ); + } + +} + +/*---------------------------------------------------------------------------- +| Returns the result of multiplying the quadruple-precision floating-point +| values `a' and `b'. The operation is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_mul( float128 a, float128 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + bSign = extractFloat128Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( ( aSig0 | aSig1 ) + || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { + return propagateFloat128NaN( a, b ); + } + if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + if ( ( aExp | aSig0 | aSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + zExp = aExp + bExp - 0x4000; + aSig0 |= LIT64( 0x0001000000000000 ); + shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); + mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); + add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); + zSig2 |= ( zSig3 != 0 ); + if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); + ++zExp; + } + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the result of dividing the quadruple-precision floating-point value +| `a' by the corresponding value `b'. The operation is performed according to +| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_div( float128 a, float128 b ) +{ + flag aSign, bSign, zSign; + int32 aExp, bExp, zExp; + bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); + bSign = extractFloat128Sign( b ); + zSign = aSign ^ bSign; + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + goto invalid; + } + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return packFloat128( zSign, 0, 0, 0 ); + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) { + if ( ( aExp | aSig0 | aSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + float_raise( float_flag_divbyzero ); + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + zExp = aExp - bExp + 0x3FFD; + shortShift128Left( + aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); + shortShift128Left( + bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); + if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { + shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); + ++zExp; + } + zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); + mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); + sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); + } + zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); + if ( ( zSig1 & 0x3FFF ) <= 4 ) { + mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); + sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the remainder of the quadruple-precision floating-point value `a' +| with respect to the corresponding value `b'. The operation is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_rem( float128 a, float128 b ) +{ + flag aSign, zSign; + int32 aExp, bExp, expDiff; + bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; + bits64 allZero, alternateASig0, alternateASig1, sigMean1; + sbits64 sigMean0; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + bSig1 = extractFloat128Frac1( b ); + bSig0 = extractFloat128Frac0( b ); + bExp = extractFloat128Exp( b ); +// bSign = extractFloat128Sign( b ); + if ( aExp == 0x7FFF ) { + if ( ( aSig0 | aSig1 ) + || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { + return propagateFloat128NaN( a, b ); + } + goto invalid; + } + if ( bExp == 0x7FFF ) { + if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); + return a; + } + if ( bExp == 0 ) { + if ( ( bSig0 | bSig1 ) == 0 ) { + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return a; + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + expDiff = aExp - bExp; + if ( expDiff < -1 ) return a; + shortShift128Left( + aSig0 | LIT64( 0x0001000000000000 ), + aSig1, + 15 - ( expDiff < 0 ), + &aSig0, + &aSig1 + ); + shortShift128Left( + bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); + q = le128( bSig0, bSig1, aSig0, aSig1 ); + if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); + expDiff -= 64; + while ( 0 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig0 ); + q = ( 4 < q ) ? q - 4 : 0; + mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); + shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); + shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); + sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); + expDiff -= 61; + } + if ( -64 < expDiff ) { + q = estimateDiv128To64( aSig0, aSig1, bSig0 ); + q = ( 4 < q ) ? q - 4 : 0; + q >>= - expDiff; + shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); + expDiff += 52; + if ( expDiff < 0 ) { + shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); + } + else { + shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); + } + mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); + sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); + } + else { + shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); + shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); + } + do { + alternateASig0 = aSig0; + alternateASig1 = aSig1; + ++q; + sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); + } while ( 0 <= (sbits64) aSig0 ); + add128( + aSig0, aSig1, alternateASig0, alternateASig1, (bits64 *)&sigMean0, &sigMean1 ); + if ( ( sigMean0 < 0 ) + || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { + aSig0 = alternateASig0; + aSig1 = alternateASig1; + } + zSign = ( (sbits64) aSig0 < 0 ); + if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); + return + normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); + +} + +/*---------------------------------------------------------------------------- +| Returns the square root of the quadruple-precision floating-point value `a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float128 float128_sqrt( float128 a ) +{ + flag aSign; + int32 aExp, zExp; + bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; + bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; + float128 z; + + aSig1 = extractFloat128Frac1( a ); + aSig0 = extractFloat128Frac0( a ); + aExp = extractFloat128Exp( a ); + aSign = extractFloat128Sign( a ); + if ( aExp == 0x7FFF ) { + if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); + if ( ! aSign ) return a; + goto invalid; + } + if ( aSign ) { + if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; + invalid: + float_raise( float_flag_invalid ); + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; + return z; + } + if ( aExp == 0 ) { + if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); + normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); + } + zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; + aSig0 |= LIT64( 0x0001000000000000 ); + zSig0 = estimateSqrt32( aExp, (bits32)(aSig0>>17 )); + shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); + zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); + doubleZSig0 = zSig0<<1; + mul64To128( zSig0, zSig0, &term0, &term1 ); + sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); + while ( (sbits64) rem0 < 0 ) { + --zSig0; + doubleZSig0 -= 2; + add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); + } + zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); + if ( ( zSig1 & 0x1FFF ) <= 5 ) { + if ( zSig1 == 0 ) zSig1 = 1; + mul64To128( doubleZSig0, zSig1, &term1, &term2 ); + sub128( rem1, 0, term1, term2, &rem1, &rem2 ); + mul64To128( zSig1, zSig1, &term2, &term3 ); + sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); + while ( (sbits64) rem1 < 0 ) { + --zSig1; + shortShift128Left( 0, zSig1, 1, &term2, &term3 ); + term3 |= 1; + term2 |= doubleZSig0; + add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); + } + zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); + } + shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); + return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_eq( float128 a, float128 b ) +{ + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. The comparison +| is performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_le( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. The comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_lt( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is equal to +| the corresponding value `b', and 0 otherwise. The invalid exception is +| raised if either operand is a NaN. Otherwise, the comparison is performed +| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_eq_signaling( float128 a, float128 b ) +{ + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + float_raise( float_flag_invalid ); + return 0; + } + return + ( a.low == b.low ) + && ( ( a.high == b.high ) + || ( ( a.low == 0 ) + && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) + ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not +| cause an exception. Otherwise, the comparison is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_le_quiet( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + == 0 ); + } + return + aSign ? le128( b.high, b.low, a.high, a.low ) + : le128( a.high, a.low, b.high, b.low ); + +} + +/*---------------------------------------------------------------------------- +| Returns 1 if the quadruple-precision floating-point value `a' is less than +| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an +| exception. Otherwise, the comparison is performed according to the IEC/IEEE +| Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +flag float128_lt_quiet( float128 a, float128 b ) +{ + flag aSign, bSign; + + if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) + && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) + || ( ( extractFloat128Exp( b ) == 0x7FFF ) + && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + ) { + if ( float128_is_signaling_nan( a ) + || float128_is_signaling_nan( b ) ) { + float_raise( float_flag_invalid ); + } + return 0; + } + aSign = extractFloat128Sign( a ); + bSign = extractFloat128Sign( b ); + if ( aSign != bSign ) { + return + aSign + && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) + != 0 ); + } + return + aSign ? lt128( b.high, b.low, a.high, a.low ) + : lt128( a.high, a.low, b.high, b.low ); + +} + +#endif diff --git a/AltairZ80/m68k/softfloat/softfloat.h b/AltairZ80/m68k/softfloat/softfloat.h index 92135e66..1ed4bccc 100644 --- a/AltairZ80/m68k/softfloat/softfloat.h +++ b/AltairZ80/m68k/softfloat/softfloat.h @@ -47,13 +47,13 @@ typedef bits32 float32; typedef bits64 float64; #ifdef FLOATX80 typedef struct { - bits16 high; - bits64 low; + bits16 high; + bits64 low; } floatx80; #endif #ifdef FLOAT128 typedef struct { - bits64 high, low; + bits64 high, low; } float128; #endif @@ -69,8 +69,8 @@ typedef struct { *----------------------------------------------------------------------------*/ extern int8 float_detect_tininess; enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 + float_tininess_after_rounding = 0, + float_tininess_before_rounding = 1 }; /*---------------------------------------------------------------------------- @@ -78,10 +78,10 @@ enum { *----------------------------------------------------------------------------*/ extern int8 float_rounding_mode; enum { - float_round_nearest_even = 0, - float_round_to_zero = 1, - float_round_down = 2, - float_round_up = 3 + float_round_nearest_even = 0, + float_round_to_zero = 1, + float_round_down = 2, + float_round_up = 3 }; /*---------------------------------------------------------------------------- @@ -89,8 +89,8 @@ enum { *----------------------------------------------------------------------------*/ extern int8 float_exception_flags; enum { - float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08, - float_flag_underflow = 0x10, float_flag_inexact = 0x20 + float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08, + float_flag_underflow = 0x10, float_flag_inexact = 0x20 }; /*---------------------------------------------------------------------------- @@ -208,11 +208,11 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b); static inline floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) { - floatx80 z; + floatx80 z; - z.low = zSig; - z.high = ( ( (bits16) zSign )<<15 ) + zExp; - return z; + z.low = zSig; + z.high = ( ( (bits16) zSign )<<15 ) + zExp; + return z; } @@ -301,13 +301,13 @@ flag float128_is_signaling_nan( float128 ); *----------------------------------------------------------------------------*/ static inline float128 - packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) + packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) { - float128 z; + float128 z; - z.low = zSig1; - z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0; - return z; + z.low = zSig1; + z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0; + return z; } @@ -333,92 +333,92 @@ static inline float128 *----------------------------------------------------------------------------*/ static inline float128 - roundAndPackFloat128( - flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 ) + roundAndPackFloat128( + flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 ) { - int8 roundingMode; - flag roundNearestEven, increment, isTiny; + int8 roundingMode; + flag roundNearestEven, increment, isTiny; - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) zSig2 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && zSig2; - } - else { - increment = ( roundingMode == float_round_up ) && zSig2; - } - } - } - if ( 0x7FFD <= (bits32) zExp ) { - if ( ( 0x7FFD < zExp ) - || ( ( zExp == 0x7FFD ) - && eq128( - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ), - zSig0, - zSig1 - ) - && increment - ) - ) { - float_raise( float_flag_overflow | float_flag_inexact ); - if ( ( roundingMode == float_round_to_zero ) - || ( zSign && ( roundingMode == float_round_up ) ) - || ( ! zSign && ( roundingMode == float_round_down ) ) - ) { - return - packFloat128( - zSign, - 0x7FFE, - LIT64( 0x0000FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) - ); - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( zExp < 0 ) { - isTiny = - ( float_detect_tininess == float_tininess_before_rounding ) - || ( zExp < -1 ) - || ! increment - || lt128( - zSig0, - zSig1, - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) - ); - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); - zExp = 0; - if ( isTiny && zSig2 ) float_raise( float_flag_underflow ); - if ( roundNearestEven ) { - increment = ( (sbits64) zSig2 < 0 ); - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && zSig2; - } - else { - increment = ( roundingMode == float_round_up ) && zSig2; - } - } - } - } - if ( zSig2 ) float_exception_flags |= float_flag_inexact; - if ( increment ) { - add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); - zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); - } - else { - if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; - } - return packFloat128( zSign, zExp, zSig0, zSig1 ); + roundingMode = float_rounding_mode; + roundNearestEven = ( roundingMode == float_round_nearest_even ); + increment = ( (sbits64) zSig2 < 0 ); + if ( ! roundNearestEven ) { + if ( roundingMode == float_round_to_zero ) { + increment = 0; + } + else { + if ( zSign ) { + increment = ( roundingMode == float_round_down ) && zSig2; + } + else { + increment = ( roundingMode == float_round_up ) && zSig2; + } + } + } + if ( 0x7FFD <= (bits32) zExp ) { + if ( ( 0x7FFD < zExp ) + || ( ( zExp == 0x7FFD ) + && eq128( + LIT64( 0x0001FFFFFFFFFFFF ), + LIT64( 0xFFFFFFFFFFFFFFFF ), + zSig0, + zSig1 + ) + && increment + ) + ) { + float_raise( float_flag_overflow | float_flag_inexact ); + if ( ( roundingMode == float_round_to_zero ) + || ( zSign && ( roundingMode == float_round_up ) ) + || ( ! zSign && ( roundingMode == float_round_down ) ) + ) { + return + packFloat128( + zSign, + 0x7FFE, + LIT64( 0x0000FFFFFFFFFFFF ), + LIT64( 0xFFFFFFFFFFFFFFFF ) + ); + } + return packFloat128( zSign, 0x7FFF, 0, 0 ); + } + if ( zExp < 0 ) { + isTiny = + ( float_detect_tininess == float_tininess_before_rounding ) + || ( zExp < -1 ) + || ! increment + || lt128( + zSig0, + zSig1, + LIT64( 0x0001FFFFFFFFFFFF ), + LIT64( 0xFFFFFFFFFFFFFFFF ) + ); + shift128ExtraRightJamming( + zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); + zExp = 0; + if ( isTiny && zSig2 ) float_raise( float_flag_underflow ); + if ( roundNearestEven ) { + increment = ( (sbits64) zSig2 < 0 ); + } + else { + if ( zSign ) { + increment = ( roundingMode == float_round_down ) && zSig2; + } + else { + increment = ( roundingMode == float_round_up ) && zSig2; + } + } + } + } + if ( zSig2 ) float_exception_flags |= float_flag_inexact; + if ( increment ) { + add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); + zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); + } + else { + if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; + } + return packFloat128( zSign, zExp, zSig0, zSig1 ); } @@ -433,28 +433,28 @@ static inline float128 *----------------------------------------------------------------------------*/ static inline float128 - normalizeRoundAndPackFloat128( - flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) + normalizeRoundAndPackFloat128( + flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) { - int8 shiftCount; - bits64 zSig2; + int8 shiftCount; + bits64 zSig2; - if ( zSig0 == 0 ) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - shiftCount = countLeadingZeros64( zSig0 ) - 15; - if ( 0 <= shiftCount ) { - zSig2 = 0; - shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); - } - else { - shift128ExtraRightJamming( - zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 ); - } - zExp -= shiftCount; - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); + if ( zSig0 == 0 ) { + zSig0 = zSig1; + zSig1 = 0; + zExp -= 64; + } + shiftCount = countLeadingZeros64( zSig0 ) - 15; + if ( 0 <= shiftCount ) { + zSig2 = 0; + shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); + } + else { + shift128ExtraRightJamming( + zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 ); + } + zExp -= shiftCount; + return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); } #endif diff --git a/AltairZ80/s100_djhdc.c b/AltairZ80/s100_djhdc.c index 79f036f2..7479c94b 100644 --- a/AltairZ80/s100_djhdc.c +++ b/AltairZ80/s100_djhdc.c @@ -1,864 +1,864 @@ -/************************************************************************* - * * - * Copyright (c) 2022 Howard M. Harte. * - * https://github.com/hharte * - * * - * Permission is hereby granted, free of charge, to any person obtaining * - * a copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to * - * the following conditions: * - * * - * The above copyright notice and this permission notice shall be * - * included in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- * - * INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * - * SOFTWARE. * - * * - * Except as contained in this notice, the names of The Authors shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * from the Authors. * - * * - * Based on s100_disk3.c * - * * - * Module Description: * - * Morrow Disk Jockey HDC-DMA Hard Disk Controller module for SIMH. * - * Reference: * - * http://www.bitsavers.org/pdf/morrow/boards/HDC_DMA_Technical_Manual_1983.pdf * - * * - *************************************************************************/ - -#include "altairz80_defs.h" -#include "sim_imd.h" - -#define DEV_NAME "DJHDC" - -#define DJHDC_MAX_CYLS 1024 -#define DJHDC_MAX_HEADS 8 -#define DJHDC_MAX_SPT 256 - -/* Debug flags */ -#define ERROR_MSG (1 << 0) -#define SEEK_MSG (1 << 1) -#define OPCODE_MSG (1 << 2) -#define RD_DATA_MSG (1 << 3) -#define WR_DATA_MSG (1 << 4) -#define IRQ_MSG (1 << 5) -#define VERBOSE_MSG (1 << 6) -#define FORMAT_MSG (1 << 7) - -#define DJHDC_MAX_DRIVES 4 - -/* DJHDC I/O Ports */ -#define DJHDC_RESET 0 /* Reset */ -#define DJHDC_START 1 /* Start */ - -#define DJHDC_LINK_ADDR 0x000050 /* Default link address in RAM */ - -#define DJHDC_STEP_DIR 0x10 /* Bit 4, Step OUT */ - -#define DJHDC_IRQ_EN_MASK 0x80 /* Interrupt enable mask */ - -#define DJHDC_OPCODE_READ_DATA 0x00 -#define DJHDC_OPCODE_WRITE_DATA 0x01 -#define DJHDC_OPCODE_READ_HEADER 0x02 -#define DJHDC_OPCODE_FORMAT_TRACK 0x03 -#define DJHDC_OPCODE_LOAD_CONSTANTS 0x04 -#define DJHDC_OPCODE_SENSE_STATUS 0x05 -#define DJHDC_OPCODE_NOOP 0x06 - -#define DJHDC_STATUS_BUSY 0x00 /* Busy */ -#define DJHDC_STATUS_NOT_READY 0x01 /* Drive not ready */ -#define DJHDC_STATUS_HEADER_NOT_FOUND 0x04 /* Sector header not found */ -#define DJHDC_STATUS_DATA_NOT_FOUND 0x05 /* Sector data not found */ -#define DJHDC_STATUS_DATA_OVERRUN 0x06 /* Data overrun(channel error) */ -#define DJHDC_STATUS_DATA_CRC_ERROR 0x07 /* Data CRC error */ -#define DJHDC_STATUS_WRITE_FAULT 0x08 /* Write fault */ -#define DJHDC_STATUS_HEADER_CRC_ERROR 0x09 /* Sector header CRC error */ -#define DJHDC_STATUS_ILLEGAL_COMMAND 0xA0 /* Illegal command */ -#define DJHDC_STATUS_COMPLETE 0xFF /* Successful completion */ - -#define DJHDC_TRACK_0_DETECT (1 << 0) /* 0 = track 0. */ -#define DJHDC_WRITE_FAULT_SIGNAL (1 << 1) /* Drive Write fault (0). */ -#define DJHDC_DRIVE_READY_SIGNAL (1 << 2) /* Drive is up to speed (0). */ - -#define DJHDC_OPCODE_MASK 0x07 - -#define DJHDC_IOPB_LEN 16 - -#define DJHDC_IOPB_SELDRV 0 -#define DJHDC_IOPB_STEP_L 1 -#define DJHDC_IOPB_STEP_H 2 -#define DJHDC_IOPB_SEL_HD 3 -#define DJHDC_IOPB_DMA_L 4 -#define DJHDC_IOPB_DMA_H 5 -#define DJHDC_IOPB_DMA_E 6 -#define DJHDC_IOPB_ARG0 7 -#define DJHDC_IOPB_ARG1 8 -#define DJHDC_IOPB_ARG2 9 -#define DJHDC_IOPB_ARG3 10 -#define DJHDC_IOPB_OPCODE 11 -#define DJHDC_IOPB_STATUS 12 -#define DJHDC_IOPB_LINK 13 -#define DJHDC_IOPB_LINK_H 14 -#define DJHDC_IOPB_LINK_E 15 - -#define DJHDC_INT 1 /* DJHDC interrupts tied to VI1 */ - -typedef struct { - UNIT *uptr; - DISK_INFO *imd; - uint16 sectsize; /* sector size, not including pre/postamble */ - uint16 nsectors; /* number of sectors/track */ - uint16 nheads; /* number of heads */ - uint16 ntracks; /* number of tracks */ - uint16 res_tracks; /* Number of reserved tracks on drive. */ - uint16 track; /* Current Track */ - - uint16 cur_sect; /* current starting sector of transfer */ - uint16 cur_cyl; /* Current Track */ - uint16 cur_head; /* Number of sectors to transfer */ - uint16 cur_sectsize;/* Current sector size */ - uint8 ready; /* Is drive ready? */ -} DJHDC_DRIVE_INFO; - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ - uint8 sel_drive; /* Currently selected drive */ - uint8 mode; /* mode (0xFF=absolute, 0x00=logical) */ - uint8 ndrives; /* Number of drives attached to the controller */ - - uint32 link_addr; /* Link Address for next IOPB */ - uint32 dma_addr; /* DMA Address for the current IOPB */ - - uint16 steps; /* Step count */ - uint8 step_dir; /* Step direction, 1 = out. */ - uint8 irq_enable; - uint8 step_delay; - uint8 head_settle_time; - uint8 sector_size_code; - - DJHDC_DRIVE_INFO drive[DJHDC_MAX_DRIVES]; - uint8 iopb[16]; -} DJHDC_INFO; - -static DJHDC_INFO djhdc_info_data = { { 0x0, 0, 0x54, 2 } }; -static DJHDC_INFO *djhdc_info = &djhdc_info_data; - -/* Disk geometries: - * IMI SCRIBE - * Sectsize: 1024 1024 - * Sectors: 8 8 - * Heads: 6 4 - * Tracks: 306 480 - */ - -/* Default geometry for a 15MB hard disk. */ -#define SCRIBE_SECTSIZE 1024 -#define SCRIBE_NSECTORS 8 -#define SCRIBE_NHEADS 4 -#define SCRIBE_NTRACKS 480 - -static const char* djhdc_opcode_str[] = { - "Read Data ", - "Write Data ", - "Read Header ", - "Format Track ", - "Load Constants", - "Sense Status ", - "No Operation ", - "Invalid " -}; - -static int32 ntracks = SCRIBE_NTRACKS; -static int32 nheads = SCRIBE_NHEADS; -static int32 nsectors = SCRIBE_NSECTORS; -static int32 sectsize = SCRIBE_SECTSIZE; - -extern uint32 PCX; -extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, CONST void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), const char* name, uint8 unmap); -extern int32 find_unit_index(UNIT *uptr); -extern void raise_scp300f_interrupt(uint8 intnum); - -/* These are needed for DMA. */ -extern void PutByteDMA(const uint32 Addr, const uint32 Value); -extern uint8 GetByteDMA(const uint32 Addr); - -#define UNIT_V_DJHDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ -#define UNIT_DJHDC_VERBOSE (1 << UNIT_V_DJHDC_VERBOSE) -#define DJHDC_CAPACITY (SCRIBE_NTRACKS * SCRIBE_NHEADS * \ - SCRIBE_NSECTORS * SCRIBE_SECTSIZE) /* Default Disk Capacity */ - -static t_stat djhdc_reset(DEVICE *djhdc_dev); -static t_stat djhdc_attach(UNIT *uptr, CONST char *cptr); -static t_stat djhdc_detach(UNIT *uptr); -static t_stat djhdc_unit_set_geometry(UNIT* uptr, int32 value, CONST char* cptr, void* desc); -static t_stat djhdc_unit_show_geometry(FILE* st, UNIT* uptr, int32 value, CONST void* desc); -static int DJHDC_Validate_CHSN(DJHDC_DRIVE_INFO* pDrive); -#ifdef DJHDC_INTERRUPTS -static void raise_djhdc_interrupt(void); -#endif /* DJHDC_INTERRUPTS */ - -static const char* djhdc_description(DEVICE *dptr); - -static int32 djhdcdev(const int32 port, const int32 io, const int32 data); - -/* static uint8 DJHDC_Read(const uint32 Addr); */ -static uint8 DJHDC_Write(const uint32 Addr, uint8 cData); - -static UNIT djhdc_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DJHDC_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DJHDC_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DJHDC_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DJHDC_CAPACITY) } -}; - -static REG djhdc_reg[] = { - { DRDATAD (NTRACKS, ntracks, 10, - "Number of tracks"), }, - { DRDATAD (NHEADS, nheads, 8, - "Number of heads"), }, - { DRDATAD (NSECTORS, nsectors, 8, - "Number of sectors per track"), }, - { DRDATAD (SECTSIZE, sectsize, 11, - "Sector size not including pre/postamble"), }, - { HRDATAD (SEL_DRIVE, djhdc_info_data.sel_drive, 3, - "Currently selected drive"), }, - { HRDATAD (MODE, djhdc_info_data.mode, 8, - "Mode (0xFF=absolute, 0x00=logical)"), }, - { HRDATAD (NDRIVES, djhdc_info_data.ndrives, 8, - "Number of drives attached to the controller"), }, - { HRDATAD (LINK_ADDR, djhdc_info_data.link_addr, 32, - "Link address for next IOPB"), }, - { HRDATAD (DMA_ADDR, djhdc_info_data.dma_addr, 32, - "DMA address for the current IOPB"), }, - { BRDATAD (IOPB, djhdc_info_data.iopb, 16, 8, 16, - "IOPB command register"), }, - { NULL } -}; - -#define DJHDC_NAME "Morrow HDC/DMA Hard Disk Controller" - -static const char* djhdc_description(DEVICE *dptr) { - if (dptr == NULL) { - return NULL; - } - return DJHDC_NAME; -} - -static MTAB djhdc_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", - &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" }, - { MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "GEOMETRY", "GEOMETRY", - &djhdc_unit_set_geometry, &djhdc_unit_show_geometry, NULL, - "Set disk geometry C:nnnn/H:n/S:nnn/N:nnnn" }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB djhdc_dt[] = { - { "ERROR", ERROR_MSG, "Error messages" }, - { "SEEK", SEEK_MSG, "Seek messages" }, - { "OPCODE", OPCODE_MSG, "Opcode messages" }, - { "READ", RD_DATA_MSG, "Read messages" }, - { "WRITE", WR_DATA_MSG, "Write messages" }, - { "IRQ", IRQ_MSG, "IRQ messages" }, - { "VERBOSE", VERBOSE_MSG, "Verbose messages" }, - { "FORMAT", FORMAT_MSG, "Format messages" }, - { NULL, 0 } -}; - -DEVICE djhdc_dev = { - DEV_NAME, djhdc_unit, djhdc_reg, djhdc_mod, - DJHDC_MAX_DRIVES, 10, 31, 1, DJHDC_MAX_DRIVES, DJHDC_MAX_DRIVES, - NULL, NULL, &djhdc_reset, - NULL, &djhdc_attach, &djhdc_detach, - &djhdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, - djhdc_dt, NULL, NULL, NULL, NULL, NULL, &djhdc_description -}; - -/* Reset routine */ -static t_stat djhdc_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ - sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &djhdcdev, "djhdcdev", TRUE); - } else { - /* Connect DJHDC at base address */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &djhdcdev, "djhdcdev", FALSE) != 0) { - sim_printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - - djhdc_info->link_addr = DJHDC_LINK_ADDR; /* After RESET, the link pointer is at 0x000050. */ - - return SCPE_OK; -} - - -/* Attach routine */ -static t_stat djhdc_attach(UNIT *uptr, CONST char *cptr) -{ - t_stat r = SCPE_OK; - DJHDC_DRIVE_INFO *pDrive; - int i = 0; - - i = find_unit_index(uptr); - if (i == -1) { - return (SCPE_IERR); - } - pDrive = &djhdc_info->drive[i]; - - pDrive->ready = 1; - pDrive->track = 5; - - if (pDrive->ntracks == 0) { - /* If geometry was not specified, default to Miniscribe 15MB */ - pDrive->ntracks = SCRIBE_NTRACKS; - pDrive->nheads = SCRIBE_NHEADS; - pDrive->nsectors = SCRIBE_NSECTORS; - pDrive->sectsize = SCRIBE_SECTSIZE; - } - - r = attach_unit(uptr, cptr); /* attach unit */ - if ( r != SCPE_OK) /* error? */ - return r; - - /* Determine length of this disk */ - if(sim_fsize(uptr->fileref) != 0) { - uptr->capac = sim_fsize(uptr->fileref); - } else { - uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize); - } - - pDrive->uptr = uptr; - - /* Default for new file is DSK */ - uptr->u3 = IMAGE_TYPE_DSK; - - if(uptr->capac > 0) { - r = assignDiskType(uptr); - if (r != SCPE_OK) { - djhdc_detach(uptr); - return r; - } - } - - if (uptr->flags & UNIT_DJHDC_VERBOSE) - sim_printf("DJHDC%d, attached to '%s', type=%s, len=%d\n", i, cptr, - uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", - uptr->capac); - - if(uptr->u3 == IMAGE_TYPE_IMD) { - if(uptr->capac < 318000) { - sim_printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); - djhdc_detach(uptr); - return SCPE_OPENERR; - } - - if (uptr->flags & UNIT_DJHDC_VERBOSE) - sim_printf("--------------------------------------------------------\n"); - djhdc_info->drive[i].imd = diskOpenEx((uptr->fileref), (uptr->flags & UNIT_DJHDC_VERBOSE), - &djhdc_dev, VERBOSE_MSG, VERBOSE_MSG); - if (uptr->flags & UNIT_DJHDC_VERBOSE) - sim_printf("\n"); - } else { - djhdc_info->drive[i].imd = NULL; - } - - return SCPE_OK; -} - - -/* Detach routine */ -static t_stat djhdc_detach(UNIT *uptr) -{ - DJHDC_DRIVE_INFO *pDrive; - t_stat r; - int32 i; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - pDrive = &djhdc_info->drive[i]; - - pDrive->ready = 0; - - if (uptr->flags & UNIT_DJHDC_VERBOSE) - sim_printf("Detach DJHDC%d\n", i); - - r = detach_unit(uptr); /* detach unit */ - if ( r != SCPE_OK) - return r; - - return SCPE_OK; -} - -/* Set geometry of the disk drive */ -static t_stat djhdc_unit_set_geometry(UNIT* uptr, int32 value, CONST char* cptr, void* desc) -{ - DJHDC_DRIVE_INFO* pDrive; - int32 i; - int32 result; - uint16 newCyls, newHeads, newSPT, newSecLen; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - pDrive = &djhdc_info->drive[i]; - - if (cptr == NULL) - return SCPE_ARG; - - result = sscanf(cptr, "C:%hd/H:%hd/S:%hd/N:%hd", &newCyls, &newHeads, &newSPT, &newSecLen); - if (result != 4) - return SCPE_ARG; - - /* Validate Cyl, Heads, Sector, Length are valid for the HDC-1001 */ - if (newCyls < 1 || newCyls > DJHDC_MAX_CYLS) { - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: Number of cylinders must be 1-%d.\n", - djhdc_info->sel_drive, DJHDC_MAX_CYLS); - return SCPE_ARG; - } - if (newHeads < 1 || newHeads > DJHDC_MAX_HEADS) { - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: Number of heads must be 1-%d.\n", - djhdc_info->sel_drive, DJHDC_MAX_HEADS); - return SCPE_ARG; - } - if (newSPT < 1 || newSPT > DJHDC_MAX_SPT) { - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: Number of sectors per track must be 1-%d.\n", - djhdc_info->sel_drive, DJHDC_MAX_SPT); - return SCPE_ARG; - } - if (newSecLen != 2048 && newSecLen != 1024 && newSecLen != 512 && newSecLen != 256 && newSecLen != 128) { - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: Sector length must be 128, 256, 512, 1024, or 2048.\n", - djhdc_info->sel_drive); - return SCPE_ARG; - } - - pDrive->ntracks = newCyls; - pDrive->nheads = newHeads; - pDrive->nsectors = newSPT; - pDrive->sectsize = newSecLen; - - return SCPE_OK; -} - -/* Show geometry of the disk drive */ -static t_stat djhdc_unit_show_geometry(FILE* st, UNIT* uptr, int32 value, CONST void* desc) -{ - DJHDC_DRIVE_INFO* pDrive; - int32 i; - - i = find_unit_index(uptr); - - if (i == -1) { - return (SCPE_IERR); - } - - pDrive = &djhdc_info->drive[i]; - - fprintf(st, "C:%d/H:%d/S:%d/N:%d", - pDrive->ntracks, pDrive->nheads, pDrive->nsectors, pDrive->sectsize); - - return SCPE_OK; -} - -static int32 djhdcdev(const int32 port, const int32 io, const int32 data) -{ - sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME ": " ADDRESS_FORMAT - " IO %s, Port %02x\n", PCX, io ? "WR" : "RD", port); - if(io) { - DJHDC_Write(port, (uint8)data); - return 0; - } else { - return(0xFF); - } -} - -static uint8 DJHDC_Write(const uint32 Addr, uint8 cData) -{ - uint32 next_link; - uint8 result = DJHDC_STATUS_COMPLETE; - uint8 i; - uint8 opcode; - - DJHDC_DRIVE_INFO *pDrive; - - /* RESET */ - if ((Addr & 1) == DJHDC_RESET) { - djhdc_info->link_addr = DJHDC_LINK_ADDR - DJHDC_IOPB_LINK; - - sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME "[%d]: RESET\n", - djhdc_info->sel_drive); - - return 0; - } - - /* START */ - - /* Read first three bytes of IOPB (link address) */ - for (i = DJHDC_IOPB_LINK; i < DJHDC_IOPB_LEN; i++) { - djhdc_info->iopb[i] = GetByteDMA((djhdc_info->link_addr) + i); - } - - next_link = djhdc_info->iopb[DJHDC_IOPB_LINK + 0]; - next_link |= djhdc_info->iopb[DJHDC_IOPB_LINK+1] << 8; - next_link |= djhdc_info->iopb[DJHDC_IOPB_LINK+2] << 16; - - /* Point IOPB to new link */ - djhdc_info->link_addr = next_link; - - /* Read remaineder of IOPB */ - for(i = 0; i < DJHDC_IOPB_LEN-3; i++) { - djhdc_info->iopb[i] = GetByteDMA((djhdc_info->link_addr) + i); - } - - /* Process the IOPB */ - djhdc_info->iopb[DJHDC_IOPB_OPCODE] = djhdc_info->iopb[DJHDC_IOPB_OPCODE] & DJHDC_OPCODE_MASK; - - opcode = djhdc_info->iopb[DJHDC_IOPB_OPCODE]; - djhdc_info->sel_drive = djhdc_info->iopb[DJHDC_IOPB_SELDRV] & 0x03; - djhdc_info->step_dir = (djhdc_info->iopb[DJHDC_IOPB_SELDRV] & DJHDC_STEP_DIR) ? 1 : 0; - - djhdc_info->steps = djhdc_info->iopb[DJHDC_IOPB_STEP_L]; - djhdc_info->steps |= djhdc_info->iopb[DJHDC_IOPB_STEP_H] << 8; - - djhdc_info->dma_addr = djhdc_info->iopb[DJHDC_IOPB_DMA_L]; - djhdc_info->dma_addr |= djhdc_info->iopb[DJHDC_IOPB_DMA_H] << 8; - djhdc_info->dma_addr |= djhdc_info->iopb[DJHDC_IOPB_DMA_E] << 16; - - sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME "[%d]: SEEK=%d %s, LINK=0x%05x, OPCODE=%x, %s DMA@0x%05x\n", - djhdc_info->sel_drive, - djhdc_info->steps, - djhdc_info->step_dir ? "OUT" : "IN", - djhdc_info->link_addr, - djhdc_info->iopb[DJHDC_IOPB_OPCODE], - djhdc_opcode_str[djhdc_info->iopb[DJHDC_IOPB_OPCODE]], - djhdc_info->dma_addr); - - pDrive = &djhdc_info->drive[djhdc_info->sel_drive]; - - if(pDrive->ready) { - /* Seek phase */ - if (djhdc_info->step_dir) { - /* Step Out */ - if (djhdc_info->steps >= pDrive->cur_cyl) { - pDrive->cur_cyl = 0; - sim_debug(SEEK_MSG, &djhdc_dev, DEV_NAME "[%d]: HOME\n", - djhdc_info->sel_drive); - } - else { - pDrive->cur_cyl -= djhdc_info->steps; - } - } - else { - /* Step In */ - pDrive->cur_cyl += djhdc_info->steps; - } - - sim_debug(SEEK_MSG, &djhdc_dev, DEV_NAME "[%d]: Current track: %d\n", - djhdc_info->sel_drive, - pDrive->cur_cyl); - - - /* Perform command */ - switch(opcode) { - case DJHDC_OPCODE_READ_DATA: - case DJHDC_OPCODE_WRITE_DATA: - { - uint32 track_len; - uint32 xfr_len; - uint32 file_offset; - uint32 xfr_count = 0; - uint8* dataBuffer; - size_t rtn; - - pDrive->cur_cyl = djhdc_info->iopb[DJHDC_IOPB_ARG0] | (djhdc_info->iopb[DJHDC_IOPB_ARG1] << 8); - pDrive->cur_head = djhdc_info->iopb[DJHDC_IOPB_ARG2]; - pDrive->cur_sect = djhdc_info->iopb[DJHDC_IOPB_ARG3] - 1; - - if (DJHDC_Validate_CHSN(pDrive) != SCPE_OK) { - result = DJHDC_STATUS_HEADER_NOT_FOUND; - break; - } - - track_len = pDrive->nsectors * pDrive->nheads * pDrive->sectsize; - - file_offset = (pDrive->cur_cyl * track_len); /* Calculate offset based on current track */ - file_offset += pDrive->nsectors * pDrive->cur_head * pDrive->sectsize; - file_offset += pDrive->cur_sect * pDrive->sectsize; - - xfr_len = pDrive->sectsize; - - dataBuffer = (uint8*)malloc(xfr_len); - if (dataBuffer == NULL) { - sim_printf("%s: error allocating memory\n", __FUNCTION__); - return (0); - } - - if (sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET) == 0) { - - if (opcode == DJHDC_OPCODE_READ_DATA) { /* Read */ - rtn = sim_fread(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref); - - sim_debug(RD_DATA_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT - " READ @0x%05x C:%04d/H:%d/S:%04d len=%d, file_offset=%d, %s\n", - djhdc_info->sel_drive, - PCX, - djhdc_info->dma_addr, - pDrive->cur_cyl, - pDrive->cur_head, - pDrive->cur_sect, - xfr_len, - file_offset, - rtn == (size_t)xfr_len ? "OK" : "NOK"); - - - /* Perform DMA Transfer */ - for (xfr_count = 0; xfr_count < xfr_len; xfr_count++) { - PutByteDMA(djhdc_info->dma_addr + xfr_count, dataBuffer[xfr_count]); - } - } - else { /* Write */ - sim_debug(WR_DATA_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT - " WRITE @0x%05x C:%04d/H:%d/S:%04d file_offset=%d, len=%d\n", - djhdc_info->sel_drive, - PCX, djhdc_info->dma_addr, - pDrive->cur_cyl, - pDrive->cur_head, - pDrive->cur_sect, - file_offset, - xfr_len); - - /* Perform DMA Transfer */ - for (xfr_count = 0; xfr_count < xfr_len; xfr_count++) { - dataBuffer[xfr_count] = GetByteDMA(djhdc_info->dma_addr + xfr_count); - } - - sim_fwrite(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref); - } - } - else { - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT " READWRITE: sim_fseek error.\n", djhdc_info->sel_drive, PCX); - } - - free(dataBuffer); - - break; - } - case DJHDC_OPCODE_READ_HEADER: - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT " READ_HEADER: not implemented.\n", djhdc_info->sel_drive, PCX); - result = DJHDC_STATUS_HEADER_NOT_FOUND; - break; - case DJHDC_OPCODE_FORMAT_TRACK: - { - uint32 track_len; - uint32 file_offset; - uint8* fmtBuffer; - uint8 head; - uint8 gap; - uint8 sector_count; - uint8 sector_size_code; - uint8 fill_byte; - - head = ~(djhdc_info->iopb[DJHDC_IOPB_SEL_HD] >> 2) & 7; - gap = djhdc_info->iopb[DJHDC_IOPB_ARG0]; - sector_count = 255 - djhdc_info->iopb[DJHDC_IOPB_ARG1]; - sector_size_code = djhdc_info->iopb[DJHDC_IOPB_ARG2]; - fill_byte = djhdc_info->iopb[DJHDC_IOPB_ARG3]; - - switch (sector_size_code) { - case 0xFF: - pDrive->cur_sectsize = 128; - break; - case 0xFE: - pDrive->cur_sectsize = 256; - break; - case 0xFC: - pDrive->cur_sectsize = 512; - break; - case 0xF8: - pDrive->cur_sectsize = 1024; - break; - case 0xF0: - pDrive->cur_sectsize = 2048; - break; - default: - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME ": Invalid sector size code: 0x%02x.\n", - djhdc_info->sector_size_code); - pDrive->cur_sectsize = 0; - result = DJHDC_STATUS_ILLEGAL_COMMAND; - break; - } - - if (DJHDC_Validate_CHSN(pDrive) != SCPE_OK) { - result = DJHDC_STATUS_HEADER_NOT_FOUND; - break; - } - - track_len = pDrive->nheads * sector_count * pDrive->sectsize; - - file_offset = pDrive->cur_cyl * track_len; /* Calculate offset based on current track */ - file_offset += head * sector_count * pDrive->sectsize; - - sim_debug(FORMAT_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT - " FORMAT C:%d/H:%d, Gap=%d, Fill=0x%02x, Count=%d, Sector Size:=%d, file offset: 0x%08x\n", - djhdc_info->sel_drive, - PCX, - pDrive->cur_cyl, - head, - gap, - fill_byte, - sector_count, - pDrive->sectsize, - file_offset); - - fmtBuffer = (uint8*)malloc(track_len); - - if (fmtBuffer == NULL) { - sim_printf("%s: error allocating memory\n", __FUNCTION__); - return (0); - } - - memset(fmtBuffer, fill_byte, track_len); - - if (sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET) == 0) { - sim_fwrite(fmtBuffer, 1, track_len, (pDrive->uptr)->fileref); - } - else { - sim_debug(WR_DATA_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT " FORMAT: sim_fseek error.\n", djhdc_info->sel_drive, PCX); - result = DJHDC_STATUS_WRITE_FAULT; - } - - free(fmtBuffer); - - break; - } - case DJHDC_OPCODE_LOAD_CONSTANTS: - djhdc_info->irq_enable = (djhdc_info->iopb[DJHDC_IOPB_ARG1] & DJHDC_IRQ_EN_MASK) ? 1 : 0; - djhdc_info->step_delay = djhdc_info->iopb[DJHDC_IOPB_ARG1] & ~DJHDC_IRQ_EN_MASK; - djhdc_info->head_settle_time = djhdc_info->iopb[DJHDC_IOPB_ARG2]; - djhdc_info->sector_size_code = djhdc_info->iopb[DJHDC_IOPB_ARG3]; - - switch (djhdc_info->sector_size_code) { - case 0x00: - pDrive->cur_sectsize = 128; - break; - case 0x01: - pDrive->cur_sectsize = 256; - break; - case 0x03: - pDrive->cur_sectsize = 512; - break; - case 0x07: - pDrive->cur_sectsize = 1024; - break; - case 0x0F: - pDrive->cur_sectsize = 2048; - break; - default: - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME ": Invalid sector size code: 0x%02x.\n", - djhdc_info->sector_size_code); - pDrive->cur_sectsize = 0; - result = DJHDC_STATUS_ILLEGAL_COMMAND; - break; - } - - sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT - " Load Constants: Interrupt Enable: %d, step delay: %d, head settle time: %d, sector size %d (code: 0x%02x)\n", - djhdc_info->sel_drive, PCX, - djhdc_info->irq_enable, - djhdc_info->step_delay, - djhdc_info->head_settle_time, - pDrive->sectsize, - djhdc_info->sector_size_code); - break; - case DJHDC_OPCODE_SENSE_STATUS: - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT " SENSE_STATUS: not implemented.\n", djhdc_info->sel_drive, PCX); - result = DJHDC_DRIVE_READY_SIGNAL; - if (pDrive->cur_cyl != 0) result = DJHDC_TRACK_0_DETECT; - break; - case DJHDC_OPCODE_NOOP: - sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT - " NOOP\n", djhdc_info->sel_drive, PCX); - break; - - default: - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT - " OPCODE=%x Unsupported\n", - djhdc_info->sel_drive, - PCX, - opcode & DJHDC_OPCODE_MASK); - result = DJHDC_STATUS_ILLEGAL_COMMAND; - break; - } - } else { /* Drive not ready */ - result = DJHDC_STATUS_NOT_READY; - } - /* Return status */ - djhdc_info->iopb[DJHDC_IOPB_STATUS] = result; - - /* Update IOPB in host memory */ - PutByteDMA(djhdc_info->link_addr + DJHDC_IOPB_STATUS, djhdc_info->iopb[DJHDC_IOPB_STATUS]); - -#ifdef DJHDC_INTERRUPTS - if(djhdc_info->irq_enable) { - raise_djhdc_interrupt(); - } -#endif /* DJHDC_INTERRUPTS */ - - return 0; -} - -/* Validate that Cyl, Head, Sector, Sector Length are valid for the current - * disk drive geometry. - */ -static int DJHDC_Validate_CHSN(DJHDC_DRIVE_INFO* pDrive) -{ - int status = SCPE_OK; - - /* Check to make sure we're operating on a valid C/H/S/N. */ - if ((pDrive->cur_cyl >= pDrive->ntracks) || - (pDrive->cur_head >= pDrive->nheads) || - (pDrive->cur_sect >= pDrive->nsectors) || - (pDrive->cur_sectsize != pDrive->sectsize)) - { - - sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: " ADDRESS_FORMAT - " ID Not Found (check disk geometry.)\n", djhdc_info->sel_drive, PCX); - - status = SCPE_IOERR; - } - - return (status); -} - -#ifdef DJHDC_INTERRUPTS -static void raise_djhdc_interrupt(void) -{ - sim_debug(IRQ_MSG, &djhdc_dev, DEV_NAME ": " ADDRESS_FORMAT " Interrupt\n", PCX); - - raise_scp300f_interrupt(DJHDC_INT); -} -#endif /* DJHDC_INTERRUPTS */ +/************************************************************************* + * * + * Copyright (c) 2022 Howard M. Harte. * + * https://github.com/hharte * + * * + * Permission is hereby granted, free of charge, to any person obtaining * + * a copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to * + * the following conditions: * + * * + * The above copyright notice and this permission notice shall be * + * included in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- * + * INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * + * SOFTWARE. * + * * + * Except as contained in this notice, the names of The Authors shall * + * not be used in advertising or otherwise to promote the sale, use or * + * other dealings in this Software without prior written authorization * + * from the Authors. * + * * + * Based on s100_disk3.c * + * * + * Module Description: * + * Morrow Disk Jockey HDC-DMA Hard Disk Controller module for SIMH. * + * Reference: * + * http://www.bitsavers.org/pdf/morrow/boards/HDC_DMA_Technical_Manual_1983.pdf * + * * + *************************************************************************/ + +#include "altairz80_defs.h" +#include "sim_imd.h" + +#define DEV_NAME "DJHDC" + +#define DJHDC_MAX_CYLS 1024 +#define DJHDC_MAX_HEADS 8 +#define DJHDC_MAX_SPT 256 + +/* Debug flags */ +#define ERROR_MSG (1 << 0) +#define SEEK_MSG (1 << 1) +#define OPCODE_MSG (1 << 2) +#define RD_DATA_MSG (1 << 3) +#define WR_DATA_MSG (1 << 4) +#define IRQ_MSG (1 << 5) +#define VERBOSE_MSG (1 << 6) +#define FORMAT_MSG (1 << 7) + +#define DJHDC_MAX_DRIVES 4 + +/* DJHDC I/O Ports */ +#define DJHDC_RESET 0 /* Reset */ +#define DJHDC_START 1 /* Start */ + +#define DJHDC_LINK_ADDR 0x000050 /* Default link address in RAM */ + +#define DJHDC_STEP_DIR 0x10 /* Bit 4, Step OUT */ + +#define DJHDC_IRQ_EN_MASK 0x80 /* Interrupt enable mask */ + +#define DJHDC_OPCODE_READ_DATA 0x00 +#define DJHDC_OPCODE_WRITE_DATA 0x01 +#define DJHDC_OPCODE_READ_HEADER 0x02 +#define DJHDC_OPCODE_FORMAT_TRACK 0x03 +#define DJHDC_OPCODE_LOAD_CONSTANTS 0x04 +#define DJHDC_OPCODE_SENSE_STATUS 0x05 +#define DJHDC_OPCODE_NOOP 0x06 + +#define DJHDC_STATUS_BUSY 0x00 /* Busy */ +#define DJHDC_STATUS_NOT_READY 0x01 /* Drive not ready */ +#define DJHDC_STATUS_HEADER_NOT_FOUND 0x04 /* Sector header not found */ +#define DJHDC_STATUS_DATA_NOT_FOUND 0x05 /* Sector data not found */ +#define DJHDC_STATUS_DATA_OVERRUN 0x06 /* Data overrun(channel error) */ +#define DJHDC_STATUS_DATA_CRC_ERROR 0x07 /* Data CRC error */ +#define DJHDC_STATUS_WRITE_FAULT 0x08 /* Write fault */ +#define DJHDC_STATUS_HEADER_CRC_ERROR 0x09 /* Sector header CRC error */ +#define DJHDC_STATUS_ILLEGAL_COMMAND 0xA0 /* Illegal command */ +#define DJHDC_STATUS_COMPLETE 0xFF /* Successful completion */ + +#define DJHDC_TRACK_0_DETECT (1 << 0) /* 0 = track 0. */ +#define DJHDC_WRITE_FAULT_SIGNAL (1 << 1) /* Drive Write fault (0). */ +#define DJHDC_DRIVE_READY_SIGNAL (1 << 2) /* Drive is up to speed (0). */ + +#define DJHDC_OPCODE_MASK 0x07 + +#define DJHDC_IOPB_LEN 16 + +#define DJHDC_IOPB_SELDRV 0 +#define DJHDC_IOPB_STEP_L 1 +#define DJHDC_IOPB_STEP_H 2 +#define DJHDC_IOPB_SEL_HD 3 +#define DJHDC_IOPB_DMA_L 4 +#define DJHDC_IOPB_DMA_H 5 +#define DJHDC_IOPB_DMA_E 6 +#define DJHDC_IOPB_ARG0 7 +#define DJHDC_IOPB_ARG1 8 +#define DJHDC_IOPB_ARG2 9 +#define DJHDC_IOPB_ARG3 10 +#define DJHDC_IOPB_OPCODE 11 +#define DJHDC_IOPB_STATUS 12 +#define DJHDC_IOPB_LINK 13 +#define DJHDC_IOPB_LINK_H 14 +#define DJHDC_IOPB_LINK_E 15 + +#define DJHDC_INT 1 /* DJHDC interrupts tied to VI1 */ + +typedef struct { + UNIT *uptr; + DISK_INFO *imd; + uint16 sectsize; /* sector size, not including pre/postamble */ + uint16 nsectors; /* number of sectors/track */ + uint16 nheads; /* number of heads */ + uint16 ntracks; /* number of tracks */ + uint16 res_tracks; /* Number of reserved tracks on drive. */ + uint16 track; /* Current Track */ + + uint16 cur_sect; /* current starting sector of transfer */ + uint16 cur_cyl; /* Current Track */ + uint16 cur_head; /* Number of sectors to transfer */ + uint16 cur_sectsize;/* Current sector size */ + uint8 ready; /* Is drive ready? */ +} DJHDC_DRIVE_INFO; + +typedef struct { + PNP_INFO pnp; /* Plug and Play */ + uint8 sel_drive; /* Currently selected drive */ + uint8 mode; /* mode (0xFF=absolute, 0x00=logical) */ + uint8 ndrives; /* Number of drives attached to the controller */ + + uint32 link_addr; /* Link Address for next IOPB */ + uint32 dma_addr; /* DMA Address for the current IOPB */ + + uint16 steps; /* Step count */ + uint8 step_dir; /* Step direction, 1 = out. */ + uint8 irq_enable; + uint8 step_delay; + uint8 head_settle_time; + uint8 sector_size_code; + + DJHDC_DRIVE_INFO drive[DJHDC_MAX_DRIVES]; + uint8 iopb[16]; +} DJHDC_INFO; + +static DJHDC_INFO djhdc_info_data = { { 0x0, 0, 0x54, 2 } }; +static DJHDC_INFO *djhdc_info = &djhdc_info_data; + +/* Disk geometries: + * IMI SCRIBE + * Sectsize: 1024 1024 + * Sectors: 8 8 + * Heads: 6 4 + * Tracks: 306 480 + */ + +/* Default geometry for a 15MB hard disk. */ +#define SCRIBE_SECTSIZE 1024 +#define SCRIBE_NSECTORS 8 +#define SCRIBE_NHEADS 4 +#define SCRIBE_NTRACKS 480 + +static const char* djhdc_opcode_str[] = { + "Read Data ", + "Write Data ", + "Read Header ", + "Format Track ", + "Load Constants", + "Sense Status ", + "No Operation ", + "Invalid " +}; + +static int32 ntracks = SCRIBE_NTRACKS; +static int32 nheads = SCRIBE_NHEADS; +static int32 nsectors = SCRIBE_NSECTORS; +static int32 sectsize = SCRIBE_SECTSIZE; + +extern uint32 PCX; +extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, CONST void *desc); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), const char* name, uint8 unmap); +extern int32 find_unit_index(UNIT *uptr); +extern void raise_scp300f_interrupt(uint8 intnum); + +/* These are needed for DMA. */ +extern void PutByteDMA(const uint32 Addr, const uint32 Value); +extern uint8 GetByteDMA(const uint32 Addr); + +#define UNIT_V_DJHDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */ +#define UNIT_DJHDC_VERBOSE (1 << UNIT_V_DJHDC_VERBOSE) +#define DJHDC_CAPACITY (SCRIBE_NTRACKS * SCRIBE_NHEADS * \ + SCRIBE_NSECTORS * SCRIBE_SECTSIZE) /* Default Disk Capacity */ + +static t_stat djhdc_reset(DEVICE *djhdc_dev); +static t_stat djhdc_attach(UNIT *uptr, CONST char *cptr); +static t_stat djhdc_detach(UNIT *uptr); +static t_stat djhdc_unit_set_geometry(UNIT* uptr, int32 value, CONST char* cptr, void* desc); +static t_stat djhdc_unit_show_geometry(FILE* st, UNIT* uptr, int32 value, CONST void* desc); +static int DJHDC_Validate_CHSN(DJHDC_DRIVE_INFO* pDrive); +#ifdef DJHDC_INTERRUPTS +static void raise_djhdc_interrupt(void); +#endif /* DJHDC_INTERRUPTS */ + +static const char* djhdc_description(DEVICE *dptr); + +static int32 djhdcdev(const int32 port, const int32 io, const int32 data); + +/* static uint8 DJHDC_Read(const uint32 Addr); */ +static uint8 DJHDC_Write(const uint32 Addr, uint8 cData); + +static UNIT djhdc_unit[] = { + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DJHDC_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DJHDC_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DJHDC_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, DJHDC_CAPACITY) } +}; + +static REG djhdc_reg[] = { + { DRDATAD (NTRACKS, ntracks, 10, + "Number of tracks"), }, + { DRDATAD (NHEADS, nheads, 8, + "Number of heads"), }, + { DRDATAD (NSECTORS, nsectors, 8, + "Number of sectors per track"), }, + { DRDATAD (SECTSIZE, sectsize, 11, + "Sector size not including pre/postamble"), }, + { HRDATAD (SEL_DRIVE, djhdc_info_data.sel_drive, 3, + "Currently selected drive"), }, + { HRDATAD (MODE, djhdc_info_data.mode, 8, + "Mode (0xFF=absolute, 0x00=logical)"), }, + { HRDATAD (NDRIVES, djhdc_info_data.ndrives, 8, + "Number of drives attached to the controller"), }, + { HRDATAD (LINK_ADDR, djhdc_info_data.link_addr, 32, + "Link address for next IOPB"), }, + { HRDATAD (DMA_ADDR, djhdc_info_data.dma_addr, 32, + "DMA address for the current IOPB"), }, + { BRDATAD (IOPB, djhdc_info_data.iopb, 16, 8, 16, + "IOPB command register"), }, + { NULL } +}; + +#define DJHDC_NAME "Morrow HDC/DMA Hard Disk Controller" + +static const char* djhdc_description(DEVICE *dptr) { + if (dptr == NULL) { + return NULL; + } + return DJHDC_NAME; +} + +static MTAB djhdc_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", + &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" }, + { MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "GEOMETRY", "GEOMETRY", + &djhdc_unit_set_geometry, &djhdc_unit_show_geometry, NULL, + "Set disk geometry C:nnnn/H:n/S:nnn/N:nnnn" }, + { 0 } +}; + +/* Debug Flags */ +static DEBTAB djhdc_dt[] = { + { "ERROR", ERROR_MSG, "Error messages" }, + { "SEEK", SEEK_MSG, "Seek messages" }, + { "OPCODE", OPCODE_MSG, "Opcode messages" }, + { "READ", RD_DATA_MSG, "Read messages" }, + { "WRITE", WR_DATA_MSG, "Write messages" }, + { "IRQ", IRQ_MSG, "IRQ messages" }, + { "VERBOSE", VERBOSE_MSG, "Verbose messages" }, + { "FORMAT", FORMAT_MSG, "Format messages" }, + { NULL, 0 } +}; + +DEVICE djhdc_dev = { + DEV_NAME, djhdc_unit, djhdc_reg, djhdc_mod, + DJHDC_MAX_DRIVES, 10, 31, 1, DJHDC_MAX_DRIVES, DJHDC_MAX_DRIVES, + NULL, NULL, &djhdc_reset, + NULL, &djhdc_attach, &djhdc_detach, + &djhdc_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), ERROR_MSG, + djhdc_dt, NULL, NULL, NULL, NULL, NULL, &djhdc_description +}; + +/* Reset routine */ +static t_stat djhdc_reset(DEVICE *dptr) +{ + PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; + + if(dptr->flags & DEV_DIS) { /* Disconnect I/O Ports */ + sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &djhdcdev, "djhdcdev", TRUE); + } else { + /* Connect DJHDC at base address */ + if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &djhdcdev, "djhdcdev", FALSE) != 0) { + sim_printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } + } + + djhdc_info->link_addr = DJHDC_LINK_ADDR; /* After RESET, the link pointer is at 0x000050. */ + + return SCPE_OK; +} + + +/* Attach routine */ +static t_stat djhdc_attach(UNIT *uptr, CONST char *cptr) +{ + t_stat r = SCPE_OK; + DJHDC_DRIVE_INFO *pDrive; + int i = 0; + + i = find_unit_index(uptr); + if (i == -1) { + return (SCPE_IERR); + } + pDrive = &djhdc_info->drive[i]; + + pDrive->ready = 1; + pDrive->track = 5; + + if (pDrive->ntracks == 0) { + /* If geometry was not specified, default to Miniscribe 15MB */ + pDrive->ntracks = SCRIBE_NTRACKS; + pDrive->nheads = SCRIBE_NHEADS; + pDrive->nsectors = SCRIBE_NSECTORS; + pDrive->sectsize = SCRIBE_SECTSIZE; + } + + r = attach_unit(uptr, cptr); /* attach unit */ + if ( r != SCPE_OK) /* error? */ + return r; + + /* Determine length of this disk */ + if(sim_fsize(uptr->fileref) != 0) { + uptr->capac = sim_fsize(uptr->fileref); + } else { + uptr->capac = (pDrive->ntracks * pDrive->nsectors * pDrive->nheads * pDrive->sectsize); + } + + pDrive->uptr = uptr; + + /* Default for new file is DSK */ + uptr->u3 = IMAGE_TYPE_DSK; + + if(uptr->capac > 0) { + r = assignDiskType(uptr); + if (r != SCPE_OK) { + djhdc_detach(uptr); + return r; + } + } + + if (uptr->flags & UNIT_DJHDC_VERBOSE) + sim_printf("DJHDC%d, attached to '%s', type=%s, len=%d\n", i, cptr, + uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK", + uptr->capac); + + if(uptr->u3 == IMAGE_TYPE_IMD) { + if(uptr->capac < 318000) { + sim_printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n"); + djhdc_detach(uptr); + return SCPE_OPENERR; + } + + if (uptr->flags & UNIT_DJHDC_VERBOSE) + sim_printf("--------------------------------------------------------\n"); + djhdc_info->drive[i].imd = diskOpenEx((uptr->fileref), (uptr->flags & UNIT_DJHDC_VERBOSE), + &djhdc_dev, VERBOSE_MSG, VERBOSE_MSG); + if (uptr->flags & UNIT_DJHDC_VERBOSE) + sim_printf("\n"); + } else { + djhdc_info->drive[i].imd = NULL; + } + + return SCPE_OK; +} + + +/* Detach routine */ +static t_stat djhdc_detach(UNIT *uptr) +{ + DJHDC_DRIVE_INFO *pDrive; + t_stat r; + int32 i; + + i = find_unit_index(uptr); + + if (i == -1) { + return (SCPE_IERR); + } + + pDrive = &djhdc_info->drive[i]; + + pDrive->ready = 0; + + if (uptr->flags & UNIT_DJHDC_VERBOSE) + sim_printf("Detach DJHDC%d\n", i); + + r = detach_unit(uptr); /* detach unit */ + if ( r != SCPE_OK) + return r; + + return SCPE_OK; +} + +/* Set geometry of the disk drive */ +static t_stat djhdc_unit_set_geometry(UNIT* uptr, int32 value, CONST char* cptr, void* desc) +{ + DJHDC_DRIVE_INFO* pDrive; + int32 i; + int32 result; + uint16 newCyls, newHeads, newSPT, newSecLen; + + i = find_unit_index(uptr); + + if (i == -1) { + return (SCPE_IERR); + } + + pDrive = &djhdc_info->drive[i]; + + if (cptr == NULL) + return SCPE_ARG; + + result = sscanf(cptr, "C:%hd/H:%hd/S:%hd/N:%hd", &newCyls, &newHeads, &newSPT, &newSecLen); + if (result != 4) + return SCPE_ARG; + + /* Validate Cyl, Heads, Sector, Length are valid for the HDC-1001 */ + if (newCyls < 1 || newCyls > DJHDC_MAX_CYLS) { + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: Number of cylinders must be 1-%d.\n", + djhdc_info->sel_drive, DJHDC_MAX_CYLS); + return SCPE_ARG; + } + if (newHeads < 1 || newHeads > DJHDC_MAX_HEADS) { + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: Number of heads must be 1-%d.\n", + djhdc_info->sel_drive, DJHDC_MAX_HEADS); + return SCPE_ARG; + } + if (newSPT < 1 || newSPT > DJHDC_MAX_SPT) { + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: Number of sectors per track must be 1-%d.\n", + djhdc_info->sel_drive, DJHDC_MAX_SPT); + return SCPE_ARG; + } + if (newSecLen != 2048 && newSecLen != 1024 && newSecLen != 512 && newSecLen != 256 && newSecLen != 128) { + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: Sector length must be 128, 256, 512, 1024, or 2048.\n", + djhdc_info->sel_drive); + return SCPE_ARG; + } + + pDrive->ntracks = newCyls; + pDrive->nheads = newHeads; + pDrive->nsectors = newSPT; + pDrive->sectsize = newSecLen; + + return SCPE_OK; +} + +/* Show geometry of the disk drive */ +static t_stat djhdc_unit_show_geometry(FILE* st, UNIT* uptr, int32 value, CONST void* desc) +{ + DJHDC_DRIVE_INFO* pDrive; + int32 i; + + i = find_unit_index(uptr); + + if (i == -1) { + return (SCPE_IERR); + } + + pDrive = &djhdc_info->drive[i]; + + fprintf(st, "C:%d/H:%d/S:%d/N:%d", + pDrive->ntracks, pDrive->nheads, pDrive->nsectors, pDrive->sectsize); + + return SCPE_OK; +} + +static int32 djhdcdev(const int32 port, const int32 io, const int32 data) +{ + sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME ": " ADDRESS_FORMAT + " IO %s, Port %02x\n", PCX, io ? "WR" : "RD", port); + if(io) { + DJHDC_Write(port, (uint8)data); + return 0; + } else { + return(0xFF); + } +} + +static uint8 DJHDC_Write(const uint32 Addr, uint8 cData) +{ + uint32 next_link; + uint8 result = DJHDC_STATUS_COMPLETE; + uint8 i; + uint8 opcode; + + DJHDC_DRIVE_INFO *pDrive; + + /* RESET */ + if ((Addr & 1) == DJHDC_RESET) { + djhdc_info->link_addr = DJHDC_LINK_ADDR - DJHDC_IOPB_LINK; + + sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME "[%d]: RESET\n", + djhdc_info->sel_drive); + + return 0; + } + + /* START */ + + /* Read first three bytes of IOPB (link address) */ + for (i = DJHDC_IOPB_LINK; i < DJHDC_IOPB_LEN; i++) { + djhdc_info->iopb[i] = GetByteDMA((djhdc_info->link_addr) + i); + } + + next_link = djhdc_info->iopb[DJHDC_IOPB_LINK + 0]; + next_link |= djhdc_info->iopb[DJHDC_IOPB_LINK+1] << 8; + next_link |= djhdc_info->iopb[DJHDC_IOPB_LINK+2] << 16; + + /* Point IOPB to new link */ + djhdc_info->link_addr = next_link; + + /* Read remaineder of IOPB */ + for(i = 0; i < DJHDC_IOPB_LEN-3; i++) { + djhdc_info->iopb[i] = GetByteDMA((djhdc_info->link_addr) + i); + } + + /* Process the IOPB */ + djhdc_info->iopb[DJHDC_IOPB_OPCODE] = djhdc_info->iopb[DJHDC_IOPB_OPCODE] & DJHDC_OPCODE_MASK; + + opcode = djhdc_info->iopb[DJHDC_IOPB_OPCODE]; + djhdc_info->sel_drive = djhdc_info->iopb[DJHDC_IOPB_SELDRV] & 0x03; + djhdc_info->step_dir = (djhdc_info->iopb[DJHDC_IOPB_SELDRV] & DJHDC_STEP_DIR) ? 1 : 0; + + djhdc_info->steps = djhdc_info->iopb[DJHDC_IOPB_STEP_L]; + djhdc_info->steps |= djhdc_info->iopb[DJHDC_IOPB_STEP_H] << 8; + + djhdc_info->dma_addr = djhdc_info->iopb[DJHDC_IOPB_DMA_L]; + djhdc_info->dma_addr |= djhdc_info->iopb[DJHDC_IOPB_DMA_H] << 8; + djhdc_info->dma_addr |= djhdc_info->iopb[DJHDC_IOPB_DMA_E] << 16; + + sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME "[%d]: SEEK=%d %s, LINK=0x%05x, OPCODE=%x, %s DMA@0x%05x\n", + djhdc_info->sel_drive, + djhdc_info->steps, + djhdc_info->step_dir ? "OUT" : "IN", + djhdc_info->link_addr, + djhdc_info->iopb[DJHDC_IOPB_OPCODE], + djhdc_opcode_str[djhdc_info->iopb[DJHDC_IOPB_OPCODE]], + djhdc_info->dma_addr); + + pDrive = &djhdc_info->drive[djhdc_info->sel_drive]; + + if(pDrive->ready) { + /* Seek phase */ + if (djhdc_info->step_dir) { + /* Step Out */ + if (djhdc_info->steps >= pDrive->cur_cyl) { + pDrive->cur_cyl = 0; + sim_debug(SEEK_MSG, &djhdc_dev, DEV_NAME "[%d]: HOME\n", + djhdc_info->sel_drive); + } + else { + pDrive->cur_cyl -= djhdc_info->steps; + } + } + else { + /* Step In */ + pDrive->cur_cyl += djhdc_info->steps; + } + + sim_debug(SEEK_MSG, &djhdc_dev, DEV_NAME "[%d]: Current track: %d\n", + djhdc_info->sel_drive, + pDrive->cur_cyl); + + + /* Perform command */ + switch(opcode) { + case DJHDC_OPCODE_READ_DATA: + case DJHDC_OPCODE_WRITE_DATA: + { + uint32 track_len; + uint32 xfr_len; + uint32 file_offset; + uint32 xfr_count = 0; + uint8* dataBuffer; + size_t rtn; + + pDrive->cur_cyl = djhdc_info->iopb[DJHDC_IOPB_ARG0] | (djhdc_info->iopb[DJHDC_IOPB_ARG1] << 8); + pDrive->cur_head = djhdc_info->iopb[DJHDC_IOPB_ARG2]; + pDrive->cur_sect = djhdc_info->iopb[DJHDC_IOPB_ARG3] - 1; + + if (DJHDC_Validate_CHSN(pDrive) != SCPE_OK) { + result = DJHDC_STATUS_HEADER_NOT_FOUND; + break; + } + + track_len = pDrive->nsectors * pDrive->nheads * pDrive->sectsize; + + file_offset = (pDrive->cur_cyl * track_len); /* Calculate offset based on current track */ + file_offset += pDrive->nsectors * pDrive->cur_head * pDrive->sectsize; + file_offset += pDrive->cur_sect * pDrive->sectsize; + + xfr_len = pDrive->sectsize; + + dataBuffer = (uint8*)malloc(xfr_len); + if (dataBuffer == NULL) { + sim_printf("%s: error allocating memory\n", __FUNCTION__); + return (0); + } + + if (sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET) == 0) { + + if (opcode == DJHDC_OPCODE_READ_DATA) { /* Read */ + rtn = sim_fread(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref); + + sim_debug(RD_DATA_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT + " READ @0x%05x C:%04d/H:%d/S:%04d len=%d, file_offset=%d, %s\n", + djhdc_info->sel_drive, + PCX, + djhdc_info->dma_addr, + pDrive->cur_cyl, + pDrive->cur_head, + pDrive->cur_sect, + xfr_len, + file_offset, + rtn == (size_t)xfr_len ? "OK" : "NOK"); + + + /* Perform DMA Transfer */ + for (xfr_count = 0; xfr_count < xfr_len; xfr_count++) { + PutByteDMA(djhdc_info->dma_addr + xfr_count, dataBuffer[xfr_count]); + } + } + else { /* Write */ + sim_debug(WR_DATA_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT + " WRITE @0x%05x C:%04d/H:%d/S:%04d file_offset=%d, len=%d\n", + djhdc_info->sel_drive, + PCX, djhdc_info->dma_addr, + pDrive->cur_cyl, + pDrive->cur_head, + pDrive->cur_sect, + file_offset, + xfr_len); + + /* Perform DMA Transfer */ + for (xfr_count = 0; xfr_count < xfr_len; xfr_count++) { + dataBuffer[xfr_count] = GetByteDMA(djhdc_info->dma_addr + xfr_count); + } + + sim_fwrite(dataBuffer, 1, xfr_len, (pDrive->uptr)->fileref); + } + } + else { + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT " READWRITE: sim_fseek error.\n", djhdc_info->sel_drive, PCX); + } + + free(dataBuffer); + + break; + } + case DJHDC_OPCODE_READ_HEADER: + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT " READ_HEADER: not implemented.\n", djhdc_info->sel_drive, PCX); + result = DJHDC_STATUS_HEADER_NOT_FOUND; + break; + case DJHDC_OPCODE_FORMAT_TRACK: + { + uint32 track_len; + uint32 file_offset; + uint8* fmtBuffer; + uint8 head; + uint8 gap; + uint8 sector_count; + uint8 sector_size_code; + uint8 fill_byte; + + head = ~(djhdc_info->iopb[DJHDC_IOPB_SEL_HD] >> 2) & 7; + gap = djhdc_info->iopb[DJHDC_IOPB_ARG0]; + sector_count = 255 - djhdc_info->iopb[DJHDC_IOPB_ARG1]; + sector_size_code = djhdc_info->iopb[DJHDC_IOPB_ARG2]; + fill_byte = djhdc_info->iopb[DJHDC_IOPB_ARG3]; + + switch (sector_size_code) { + case 0xFF: + pDrive->cur_sectsize = 128; + break; + case 0xFE: + pDrive->cur_sectsize = 256; + break; + case 0xFC: + pDrive->cur_sectsize = 512; + break; + case 0xF8: + pDrive->cur_sectsize = 1024; + break; + case 0xF0: + pDrive->cur_sectsize = 2048; + break; + default: + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME ": Invalid sector size code: 0x%02x.\n", + djhdc_info->sector_size_code); + pDrive->cur_sectsize = 0; + result = DJHDC_STATUS_ILLEGAL_COMMAND; + break; + } + + if (DJHDC_Validate_CHSN(pDrive) != SCPE_OK) { + result = DJHDC_STATUS_HEADER_NOT_FOUND; + break; + } + + track_len = pDrive->nheads * sector_count * pDrive->sectsize; + + file_offset = pDrive->cur_cyl * track_len; /* Calculate offset based on current track */ + file_offset += head * sector_count * pDrive->sectsize; + + sim_debug(FORMAT_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT + " FORMAT C:%d/H:%d, Gap=%d, Fill=0x%02x, Count=%d, Sector Size:=%d, file offset: 0x%08x\n", + djhdc_info->sel_drive, + PCX, + pDrive->cur_cyl, + head, + gap, + fill_byte, + sector_count, + pDrive->sectsize, + file_offset); + + fmtBuffer = (uint8*)malloc(track_len); + + if (fmtBuffer == NULL) { + sim_printf("%s: error allocating memory\n", __FUNCTION__); + return (0); + } + + memset(fmtBuffer, fill_byte, track_len); + + if (sim_fseek((pDrive->uptr)->fileref, file_offset, SEEK_SET) == 0) { + sim_fwrite(fmtBuffer, 1, track_len, (pDrive->uptr)->fileref); + } + else { + sim_debug(WR_DATA_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT " FORMAT: sim_fseek error.\n", djhdc_info->sel_drive, PCX); + result = DJHDC_STATUS_WRITE_FAULT; + } + + free(fmtBuffer); + + break; + } + case DJHDC_OPCODE_LOAD_CONSTANTS: + djhdc_info->irq_enable = (djhdc_info->iopb[DJHDC_IOPB_ARG1] & DJHDC_IRQ_EN_MASK) ? 1 : 0; + djhdc_info->step_delay = djhdc_info->iopb[DJHDC_IOPB_ARG1] & ~DJHDC_IRQ_EN_MASK; + djhdc_info->head_settle_time = djhdc_info->iopb[DJHDC_IOPB_ARG2]; + djhdc_info->sector_size_code = djhdc_info->iopb[DJHDC_IOPB_ARG3]; + + switch (djhdc_info->sector_size_code) { + case 0x00: + pDrive->cur_sectsize = 128; + break; + case 0x01: + pDrive->cur_sectsize = 256; + break; + case 0x03: + pDrive->cur_sectsize = 512; + break; + case 0x07: + pDrive->cur_sectsize = 1024; + break; + case 0x0F: + pDrive->cur_sectsize = 2048; + break; + default: + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME ": Invalid sector size code: 0x%02x.\n", + djhdc_info->sector_size_code); + pDrive->cur_sectsize = 0; + result = DJHDC_STATUS_ILLEGAL_COMMAND; + break; + } + + sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT + " Load Constants: Interrupt Enable: %d, step delay: %d, head settle time: %d, sector size %d (code: 0x%02x)\n", + djhdc_info->sel_drive, PCX, + djhdc_info->irq_enable, + djhdc_info->step_delay, + djhdc_info->head_settle_time, + pDrive->sectsize, + djhdc_info->sector_size_code); + break; + case DJHDC_OPCODE_SENSE_STATUS: + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT " SENSE_STATUS: not implemented.\n", djhdc_info->sel_drive, PCX); + result = DJHDC_DRIVE_READY_SIGNAL; + if (pDrive->cur_cyl != 0) result = DJHDC_TRACK_0_DETECT; + break; + case DJHDC_OPCODE_NOOP: + sim_debug(VERBOSE_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT + " NOOP\n", djhdc_info->sel_drive, PCX); + break; + + default: + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "[%d]: " ADDRESS_FORMAT + " OPCODE=%x Unsupported\n", + djhdc_info->sel_drive, + PCX, + opcode & DJHDC_OPCODE_MASK); + result = DJHDC_STATUS_ILLEGAL_COMMAND; + break; + } + } else { /* Drive not ready */ + result = DJHDC_STATUS_NOT_READY; + } + /* Return status */ + djhdc_info->iopb[DJHDC_IOPB_STATUS] = result; + + /* Update IOPB in host memory */ + PutByteDMA(djhdc_info->link_addr + DJHDC_IOPB_STATUS, djhdc_info->iopb[DJHDC_IOPB_STATUS]); + +#ifdef DJHDC_INTERRUPTS + if(djhdc_info->irq_enable) { + raise_djhdc_interrupt(); + } +#endif /* DJHDC_INTERRUPTS */ + + return 0; +} + +/* Validate that Cyl, Head, Sector, Sector Length are valid for the current + * disk drive geometry. + */ +static int DJHDC_Validate_CHSN(DJHDC_DRIVE_INFO* pDrive) +{ + int status = SCPE_OK; + + /* Check to make sure we're operating on a valid C/H/S/N. */ + if ((pDrive->cur_cyl >= pDrive->ntracks) || + (pDrive->cur_head >= pDrive->nheads) || + (pDrive->cur_sect >= pDrive->nsectors) || + (pDrive->cur_sectsize != pDrive->sectsize)) + { + + sim_debug(ERROR_MSG, &djhdc_dev, DEV_NAME "%d: " ADDRESS_FORMAT + " ID Not Found (check disk geometry.)\n", djhdc_info->sel_drive, PCX); + + status = SCPE_IOERR; + } + + return (status); +} + +#ifdef DJHDC_INTERRUPTS +static void raise_djhdc_interrupt(void) +{ + sim_debug(IRQ_MSG, &djhdc_dev, DEV_NAME ": " ADDRESS_FORMAT " Interrupt\n", PCX); + + raise_scp300f_interrupt(DJHDC_INT); +} +#endif /* DJHDC_INTERRUPTS */ diff --git a/AltairZ80/s100_tdd.c b/AltairZ80/s100_tdd.c index df1e5b26..33f230f0 100644 --- a/AltairZ80/s100_tdd.c +++ b/AltairZ80/s100_tdd.c @@ -1,180 +1,180 @@ -/************************************************************************* - * * - * Copyright (c) 2022 Howard M. Harte. * - * https://github.com/hharte * - * * - * Permission is hereby granted, free of charge, to any person obtaining * - * a copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to * - * the following conditions: * - * * - * The above copyright notice and this permission notice shall be * - * included in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- * - * INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * - * SOFTWARE. * - * * - * Except as contained in this notice, the names of The Authors shall * - * not be used in advertising or otherwise to promote the sale, use or * - * other dealings in this Software without prior written authorization * - * from the Authors. * - * * - * Based on s100_64fdc.c * - * * - * Module Description: * - * Tarbell Double-Density Floppy Controller module for SIMH. * - * This module is a wrapper around the wd179x FDC module. * - * * - * Reference: * - * http://www.bitsavers.org/pdf/tarbell/Tarbell_Double_Density_Floppy_Disk_Interface_Jul81.pdf - * * - *************************************************************************/ - -#include "altairz80_defs.h" -#include "sim_defs.h" -#include "wd179x.h" - -#define DEV_NAME "TDD" - -/* Debug flags */ -#define STATUS_MSG (1 << 0) -#define DRIVE_MSG (1 << 1) -#define VERBOSE_MSG (1 << 2) -#define IRQ_MSG (1 << 3) - -#define TDD_MAX_DRIVES 4 - -#define TDD_IO_BASE 0x7C -#define TDD_IO_SIZE 0x2 -#define TDD_IO_MASK (TDD_IO_SIZE - 1) - -typedef struct { - PNP_INFO pnp; /* Plug and Play */ -} TDD_INFO; - -extern WD179X_INFO_PUB *wd179x_infop; - -static TDD_INFO tdd_info_data = { { 0x0000, 0, TDD_IO_BASE, TDD_IO_SIZE } }; - -extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, CONST void *desc); -extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, - int32 (*routine)(const int32, const int32, const int32), const char* name, uint8 unmap); - -extern uint32 PCX; /* external view of PC */ - -#define TDD_CAPACITY (77*1*26*128) /* Default SSSD 8" (IBM 3740) Disk Capacity */ - -static t_stat tdd_reset(DEVICE *tdd_dev); - -static int32 tdd_control(const int32 port, const int32 io, const int32 data); -static const char* tdd_description(DEVICE *dptr); - -#define TDD_FLAG_EOJ (1 << 7) /* End of Job (INTRQ) */ - -static UNIT tdd_unit[] = { - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) }, - { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) } -}; - -static REG tdd_reg[] = { - { NULL } -}; - -#define TDD_NAME "Tarbell Double-Density FDC" - -static const char* tdd_description(DEVICE *dptr) { - if (dptr == NULL) { - return NULL; - } - return TDD_NAME; -} - -static MTAB tdd_mod[] = { - { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", - &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" }, - { 0 } -}; - -/* Debug Flags */ -static DEBTAB tdd_dt[] = { - { "STATUS", STATUS_MSG, "Status messages" }, - { "DRIVE", DRIVE_MSG, "Drive messages" }, - { "VERBOSE", VERBOSE_MSG, "Verbose messages" }, - { "IRQ", IRQ_MSG, "IRQ messages" }, - { NULL, 0 } -}; - -DEVICE tdd_dev = { - DEV_NAME, tdd_unit, tdd_reg, tdd_mod, - TDD_MAX_DRIVES, 10, 31, 1, TDD_MAX_DRIVES, TDD_MAX_DRIVES, - NULL, NULL, &tdd_reset, - NULL, &wd179x_attach, &wd179x_detach, - &tdd_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0, - tdd_dt, NULL, NULL, NULL, NULL, NULL, &tdd_description -}; - -/* Reset routine */ -static t_stat tdd_reset(DEVICE *dptr) -{ - PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; - - if(dptr->flags & DEV_DIS) { /* Disconnect ROM and I/O Ports */ - /* Unmap I/O Ports */ - sim_map_resource(pnp->io_base, 1, RESOURCE_TYPE_IO, &tdd_control, "tdd_control", TRUE); - } else { - /* Connect TDD Disk Flags and Control Register */ - if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &tdd_control, "tdd_control", FALSE) != 0) { - sim_printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); - return SCPE_ARG; - } - } - - return SCPE_OK; -} - -/* Tarbell pp. 12-5 Disk Control/Status */ -static int32 tdd_control(const int32 port, const int32 io, const int32 data) -{ - int32 result = 0; - if(io) { /* I/O Write */ - if ((port & TDD_IO_MASK) == 0) { - wd179x_infop->fdc_head = (data & 0x40) >> 6; - wd179x_infop->sel_drive = (data & 0x30) >> 4; - wd179x_infop->ddens = (data & 0x08) >> 3; - - sim_debug(DRIVE_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT " WR CTRL(0x%02x) = 0x%02x: Drive: %d, Head: %d, %s-Density.\n", - PCX, port, - data & 0xFF, - wd179x_infop->sel_drive, - wd179x_infop->fdc_head, - wd179x_infop->ddens == 1 ? "Double" : "Single"); - } else { - sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT - " Write Extended Address, Port 0x%02x=0x%02x\n", PCX, port, data); - } - } else { /* I/O Read */ - if ((port & TDD_IO_MASK) == 0) { - result = (wd179x_infop->intrq) ? 0 : TDD_FLAG_EOJ; - sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT - " Read EOJ, Port 0x%02x Result 0x%02x\n", PCX, port, result); - } else { - result = (wd179x_infop->drq) ? TDD_FLAG_EOJ : 0; - sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT - " Read DRQ, Port 0x%02x Result 0x%02x\n", PCX, port, result); - } - } - - return result; -} +/************************************************************************* + * * + * Copyright (c) 2022 Howard M. Harte. * + * https://github.com/hharte * + * * + * Permission is hereby granted, free of charge, to any person obtaining * + * a copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to * + * the following conditions: * + * * + * The above copyright notice and this permission notice shall be * + * included in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- * + * INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * + * SOFTWARE. * + * * + * Except as contained in this notice, the names of The Authors shall * + * not be used in advertising or otherwise to promote the sale, use or * + * other dealings in this Software without prior written authorization * + * from the Authors. * + * * + * Based on s100_64fdc.c * + * * + * Module Description: * + * Tarbell Double-Density Floppy Controller module for SIMH. * + * This module is a wrapper around the wd179x FDC module. * + * * + * Reference: * + * http://www.bitsavers.org/pdf/tarbell/Tarbell_Double_Density_Floppy_Disk_Interface_Jul81.pdf + * * + *************************************************************************/ + +#include "altairz80_defs.h" +#include "sim_defs.h" +#include "wd179x.h" + +#define DEV_NAME "TDD" + +/* Debug flags */ +#define STATUS_MSG (1 << 0) +#define DRIVE_MSG (1 << 1) +#define VERBOSE_MSG (1 << 2) +#define IRQ_MSG (1 << 3) + +#define TDD_MAX_DRIVES 4 + +#define TDD_IO_BASE 0x7C +#define TDD_IO_SIZE 0x2 +#define TDD_IO_MASK (TDD_IO_SIZE - 1) + +typedef struct { + PNP_INFO pnp; /* Plug and Play */ +} TDD_INFO; + +extern WD179X_INFO_PUB *wd179x_infop; + +static TDD_INFO tdd_info_data = { { 0x0000, 0, TDD_IO_BASE, TDD_IO_SIZE } }; + +extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, CONST void *desc); +extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type, + int32 (*routine)(const int32, const int32, const int32), const char* name, uint8 unmap); + +extern uint32 PCX; /* external view of PC */ + +#define TDD_CAPACITY (77*1*26*128) /* Default SSSD 8" (IBM 3740) Disk Capacity */ + +static t_stat tdd_reset(DEVICE *tdd_dev); + +static int32 tdd_control(const int32 port, const int32 io, const int32 data); +static const char* tdd_description(DEVICE *dptr); + +#define TDD_FLAG_EOJ (1 << 7) /* End of Job (INTRQ) */ + +static UNIT tdd_unit[] = { + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) }, + { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, TDD_CAPACITY) } +}; + +static REG tdd_reg[] = { + { NULL } +}; + +#define TDD_NAME "Tarbell Double-Density FDC" + +static const char* tdd_description(DEVICE *dptr) { + if (dptr == NULL) { + return NULL; + } + return TDD_NAME; +} + +static MTAB tdd_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", + &set_iobase, &show_iobase, NULL, "Sets disk controller I/O base address" }, + { 0 } +}; + +/* Debug Flags */ +static DEBTAB tdd_dt[] = { + { "STATUS", STATUS_MSG, "Status messages" }, + { "DRIVE", DRIVE_MSG, "Drive messages" }, + { "VERBOSE", VERBOSE_MSG, "Verbose messages" }, + { "IRQ", IRQ_MSG, "IRQ messages" }, + { NULL, 0 } +}; + +DEVICE tdd_dev = { + DEV_NAME, tdd_unit, tdd_reg, tdd_mod, + TDD_MAX_DRIVES, 10, 31, 1, TDD_MAX_DRIVES, TDD_MAX_DRIVES, + NULL, NULL, &tdd_reset, + NULL, &wd179x_attach, &wd179x_detach, + &tdd_info_data, (DEV_DISABLE | DEV_DIS | DEV_DEBUG), 0, + tdd_dt, NULL, NULL, NULL, NULL, NULL, &tdd_description +}; + +/* Reset routine */ +static t_stat tdd_reset(DEVICE *dptr) +{ + PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt; + + if(dptr->flags & DEV_DIS) { /* Disconnect ROM and I/O Ports */ + /* Unmap I/O Ports */ + sim_map_resource(pnp->io_base, 1, RESOURCE_TYPE_IO, &tdd_control, "tdd_control", TRUE); + } else { + /* Connect TDD Disk Flags and Control Register */ + if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &tdd_control, "tdd_control", FALSE) != 0) { + sim_printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base); + return SCPE_ARG; + } + } + + return SCPE_OK; +} + +/* Tarbell pp. 12-5 Disk Control/Status */ +static int32 tdd_control(const int32 port, const int32 io, const int32 data) +{ + int32 result = 0; + if(io) { /* I/O Write */ + if ((port & TDD_IO_MASK) == 0) { + wd179x_infop->fdc_head = (data & 0x40) >> 6; + wd179x_infop->sel_drive = (data & 0x30) >> 4; + wd179x_infop->ddens = (data & 0x08) >> 3; + + sim_debug(DRIVE_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT " WR CTRL(0x%02x) = 0x%02x: Drive: %d, Head: %d, %s-Density.\n", + PCX, port, + data & 0xFF, + wd179x_infop->sel_drive, + wd179x_infop->fdc_head, + wd179x_infop->ddens == 1 ? "Double" : "Single"); + } else { + sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT + " Write Extended Address, Port 0x%02x=0x%02x\n", PCX, port, data); + } + } else { /* I/O Read */ + if ((port & TDD_IO_MASK) == 0) { + result = (wd179x_infop->intrq) ? 0 : TDD_FLAG_EOJ; + sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT + " Read EOJ, Port 0x%02x Result 0x%02x\n", PCX, port, result); + } else { + result = (wd179x_infop->drq) ? TDD_FLAG_EOJ : 0; + sim_debug(STATUS_MSG, &tdd_dev, DEV_NAME ": " ADDRESS_FORMAT + " Read DRQ, Port 0x%02x Result 0x%02x\n", PCX, port, result); + } + } + + return result; +} diff --git a/AltairZ80/wd179x.c b/AltairZ80/wd179x.c index 0a0b8e6c..804ea35d 100644 --- a/AltairZ80/wd179x.c +++ b/AltairZ80/wd179x.c @@ -1203,15 +1203,15 @@ static uint8 Do1793Command(uint8 cCommand) " Verify ", wd179x_info->sel_drive, PCX); if (pDrive->uptr->u3 == IMAGE_TYPE_IMD) { if (sectSeek(pDrive->imd, pDrive->track, wd179x_info->fdc_head) != SCPE_OK) { - sim_debug(SEEK_MSG, &wd179x_dev, "FAILED\n"); - wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ + sim_debug(SEEK_MSG, &wd179x_dev, "FAILED\n"); + wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ } else if (testMode(pDrive)) { - wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ - sim_debug(SEEK_MSG, &wd179x_dev, "NOT FOUND\n"); + wd179x_info->fdc_status |= WD179X_STAT_NOT_FOUND; /* Sector not found */ + sim_debug(SEEK_MSG, &wd179x_dev, "NOT FOUND\n"); } else { - sim_debug(SEEK_MSG, &wd179x_dev, "Ok\n"); + sim_debug(SEEK_MSG, &wd179x_dev, "Ok\n"); } - } + } } if (pDrive->track == 0) {