Compare commits

...

50 Commits

Author SHA1 Message Date
Peter Rutenbar
a9b2af09c0
Update README.md
Added a note of appreciation for issues/PRs
2023-03-29 10:49:13 -07:00
Peter Rutenbar
2b4768daee Update README.md 2017-04-17 11:52:13 -07:00
Peter Rutenbar
3fd03263fa Merge pull request #12 from mietek/master
Fix linking with Xcode 7
2016-09-04 02:02:17 -07:00
Miëtek Bak
578d274ab0 Fix linking with Xcode 7
Closes #11.
2015-11-28 22:03:13 +00:00
Miëtek Bak
bbb89edf8c Update .gitignore 2015-11-28 22:03:12 +00:00
Peter Rutenbar
70cf3734fb Update README.md 2015-09-13 20:16:46 -07:00
Peter Rutenbar
d26cbef0c1 Closing out some final simple changes 2015-09-13 19:11:18 -07:00
Peter Rutenbar
0322e558b4 Preliminary support for ethernet/multiple screens in cocoa client 2015-09-13 00:39:58 -07:00
Peter Rutenbar
1ab8a6a988 Fixed bugs in addx, subx, and cmpm
(cmpm was setting the CC codes based on a garbage source operand, so fixing that might fix a lot of other problems)
2015-09-10 16:27:00 -04:00
Peter Rutenbar
7f8b393fcc Fixed that dumb bsun bug 2015-09-04 12:01:01 -04:00
Peter Rutenbar
c0439a2f57 Fixed some integer division bugs, and other misc bugs 2015-09-01 16:04:30 -04:00
Peter Rutenbar
2ffbc963d2 Implemented chk2/cmp2, sbcd, and nbcd 2015-08-31 17:33:52 -04:00
Peter Rutenbar
36fdd1a6d6 Fixed/implemented roxx_mem, rox_mem, abcd, pack, unpk, cas2
Trying to finish up the last few unimplemented 68020 insts
2015-08-31 01:57:37 -04:00
Peter Rutenbar
3bc6aed00a Some preliminary work on ASC (Apple Sound Chip) emulation 2015-08-24 22:41:52 -04:00
Peter Rutenbar
b936ace3eb Update README.md 2015-04-09 22:22:51 -04:00
Peter Rutenbar
a66ad6d9b4 A/UX 3 should boot reliably now
- Added a hack to bypass SetUpTimeK, which works on 3.0.0,
  not sure about other versions.
2015-01-29 23:20:23 -05:00
Peter Rutenbar
476a8bb570 Major speed improvements (25-50%)
There may be bugs lurking in it. On my Core i7 macbook pro,
shoebill now runs so fast that SetUpTimeK() on A/UX 3 hangs.
(SetUpTimeK tries to time a dbra loop, and refuses to accept any
speed faster than a certain threshold, which shoebill is now
surpassing. If you see A/UX hanging early in boot, it's probably
that.)

- Added a new specialized cache for instruction stream reads
-- This also lets us distinguish between data and instruction
   reads, which the 68020 does. Instruction reads are now done
   with the correct function code (2 or 6), although that
   doesn't currently fix or improve anything currently
- Added an obvious condition code optimization, dunno how I missed
  it earlier
- Other little changes
2015-01-29 00:19:57 -05:00
Peter Rutenbar
76f2b35170 Unbroke shoebill, speed improvements
- Fixed inst_ext, which was completely broken since
  last commit, whoops!
- Added a bunch of __builtin_expect()s in all the
  critical paths, and now Marathon runs quite noticeably
  faster.
- Fixed (I think) all the SDL makefiles
2015-01-26 22:26:30 -05:00
Peter Rutenbar
9c3640cf48 fcmp and various other changes
- Read the 68881 docs for fcmp more carefully, and tweaked it to more
  accurately implement the (documented) behavior
- Implemented de-un-normalizing for all x80 softfloat ops
- Some other changes I don't remember - it's my emulator, I can be vague
  if I want XD
2014-12-10 22:22:45 -05:00
Peter Rutenbar
aea23c6dfc Implemented ftentox and fixed fscale again
- (Badly) worked around a clang bug to implement ftentox
- (Very badly) fixed another edge case in fscale
- Found another bug in softfloat (floatx80_to_int32)
-- Not so sure anymore that my floatx80/subnormal math fix works right.
   Just figured out that x80's exp is relative to the second mantissa
   bit. float128{exp=0x3fff, man=0} == floatx80{exp=0x3fff, man=0x800...}
   even though x80 has an explicit bit, the exponents are the same...
2014-11-24 01:31:53 -05:00
Peter Rutenbar
9e91b8067a Fixed a million SoftFloat bugs, and an edge case in fscale
SoftFloat's support for subnormal numbers is completely broken
on floatx80. Particularly when the result of an op on a subnormal
number is normal, and vice versa. I'm not completely sure that
my fixes are correct, or that they didn't break anything. I need
to do more testing.

Also fixed an edge case in fscale that gets weird when the
input goes from normal to subnormal... oh, and I still need to
fix the opposite case.
2014-11-23 19:41:06 -05:00
Peter Rutenbar
8142098fa1 Implemented fgetman,fscale,fsincos, and partial-fixed a softfloat bug
- fgetman, fscale, and fsincos are implemented but not tested at all

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

- also, I checked in the wrong core/Makefile with the last commit.
  Re-committing the correct Makefile
2014-11-22 16:47:49 -05:00
Peter Rutenbar
f04e039dca Promoting newfpu to be the current fpu (aka fpu.c)
Just merged the newfpu branch to master, almost everything
is implemented, but there are clearly lots of problems still.

(According to xcalc, sin(3.1415927) == 0.054803665, which is
pretty far beyond the acceptable error margin.)
2014-11-10 20:40:54 -05:00
Peter Rutenbar
c8e7ba594c Implemented fatanh,cosh,etox,etoxm1,lognp1,tanh, and twotox
but not ftentox, because this hits a clang bug. Clang 3.5
(and earlier?) wants to optimize pow(10.0, x) to
__exp10(x), but __exp10() doesn't exist in the 10.8 SDK,
so the linker fails. There's probably some simple workaround...
2014-11-09 15:31:48 -05:00
Peter Rutenbar
7fa1e15257 Implemented flog2, flog10, and flogn, fixed fneg
xeyes works now
2014-11-09 13:56:16 -05:00
Peter Rutenbar
c7a28b8520 Implemented fsin,fcos,ftan,fatan,fasin,facos
Not sure if they work exactly right yet - xeyes is messed up,
but xclock seems to work.
2014-11-09 13:16:34 -05:00
Peter Rutenbar
0910915301 Finished the native-half of the transcendental impls
... for x86. Remains to be seen whether this will *really*
work on PowerPC or other architectures.
2014-11-09 12:25:39 -05:00
Peter Rutenbar
937a28a8bb Implemented frem, fmod, fsglmul/div, and fixed fabs
- And also fixed an assert
- New frem impl is slower, but easier to get the quotient bits.
2014-11-09 10:56:58 -05:00
Peter Rutenbar
db111528e8 Marathon works!
Fixed a bunch of dumb bugs, and now newfpu is working almost as well as old-fpu.
Presumably it's also running much more slowly, but I'm not noticing a speed difference.
2014-11-07 19:55:13 -05:00
Peter Rutenbar
df66c085da fmovecr now actually works
a cursory boot of 3.0.0 didn't reveal any asserts, except for x11. And I'm sure Marathon will die, and Mathematica, etc. Calculator works though. IE 2 hangs, and finder shutdown crashes.

... getting there
2014-11-06 01:12:28 -05:00
Peter Rutenbar
18c5a2b261 Newfpu works enough to "boot" A/UX
... but that's not saying much
2014-11-06 00:13:31 -05:00
Peter Rutenbar
2d04c6c104 Implemented fmovem_control()
I'm on a roll
2014-11-05 21:40:07 -05:00
Peter Rutenbar
2790b03327 Added a bunch of disassemblers for newfpu 2014-11-05 18:31:33 -05:00
Peter Rutenbar
688199cf6d Dumping a lot of new FPU-related changes in a new branch
A/UX doesn't even come close to booting yet with the new FPU,
but we're getting there. I don't want to trash master with
a code base that doesn't work. Also, I turned off ethernet
in the cocoa GUI, since the TAP driver isn't working right
on 10.10 yet.
2014-11-05 13:38:51 -05:00
pruten
a155eb7734 Merge branch 'master' of https://github.com/pruten/Shoebill 2014-10-16 15:55:19 -04:00
pruten
7c96e7c101 Began implementing a few more newfpu instructions
Though Motorola's documentation is surprisingly buggy
and imprecise.
2014-10-16 15:53:32 -04:00
Peter Rutenbar
16f1af72f8 Update README.md 2014-10-15 18:11:54 -04:00
pruten
78fbd8235f Refactored a big chunk of newfpu
- the framework for throwing exceptions should work correctly now
- NaNs and signaling NaNs should work
- condition codes are set now
- write-back and rounding (including throwing INEX2) are now implemented

(Note: you can't actually use any of this code yet, and it doesn't actually
       fully implement any fmath_* instructions yet)
2014-10-13 23:21:06 -04:00
pruten
c9adc49a82 More minor tweaks to newfpu 2014-10-07 22:37:22 -04:00
pruten
adc2e16ffd Implemented CAS
It compiles, but I haven't even tested it once. *fingers crossed*
2014-09-28 19:40:16 -04:00
pruten
bb6d1e719f More half-baked newfpu goodness
Once the framework for handling exceptions, accrued exceptions,
condition codes, and rounding is done, I can start implementing
actual "fmath" instructions. Everything not handled by softfloat
will be imprecisely and hackily implemented by using the best
available native float math (e.g. cosf(), cos(), or cosl())
2014-09-28 16:51:08 -04:00
pruten
bb2ec0a27d Working on a total FPU rewrite based on softfloat
5 instructions down, a million more to go
2014-09-27 13:46:57 -04:00
pruten
a0810f55b9 Added a hook for shutdown
To which the Macintosh II usually responds by powering off
2014-09-22 17:02:17 -04:00
pruten
b29c69453e Mostly-working ethernet and various changes
This may break the linux/windows builds - I haven't tried to compile
on those platforms yet.

- Ethernet is more or less working with a hardcoded /dev/tun0 network interface
and hardcoded MAC address, though there's no automatic ifconfig/route
configuration yet.

- Instructions TAS and ILLEGAL are implemented now

- Fixed some bugs in MOVEP

- Implemented some other instruction disassemblers

- Other little changes
2014-09-11 03:40:20 -04:00
pruten
4af4262993 Implemented movep 2014-08-30 05:10:54 -04:00
name
fd31d642b0 Lots of new ethernet-related code (doesn't work yet)
The board is basically implemented. It's just a dummy slot ROM
with no driver or primary/secondary init, that looks enough
like the Apple EtherTalk card. The DP8390 controller chip
has its address space implemented, and some of its registers
work. Lots more work to do on that

With slog() tracing enabled, you can see A/UX try to send a
multicast ethernet frame, then give up waiting for some kind
of response from the chip, then decide that the ethernet
controller is dead and print an error to console
2014-08-27 19:37:26 -04:00
Peter Rutenbar
20fedf386b Improved SCSI a bit.
Apple HD SC Setup still doesn't work, but it won't crash anymore.
Non-existent SCSI devices can no longer be selected
2014-07-28 01:09:16 -04:00
Peter Rutenbar
ea23ef3ac6 Update README.md 2014-07-03 22:10:32 -04:00
Peter Rutenbar
df614785c9 Update README.md 2014-07-03 22:09:05 -04:00
Peter Rutenbar
4ac0c6c4b2 Update README.md 2014-06-30 19:06:33 -04:00
43 changed files with 15333 additions and 2105 deletions

2
.gitignore vendored
View File

@ -4,3 +4,5 @@
*.xcworkspace
xcuserdata
/gui/build
/debugger/debugger
/debugger/debugger.dSYM

View File

@ -4,36 +4,43 @@ A Macintosh II emulator that runs A/UX (and A/UX only).
Shoebill is an all-new, BSD-licensed Macintosh II emulator designed from the ground up with the singular goal of running A/UX.
Shoebill requires OS X, a Macintosh II, IIx or IIcx ROM, and a disk image with A/UX installed.
Shoebill requires a Macintosh II, IIx or IIcx ROM, and a disk image with A/UX installed.
[Download the latest release], and then see the [getting started] wiki.
Also check out [screenshots].
__Update (May 24, 2014): [Shoebill 0.0.3 is available]__
__Update (March 29, 2023): About issues/pull requests__
####Supports
* A/UX 1.1.1 through 3.0.0 (but not 3.0.1 or higher, yet)
__I just wanted to say that I appreciate some folks are still using Shoebill and submitting issues and pull requests. I wish I could continue working on this project, but there's a likely conflict of interest, and so I've mostly avoided pushing changes. I apologize for being unable to address the many, many bugs in this repo. (Also for anyone unaware, [Qemu is now able] now to run A/UX 3.x on its emulated Quadra 800.)__
####Currently Implements
__Update (Sept 13, 2015): [Shoebill 0.0.5 is available]__
__This will probably be the last release. I won't be able to work on Shoebill going forward (by contractual obligation), so I wanted to race out one last release. Only an OS X binary is available, sorry, and it's very unpolished. But the SDL GUI should still build on linux/windows.__
#### Supports
* A/UX 1.1.1 through 3.1 (and 3.1.1 a little)
#### Currently Implements
* 68020 CPU (mostly)
* 68881 FPU (a little)
* 68881 FPU (mostly)
* 68851 PMMU (just enough to boot A/UX)
* SCSI
* ADB
* A NuBus video card with 8-bit resolution
* PRAM (as of v0.0.3)
* PRAM
* Ethernet (via emulated Apple EtherTalk/DP8390 card)
* A NuBus video card with 24-bit depth.
#### Does not implement (yet)
* Sound
* Floppy
* Serial ports
* Ethernet
* VIA timers
* Support for multiple screens, or 16/24-bit resolutions
[Download the latest release]:https://github.com/pruten/Shoebill/releases
[getting started]:https://github.com/pruten/Shoebill/wiki/Getting-Started
[screenshots]:https://github.com/pruten/Shoebill/wiki/Screenshots
[Shoebill 0.0.3 is available]:https://github.com/pruten/Shoebill/releases
[Shoebill 0.0.5 is available]:https://github.com/pruten/Shoebill/releases
[The thread on emaculation.com]:http://www.emaculation.com/forum/viewtopic.php?f=7&t=8288
[Qemu is now able]:https://virtuallyfun.com/2021/09/02/qemus-macintosh-quadra-in-alpha-usability-runs-a-ux/

View File

@ -6,8 +6,8 @@ CFLAGS = -O3 -ggdb -flto -Wno-deprecated-declarations
DEPS = mc68851.h shoebill.h Makefile macro.pl
NEED_DECODER = cpu dis
NEED_PREPROCESSING = adb fpu mc68851 mem via floppy core_api
NEED_NOTHING = atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer sound ethernet
NEED_PREPROCESSING = adb mc68851 mem via floppy core_api fpu
NEED_NOTHING = atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer sound ethernet SoftFloat/softfloat
# Object files that can be compiled directly from the source
OBJ_NEED_NOTHING = $(patsubst %,$(TEMP)/%.o,$(NEED_NOTHING))
@ -78,6 +78,7 @@ $(TEMP)/decoder_gen: decoder_gen.c $(DEPS)
$(TEMP):
mkdir -p $(TEMP)
mkdir -p $(TEMP)/SoftFloat
clean:
rm -rf $(TEMP)

68
core/SoftFloat/386-GCC.h Normal file
View File

@ -0,0 +1,68 @@
/*----------------------------------------------------------------------------
| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
*----------------------------------------------------------------------------*/
#define LITTLEENDIAN
/*----------------------------------------------------------------------------
| 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 char flag;
typedef unsigned char uint8;
typedef signed char int8;
typedef int uint16;
typedef int int16;
typedef unsigned int uint32;
typedef signed int int32;
#ifdef BITS64
typedef unsigned long long int uint64;
typedef signed long long int int64;
#endif
/*----------------------------------------------------------------------------
| 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 unsigned char bits8;
typedef signed char sbits8;
typedef unsigned short int bits16;
typedef signed short int sbits16;
typedef unsigned int bits32;
typedef signed int sbits32;
#ifdef BITS64
typedef unsigned long long int bits64;
typedef signed long long int sbits64;
#endif
#ifdef BITS64
/*----------------------------------------------------------------------------
| 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##LL
#endif
/*----------------------------------------------------------------------------
| 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'.
*----------------------------------------------------------------------------*/
#define INLINE static

View File

@ -0,0 +1,728 @@
/*
* SoftFloat with lots of fixes and modified for use by Shoebill.
*
* Based on SoftFloat 2b by John R. Hauser.
* Modifications by Peter Rutenbar. (pruten@gmail.com)
*/
/*============================================================================
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'.
*----------------------------------------------------------------------------*/
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'.
*----------------------------------------------------------------------------*/
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'.)
*----------------------------------------------------------------------------*/
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<<negCount ) | ( a1 != 0 );
z0 = 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'.
*----------------------------------------------------------------------------*/
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<<negCount ) | ( a1>>count );
z0 = a0>>count;
}
else {
// [shoebill] This is a bug, right? ( count < 64 ) can never be true
// z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
z1 = ( count < 128 ) ? ( 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'.
*----------------------------------------------------------------------------*/
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<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
z0 = a0>>count;
}
else {
if ( count == 64 ) {
z1 = a0 | ( a1 != 0 );
}
else if ( count < 128 ) {
z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
}
else {
z1 = ( ( a0 | a1 ) != 0 );
}
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
| by 64 _plus_ the number of bits given in `count'. The shifted result is
| at most 128 nonzero bits; these are broken into two 64-bit pieces which are
| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
| off form a third 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
| `z2Ptr'. The value of `count' can be arbitrarily large.
| (This routine makes more sense if `a0', `a1', and `a2' are considered
| to form a fixed-point value with binary point between `a1' and `a2'. 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 locations pointed to
| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
| corrupted as described above, and is returned at the location pointed to by
| `z2Ptr'.)
*----------------------------------------------------------------------------*/
INLINE void
shift128ExtraRightJamming(
bits64 a0,
bits64 a1,
bits64 a2,
int16 count,
bits64 *z0Ptr,
bits64 *z1Ptr,
bits64 *z2Ptr
)
{
bits64 z0, z1, z2;
int8 negCount = ( - count ) & 63;
if ( count == 0 ) {
z2 = a2;
z1 = a1;
z0 = a0;
}
else {
if ( count < 64 ) {
z2 = a1<<negCount;
z1 = ( a0<<negCount ) | ( a1>>count );
z0 = a0>>count;
}
else {
if ( count == 64 ) {
z2 = a1;
z1 = a0;
}
else {
a2 |= a1;
if ( count < 128 ) {
z2 = a0<<negCount;
z1 = 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'.
*----------------------------------------------------------------------------*/
INLINE void
shortShift128Left(
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
{
*z1Ptr = a1<<count;
*z0Ptr =
( count == 0 ) ? a0 : ( a0<<count ) | ( 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'.
*----------------------------------------------------------------------------*/
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<<count;
z1 = a1<<count;
z0 = a0<<count;
if ( 0 < count ) {
negCount = ( ( - count ) & 63 );
z1 |= 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'.
*----------------------------------------------------------------------------*/
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'.
*----------------------------------------------------------------------------*/
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;
int8 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'.
*----------------------------------------------------------------------------*/
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'.
*----------------------------------------------------------------------------*/
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;
int8 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'.
*----------------------------------------------------------------------------*/
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'.
*----------------------------------------------------------------------------*/
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'.
*----------------------------------------------------------------------------*/
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 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 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.
*----------------------------------------------------------------------------*/
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.
*----------------------------------------------------------------------------*/
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.
*----------------------------------------------------------------------------*/
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.
*----------------------------------------------------------------------------*/
INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
{
return ( a0 != b0 ) || ( a1 != b1 );
}

View File

@ -0,0 +1,464 @@
/*============================================================================
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.
=============================================================================*/
/*----------------------------------------------------------------------------
| 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 0xFFC00000
/*----------------------------------------------------------------------------
| 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 ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a;
returnLargerSignificand:
if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
return ( a < b ) ? a : b;
}
else {
return b;
}
}
/*----------------------------------------------------------------------------
| The pattern for a default generated double-precision NaN.
*----------------------------------------------------------------------------*/
#define float64_default_nan LIT64( 0xFFF8000000000000 )
/*----------------------------------------------------------------------------
| 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 ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a;
returnLargerSignificand:
if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
return ( a < b ) ? a : b;
}
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( 0xC000000000000000 )
/*----------------------------------------------------------------------------
| 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.
*----------------------------------------------------------------------------*/
static 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 ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a;
returnLargerSignificand:
if ( a.low < b.low ) return b;
if ( b.low < a.low ) return a;
return ( a.high < b.high ) ? a : b;
}
else {
return b;
}
}
#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( 0xFFFF800000000000 )
#define float128_default_nan_low LIT64( 0x0000000000000000 )
/*----------------------------------------------------------------------------
| 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 ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a;
returnLargerSignificand:
if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
return ( a.high < b.high ) ? a : b;
}
else {
return b;
}
}
#endif

5400
core/SoftFloat/softfloat.c Normal file

File diff suppressed because it is too large Load Diff

259
core/SoftFloat/softfloat.h Normal file
View File

@ -0,0 +1,259 @@
/*============================================================================
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 unsigned int float32;
typedef unsigned long long float64;
#ifdef FLOATX80
typedef struct {
unsigned long long low;
unsigned short high;
} floatx80;
#endif
#ifdef FLOAT128
typedef struct {
unsigned long long low, high;
} float128;
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point underflow tininess-detection mode.
*----------------------------------------------------------------------------*/
extern signed char float_detect_tininess;
enum {
float_tininess_after_rounding = 0,
float_tininess_before_rounding = 1
};
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point rounding mode.
*----------------------------------------------------------------------------*/
extern signed char float_rounding_mode;
enum {
float_round_nearest_even = 0,
float_round_down = 1,
float_round_up = 2,
float_round_to_zero = 3
};
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point exception flags.
*----------------------------------------------------------------------------*/
extern signed char float_exception_flags;
enum {
float_flag_invalid = 1,
float_flag_divbyzero = 4,
float_flag_overflow = 8,
float_flag_underflow = 16,
float_flag_inexact = 32
};
/*----------------------------------------------------------------------------
| Routine to raise any or all of the software IEC/IEEE floating-point
| exception flags.
*----------------------------------------------------------------------------*/
void float_raise( signed char );
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float32 int32_to_float32( int );
float64 int32_to_float64( int );
#ifdef FLOATX80
floatx80 int32_to_floatx80( int );
#endif
#ifdef FLOAT128
float128 int32_to_float128( int );
#endif
float32 int64_to_float32( long long );
float64 int64_to_float64( long long );
#ifdef FLOATX80
floatx80 int64_to_floatx80( long long );
#endif
#ifdef FLOAT128
float128 int64_to_float128( long long );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int float32_to_int32( float32 );
int float32_to_int32_round_to_zero( float32 );
long long float32_to_int64( float32 );
long long 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 );
char float32_eq( float32, float32 );
char float32_le( float32, float32 );
char float32_lt( float32, float32 );
char float32_eq_signaling( float32, float32 );
char float32_le_quiet( float32, float32 );
char float32_lt_quiet( float32, float32 );
char float32_is_signaling_nan( float32 );
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
int float64_to_int32( float64 );
int float64_to_int32_round_to_zero( float64 );
long long float64_to_int64( float64 );
long long 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 );
char float64_eq( float64, float64 );
char float64_le( float64, float64 );
char float64_lt( float64, float64 );
char float64_eq_signaling( float64, float64 );
char float64_le_quiet( float64, float64 );
char float64_lt_quiet( float64, float64 );
char float64_is_signaling_nan( float64 );
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
int floatx80_to_int32( floatx80 );
int floatx80_to_int32_round_to_zero( floatx80 );
long long floatx80_to_int64( floatx80 );
long long 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
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision rounding precision. Valid
| values are 32, 64, and 80.
*----------------------------------------------------------------------------*/
extern signed char 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 );
char floatx80_eq( floatx80, floatx80 );
char floatx80_le( floatx80, floatx80 );
char floatx80_lt( floatx80, floatx80 );
char floatx80_eq_signaling( floatx80, floatx80 );
char floatx80_le_quiet( floatx80, floatx80 );
char floatx80_lt_quiet( floatx80, floatx80 );
char floatx80_is_signaling_nan( floatx80 );
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Software IEC/IEEE quadruple-precision conversion routines.
*----------------------------------------------------------------------------*/
int float128_to_int32( float128 );
int float128_to_int32_round_to_zero( float128 );
long long float128_to_int64( float128 );
long long 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 );
char float128_eq( float128, float128 );
char float128_le( float128, float128 );
char float128_lt( float128, float128 );
char float128_eq_signaling( float128, float128 );
char float128_le_quiet( float128, float128 );
char float128_lt_quiet( float128, float128 );
char float128_is_signaling_nan( float128 );
#endif

View File

@ -56,7 +56,8 @@ void shoebill_stop()
pthread_join(shoe.via_thread_pid, NULL);
pthread_mutex_destroy(&shoe.via_clock_thread_lock);
unstop_cpu_thread(); // wake up the CPU thread if it was STOPPED
// wake up the CPU thread if it was STOPPED
unstop_cpu_thread();
pthread_join(shoe.cpu_thread_pid, NULL);
pthread_mutex_destroy(&shoe.cpu_thread_lock);
@ -68,6 +69,11 @@ void shoebill_stop()
shoe.running = 0;
// Destroy all the nubus cards
for (i=0; i<15; i++)
if (shoe.slots[i].destroy_func)
shoe.slots[i].destroy_func(i);
// Close all the SCSI disk images
for (i=0; i<8; i++) {
if (shoe.scsi_devices[i].f)
@ -109,15 +115,15 @@ void *_cpu_thread (void *arg)
pthread_mutex_lock(&shoe.cpu_thread_lock);
while (1) {
if (shoe.cpu_thread_notifications) {
if sunlikely(shoe.cpu_thread_notifications) {
// If there's an interrupt pending
if (shoe.cpu_thread_notifications & 0xff) {
if slikely(shoe.cpu_thread_notifications & 0xff) {
// process_pending_interrupt() may clear SHOEBILL_STATE_STOPPED
process_pending_interrupt();
}
if (shoe.cpu_thread_notifications & SHOEBILL_STATE_RETURN) {
if sunlikely(shoe.cpu_thread_notifications & SHOEBILL_STATE_RETURN) {
pthread_mutex_unlock(&shoe.cpu_thread_lock);
return NULL;
}
@ -165,7 +171,7 @@ struct __attribute__ ((__packed__)) kernel_info {
// A series of DrvQEl (drive queue elements) follow this structure
};
/* Inside Macintosh: Files 2-85 throughtfully provides this information
/* Inside Macintosh: Files 2-85 thoughtfully provides this information
* on the secret internal flags:
*
* The File Manager also maintains four flag bytes preceding each drive queue element.
@ -548,6 +554,7 @@ uint32_t shoebill_install_video_card(shoebill_config_t *config, uint8_t slotnum,
shoe.slots[slotnum].connected = 1;
shoe.slots[slotnum].read_func = nubus_video_read_func;
shoe.slots[slotnum].write_func = nubus_video_write_func;
shoe.slots[slotnum].destroy_func = NULL;
shoe.slots[slotnum].interrupts_enabled = 1;
nubus_video_init(ctx, slotnum, width, height, scanline_width);
return 1;
@ -570,11 +577,34 @@ uint32_t shoebill_install_tfb_card(shoebill_config_t *config, uint8_t slotnum)
shoe.slots[slotnum].connected = 1;
shoe.slots[slotnum].read_func = nubus_tfb_read_func;
shoe.slots[slotnum].write_func = nubus_tfb_write_func;
shoe.slots[slotnum].destroy_func = NULL;
shoe.slots[slotnum].interrupts_enabled = 1;
nubus_tfb_init(ctx, slotnum);
return 1;
}
uint32_t shoebill_install_ethernet_card(shoebill_config_t *config, uint8_t slotnum, uint8_t ethernet_addr[6], int tap_fd)
{
shoebill_card_ethernet_t *ctx;
if (shoe.slots[slotnum].card_type != card_none) {
sprintf(config->error_msg, "This slot (%u) already has a card\n", slotnum);
return 0;
}
ctx = p_alloc(shoe.pool, sizeof(shoebill_card_ethernet_t));
shoe.slots[slotnum].ctx = ctx;
shoe.slots[slotnum].card_type = card_shoebill_ethernet;
shoe.slots[slotnum].connected = 1;
shoe.slots[slotnum].read_func = nubus_ethernet_read_func;
shoe.slots[slotnum].write_func = nubus_ethernet_write_func;
shoe.slots[slotnum].destroy_func = nubus_ethernet_destroy_func;
shoe.slots[slotnum].interrupts_enabled = 1;
nubus_ethernet_init(ctx, slotnum, ethernet_addr, tap_fd);
return 1;
}
shoebill_video_frame_info_t shoebill_get_video_frame(uint8_t slotnum,
_Bool just_params)
{
@ -621,7 +651,7 @@ uint32_t shoebill_initialize(shoebill_config_t *config)
shoe.pool = p_new_pool(NULL);
fpu_setup_jump_table();
fpu_initialize();
// Try to load the ROM
if (config->rom_path == NULL) {
@ -707,7 +737,10 @@ uint32_t shoebill_initialize(shoebill_config_t *config)
init_adb_state();
init_scsi_bus_state();
init_iwm_state();
init_asc_state();
/* Invalidate the pc cache */
invalidate_pccache();
set_sr(0x2000);
shoe.pc = pc;
@ -769,6 +802,9 @@ void shoebill_restart (void)
// clear the pmmu cache
memset(shoe.pmmu_cache, 0, sizeof(shoe.pmmu_cache));
// Invalidate the pc cache
invalidate_pccache();
// Reset all CPU registers
memset(shoe.d, 0, sizeof(shoe.d));
memset(shoe.a, 0, sizeof(shoe.a));
@ -783,6 +819,8 @@ void shoebill_restart (void)
// Reset all pmmu registers
shoe.crp = shoe.srp = shoe.drp = 0;
shoe.tc = 0;
shoe.tc_pagesize = shoe.tc_pagemask = 0;
shoe.tc_ps = shoe.tc_is = shoe.tc_is_plus_ps = shoe.tc_enable = shoe.tc_sre = 0;
shoe.pcsr = 0;
shoe.ac = 0;
memset(shoe.bad, 0, sizeof(shoe.bad));
@ -793,11 +831,7 @@ void shoebill_restart (void)
shoe.psr.word = 0;
// Reset all FPU registers
shoe.fpiar = 0;
shoe.fpcr.raw = 0;
shoe.fpsr.raw = 0;
memset(shoe.fp, 0, sizeof(shoe.fp));
fpu_reset();
// Free the old unix coff_file,
coff_free(shoe.coff);
@ -992,6 +1026,8 @@ void slog(const char *fmt, ...)
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}

1183
core/cpu.c

File diff suppressed because it is too large Load Diff

View File

@ -1493,14 +1493,8 @@ void begin_definitions()
/* --- FPU (68881) instructions --- */
{
inst_t *inst = new_inst("fpu_decode", "2", 1);
add_range(inst, "1111 001 xxx xxxxxx");
no_ea(inst);
}
/* { // all other fpu ops
inst_t *inst = new_inst("fpu_decode", "2", 1);
{ // all other fpu ops
inst_t *inst = new_inst("fpu_other", "2", 1);
add_range(inst, "1111 001 000 MMMMMM");
ea_all(inst);
}
@ -1511,9 +1505,30 @@ void begin_definitions()
ea_data_alterable(inst);
}
{ // FDBcc
inst_t *inst = new_inst("fdbcc", "2", 1);
add_range(inst, "1111 001 001 001xxx");
no_ea(inst);
}
{ // FTRAPcc
inst_t *inst = new_inst("ftrapcc", "2", 1);
add_range(inst, "1111 001 001 111 010");
add_range(inst, "1111 001 001 111 011");
add_range(inst, "1111 001 001 111 100");
no_ea(inst);
}
{ // FBcc
inst_t *inst = new_inst("fbcc", "2", 1);
add_range(inst, "1111 001 01x xxxxxx");
sub_range(inst, "1111 001 010 000000"); // fnop
no_ea(inst);
}
{ // fnop
inst_t *inst = new_inst("fnop", "2", 1);
add_range(inst, "1111 001 010 000000");
no_ea(inst);
}
@ -1529,7 +1544,7 @@ void begin_definitions()
add_range(inst, "1111 001 101 MMMMMM");
ea_control(inst);
ea_add_mode(inst, EA_011);
}*/
}
}

View File

@ -47,6 +47,12 @@ uint16_t dis_next_word (void)
return next;
}
uint32_t dis_next_long (void)
{
uint32_t next = dis_next_word();
return (next << 16) | dis_next_word();
}
//
// EA decoder routines
//
@ -269,8 +275,13 @@ char* decode_ea_rw (uint8_t mr, uint8_t sz)
} else if (sz == 2) {
sprintf(str, "0x%04x", ext);
} else {
const uint16_t ext2 = dis_next_word();
sprintf(str, "0x%04x%04x", ext, ext2);
uint32_t i;
assert((sz & 1) == 0);
sprintf(str, "0x%04x", ext);
for (i=2; i<sz; i+=2) {
const uint16_t ext2 = dis_next_word();
sprintf(str + strlen(str), "%04x", ext2);
}
}
return str;
}
@ -290,7 +301,8 @@ char* decode_ea_addr (uint8_t mr)
char *str = dis.ea_str_internal + dis.ea_last_pos_internal;
dis.ea_last_pos_internal = (dis.ea_last_pos_internal+256) % 1024;
switch (mode) {
case 0 ... 1: { // Data/address register direct mode
case 0:
case 1: { // Data/address register direct mode
sprintf(str, "???");
return str;
}
@ -299,11 +311,11 @@ char* decode_ea_addr (uint8_t mr)
return str;
}
case 3: { // address register indirect with postincrement mode
sprintf(str, "???");
sprintf(str, "(a%u)+", reg);
return str;
}
case 4: { // address register indirect with predecrement mode
sprintf(str, "???");
sprintf(str, "-(a%u)", reg);
return str;
}
case 5: { // address register indirect with displacement mode
@ -537,7 +549,18 @@ void dis_eori_to_sr() {
}
void dis_movep() {
sprintf(dis.str, "movep???");
const int16_t disp = dis_next_word();
~decompose(dis_op, 0000 ddd 1 s r 001 aaa);
if (r) { // reg -> mem
sprintf(dis.str, "movep.%c d%u,%s0x%x(a%u)", "wl"[s], d,
(disp >= 0) ? "" : "-", abs(disp), a);
}
else { // mem -> reg
sprintf(dis.str, "movep.%c %s0x%x(a%u),d%u", "wl"[s],
(disp >= 0) ? "" : "-", abs(disp), a, d);
}
}
void dis_bfextu() {
@ -754,7 +777,7 @@ void dis_long_div () {
sprintf(dest, "d%u", R);
if (Q != R)
sprintf(dest+2, ":d%u", Q);
sprintf(dis.str, "div%c%s.l %s,%s", "us"[u], s?"":"l", decode_ea_rw(M, 4), dest);
sprintf(dis.str, "div%c%s.l %s,%s", "us"[u], s?"l":"", decode_ea_rw(M, 4), dest);
}
void dis_cmpm () {
@ -1093,11 +1116,16 @@ void dis_pea() {
}
void dis_nbcd() {
sprintf(dis.str, "nbcd???");
~decompose(dis_op, 0100 1000 00 MMMMMM);
sprintf(dis.str, "nbcd %s", decode_ea_rw(M, 1));
}
void dis_sbcd() {
sprintf(dis.str, "sbcd???");
~decompose(dis_op, 1000 yyy 10000 r xxx);
if (r)
sprintf(dis.str, "sbcd d%u,d%u", x, y);
else
sprintf(dis.str, "sbcd -(a%u),-(a%u)", x, y);
}
void dis_pack() {
@ -1119,7 +1147,8 @@ void dis_divs() {
}
void dis_bkpt() {
sprintf(dis.str, "bkpt???");
~decompose(dis_op, 0100 1000 0100 1 vvv);
sprintf(dis.str, "bkpt %u", v);
}
void dis_swap() {
@ -1400,23 +1429,43 @@ void dis_move16 () {
}
void dis_rtm () {
sprintf(dis.str, "rtm???");
~decompose(dis_op, 0000 0110 1100 d rrr);
sprintf(dis.str, "rtm %c%u", "da"[d], r);
}
void dis_tas () {
sprintf(dis.str, "tas???");
~decompose(dis_op, 1000 rrr 011 MMMMMM);
sprintf(dis.str, "tas.b %s", decode_ea_rw(M, 1));
}
void dis_trapcc() {
sprintf(dis.str, "trapcc???");
~decompose(dis_op, 0101 cccc 11111 ooo);
const char *condition_names[16] = {
"t", "ra", "hi", "ls", "cc", "cs", "ne", "eq",
"vc", "vs", "pl", "mi", "ge", "lt", "gt", "le"
};
uint32_t data;
switch (o) {
case 2:
data = dis_next_word();
sprintf(dis.str, "trap%s.w 0x%04x", condition_names[c], data);
break;
case 3:
data = dis_next_long();
sprintf(dis.str, "trap%s.l 0x%08x", condition_names[c], data);
break;
case 4:
sprintf(dis.str, "trap%s", condition_names[c]);
break;
}
}
void dis_trapv() {
sprintf(dis.str, "trapv???");
sprintf(dis.str, "trapv");
}
void dis_mc68851_decode() {
~decompose(dis_op, 1111 000 a b c MMMMMM);
@ -1484,6 +1533,203 @@ void dis_mc68851_decode() {
assert(!"never get here");
}
const char *_fcc_names[32] = {
"f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or",
"un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t",
"sf", "seq", "gt", "ge", "lt", "le", "gl", "gle",
"ngle", "ngl", "nle", "nlt", "nge", "ngt", "sne", "st"
};
static void dis_fmove_to_mem(uint16_t ext)
{
const uint8_t _format_sizes[8] = {4, 4, 12, 12, 2, 8, 1, 12};
~decompose(dis_op, 1111 001 000 MMMMMM);
~decompose(ext, 011 fff sss kkkkkkk);
sprintf(dis.str, "fmove.%c", "lsxpwdbp"[f]);
if (f == 3)
sprintf(dis.str + strlen(dis.str), "{#%u}", k);
else
sprintf(dis.str + strlen(dis.str), "{d%u}", k >> 4);
sprintf(dis.str + strlen(dis.str), " fp%u,%s", s,
decode_ea_rw(M, _format_sizes[f]));
}
static void dis_fmovem_control(uint16_t ext)
{
~decompose(dis_op, 1111 001 000 MMMMMM);
~decompose(ext, 10 d CSI 0000 000000);
sprintf(dis.str, "fmovem.l ");
const uint16_t count = C + S + I;
if (count == 0)
sprintf(dis.str + strlen(dis.str), "0,");
if (C)
sprintf(dis.str + strlen(dis.str), "fpcr%s", (count > 1)?"&":",");
if (S)
sprintf(dis.str + strlen(dis.str), "fpsr%s", ((S+I) > 1)?"&":",");
if (I)
sprintf(dis.str + strlen(dis.str), "fpiar,");
sprintf(dis.str + strlen(dis.str), "%s", decode_ea_rw(M, count * 4));
}
static void dis_fmovem(uint16_t ext)
{
~decompose(dis_op, 1111 001 000 mmmrrr);
~decompose(dis_op, 1111 001 000 MMMMMM);
~decompose(ext, 11 d ps 000 LLLLLLLL); // Static register mask
~decompose(ext, 11 0 00 000 0yyy0000); // Register for dynamic mode
if (s) { // if dynamic mode
if (d) // mem -> reg
sprintf(dis.str, "fmovem.x %s,a%u", decode_ea_rw(M, 4), y);
else
sprintf(dis.str, "fmovem.x a%u,%s", y, decode_ea_rw(M, 4));
return;
}
uint32_t i, count=0;
char list[64] = "";
uint8_t oldmask = L, mask = L;
// for predecrement mode, the mask is reversed
if (m == 4) {
for (i=0; i<8; i++) {
mask <<= 1;
mask |= (oldmask & 1);
oldmask >>= 1;
count++;
}
}
for (i=0; i<8; i++) {
if (mask & 0x80)
sprintf(list + strlen(list), "fp%u.", i);
mask <<= 1;
}
if (d) // mem -> reg
sprintf(dis.str, "fmovem.x %s,%s", decode_ea_rw(M, 4), list);
else // reg -> mem
sprintf(dis.str, "fmovem.x %s,%s", list, decode_ea_rw(M, 4));
}
void dis_fscc () {
~decompose(dis_op, 1111 001 001 MMMMMM);
const uint16_t ext = dis_next_word();
~decompose(ext, 0000 0000 00 0ccccc);
sprintf(dis.str, "fs%s.b %s", _fcc_names[c], decode_ea_rw(M, 1));
}
void dis_fbcc () {
~decompose(dis_op, 1111 001 01s 0ccccc);
uint32_t new_pc = dis.orig_pc + 2;
if (s == 0) {
const int16_t tmp = dis_next_word();
new_pc += tmp;
}
else
new_pc += dis_next_long();
sprintf(dis.str, "fb%s.%c *0x%08x", _fcc_names[c], "wl"[s], new_pc);
}
void dis_fsave () {
~decompose(dis_op, 1111 001 100 MMMMMM);
sprintf(dis.str, "fsave %s", decode_ea_addr(M));
}
void dis_frestore () {
~decompose(dis_op, 1111 001 101 MMMMMM);
sprintf(dis.str, "frestore %s", decode_ea_addr(M));
}
void dis_fpu_other () {
~decompose(dis_op, 1111 001 000 MMMMMM);
const uint16_t ext = dis_next_word();
~decompose(ext, ccc xxx yyy eeeeeee);
switch (c) {
case 0: // Reg to reg
dis_fmath(dis_op, ext, dis.str);
return;
case 1: // unused
sprintf(dis.str, "f???");
return;
case 2: // Memory->reg & movec
dis_fmath(dis_op, ext, dis.str);
return;
case 3: // reg->mem
dis_fmove_to_mem(ext);
return;
case 4: // mem -> sys ctl registers
case 5: // sys ctl registers -> mem
dis_fmovem_control(ext);
return;
case 6: // movem to fp registers
case 7: // movem to memory
dis_fmovem(ext);
return;
}
}
void dis_fdbcc () {
~decompose(dis_op, 1111 001 001 001 rrr);
const uint16_t ext = dis_next_word();
~decompose(ext, 0000 0000 00 0ccccc);
const int16_t disp = dis_next_word();
// FIXME: 68kprm is helpfully unclear about which address
// to add the displacement. Based on cpDBcc, dbcc, bcc, and fbcc,
// I'm guessing it starts at the address *of* the displacement
const uint32_t newpc = dis.orig_pc + 4 + disp;
sprintf(dis.str, "fdb%s d%u,0x%08x", _fcc_names[c], r, newpc);
}
void dis_ftrapcc () {
~decompose(dis_op, 1111 001 001 111 ooo);
const uint16_t ext = dis_next_word();
~decompose(ext, 0000 0000 00 0ccccc);
uint32_t data;
switch (o) {
case 2:
data = dis_next_word();
sprintf(dis.str, "ftrap%s.w 0x%04x", _fcc_names[c], data);
break;
case 3:
data = dis_next_long();
sprintf(dis.str, "ftrap%s.l 0x%08x", _fcc_names[c], data);
break;
case 4:
sprintf(dis.str, "ftrap%s", _fcc_names[c]);
break;
default:
sprintf(dis.str, "ftrap????");
break;
}
}
void dis_fnop () {
const uint16_t ext = dis_next_word();
sprintf(dis.str, "fnop");
}
#include "dis_decoder_guts.c"
/*

View File

@ -0,0 +1,862 @@
/*
* Copyright (c) 2014, Peter Rutenbar <pruten@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "shoebill.h"
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/select.h>
#include "ethernet_rom/rom.c"
static uint32_t compute_nubus_crc(uint8_t *rom, uint32_t len)
{
uint32_t i, sum = 0;
for (i=0; i<len; i++) {
uint8_t byte = rom[i];
if (i==(len-9) || i==(len-10) || i==(len-11) || i==(len-12))
byte = 0;
sum = (sum << 1) + (sum >> 31) + byte;
}
rom[len-9] = sum & 0xff;
rom[len-10] = (sum >> 8) & 0xff;
rom[len-11] = (sum >> 16) & 0xff;
rom[len-12] = (sum >> 24) & 0xff;
return sum;
}
#define ETHPAGE() (ctx->cr >> 6)
const char *eth_r0_reg_names[16] = {
"cr", "clda0", "clda1", "bnry",
"tsr", "ncr", "fifo", "isr",
"crda0", "crda1", "reserved1", "reserved2",
"rsr", "cntr0", "cntr1", "cntr2"
};
const char *eth_1_reg_names[16] = {
"cr", "par0", "par1", "par2",
"par3", "par4", "par5", "curr",
"mar0", "mar1", "mar2", "mar3",
"mar4", "mar5", "mar6", "mar7"
};
const char *eth_w0_reg_names[16] = {
"cr", "pstart", "pstop", "bnry",
"tpsr", "tbcr0", "tbcr1", "isr",
"rsar0", "rsar1", "rbcr0", "rbcr1",
"rcr", "tcr", "dcr", "imr"
};
// command register bit masks
enum ether_cr_masks {
cr_stp = 1<<0, // stop
cr_sta = 1<<1, // start
cr_txp = 1<<2, // transmit packet
cr_rd0 = 1<<3, // remote dma command (0)
cr_rd1 = 1<<4, // remote dma command (1)
cr_rd2 = 1<<5, // remote dma command (2)
cr_ps0 = 1<<6, // page select (0)
cr_ps1 = 1<<7, // page select (1)
};
// interrupt service register bit masks
enum ether_isr_masks {
isr_prx = 1<<0, // packet received
isr_ptx = 1<<1, // packet transmitted
isr_rxe = 1<<2, // receive error
isr_txe = 1<<3, // transmit error
isr_ovw = 1<<4, // overwrite warning
isr_cnt = 1<<5, // counter overflow
isr_rdc = 1<<6, // remote dma complete
isr_rst = 1<<7, // reset status (not actually an interrupt)
};
// interrupt mask register bit masks
enum ether_imr_masks {
imr_pxre = 1<<0, // packet received interrupt enable
imr_ptxe = 1<<1, // packet transmitted interrupt enable
imr_rxee = 1<<2, // receive error interrupt enable
imr_txee = 1<<3, // transmit error interrupt enable
imr_ovwe = 1<<4, // overwrite warning interrupt enable
imr_cnte = 1<<5, // counter overflow interrupt enable
imr_rdce = 1<<6, // dma complete
};
// receive configuration register bit masks
enum ether_rcr_masks {
rcr_sep = 1<<0, // save error packets
rcr_ar = 1<<1, // accept runt packets
rcr_ab = 1<<2, // accept broadcast
rcr_am = 1<<3, // accept multicast
rcr_pro = 1<<4, // promiscuous physical
rcr_mon = 1<<5, // monitor mode
};
// transmit configuration register bit masks
enum ether_tcr_masks {
tcr_crc = 1<<0, // inhibit crc
tcr_lb0 = 1<<1, // encoded loopback control (0)
tcr_lb1 = 1<<2, // encoded loopback control (1)
tcr_atd = 1<<3, // auto transmit disable
tcr_ofst = 1<<4, // collision offset enable
};
// data configuration register bit masks
enum ether_dcr_masks {
dcr_wts = 1<<0, // word transfer select
dcr_bos = 1<<1, // byte order select
dcr_las = 1<<2, // long address select
dcr_ls = 1<<3, // loopback select
dcr_arm = 1<<4, // auto-initialize remote
dcr_ft0 = 1<<5, // fifo threshhold select (0)
dcr_ft1 = 1<<6, // fifo threshhold select (1)
};
// receive status register
enum ether_rsr_masks {
rsr_prx = 1<<0, // packet received intact
rsr_crc = 1<<1, // crc error
rsr_fae = 1<<2, // frame alignment error
rsr_fo = 1<<3, // fifo overrun
rsr_mpa = 1<<4, // missed packet
rsr_phy = 1<<5, // physical/multicast address (0->phys, 1->multi)
rsr_dis = 1<<6, // received disabled
rsr_dfr = 1<<7, // deferring
};
static void _nubus_interrupt(uint8_t slotnum)
{
shoe.via[1].rega_input &= 0x3f & ~(1 << (slotnum - 9));
via_raise_interrupt(2, IFR_CA1);
}
static void _clear_nubus_interrupt(uint8_t slotnum)
{
shoe.via[1].rega_input |= (1 << (slotnum - 9));
}
/*
* How many recv buffers (256-byte buffers) does the
* given number of bytes require?
*/
#define eth_recv_required_bufs(a) ({ \
const uint32_t sz = (a); \
(sz >> 8) + ((sz & 0xff) != 0); \
})
/*
* The number of 256-byte buffers available for writing
* in the receive buffer (between ctx->curr and ctx->bnry)
*/
#define eth_recv_free_bufs() ({ \
const uint8_t boundary = (ctx->bnry >= ctx->pstop) ? ctx->pstart : ctx->bnry; \
const uint8_t curr = (ctx->curr >= ctx->pstop) ? ctx->pstart : ctx->curr; \
const uint8_t total_bufs = ctx->pstop - ctx->pstart; \
uint8_t f; \
if (curr == boundary) \
f = 0; /* This shouldn't happen */ \
else if (curr > boundary) \
f = (ctx->pstop - curr) + (boundary- ctx->pstart) - 1; \
else \
f = boundary - curr - 1; \
f; \
})
void *_ethernet_receiver_thread(void *arg)
{
const uint8_t multicast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
shoebill_card_ethernet_t *ctx = (shoebill_card_ethernet_t*)arg;
uint8_t *buf = malloc(4096);
assert(buf);
// While nubus_ethernet_destroy() hasn't been called
while (!ctx->teardown) {
struct timeval tv;
fd_set fdset;
int ret;
uint32_t i;
FD_ZERO(&fdset);
FD_SET(ctx->tap_fd, &fdset);
tv.tv_sec = 0;
tv.tv_usec = 100000;
ret = select(ctx->tap_fd + 1, &fdset, NULL, NULL, &tv);
assert(ret != -1);
if (FD_ISSET(ctx->tap_fd, &fdset)) {
FD_CLR(ctx->tap_fd, &fdset);
/*
* Read in the next packet, leaving space for the 4 byte
* header
*/
int actual_packet_length = read(ctx->tap_fd, buf + 4, 4092);
slog("ethernet: received packet bnry=%x curr=%x pstart=%x pstop=%x cr=%x ret=%d frame=0x%02x%02x\n",
ctx->bnry, ctx->curr, ctx->pstart, ctx->pstop, ctx->cr, actual_packet_length,
buf[0x10], buf[0x11]);
/*
* If it's a bogus packet length, reject it
* (what's the actual minimum allowable packet length?)
*/
if (actual_packet_length <= 12) {
slog("ethernet: too small len\n");
continue;
}
/* I'm sure A/UX can't handle > 2kb packets */
if (actual_packet_length > 2048) {
slog("ethernet: too high len\n");
continue;
}
/* If it's neither multicast nor addressed to us, reject it */
if ((memcmp(buf + 4, ctx->ethernet_addr, 6) != 0) &&
(memcmp(buf + 4, multicast_addr, 6) != 0)) {
slog("ethernet: bad address\n");
continue;
}
/* A/UX seems to expect a minimum packet length (60 bytes??) */
if (actual_packet_length < 60)
actual_packet_length = 60;
/* The number of bytes to write + the 4 byte header */
const uint32_t received_bytes = actual_packet_length + 4;
pthread_mutex_lock(&ctx->lock);
/*
* If the card isn't initialized yet, just drop the packet
*/
if (ctx->cr & cr_stp) {
slog("ethernet: uninit\n");
pthread_mutex_unlock(&ctx->lock);
continue;
}
/*
* If the receive-register state is bogus, just drop the
* packet
*/
if ((ctx->pstop <= ctx->pstart) ||
(ctx->curr < ctx->pstart) ||
(ctx->bnry < ctx->pstart) ||
(ctx->pstop > 0x40) ||
(ctx->pstart == 0)) {
// This shouldn't happen if the card is initialized
assert(!"ethernet: receive register state is bogus");
pthread_mutex_unlock(&ctx->lock);
continue;
}
slog("ethernet: success, req=%u free=%u\n", eth_recv_required_bufs(received_bytes), eth_recv_free_bufs());
/*
* If there isn't enough buffer space to store the packet,
* block until ctx->bnry is modified.
*/
const uint8_t required_bufs = eth_recv_required_bufs(received_bytes);
while (eth_recv_free_bufs() < required_bufs) {
pthread_mutex_unlock(&ctx->lock);
if (ctx->teardown)
goto bail;
printf("ethernet: sleeping\n");
usleep(50); // FIXME: use a cond variable here
pthread_mutex_lock(&ctx->lock);
}
/* Roll around ctx->curr if necessary */
if (ctx->curr >= ctx->pstop)
ctx->curr = ctx->pstart;
const uint8_t orig_curr = ctx->curr;
/* Copy the packet to card RAM */
for (i = 0; i < required_bufs; i++) {
assert(ctx->curr != ctx->bnry); // this can't happen if we did our math right earlier
uint8_t *ptr = &ctx->ram[ctx->curr * 256];
memcpy(ptr, &buf[i * 256], 256);
ctx->curr++;
if (ctx->curr >= ctx->pstop)
ctx->curr = ctx->pstart;
}
assert(ctx->curr != ctx->bnry); // this can't happen if we did our math right earlier
/* The packet was received intact */
ctx->rsr = rsr_prx;
/* Fill in the 4 byte packet header */
ctx->ram[orig_curr * 256 + 0] = ctx->rsr;
ctx->ram[orig_curr * 256 + 1] = ctx->curr;
ctx->ram[orig_curr * 256 + 2] = received_bytes & 0xff; // low byte
ctx->ram[orig_curr * 256 + 3] = (received_bytes >> 8) & 0xff; // high byte
/* If the prx interrupt is enabled, interrupt */
if (ctx->imr & imr_pxre) {
ctx->isr |= isr_prx;
_nubus_interrupt(ctx->slotnum);
}
slog("ethernet: received packet (len=%d)\n", ret);
pthread_mutex_unlock(&ctx->lock);
}
}
bail:
free(buf);
return NULL;
}
/*
_Bool sent_arp_response = 0;
const uint8_t arp_response[60] = {
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // router's MAC address
0x22, 0x33, 0x55, 0x77, 0xbb, 0xdd, // card MAC address
0x08, 0x06, // ARP frame
0x00, 0x01, // Ethernet
0x08, 0x00, // IP
0x06, // MAC size
0x04, // IP size
0x00, 0x02, // reply
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // router's MAC address
192, 168, 2, 1, // router IP address
0x22, 0x33, 0x55, 0x77, 0xbb, 0xdd, // card MAC address
192, 168, 2, 100, // card IP address
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // padding
};
void _test_write_packet(shoebill_card_ethernet_t *ctx)
{
slog("ethernet: writing packet to curr=0x%02x\n", ctx->curr);
uint8_t *ptr = &ctx->ram[ctx->curr * 256];
// The packet was received intact
ctx->rsr = rsr_prx;
// The next packet address is the next 256 byte chunk
ctx->curr += 1;
ptr[0] = ctx->rsr;
ptr[1] = ctx->curr; // next packet ptr (8 bit)
ptr[2] = 60; // low byte of the packet size
ptr[3] = 0; // high byte of the packet size
memcpy(ptr + 4, arp_response, 60); // the packet
if (ctx->imr & imr_pxre)
ctx->isr |= isr_prx;
_nubus_interrupt(ctx->slotnum);
}
*/
void *_ethernet_sender_thread(void *arg)
{
shoebill_card_ethernet_t *ctx = (shoebill_card_ethernet_t*)arg;
slog("ethernet: ethernet_sender_thread starts...\n");
// While nubus_ethernet_destroy() hasn't been called
while (!ctx->teardown) {
struct timeval now;
struct timespec later;
int ret;
// Wait on the condition variable, with a timeout of 100ms
// slog("ethernet: locking cond mutex...\n");
pthread_mutex_lock(&ctx->sender_cond_mutex);
// slog("ethernet: locked cond mutex...\n");
gettimeofday(&now, NULL);
later.tv_sec = now.tv_sec;
later.tv_nsec = (now.tv_usec * 1000) + (1000000000 / 10);
if (later.tv_nsec >= 1000000000) {
later.tv_nsec -= 1000000000;
later.tv_sec++;
}
// slog("ethernet: waiting on cond...\n");
pthread_cond_timedwait(&ctx->sender_cond,
&ctx->sender_cond_mutex,
&later);
assert(pthread_mutex_unlock(&ctx->sender_cond_mutex) == 0);
// Only proceed if there's a packet ready to send
if (!ctx->send_ready)
continue;
slog("ethernet: sender thread wakes up...\n");
ctx->send_ready = 0;
// --- Send the packet here ---
assert(ctx->tbcr <= 2048); // sanity check the packet len
assert(ctx->tbcr >= 42);
ret = write(ctx->tap_fd, ctx->ram, ctx->tbcr);
if (ret != ctx->tbcr) {
slog("ethernet: write() returned %d, not %d errno=%d\n", ret, ctx->tbcr, errno);
}
// Lock the ethernet context (we're going to manipulate the ethernet registers)
pthread_mutex_lock(&ctx->lock);
// indicate that the packet has been sent
ctx->cr &= ~cr_txp; // clear the command register txp bit
ctx->isr |= isr_ptx; // interrupt status: packet transmitted with no errors
// the "packet transmitted" interrupt really should be enabled
if (ctx->imr & imr_ptxe) {
_nubus_interrupt(ctx->slotnum);
slog("ethernet: sender: sending interrupt to slot %u\n", ctx->slotnum);
}
assert(pthread_mutex_unlock(&ctx->lock) == 0);
}
return NULL;
}
void nubus_ethernet_init(void *_ctx, uint8_t slotnum, uint8_t ethernet_addr[6], int tap_fd)
{
shoebill_card_ethernet_t *ctx = (shoebill_card_ethernet_t*)_ctx;
memset(ctx, 0, sizeof(shoebill_card_ethernet_t));
memcpy(ctx->rom, _ethernet_rom, 4096);
memcpy(ctx->ethernet_addr, ethernet_addr, 6);
memcpy(ctx->rom, ethernet_addr, 6);
ctx->rom[6] = 0x00;
ctx->rom[7] = 0x00;
ctx->slotnum = slotnum; // so the threads know which slot this is
pthread_mutex_init(&ctx->lock, NULL);
pthread_cond_init(&ctx->sender_cond, NULL);
pthread_mutex_init(&ctx->sender_cond_mutex, NULL);
pthread_create(&ctx->sender_pid, NULL, _ethernet_sender_thread, ctx);
pthread_create(&ctx->receiver_pid, NULL, _ethernet_receiver_thread, ctx);
/*
* The first 8 bytes contain the MAC address
* and aren't part of the CRC
*/
compute_nubus_crc(&ctx->rom[8], 4096 - 8);
ctx->cr |= cr_stp; // "STP powers up high"
ctx->isr |= isr_rst; // I presume ISR's RST powers up high too
/* Platform-specific tap code */
ctx->tap_fd = tap_fd;
}
void nubus_ethernet_destroy_func(uint8_t slotnum)
{
shoebill_card_ethernet_t *ctx = (shoebill_card_ethernet_t*)shoe.slots[slotnum].ctx;
ctx->teardown = 1;
pthread_join(ctx->sender_pid, NULL);
pthread_join(ctx->receiver_pid, NULL);
pthread_mutex_destroy(&ctx->lock);
pthread_mutex_destroy(&ctx->sender_cond_mutex);
pthread_cond_destroy(&ctx->sender_cond);
}
uint32_t nubus_ethernet_read_func(const uint32_t rawaddr,
const uint32_t size,
const uint8_t slotnum)
{
shoebill_card_ethernet_t *ctx = (shoebill_card_ethernet_t*)shoe.slots[slotnum].ctx;
uint32_t result = 0;
pthread_mutex_lock(&ctx->lock);
switch ((rawaddr >> 16) & 0xf) {
case 0xd: { // ram
const uint16_t addr = rawaddr & 0x3fff;
uint8_t *ram = ctx->ram;
if (size == 1)
result = ram[addr];
else if (size == 2) {
result = ram[addr] << 8;
result |= ram[(addr+1) & 0x3fff];
}
else
assert(!"read: bogus size");
// slog("ethernet: reading from ram addr 0x%x sz=%u ", addr, size);
goto done;
}
case 0xe: { // registers
// For some reason, the register address bits are all inverted
const uint8_t reg = 15 ^ ((rawaddr >> 2) & 15);
assert(size == 1);
{
const char *name = "???";
if (ETHPAGE() == 0) name = eth_r0_reg_names[reg];
else if (ETHPAGE() == 1) name = eth_1_reg_names[reg];
slog("ethernet: reading from register %u (%s) (raw=0x%x) pc=0x%x ", reg, name, rawaddr, shoe.pc);
}
if (reg == 0) { // command register (exists in all pages)
result = ctx->cr;
goto done;
} else if (ETHPAGE() == 0) { // page 0
switch (reg) {
default:
assert(!"never get here");
goto done;
case 1: // clda0 (current local dma address 0)
goto done;
case 2: // clda1 (current local dma address 1)
goto done;
case 3: // bnry (boundary pointer)
result = ctx->bnry;
goto done;
case 4: // tsr (transmit status)
goto done;
case 5: // ncr (number of collisions)
goto done;
case 6: // fifo
goto done;
case 7: // isr (interrupt status register)
result = ctx->isr;
// test test test
// if we're reading isr_ptx for the first time,
// send a test packet (but never again)
/*if ((result & isr_ptx) && (!sent_arp_response)) {
sent_arp_response = 1;
_test_write_packet(ctx);
}*/
goto done;
case 8: // crda0 (current remote DMA address 0)
goto done;
case 9: // crda1 (current remote DMA address 1)
goto done;
case 10: // reserved 1
assert(!"read to reserved 1");
goto done;
case 11: // reserved 2
assert(!"read to reserved 2");
goto done;
case 12: // rsr (receive status register)
result = ctx->rsr;
goto done;
case 13: // cntr0 (tally counter 0 (frame alignment errors))
goto done;
case 14: // cntr1 (tally counter 1 (crc errors))
goto done;
case 15: // cntr2 (tally counter 2 (missed packet errors))
goto done;
}
} else if (ETHPAGE() == 1) { // page 1
switch (reg) {
default:
assert(!"never get here");
goto done;
case 1: // par (physical address)
case 2:
case 3:
case 4:
case 5:
case 6:
result = ctx->par[reg - 1];
goto done;
case 7: // curr (current page register)
result = ctx->curr;
goto done;
case 8: // mar (multicast address)
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
result = ctx->mar[reg - 8];
goto done;
}
} else
assert(!"read: Somebody accessed page 2 or 3!");
assert(!"never get here");
goto done;
}
case 0xf: { // rom
// Byte lanes = 0101 (respond to shorts)
// respond to (addr & 3 == 0) and (addr & 3 == 2)
// xxxx00 xxxx10
if ((rawaddr & 1) == 0)
result = ctx->rom[(rawaddr >> 1) % 4096];
slog("ethernet: reading from rom addr=%x ", rawaddr);
goto done;
}
default: // Not sure what happens when you access a different addr
assert(!"read: unknown ethernet register");
}
done:
pthread_mutex_unlock(&ctx->lock);
slog("result = 0x%x\n", result);
// slog("ethernet: reading 0x%x sz=%u from addr 0x%x\n", result, size, rawaddr);
return result;
}
void nubus_ethernet_write_func(const uint32_t rawaddr,
const uint32_t size,
const uint32_t data,
const uint8_t slotnum)
{
shoebill_card_ethernet_t *ctx = (shoebill_card_ethernet_t*)shoe.slots[slotnum].ctx;
uint32_t i;
pthread_mutex_lock(&ctx->lock);
switch ((rawaddr >> 16) & 0xf) {
case 0xd: { // ram
const uint16_t addr = rawaddr & 0x3fff;
uint8_t *ram = ctx->ram;
if (size == 1)
ram[addr] = data;
else if (size == 2) {
ram[addr] = data >> 8;
ram[(addr+1) & 0x3fff] = data & 0xff;
}
else
assert(!"write: bogus size");
// slog("ethernet: writing 0x%x sz=%u to ram addr 0x%x\n", data, size, addr);
goto done;
}
case 0xe: { // registers
// For some reason, the register address bits are all inverted
const uint8_t reg = 15 ^ ((rawaddr >> 2) & 15);
assert(size == 1);
{
const char *name = "???";
if (ETHPAGE() == 0) name = eth_w0_reg_names[reg];
else if (ETHPAGE() == 1) name = eth_1_reg_names[reg];
slog("ethernet: writing 0x%02x to register %u (%s) (rawaddr=0x%x) pc=0x%x\n", data, reg, name, rawaddr, shoe.pc);
}
if (reg == 0) { // command register (exists in all pages)
// If we're setting TXP, wake up the sender thread
if (((ctx->cr & cr_txp) == 0) &&
((data & cr_txp) != 0)) {
ctx->send_ready = 1;
assert(pthread_mutex_lock(&ctx->sender_cond_mutex) == 0);
assert(pthread_cond_signal(&ctx->sender_cond) == 0);
assert(pthread_mutex_unlock(&ctx->sender_cond_mutex) == 0);
}
// if we're setting STA, clear isr_rst
if (data & cr_sta)
ctx->isr &= ~isr_rst;
// FIXME: if we're setting STP, then we probably need to set isr_rst
ctx->cr = data;
goto done;
} else if (ETHPAGE() == 0) { // page 0
switch (reg) {
default:
assert(!"never get here");
goto done;
case 1: // pstart (page start)
ctx->pstart = data;
goto done;
case 2: // pstop (page stop)
ctx->pstop = data;
goto done;
case 3: // bnry (boundary pointer)
ctx->bnry = data;
goto done;
case 4: // tpsr (transmit page start address)
ctx->tpsr = data;
goto done;
case 5: // tbcr0 (transmit byte count 0)
ctx->tbcr = (ctx->tbcr & 0xff00) | data;
goto done;
case 6: // tbcr1 (transmit byte count 1)
ctx->tbcr = (ctx->tbcr & 0x00ff) | (data<<8);
goto done;
case 7: { // isr (interrupt status)
// writing 1's clears the bits in the ISR
uint8_t mask = data & 0x7f; // but not the RST bit
ctx->isr &= ~mask;
/*
* If there are packets yet to be processed,
* then continue to assert the isr_prx bit
*/
uint8_t inc_boundary = ctx->bnry + 1;
if (inc_boundary >= ctx->pstop)
inc_boundary = ctx->pstart;
if (ctx->curr != inc_boundary)
ctx->isr |= isr_prx;
/*
* If prx and ptx are no longer asserted,
* then we may clear the nubus interrupt.
*/
if (((ctx->isr & (isr_prx | isr_ptx)) == 0) &&
((ctx->cr & cr_stp) == 0))
_clear_nubus_interrupt(slotnum);
goto done;
}
case 8: // rsar0 (remote start address 0)
goto done;
case 9: // rsar1 (remote start address 1)
goto done;
case 10: // rbcr0 (remote byte count 0)
goto done;
case 11: // rbcr1 (remote byte count 1)
goto done;
case 12: // rcr (receive configuration)
ctx->rcr = data;
goto done;
case 13: // tcr (transmit configuration)
ctx->tcr = data;
goto done;
case 14: // dcr (data configuration)
ctx->dcr = data;
goto done;
case 15: // imr (interrupt mask)
ctx->imr = data & 0x7f;
goto done;
}
} else if (ETHPAGE() == 1) { // page 1
switch (reg) {
default:
assert(!"never get here");
goto done;
case 1: // par (physical address)
case 2:
case 3:
case 4:
case 5:
case 6:
ctx->par[reg - 1] = data;
goto done;
case 7: // curr (current page register)
ctx->curr = data;
goto done;
case 8: // mar (multicast address)
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
ctx->mar[reg - 8] = data;
goto done;
}
} else
assert(!"write: Somebody accessed page 2 or 3!");
assert(!"never get here");
goto done;
}
default:
assert(!"write: unknown ethernet register");
}
done:
pthread_mutex_unlock(&ctx->lock);
return;
}

BIN
core/ethernet_rom/rom.bin Normal file

Binary file not shown.

514
core/ethernet_rom/rom.c Normal file
View File

@ -0,0 +1,514 @@
uint8_t _ethernet_rom[4096] = {
0x77, 0x6f, 0x6f, 0x66, 0x00, 0x00, 0x00, 0x00,
0x77, 0x6f, 0x6f, 0x66, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x0c, 0x80, 0x00, 0x00, 0x64,
0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14,
0x02, 0x00, 0x00, 0x18, 0x20, 0x00, 0x00, 0x08,
0x24, 0x00, 0x00, 0x28, 0xff, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x53, 0x68, 0x6f, 0x65, 0x62, 0x69, 0x6c, 0x6c,
0x20, 0x50, 0x68, 0x6f, 0x6e, 0x79, 0x20, 0x45,
0x74, 0x68, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x00,
0x01, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x14,
0x04, 0x00, 0x00, 0x18, 0x53, 0x68, 0x6f, 0x65,
0x62, 0x69, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x52, 0x65, 0x76, 0x2d, 0x31, 0x00, 0x00, 0x00,
0x42, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x18,
0x0a, 0x00, 0x00, 0x30, 0x80, 0xff, 0xff, 0x7c,
0xff, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01, 0x4e, 0x65, 0x74, 0x77,
0x6f, 0x72, 0x6b, 0x5f, 0x45, 0x74, 0x68, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x5f, 0x53, 0x68, 0x6f,
0x65, 0x62, 0x69, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x24,
0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x5a, 0x93, 0x2b, 0xc7, 0x00, 0xa5
};

View File

@ -0,0 +1 @@
# File: shoebill_ether.make # Target: shoebill_ether # Sources: shoebill_ether_rom.a OBJECTS = shoebill_ether_rom.a.o shoebill_ether ÄÄ shoebill_ether.make {OBJECTS} Link ¶ {OBJECTS} ¶ -o shoebill_ether shoebill_ether_rom.a.o Ä shoebill_ether.make shoebill_ether_rom.a Asm shoebill_ether_rom.a

View File

@ -0,0 +1 @@
MACHINE MC68020 STRING C PRINT OFF ; What does this do? INCLUDE 'SysErr.a' INCLUDE 'SysEqu.a' INCLUDE 'ROMEqu.a' INCLUDE 'SlotEqu.a' INCLUDE 'TimeEqu.a' INCLUDE 'Traps.a' INCLUDE 'VideoEqu.a' INCLUDE 'QuickEqu.a' PRINT ON VideoDeclROM MAIN WITH VDPageInfo,SlotIntQElement ; EtherAddr is placed here, before sResourceDir and out of the range of the CRC ; check, because I guess it was too difficult to recompute the CRC when they were ; burning EPROMs back in 1986. ; So there's some ugly offset-accounting to make the rom seem (4096-8) bytes long, ; but still access this MAC address. myEtherAddr dc.l 'woof' dc.l 'woof' FormatBlockSize EQU 20 ROMSize EQU 4096 MyBoardID EQU $0008 ; Apple EtherTalk board ID ; ---- sResource directory ---- CategoryBoard EQU 1 CategoryEther EQU 128 sResourceDir OSLstEntry CategoryBoard, sResourceBoard OSLstEntry CategoryEther, sResourceEther DatLstEntry endOfList,0 ; ---- Board sResource ---- sResourceBoard OSLstEntry sRsrcType, boardType OSLstEntry sRsrcName, boardName DatLstEntry boardID, MyBoardID OSLstEntry vendorInfo, myVendorInfo ; No primary or secondary init needed (phew) DatLstEntry endOfList, 0 boardType DC.W CatBoard ; category DC.W TypBoard ; type DC.W 0 ; driver sw ? DC.W 0 ; driver hw ? STRING C boardName DC.L 'Shoebill Phony Ethernet' myVendorInfo OSLstEntry VendorId, myVendorID OSLstEntry RevLevel, myRevLevel OSLstEntry PartNum, myPartNum myVendorID DC.L 'Shoebill' myRevLevel DC.L 'Rev-1' myPartNum DC.L 'Bort' ; ---- Ethernet sResource ---- sResourceEther OSLstEntry sRsrcType, myEtherType OSLstEntry sRsrcName, myEtherName OSLstEntry MinorBaseOS, myMinorBaseOS dc.w $80ff ; 80 -> MAC address, $FFFFxx relative address of the MAC address dc.w -*+2 DatLstEntry endOfList, 0 myEtherType dc.w CatNetwork dc.w TypEtherNet dc.w 0 ; drvrSw, doesn't matter dc.w 1 ; drvrHw, this is DrHw3Com on Apple EtherTalk myEtherName dc.l 'Network_Ethernet_Shoebill' myMinorBaseOS DC.L $D0000 STRING C ; ---- Format block ---- ; Pad to align this structure with the end of the rom ORG ROMSize-FormatBlockSize ; Offset to sResource directory ;OSLstEntry 0,sResourceDir DC.L (sResourceDir-*)**$00FFFFFF DC.L ROMSize-8 DC.L 0 ; CRC goes here DC.B 1 ; Rom revision level DC.B AppleFormat DC.L TestPattern DC.B 0 ; Reserved DC.B $A5 ; Byte lanes 1010 0101 (LSB from CPU's perspective) ENDP END

View File

@ -172,7 +172,7 @@ void throw_address_error()
shoe.abort = 1;
}
static void throw_frame_zero(uint16_t sr, uint32_t pc, uint16_t vector_num)
void throw_frame_zero(uint16_t sr, uint32_t pc, uint16_t vector_num)
{
// set supervisor bit
set_sr_s(1);

4304
core/fpu.c

File diff suppressed because it is too large Load Diff

View File

@ -83,6 +83,9 @@ void inst_mc68851_pflushr(uint16_t ext){
// Just nuke the entire cache
memset(shoe.pmmu_cache[0].valid_map, 0, PMMU_CACHE_SIZE/8);
memset(shoe.pmmu_cache[1].valid_map, 0, PMMU_CACHE_SIZE/8);
/* Invalidate the pc cache */
invalidate_pccache();
}
void inst_mc68851_pflush(uint16_t ext){
@ -91,6 +94,9 @@ void inst_mc68851_pflush(uint16_t ext){
memset(shoe.pmmu_cache[0].valid_map, 0, PMMU_CACHE_SIZE/8);
memset(shoe.pmmu_cache[1].valid_map, 0, PMMU_CACHE_SIZE/8);
// slog("%s: Error, not implemented!\n", __func__);
/* Invalidate the pc cache */
invalidate_pccache();
}
void inst_mc68851_pmove(uint16_t ext){
@ -100,6 +106,12 @@ void inst_mc68851_pmove(uint16_t ext){
~decompose(shoe.op, 1111 000 000 MMMMMM);
~decompose(ext, fff ppp w 0000 nnn 00);
/*
* For simplicity, just blow away pccache whenever
* the PMMU state changes at all
*/
if (!w)
invalidate_pccache();
// instruction format #1
@ -119,7 +131,16 @@ void inst_mc68851_pmove(uint16_t ext){
switch (p) {
case 0: // tc
if (!w) shoe.tc = shoe.dat & 0x83FFFFFF;
if (!w) {
shoe.tc = shoe.dat & 0x83FFFFFF;
shoe.tc_is = (shoe.tc >> 16) & 0xf;
shoe.tc_ps = (shoe.tc >> 20) & 0xf;
shoe.tc_pagesize = 1 << shoe.tc_ps;
shoe.tc_pagemask = shoe.tc_pagesize - 1;
shoe.tc_is_plus_ps = shoe.tc_is + shoe.tc_ps;
shoe.tc_enable = (shoe.tc >> 31) & 1;
shoe.tc_sre = (shoe.tc >> 25) & 1;
}
else {
shoe.dat = shoe.tc;
//if (!tc_fcl()) assert(!"pmove->tc: function codes not supported\n");
@ -193,7 +214,7 @@ static int64_t ptest_search(const uint32_t _logical_addr, const uint64_t rootp)
uint8_t i;
uint64_t desc = rootp; // Initial descriptor is the root pointer descriptor
uint8_t desc_size = 1; // And the root pointer descriptor is always 8 bytes (1==8 bytes, 0==4 bytes)
uint8_t used_bits = tc_is(); // Keep track of how many bits will be the effective "page size"
uint8_t used_bits = shoe.tc_is; // Keep track of how many bits will be the effective "page size"
// (If the table search terminates early (before used_bits == ts_ps()),
// then this will be the effective page size. That is, the number of bits
// we or into the physical addr from the virtual addr)
@ -315,7 +336,7 @@ void inst_mc68851_ptest(uint16_t ext){
~decompose(shoe.op, 1111 0000 00 MMMMMM);
~decompose(ext, 100 LLL R AAAA FFFFF); // Erata in 68kPRM - F is 6 bits, and A is 3
assert(tc_enable()); // XXX: Throws some exception if tc_enable isn't set
assert(shoe.tc_enable); // XXX: Throws some exception if tc_enable isn't set
assert(tc_fcl() == 0); // XXX: I can't handle function code lookups, and I don't want to
assert(L == 7); // XXX: Not currently handling searching to a particular level

View File

@ -34,17 +34,13 @@
void _physical_get_ram (void)
{
uint64_t *addr;
if (shoe.physical_addr < shoe.physical_mem_size)
if slikely(shoe.physical_addr < shoe.physical_mem_size)
addr = (uint64_t*)&shoe.physical_mem_base[shoe.physical_addr];
else
addr = (uint64_t*)&shoe.physical_mem_base[shoe.physical_addr % shoe.physical_mem_size];
const uint8_t bits = (8 - shoe.physical_size) * 8;
shoe.physical_dat = ntohll(*addr) >> bits;
if ((shoe.physical_addr >= 256) && (shoe.physical_addr < 0x4000)) {
slog("LOMEM get: *0x%08x = 0x%x\n", shoe.physical_addr, (uint32_t)shoe.physical_dat);
}
}
void _physical_get_rom (void)
@ -81,7 +77,7 @@ void _physical_get_io (void)
return ;
case 0x50014000 ... 0x50015fff: // Sound
// slog("physical_get: got read to sound\n");
shoe.physical_dat = sound_dma_read_raw(shoe.physical_addr - 0x50014000, shoe.physical_size);
shoe.physical_dat = sound_dma_read_raw(shoe.physical_addr & 0x1fff, shoe.physical_size);
// slog("soundsound read : register 0x%04x sz=%u\n",
//shoe.physical_addr - 0x50014000, shoe.physical_size);
// shoe.physical_dat = 0;
@ -99,7 +95,7 @@ void _physical_get_io (void)
void _physical_get_super_slot (void)
{
const uint32_t slot = shoe.physical_addr >> 28;
if (shoe.slots[slot].connected)
if slikely(shoe.slots[slot].connected)
shoe.physical_dat = shoe.slots[slot].read_func(shoe.physical_addr,
shoe.physical_size,
slot);
@ -111,7 +107,7 @@ void _physical_get_super_slot (void)
void _physical_get_standard_slot (void)
{
const uint32_t slot = (shoe.physical_addr >> 24) & 0xf;
if (shoe.slots[slot].connected)
if slikely(shoe.slots[slot].connected)
shoe.physical_dat = shoe.slots[slot].read_func(shoe.physical_addr,
shoe.physical_size,
slot);
@ -209,7 +205,7 @@ void _physical_set_io (void)
scsi_dma_write(shoe.physical_dat);
return ;
case 0x50014000 ... 0x50015fff: // Sound
sound_dma_write_raw(shoe.physical_addr - 0x50014000, shoe.physical_size, shoe.physical_dat);
sound_dma_write_raw(shoe.physical_addr & 0x1fff, shoe.physical_size, shoe.physical_dat);
// slog("soundsound write: register 0x%04x sz=%u dat=0x%x\n",
// shoe.physical_addr - 0x50014000, shoe.physical_size, (uint32_t)shoe.physical_dat);
// slog("physical_set: got write to sound\n");
@ -293,33 +289,52 @@ const physical_set_ptr physical_set_jump_table[16] = {
}
static _Bool check_pmmu_cache(void)
static _Bool check_pmmu_cache_write(void)
{
const _Bool use_srp = (tc_sre() && (shoe.logical_fc >= 4));
const _Bool use_srp = (shoe.tc_sre && (shoe.logical_fc >= 5));
// logical addr [is]xxxxxxxxxxxx[ps] -> value xxxxxxxxxxxx
const uint32_t value = (shoe.logical_addr << tc_is()) >> (tc_is() + tc_ps());
const uint32_t value = (shoe.logical_addr << shoe.tc_is) >> shoe.tc_is_plus_ps;
// value xxx[xxxxxxxxx] -> key xxxxxxxxx
const uint32_t key = value & (PMMU_CACHE_SIZE-1); // low PMMU_CACHE_KEY_BITS bits
const uint32_t key = value & (PMMU_CACHE_SIZE - 1); // low PMMU_CACHE_KEY_BITS bits
const pmmu_cache_entry_t entry = shoe.pmmu_cache[use_srp].entry[key];
const _Bool is_set = (shoe.pmmu_cache[use_srp].valid_map[key/8] >> (key & 7)) & 1;
const _Bool values_match = (entry.logical_value == value);
const _Bool first_modify = !(shoe.logical_is_write && !entry.modified);
const _Bool not_write_protected = !(shoe.logical_is_write && entry.wp);
const _Bool is_set = (shoe.pmmu_cache[use_srp].valid_map[key >> 3] >> (key & 7)) & 1;
const uint32_t ps_mask = 0xffffffff >> entry.used_bits;
const uint32_t v_mask = ~~ps_mask;
shoe.physical_addr = ((entry.physical_addr<<8) & v_mask) | (shoe.logical_addr & ps_mask);
return is_set && values_match && first_modify && not_write_protected;
return is_set && (entry.logical_value == value) && entry.modified && !entry.wp;
}
static _Bool check_pmmu_cache_read(void)
{
const _Bool use_srp = (shoe.tc_sre && (shoe.logical_fc >= 5));
// logical addr [is]xxxxxxxxxxxx[ps] -> value xxxxxxxxxxxx
const uint32_t value = (shoe.logical_addr << shoe.tc_is) >> shoe.tc_is_plus_ps;
// value xxx[xxxxxxxxx] -> key xxxxxxxxx
const uint32_t key = value & (PMMU_CACHE_SIZE - 1); // low PMMU_CACHE_KEY_BITS bits
const pmmu_cache_entry_t entry = shoe.pmmu_cache[use_srp].entry[key];
const _Bool is_set = (shoe.pmmu_cache[use_srp].valid_map[key >> 3] >> (key & 7)) & 1;
const uint32_t ps_mask = 0xffffffff >> entry.used_bits;
const uint32_t v_mask = ~~ps_mask;
shoe.physical_addr = ((entry.physical_addr<<8) & v_mask) | (shoe.logical_addr & ps_mask);
return is_set && (entry.logical_value == value);
}
static void translate_logical_addr()
{
const uint8_t use_srp = (tc_sre() && (shoe.logical_fc >= 4));
const uint8_t use_srp = (shoe.tc_sre && (shoe.logical_fc >= 5));
assert((0x66 >> shoe.logical_fc) & 1); // we only support these FCs for now
uint64_t *rootp_ptr = (use_srp ? (&shoe.srp) : (&shoe.crp));
const uint64_t rootp = *rootp_ptr;
uint8_t desc_did_change = 0;
@ -329,7 +344,7 @@ static void translate_logical_addr()
uint8_t i;
uint64_t desc = rootp; // Initial descriptor is the root pointer descriptor
uint8_t desc_size = 1; // And the root pointer descriptor is always 8 bytes (1==8 bytes, 0==4 bytes)
uint8_t used_bits = tc_is(); // Keep track of how many bits will be the effective "page size"
uint8_t used_bits = shoe.tc_is; // Keep track of how many bits will be the effective "page size"
// (If the table search terminates early (before used_bits == ts_ps()),
// then (32 - used_bits) will be the effective page size. That is, the number of bits
// we or into the physical addr from the virtual addr)
@ -342,7 +357,7 @@ static void translate_logical_addr()
// TODO: Check limit here
// If root descriptor is invalid, throw a bus error
if (rp_dt(rootp) == 0) {
if sunlikely(rp_dt(rootp) == 0) {
throw_bus_error(shoe.logical_addr, shoe.logical_is_write);
return ;
}
@ -377,7 +392,7 @@ static void translate_logical_addr()
const uint8_t dt = desc_dt(desc, desc_size);
// If this descriptor is invalid, throw a bus error
if (dt == 0) {
if sunlikely(dt == 0) {
throw_bus_error(shoe.logical_addr, shoe.logical_is_write);
return ;
}
@ -395,7 +410,7 @@ static void translate_logical_addr()
get_desc(desc & 0xfffffff0, (4 << desc_size));
// I think it's possible for an indirect descriptor to point to an invalid descriptor...
if (desc_dt(desc, desc_size) == 0) {
if sunlikely(desc_dt(desc, desc_size) == 0) {
throw_bus_error(shoe.logical_addr, shoe.logical_is_write);
return ;
}
@ -426,7 +441,7 @@ search_done:
wp |= desc_wp(desc, desc_size); // or in the wp flag for this page descriptor
// And finally throw a bus error
if (wp && shoe.logical_is_write) {
if sunlikely(wp && shoe.logical_is_write) {
throw_bus_error(shoe.logical_addr, shoe.logical_is_write);
return ;
}
@ -447,7 +462,7 @@ search_done:
/* --- insert this translation into pmmu_cache --- */
// logical addr [is]xxxxxxxxxxxx[ps] -> value xxxxxxxxxxxx
const uint32_t value = (shoe.logical_addr << tc_is()) >> (tc_is() + tc_ps());
const uint32_t value = (shoe.logical_addr << shoe.tc_is) >> shoe.tc_is_plus_ps;
// value xxx[xxxxxxxxx] -> key xxxxxxxxx
const uint32_t key = value & (PMMU_CACHE_SIZE-1); // low PMMU_CACHE_KEY_BITS bits
@ -467,11 +482,11 @@ void logical_get (void)
{
// If address translation isn't enabled, this is a physical address
if (!tc_enable()) {
if sunlikely(!shoe.tc_enable) {
shoe.physical_addr = shoe.logical_addr;
shoe.physical_size = shoe.logical_size;
physical_get();
if (shoe.abort) {
if sunlikely(shoe.abort) {
shoe.abort = 0;
throw_long_bus_error(shoe.logical_addr, 0);
return ;
@ -483,29 +498,26 @@ void logical_get (void)
const uint32_t logical_size = shoe.logical_size;
const uint32_t logical_addr = shoe.logical_addr;
const uint16_t ps = tc_ps(); // log2 of the page size
const uint32_t pagesize = 1 << ps; // the page size
const uint32_t pagemask = pagesize-1; // a mask of the page bits
const uint32_t pagemask = shoe.tc_pagemask;
const uint32_t pageoffset = logical_addr & pagemask;
shoe.logical_is_write = 0;
// Common case: the read is contained entirely within a page
if (!((pageoffset + logical_size - 1) >> ps)) {
if (!check_pmmu_cache()) {
if slikely(!((pageoffset + logical_size - 1) >> shoe.tc_ps)) {
if sunlikely(!check_pmmu_cache_read()) {
shoe.logical_is_write = 0;
translate_logical_addr();
if (shoe.abort)
if sunlikely(shoe.abort)
return ;
}
if (shoe.physical_addr < shoe.physical_mem_size) {
if slikely(shoe.physical_addr < shoe.physical_mem_size) {
// Fast path
shoe.logical_dat = ntohll(*(uint64_t*)&shoe.physical_mem_base[shoe.physical_addr]) >> ((8-logical_size)*8);
}
else {
shoe.physical_size = logical_size;
physical_get();
if (shoe.abort) {
if sunlikely(shoe.abort) {
shoe.abort = 0;
throw_long_bus_error(logical_addr, 0);
return ;
@ -519,11 +531,13 @@ void logical_get (void)
const uint32_t size_a = logical_size - size_b;
const uint32_t addr_b = addr_a + size_a;
shoe.logical_is_write = 0;
shoe.logical_addr = addr_a;
shoe.logical_size = size_a;
if (!check_pmmu_cache()) {
if sunlikely(!check_pmmu_cache_read()) {
translate_logical_addr();
if (shoe.abort)
if sunlikely(shoe.abort)
return ;
}
@ -531,16 +545,16 @@ void logical_get (void)
shoe.logical_addr = addr_b;
shoe.logical_size = size_b;
if (!check_pmmu_cache()) {
if sunlikely(!check_pmmu_cache_read()) {
translate_logical_addr();
if (shoe.abort)
if sunlikely(shoe.abort)
return ;
}
const uint32_t p_addr_b = shoe.physical_addr;
shoe.physical_size = size_b;
physical_get();
if (shoe.abort) {
if sunlikely(shoe.abort) {
shoe.abort = 0;
throw_long_bus_error(shoe.logical_addr, 0);
return ;
@ -550,7 +564,7 @@ void logical_get (void)
shoe.physical_addr = p_addr_a;
shoe.physical_size = size_a;
physical_get();
if (shoe.abort) {
if sunlikely(shoe.abort) {
shoe.abort = 0;
throw_long_bus_error(shoe.logical_addr, 0);
return ;
@ -563,7 +577,7 @@ void logical_get (void)
void logical_set (void)
{
// If address translation isn't enabled, this is a physical address
if (!tc_enable()) {
if sunlikely(!shoe.tc_enable) {
shoe.physical_addr = shoe.logical_addr;
shoe.physical_size = shoe.logical_size;
shoe.physical_dat = shoe.logical_dat;
@ -574,20 +588,18 @@ void logical_set (void)
const uint32_t logical_size = shoe.logical_size;
const uint32_t logical_addr = shoe.logical_addr;
const uint16_t ps = tc_ps(); // log2 of the page size
const uint32_t pagesize = 1 << ps; // the page size
const uint32_t pagemask = pagesize-1; // a mask of the page bits
const uint32_t pagemask = shoe.tc_pagemask;
const uint32_t pageoffset = logical_addr & pagemask;
// Make the translate function fail if the page is write-protected
shoe.logical_is_write = 1;
// Common case: this write is contained entirely in one page
if (!((pageoffset + logical_size - 1) >> ps)) {
if slikely(!((pageoffset + logical_size - 1) >> shoe.tc_ps)) {
// Common case: the write is contained entirely within a page
if (!check_pmmu_cache()) {
if sunlikely(!check_pmmu_cache_write()) {
translate_logical_addr();
if (shoe.abort)
if sunlikely(shoe.abort)
return ;
}
@ -605,18 +617,18 @@ void logical_set (void)
shoe.logical_addr = addr_a;
shoe.logical_size = size_a;
if (!check_pmmu_cache()) {
if sunlikely(!check_pmmu_cache_write()) {
translate_logical_addr();
if (shoe.abort)
if sunlikely(shoe.abort)
return ;
}
const uint32_t p_addr_a = shoe.physical_addr;
shoe.logical_addr = addr_b;
shoe.logical_size = size_b;
if (!check_pmmu_cache()) {
if sunlikely(!check_pmmu_cache_write()) {
translate_logical_addr();
if (shoe.abort)
if sunlikely(shoe.abort)
return ;
}
const uint32_t p_addr_b = shoe.physical_addr;
@ -635,12 +647,163 @@ void logical_set (void)
}
}
/* --- PC cache routines --- */
#pragma mark PC cache routines
static uint16_t pccache_miss(const uint32_t pc)
{
const uint32_t pagemask = shoe.tc_pagemask;
const uint32_t pageoffset = pc & pagemask;
uint32_t paddr;
/*
* I think the instruction decoder uses these
* these function codes:
* 6 -> supervisor program space,
* 2 -> user program space
*/
shoe.logical_fc = sr_s() ? 6 : 2;
shoe.logical_addr = pc;
if sunlikely(!check_pmmu_cache_read()) {
shoe.logical_is_write = 0;
translate_logical_addr();
if sunlikely(shoe.abort)
goto fail;
}
paddr = shoe.physical_addr ^ pageoffset;
shoe.pccache_use_srp = shoe.tc_sre && sr_s();
shoe.pccache_logical_page = pc ^ pageoffset;
if (paddr < 0x40000000) {
/* Address in RAM */
if sunlikely(paddr >= shoe.physical_mem_size)
paddr %= shoe.physical_mem_size;
shoe.pccache_ptr = &shoe.physical_mem_base[paddr];
return ntohs(*(uint16_t*)(shoe.pccache_ptr + pageoffset));
}
else if (paddr < 0x50000000) {
/* Address in ROM */
shoe.pccache_ptr = &shoe.physical_rom_base[paddr & (shoe.physical_rom_size - 1)];
return ntohs(*(uint16_t*)(shoe.pccache_ptr + pageoffset));
}
/*
* For now, only supporting reads from RAM and ROM.
* This could easily be supported by just calling
* physical_get() and leaving the cache invalid,
* but I don't think A/UX ever tries to execute outside
* RAM/ROM.
*/
assert(!"pccache_miss: neither RAM nor ROM!\n");
fail:
invalidate_pccache();
return 0;
}
uint16_t pccache_nextword(const uint32_t pc)
{
if (sunlikely(pc & 1))
goto odd_addr;
if slikely(shoe.tc_enable) {
const uint32_t pc_offset = pc & shoe.tc_pagemask;
const uint32_t pc_page = pc ^ pc_offset;
const uint32_t use_srp = shoe.tc_sre && sr_s();
/* If the cache exists and is valid */
if slikely((shoe.pccache_use_srp == use_srp) && (shoe.pccache_logical_page == pc_page)) {
// printf("pccache_nextword: hit: pc=%x\n", pc);
return ntohs(*(uint16_t*)(shoe.pccache_ptr + pc_offset));
}
// printf("pccache_nextword: miss: pc=%x\n", pc);
return pccache_miss(pc);
}
else {
uint32_t paddr = pc;
if (paddr < 0x40000000) {
/* Address in RAM */
if sunlikely(paddr >= shoe.physical_mem_size)
paddr %= shoe.physical_mem_size;
return ntohs(*(uint16_t*)(&shoe.physical_mem_base[paddr]));
}
else if (paddr < 0x50000000) {
/* Address in ROM */
return ntohs(*(uint16_t*)&shoe.physical_rom_base[paddr & (shoe.physical_rom_size - 1)]);
}
assert(!"!tc_enable: neither RAM nor RAM\n");
}
odd_addr:
assert(!"odd pc address!\n");
return 0;
}
uint32_t pccache_nextlong(const uint32_t pc)
{
if slikely(shoe.tc_enable) {
const uint32_t lastpage = shoe.pccache_logical_page;
const uint32_t pc_offset = pc & shoe.tc_pagemask;
const uint32_t pc_page = pc ^ pc_offset;
const uint32_t use_srp = shoe.tc_sre && sr_s();
/* If the cache exists, is valid, and the read is contained entirely within 1 page */
if slikely((shoe.pccache_use_srp == use_srp) && (lastpage == pc_page) && !((pc_offset + 3) >> shoe.tc_ps)) {
const uint32_t result = ntohl(*(uint32_t*)(shoe.pccache_ptr + pc_offset));
if (sunlikely(pc_offset & 1))
goto odd_addr;
return result;
}
const uint32_t result_high = pccache_nextword(pc) << 16;
if sunlikely(shoe.abort)
return 0;
return result_high | pccache_nextword(pc + 2);
}
else {
uint32_t paddr = pc;
if sunlikely(paddr & 1)
goto odd_addr;
if (paddr < 0x40000000) {
/* Address in RAM */
if sunlikely(paddr >= shoe.physical_mem_size)
paddr %= shoe.physical_mem_size;
return ntohl(*(uint32_t*)(&shoe.physical_mem_base[paddr]));
}
else if (paddr < 0x50000000) {
/* Address in ROM */
return ntohl(*(uint32_t*)&shoe.physical_rom_base[paddr & (shoe.physical_rom_size - 1)]);
}
assert(!"!tc_enable: neither RAM nor RAM\n");
}
odd_addr:
assert(!"odd pc address!\n");
return 0;
}
/* --- EA routines --- */
#pragma mark EA routines
#define nextword(pc) ({const uint16_t w=lget((pc),2);if (shoe.abort){return;}(pc)+=2; w;})
#define nextlong(pc) ({const uint32_t L=lget((pc),4);if (shoe.abort){return;}(pc)+=4; L;})
#define nextword(pc) ({const uint16_t w = pccache_nextword(pc); if sunlikely(shoe.abort) return; (pc) += 2; w;})
#define nextlong(pc) ({const uint32_t L = pccache_nextlong(pc); if sunlikely(shoe.abort) return; (pc) += 4; L;})
// ea_decode_extended() - find the EA for those hiddeous 68020 addr modes
static void ea_decode_extended()
@ -760,7 +923,7 @@ static void ea_decode_extended()
case ~b(1001): case ~b(1010): case ~b(1011): {
// Indirect preindexed
const uint32_t intermediate = lget(base_addr + base_disp + index_val, 4);
if (shoe.abort) return ;
if sunlikely(shoe.abort) return ;
shoe.extended_addr = intermediate + outer_disp;
shoe.extended_len = mypc - start_pc;
// slog("addr=0x%x len=%u\n", shoe.extended_addr, shoe.extended_len);
@ -770,7 +933,7 @@ static void ea_decode_extended()
case ~b(0101): case ~b(0110): case ~b(0111): {
// Indirect postindexed
const uint32_t intermediate = lget(base_addr + base_disp, 4);
if (shoe.abort) return ;
if sunlikely(shoe.abort) return ;
shoe.extended_addr = intermediate + index_val + outer_disp;
shoe.extended_len = mypc - start_pc;
return ;
@ -847,7 +1010,7 @@ void _ea_011_write (void)
const uint8_t delta = ((reg==7) && (shoe.sz==1)) ? 2 : shoe.sz;
lset(shoe.a[reg], shoe.sz, shoe.dat);
if (!shoe.abort)
if slikely(!shoe.abort)
shoe.a[reg] += delta;
}
@ -870,7 +1033,7 @@ void _ea_100_write (void)
const uint8_t delta = ((reg==7) && (shoe.sz==1)) ? 2 : shoe.sz;
lset(shoe.a[reg] - delta, shoe.sz, shoe.dat);
if (!shoe.abort)
if slikely(!shoe.abort)
shoe.a[reg] -= delta;
}
@ -902,7 +1065,7 @@ void _ea_101_addr (void)
void _ea_110_read (void)
{
ea_decode_extended();
if (!shoe.abort)
if slikely(!shoe.abort)
shoe.dat = lget(shoe.extended_addr, shoe.sz);
shoe.uncommitted_ea_read_pc = shoe.pc + shoe.extended_len;
}
@ -913,16 +1076,16 @@ void _ea_110_read_commit (void)
void _ea_110_write (void)
{
ea_decode_extended();
if (!shoe.abort) {
if slikely(!shoe.abort) {
lset(shoe.extended_addr, shoe.sz, shoe.dat);
if (!shoe.abort)
if slikely(!shoe.abort)
shoe.pc += shoe.extended_len;
}
}
void _ea_110_addr (void)
{
ea_decode_extended();
if (!shoe.abort) {
if slikely(!shoe.abort) {
shoe.dat = shoe.extended_addr;
shoe.pc += shoe.extended_len;
}
@ -998,7 +1161,7 @@ void _ea_111_010_addr (void)
void _ea_111_011_read (void)
{
ea_decode_extended();
if (!shoe.abort)
if slikely(!shoe.abort)
shoe.dat = lget(shoe.extended_addr, shoe.sz);
shoe.uncommitted_ea_read_pc = shoe.pc + shoe.extended_len;
}
@ -1009,7 +1172,7 @@ void _ea_111_011_read_commit (void)
void _ea_111_011_addr (void)
{
ea_decode_extended();
if (!shoe.abort) {
if slikely(!shoe.abort) {
shoe.dat = shoe.extended_addr;
shoe.pc += shoe.extended_len;
}

1539
core/oldfpu.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -310,45 +310,21 @@ static void scsi_buf_set (uint8_t byte)
switch_status_phase(0); // switch to the status phase, with a status byte of 0
break;
case 0x15: // mode select (6)
slog("scsi_buf_set: responding to mode-select\n");
switch_status_phase(0);
break;
case 0x25: // read capacity (10)
slog("scsi_buf_set: responding to read-capacity\n");
// bytes [0,3] -> BE number of blocks
shoe.scsi.buf[0] = (dev->num_blocks >> 24) & 0xff;
shoe.scsi.buf[1] = (dev->num_blocks >> 16) & 0xff;
shoe.scsi.buf[2] = (dev->num_blocks >> 8) & 0xff;
shoe.scsi.buf[3] = (dev->num_blocks) & 0xff;
// bytes [4,7] -> BE block size (needs to be 512)
shoe.scsi.buf[4] = (dev->block_size >> 24) & 0xff;
shoe.scsi.buf[5] = (dev->block_size >> 16) & 0xff;
shoe.scsi.buf[6] = (dev->block_size >> 8) & 0xff;
shoe.scsi.buf[7] = (dev->block_size) & 0xff;
shoe.scsi.in_i = 0;
shoe.scsi.in_len = 8;
switch_data_in_phase();
break;
case 0x12: { // inquiry command (6)
slog("scsi_buf_set: responding to inquiry\n");
case 0x3: { // request sense (6)
const uint8_t alloc_len = shoe.scsi.buf[4];
const uint8_t control = shoe.scsi.buf[5];
const _Bool desc = shoe.scsi.buf[1] & 1;
switch_status_phase(2); // CHECK_CONDITION
scsi_handle_inquiry_command(alloc_len);
break;
}
case 0x8: { // read (6)
const uint32_t offset =
(shoe.scsi.buf[1] << 16) |
(shoe.scsi.buf[2] << 8 ) |
(shoe.scsi.buf[3]);
(shoe.scsi.buf[1] << 16) |
(shoe.scsi.buf[2] << 8 ) |
(shoe.scsi.buf[3]);
const uint16_t len = (shoe.scsi.buf[4]==0) ? 0x100 : shoe.scsi.buf[4]; // len==0 -> 256 sectors
assert(dev->f);
@ -374,12 +350,12 @@ static void scsi_buf_set (uint8_t byte)
switch_data_in_phase();
break;
}
case 0xa: { // write (6)
const uint32_t offset =
(shoe.scsi.buf[1] << 16) |
(shoe.scsi.buf[2] << 8 ) |
(shoe.scsi.buf[3]);
(shoe.scsi.buf[1] << 16) |
(shoe.scsi.buf[2] << 8 ) |
(shoe.scsi.buf[3]);
const uint16_t len = (shoe.scsi.buf[4]==0) ? 0x100 : shoe.scsi.buf[4]; // len==0 -> 256 sectors
slog("scsi_buf_set: Responding to write at off=%u len=%u\n", offset, len);
@ -394,9 +370,70 @@ static void scsi_buf_set (uint8_t byte)
switch_data_out_phase();
break;
}
case 0x12: { // inquiry command (6)
slog("scsi_buf_set: responding to inquiry\n");
const uint8_t alloc_len = shoe.scsi.buf[4];
scsi_handle_inquiry_command(alloc_len);
break;
}
case 0x15: // mode select (6)
slog("scsi_buf_set: responding to mode-select\n");
switch_status_phase(0);
break;
case 0x1a: { // mode sense (6)
const _Bool dbd = (shoe.scsi.buf[1] >> 3) & 1;
const uint8_t pc = (shoe.scsi.buf[2] >> 6) & 3;
const uint8_t page_code = shoe.scsi.buf[2] & 0x3f;
const uint8_t subpage_code = shoe.scsi.buf[3];
const uint8_t alloc_len = shoe.scsi.buf[4];
const uint8_t control = shoe.scsi.buf[6];
slog("scsi_bug_set: responding to mode-sense\n");
slog("dbd=%u pc=%u page_code=%u subpage_code=%u alloc_len=%u control=%u\n",
dbd, pc, page_code, subpage_code, alloc_len, control);
// FIXME: set sense code!
switch_status_phase(2); // CHECK_CONDITION
}
case 0x25: // read capacity (10)
slog("scsi_buf_set: responding to read-capacity\n");
// bytes [0,3] -> BE number of blocks
shoe.scsi.buf[0] = (dev->num_blocks >> 24) & 0xff;
shoe.scsi.buf[1] = (dev->num_blocks >> 16) & 0xff;
shoe.scsi.buf[2] = (dev->num_blocks >> 8) & 0xff;
shoe.scsi.buf[3] = (dev->num_blocks) & 0xff;
// bytes [4,7] -> BE block size (needs to be 512)
shoe.scsi.buf[4] = (dev->block_size >> 24) & 0xff;
shoe.scsi.buf[5] = (dev->block_size >> 16) & 0xff;
shoe.scsi.buf[6] = (dev->block_size >> 8) & 0xff;
shoe.scsi.buf[7] = (dev->block_size) & 0xff;
shoe.scsi.in_i = 0;
shoe.scsi.in_len = 8;
switch_data_in_phase();
break;
case 0x28: { // read (10)
// FIXME: set sense code!
switch_status_phase(2); // CHECK_CONDITION
break;
}
default:
assert(!"unknown commmand!");
printf("unknown scsi command (0x%02x)\n", shoe.scsi.buf[0]);
// FIXME: set sense code
switch_status_phase(2); // CHECK_CONDITION
break;
}
@ -548,8 +585,14 @@ void scsi_reg_write ()
assert(id != 8);
shoe.scsi.target_id = id;
slog("scsi_reg_write: selected target id %u\n", id);
shoe.scsi.target_bsy = 1; // target asserts BSY to acknowledge being selected
shoe.scsi.phase = SELECTION;
if (shoe.scsi_devices[shoe.scsi.target_id].f == NULL) {
shoe.scsi.phase = BUS_FREE;
}
else {
shoe.scsi.target_bsy = 1; // target asserts BSY to acknowledge being selected
shoe.scsi.phase = SELECTION;
}
break;
}

View File

@ -51,8 +51,9 @@
#include <machine/endian.h>
#include <libkern/OSByteOrder.h>
#ifndef ntohll
#define ntohll(x) OSSwapBigToHostInt64(x)
#endif
#else /* #if (defined __APPLE__) */
#if __BYTE_ORDER == __LITTLE_ENDIAN
@ -78,6 +79,9 @@
#endif
#define slikely(e) (__builtin_expect(!!(e), 1))
#define sunlikely(e) (__builtin_expect(!!(e), 0))
/*
* core_api.c stuff
*/
@ -133,6 +137,9 @@ uint32_t shoebill_install_video_card(shoebill_config_t *config, uint8_t slotnum,
uint32_t shoebill_install_tfb_card(shoebill_config_t *config, uint8_t slotnum);
/* Call this after shoebill_initialize() to add an ethernet card */
uint32_t shoebill_install_ethernet_card(shoebill_config_t *config, uint8_t slotnum, uint8_t ethernet_addr[6], int tap_fd);
/* Get a video frame from a particular video card */
shoebill_video_frame_info_t shoebill_get_video_frame(uint8_t slotnum, _Bool just_params);
@ -254,11 +261,11 @@ uint8_t* shoebill_extract_kernel(const char *disk_path, const char *kernel_path,
#define set_sr_t1(b) {shoe.sr &= (~(1<<15)); shoe.sr |= (((b)!=0)<<15);}
// MMU
#define tc_enable() (shoe.tc >> 31)
#define tc_sre() ((shoe.tc >> 25) & 1)
#define _tc_enable() (shoe.tc >> 31) // _tc_enable,sre,ps,is are all extracted in shoe.tc_*
#define _tc_sre() ((shoe.tc >> 25) & 1)
#define tc_fcl() ((shoe.tc >> 24) & 1)
#define tc_ps() ((shoe.tc >> 20) & 0xf)
#define tc_is() ((shoe.tc >> 16) & 0xf)
#define _tc_ps() ((shoe.tc >> 20) & 0xf)
#define _tc_is() ((shoe.tc >> 16) & 0xf)
#define tc_tia() ((shoe.tc >> 12) & 0xf)
#define tc_tib() ((shoe.tc >> 8) & 0xf)
#define tc_tic() ((shoe.tc >> 4) & 0xf)
@ -410,6 +417,27 @@ typedef struct {
dbg_breakpoint_t *breakpoints;
} debugger_state_t;
// Sound (Apple Sound Chip)
void sound_dma_write_raw(uint16_t addr, uint8_t sz, uint32_t data);
uint32_t sound_dma_read_raw(uint16_t addr, uint8_t sz);
void init_asc_state(void);
typedef struct {
uint8_t buf[0x800];
uint8_t version; // read-only
uint8_t asc_mode;
uint8_t channel_ctrl;
uint8_t fifo_ctrl;
uint8_t fifo_intr; // read-only
uint8_t unknown1;
uint8_t volume_ctrl;
uint8_t clock_ctrl;
uint16_t left_ptr, right_ptr;
} apple_sound_chip_registers_t;
typedef enum {
adb_talk,
adb_listen,
@ -593,19 +621,69 @@ typedef struct {
} shoebill_card_tfb_t;
typedef struct {
// Doesn't exist yet
// Card ROM (4kb)
uint8_t rom[0x1000];
// Card RAM (16kb buffer, apparently)
uint8_t ram[0x4000];
// Card MAC address
uint8_t ethernet_addr[6];
// Card slot number
uint8_t slotnum;
// -- thread state --
uint8_t recv_buf[4096], send_buf[4096];
uint16_t recv_len, send_len;
_Bool teardown, send_ready;
pthread_t sender_pid, receiver_pid;
pthread_mutex_t lock, sender_cond_mutex;
pthread_cond_t sender_cond;
// -- registers --
uint8_t cr; // command register, all pages, read/write
// Page 0 registers
uint8_t isr; // interrupt status register, read/write
uint8_t imr; // interrupt mask register, write
uint8_t dcr; // data configuration register (write)
uint8_t tcr; // transmit configuration register (write)
uint8_t rcr; // receive configuration register (write)
uint8_t pstart; // receive buffer start pointer (write)
uint8_t pstop; // receive buffer boundary (write)
uint8_t bnry; // a different kind of receive buffer boundary (read/write)
uint8_t tpsr; // transmit page start pointer (write)
uint16_t tbcr; // transmit buffer count register (write)
uint8_t rsr; // receive status register (read)
// Page 1 registers (read/write)
uint8_t mar[8]; // multicast address
uint8_t par[6]; // physical address
uint8_t curr; // current page
int tap_fd;
} shoebill_card_ethernet_t;
typedef enum {
card_none = 0, // Empty slot
card_toby_frame_buffer, // Original Macintosh II video card
card_shoebill_video, // Fancy 21st-century Shoebill video card
card_shoebill_ethernet // FIXME: doesn't exist yet
card_shoebill_ethernet // "Register-compatible" Apple EtherTalk card
} card_names_t;
typedef struct {
uint32_t (*read_func)(uint32_t, uint32_t, uint8_t);
void (*write_func)(uint32_t, uint32_t, uint32_t, uint8_t);
void (*destroy_func)(uint8_t);
uint8_t slotnum;
_Bool connected;
@ -681,6 +759,11 @@ typedef struct {
_Bool logical_is_write; // <- boolean: true iff the operation is logical_set()
uint8_t logical_fc; // logical function code
#define invalidate_pccache() do {shoe.pccache_use_srp = 2;} while (0)
uint32_t pccache_use_srp; // 1 -> use srp, 0 -> use crp, other -> pccache is invalid
uint32_t pccache_logical_page;
uint8_t *pccache_ptr;
// -- PMMU caching structures ---
#define PMMU_CACHE_KEY_BITS 10
#define PMMU_CACHE_SIZE (1<<PMMU_CACHE_KEY_BITS)
@ -716,6 +799,10 @@ typedef struct {
// 68851 registers
uint64_t crp, srp, drp; // user/supervisor/DMA root pointers
uint32_t tc; // translation control
uint32_t tc_pagesize, tc_pagemask; // page size and page mask
uint8_t tc_ps, tc_is, tc_is_plus_ps, tc_enable, tc_sre; // commonly read bits in shoe.tc
uint16_t pcsr; // PMMU cache status
uint16_t ac; // access control
uint16_t bad[8]; // breakpoint acknowledge data registers
@ -740,61 +827,11 @@ typedef struct {
} bits;
} psr;
// FPU registers
uint32_t fpiar; // FPU iaddr
// fpu_state_t pointer
// (declared here as a void*, to prevent other files
// from needing to include SoftFloat/softfloat.h)
void *fpu_state;
union { // fpcr, fpu control register
struct {
// Mode control byte
uint16_t mc_zero : 4; // zero/dummy
uint16_t mc_rnd : 2; // rounding mode
uint16_t mc_prec : 2; // rounding precision
// Exception enable byte
uint16_t ee_inex1 : 1; // inexact decimal input
uint16_t ee_inex2 : 1; // inxact operation
uint16_t ee_dz : 1; // divide by zero
uint16_t ee_unfl : 1; // underflow
uint16_t ee_ovfl : 1; // overflow
uint16_t ee_operr : 1; // operand error
uint16_t ee_snan : 1; // signalling not a number
uint16_t ee_bsun : 1; // branch/set on unordered
} b;
uint16_t raw;
} fpcr;
union { // fpsr, fpu status register
struct {
// Accrued exception byte
uint32_t dummy1 : 3; // dummy/zero
uint32_t ae_inex : 1; // inexact
uint32_t ae_dz : 1; // divide by zero
uint32_t ae_unfl : 1; // underflow
uint32_t ae_ovfl : 1; // overflow
uint32_t ae_iop : 1; // invalid operation
// Exception status byte
uint32_t es_inex1 : 1; // inexact decimal input
uint32_t es_inex2 : 1; // inxact operation
uint32_t es_dz : 1; // divide by zero
uint32_t es_unfl : 1; // underflow
uint32_t es_ovfl : 1; // overflow
uint32_t es_operr : 1; // operand error
uint32_t es_snan : 1; // signalling not a number
uint32_t es_bsun : 1; // branch/set on unordered
// Quotient byte
uint32_t qu_quotient : 7;
uint32_t qu_s : 1;
// Condition code byte
uint32_t cc_nan : 1; // not a number
uint32_t cc_i : 1; // infinity
uint32_t cc_z : 1; // zero
uint32_t cc_n : 1; // negative
uint32_t dummy2 : 4; // dummy/zero
} b;
uint32_t raw;
} fpsr;
long double fp[8]; // 80 bit floating point general registers
// -- Interrupts/VIA chips --
@ -804,6 +841,7 @@ typedef struct {
pram_state_t pram;
keyboard_state_t key;
mouse_state_t mouse;
apple_sound_chip_registers_t asc;
iwm_state_t iwm;
@ -825,9 +863,27 @@ typedef struct {
extern global_shoebill_context_t shoe; // declared in cpu.c
// fpu.c functions
void inst_fpu_decode(void);
void dis_fpu_decode(void);
void fpu_setup_jump_table();
void inst_fscc();
void inst_fbcc();
void inst_fsave();
void inst_frestore();
void inst_ftrapcc();
void inst_fdbcc();
void inst_fnop();
void inst_fpu_other();
void dis_fscc();
void dis_fbcc();
void dis_fsave();
void dis_frestore();
void dis_ftrapcc();
void dis_fdbcc();
void dis_fnop();
void dis_fpu_other();
void dis_fmath (uint16_t op, uint16_t ext, char *output);
void fpu_initialize();
void fpu_reset();
// cpu.c fuctions
void cpu_step (void);
@ -842,10 +898,14 @@ void throw_illegal_instruction();
void throw_privilege_violation();
void throw_divide_by_zero();
void throw_frame_two (uint16_t sr, uint32_t next_pc, uint32_t vector_num, uint32_t orig_pc);
void throw_frame_zero(uint16_t sr, uint32_t pc, uint16_t vector_num);
// mem.c functions
uint16_t pccache_nextword(uint32_t pc);
uint32_t pccache_nextlong(uint32_t pc);
//void physical_get (void);
typedef void (*physical_get_ptr) (void);
typedef void (*physical_set_ptr) (void);
@ -853,7 +913,12 @@ extern const physical_get_ptr physical_get_jump_table[16];
extern const physical_set_ptr physical_set_jump_table[16];
#define physical_set() physical_set_jump_table[shoe.physical_addr >> 28]()
#define pset(addr, s, val) {shoe.physical_addr=(addr); shoe.physical_size=(s); shoe.physical_dat=(val); physical_set();}
#define pset(addr, s, val) do { \
shoe.physical_addr=(addr); \
shoe.physical_size=(s); \
shoe.physical_dat=(val); \
physical_set(); \
} while (0)
#define physical_get() physical_get_jump_table[shoe.physical_addr >> 28]()
#define pget(addr, s) ({shoe.physical_addr=(addr); shoe.physical_size=(s); physical_get(); shoe.physical_dat;})
@ -866,26 +931,17 @@ void logical_get (void);
logical_get(); \
shoe.logical_dat; \
})
#define lget(addr, s) ({ \
shoe.logical_addr=(addr); \
shoe.logical_size=(s); \
shoe.logical_fc = (sr_s() ? 5 : 1); \
logical_get(); \
shoe.logical_dat; \
})
#define lget(addr, s) lget_fc((addr), (s), (sr_s() ? 5 : 1))
void logical_set (void);
#define lset_fc(addr, s, val, fc) {\
#define lset_fc(addr, s, val, fc) do { \
shoe.logical_addr=(addr); \
shoe.logical_size=(s); \
shoe.logical_dat=(val); \
shoe.logical_fc = (fc); \
logical_set();\
}
#define lset(addr, s, val) { \
lset_fc((addr), (s), (val), sr_s() ? 5 : 1) \
}
} while (0)
#define lset(addr, s, val) lset_fc((addr), (s), (val), sr_s() ? 5 : 1)
typedef void (*_ea_func) (void);
extern const _ea_func ea_read_jump_table[64];
@ -899,10 +955,10 @@ extern const _ea_func ea_addr_jump_table[64];
#define ea_addr() ea_addr_jump_table[shoe.mr]()
#define call_ea_read(M, s) {shoe.mr=(M);shoe.sz=(s);ea_read();if (shoe.abort) return;}
#define call_ea_write(M, s) {shoe.mr=(M);shoe.sz=(s);ea_write();if (shoe.abort) return;}
#define call_ea_read_commit(M, s) {shoe.mr=(M);shoe.sz=(s);ea_read_commit();if (shoe.abort) return;}
#define call_ea_addr(M) {shoe.mr=(M);ea_addr();if (shoe.abort) return;}
#define call_ea_read(M, s) {shoe.mr=(M);shoe.sz=(s);ea_read();if sunlikely(shoe.abort) return;}
#define call_ea_write(M, s) {shoe.mr=(M);shoe.sz=(s);ea_write();if sunlikely(shoe.abort) return;}
#define call_ea_read_commit(M, s) {shoe.mr=(M);shoe.sz=(s);ea_read_commit();if sunlikely(shoe.abort) return;}
#define call_ea_addr(M) {shoe.mr=(M);ea_addr();if sunlikely(shoe.abort) return;}
#define push_a7(_dat, _sz) {shoe.a[7]-=(_sz);lset(shoe.a[7], (_sz), (_dat));}
@ -1024,8 +1080,10 @@ void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size,
shoebill_video_frame_info_t nubus_video_get_frame(shoebill_card_video_t *ctx,
_Bool just_params);
// Sound (Apple Sound Chip)
void sound_dma_write_raw(uint16_t addr, uint8_t sz, uint32_t data);
uint32_t sound_dma_read_raw(uint16_t addr, uint8_t sz);
// Apple EtherTalk
void nubus_ethernet_init(void *_ctx, uint8_t slotnum, uint8_t ethernet_addr[6], int tap_fd);
uint32_t nubus_ethernet_read_func(uint32_t, uint32_t, uint8_t);
void nubus_ethernet_write_func(uint32_t, uint32_t, uint32_t, uint8_t);
void nubus_ethernet_destroy_func(uint8_t);
#endif // _SHOEBILL_H

View File

@ -1,30 +1,181 @@
/*
* Copyright (c) 2014, Peter Rutenbar <pruten@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Props to MESS for their EASC register map: http://www.mess.org/mess/driver_info/easc
* EASC's PCM mode is backwards compatible with ASC, so their registers are very similar.
*/
#include <assert.h>
#include <string.h>
#include "../core/shoebill.h"
#define r_ptr (0x400 + (asc->right_ptr & 0x3ff)) /* right buf ptr */
#define l_ptr (asc->left_ptr & 0x3ff) /* left buf ptr */
#define m_ptr (asc->left_ptr & 0x7ff) /* mono buf ptr */
void init_asc_state(void)
{
memset(&shoe.asc, 0, sizeof(shoe.asc));
shoe.asc.version = 0x00; // My Mac II's ASC reports 0x00 as its version.
// From the ROM, it looks like other Mac II ASC masks have different version numbers
}
static uint8_t sound_dma_read_byte(uint16_t addr)
{
if (addr == 0x804)
return 0xff;
apple_sound_chip_registers_t *asc = &shoe.asc;
if (addr < 0x800) {
if (asc->asc_mode == 1) {
// PCM mode (FIFO is append-only)
if (asc->channel_ctrl & 2) {
// stereo mode - return the byte referenced by the right pointer
return asc->buf[r_ptr];
}
else {
// mono mode - return the byte referenced by the left pointer
return asc->buf[m_ptr];
}
}
else {
// Off or wavetable mode (FIFO is random access)
return asc->buf[addr];
}
}
switch (addr) {
case 0x800: // Version
return asc->version;
case 0x801: // ASC-mode
return asc->asc_mode;
case 0x802: // Channel control
return asc->channel_ctrl;
case 0x803: // FIFO control
return asc->fifo_ctrl;
case 0x804: // FIFO interrupt
//return asc->fifo_intr;
return 0xff;
case 0x805: // Unknown (??)
return asc->unknown1;
case 0x806: // Volume control
return asc->volume_ctrl;
case 0x807: // Clock control
return asc->clock_ctrl;
}
return 0;
}
static void sound_dma_write_byte(uint16_t addr, uint8_t data)
{
if (addr >= 0x800) {
// registers
}
else if (addr >= 0x400) {
// Buf B
apple_sound_chip_registers_t *asc = &shoe.asc;
if (addr < 0x800) { // buf_a/b
if (asc->asc_mode == 1) {
// PCM mode (FIFO is append-only)
if (asc->channel_ctrl & 2) {
// stereo mode - each channel has its own buffer pointer
if (addr < 0x400) {
// left buffer
asc->buf[l_ptr] = data;
asc->left_ptr++;
}
else {
// right buffer
asc->buf[r_ptr] = data;
asc->right_ptr++;
}
return ;
}
else {
// Mono mode
asc->buf[m_ptr] = data;
asc->left_ptr++;
return ;
}
}
else {
// Off or wavetable mode (FIFO is random access)
asc->buf[addr] = data;
return ;
}
}
else {
// Buf A
/*FILE *f = fopen("buf_a.dmp", "ab");
if (f) {
fwrite(&data, 1, 1, f);
fclose(f);
}*/
switch (addr) {
case 0x800: // Version
// Version is read-only
break;
case 0x801: // ASC-mode
// ASC version 0x00 preserves the low 2 bits
asc->asc_mode = data & 0x03;
assert(asc->asc_mode != 3); // mode-3 produces noise, but isn't deterministic
break;
case 0x802: // Channel control
// ASC version 0x00 preserves the high bit and low 2 bits
asc->channel_ctrl = data & 0x83;
break;
case 0x803: // FIFO control
// ASC version 0x00 preserves the low 2 bits
asc->fifo_ctrl = data & 0x83;
break;
case 0x804: // FIFO interrupt
// FIFO interrupt is read-only
break;
case 0x805: // unknown (???)
// ASC version 0x00 preserves the high bit and low 4 bits
// (But what does it do?)
asc->unknown1 = data & 0x8f;
break;
case 0x806: // Volume control
// ASC version 0x00 preserves the high 6 bits
asc->volume_ctrl = data & 0xfc;
break;
case 0x807: // Clock control
// ASC version 0x00 preserves the low 2 bits
asc->clock_ctrl = data & 0x03;
break;
}
}
}
@ -48,4 +199,81 @@ uint32_t sound_dma_read_raw(uint16_t addr, uint8_t sz)
}
return result;
}
}
/*
ASC notes:
buf_a (0x000-0x3ff) -> left
buf_b (0x400-0x7ff) -> right
writing to any address in buf_a or buf_b appends to the end pointer in the ring buffer (ignoring the address)
reading from any address returns... the currently-being-read byte? Or the about-to-be-overwritten byte?
(def one or the other)
- Update: MODE=0: You can do regular random read/write access to buf_a/b when MODE=0.
MODE=1: Writing anywhere within the buffer automatically appends to the end of the ring buffer
For stereo mode, writing between 0-0x3ff appends to buf_a, 0x400-0x7ff to buf_b
Reading anywhere in the buffer is strange - it seems non-deterministic.
Update 2: no wait, it's returning the byte at buf_b's ring pointer, does it always do that?
Update 3: yes, it looks like reading anywhere returns the byte at buf_b's pointer in stereo mode,
and buf_a's pointer in mono mode
MODE=2: Same as MODE=0 (?)
- ASC maintains two distinct ring buffer pointers for stereo mode
0x800 - Version (?) MacII only ever seems to TST.B it
(READ ONLY)
$00 -> My Mac II's ASC's version
$?? -> Mac II's ROM is aware of other non-$00 ASC masks
$b0 -> EASC
0x801 - Mode (?) 0 == no output, 1 == PCM, 2 == wavetable, 3 == hissing static(??)
- Preserves low 2 bits, ignores high 6 bits
0x802 - Channel selector
Preserves mask 0x83 (high bit, low 2 bits)
- High bit is set if engine overflow (according to MESS)
- Low bits, 0x?2 -> stereo output (buf_a -> left, buf_b -> right)
0x?0 -> Mono output (from buf_a)
- Switching to stereo from mono produces a blip of sound in the right ear, unless the fifo has been cleared (buf_b), (or unless there was nothing in buf_b to start with)
0x803 - Fifo control (cycle 0x80 to reset the internal FIFO pointer (pointers?))
Preserves mask 0x83 (high bit, low 2 bits)
0x804 - Fifo interrupt status
(READ ONLY, doesnt preserve any written bits (doesnt acknowledge writes at all?))
0x805 - ???
- Preserves bits at 0x8F, (high bit, low 4 bits), doesn't seem to do anything
0x806 - Volume control (high 3 bits)
Preserves top 6 bits, ignores bottom 2 bits. (Only top 3 bits control volume)
0x807 - Clock rate select (0, 2, or 3, I think)
0x00 -> 11127hz
0x01 -> Illegal???
0x02 -> 11025hz
0x03 -> 22050hz
Writes to fifo_a/b(?) seem to block for clock rates 0, 2, and 3, but not 1. The speaker clicks like the sound chip is turning off when you set clock to 0x01.
ASC has more registers past 0x807 for wave table control
*/

View File

@ -31,6 +31,7 @@
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include "../core/shoebill.h"
char *via_reg_str[16] = {
@ -471,15 +472,21 @@ void init_via_state (uint8_t pram_data[256], shoebill_pram_callback_t callback,
* Bit 5 - input - v2TM0A (nubus transfer what??)
* Bit 4 - input - v2TM1A
* Bit 3 - output - AMU/PMMU control
* Bit 2 - output - v2PowerOff
* Bit 2 - output - v2PowerOff (but leave this in input mode)
* Bit 1 - output - v2BusLk
* Bit 0 - output - v2cdis
*/
shoe.via[1].ddrb = ~b(10001111);
shoe.via[1].ddrb = 0x00;
shoe.via[1].ddrb = ~b(10001011);
// FIXME: apparently via2/regb bit 7 is tied to VIA1, and driven by timer T1, to
// generate 60.15hz (really 60.0hz) interrupts on VIA1
// emulate this more accurately!
// The power unit is wired to bit 2, waiting for it to be set 0.
// I guess we're supposed to leave it as an input, because the shutdown
// routine first sets the bit to 0, *then* switches the direction to output.
// FIXME: verify that this is correct
/* -- Initialize PRAM -- */
pram_state_t *pram = &shoe.pram;
@ -498,6 +505,7 @@ void init_via_state (uint8_t pram_data[256], shoebill_pram_callback_t callback,
}
#define E_CLOCK 783360
#define V2POWEROFF_MASK 0x04
#define _via_get_delta_counter(last_set) ({ \
const long double delta_t = now - (last_set); \
@ -514,6 +522,12 @@ void init_via_state (uint8_t pram_data[256], shoebill_pram_callback_t callback,
#define VIA_REGB_PINS(n) ((shoe.via[(n)-1].regb_output & shoe.via[(n)-1].ddrb) | \
(shoe.via[(n)-1].regb_input & (~~shoe.via[(n)-1].ddrb)))
static void _via_poweroff(void)
{
slog("Poweroff!\n");
// exit(0);
}
static uint8_t via_read_reg(const uint8_t vianum, const uint8_t reg, const long double now)
{
via_state_t *via = &shoe.via[vianum - 1];
@ -570,7 +584,32 @@ static uint8_t via_read_reg(const uint8_t vianum, const uint8_t reg, const long
return via->ddra;
case VIA_T2C_HI: {
const uint16_t counter = via->t2c - (uint16_t)_via_get_delta_counter(via->t2_last_set);
uint16_t counter = via->t2c - (uint16_t)_via_get_delta_counter(via->t2_last_set);
/*
* This is a hack to allow A/UX 3.x.x to boot on fast hosts.
* The A/UX 3 kernel calls a function, SetUpTimeK, during boot
* to run a giant drba-to-self loop and time it via T2C.
* If the loop completes too quickly, (quicker than 0x492 E_CLOCK
* ticks on 3.0.0), it rejects it and tries again.
*
* SetUpTimeK reads T2C twice and compares them to determine the
* time elapsed. I don't want to count on getting the order correct,
* however. Therefore, we will fake it out by randomly adding 0x500
* to the the value of the clock whenever it's read by SetUpTimeK.
* By the Monte Carlo method, we'll eventually get a case where
* two sequential reads differ by at least 0x500.
*
* FIXME: optimize this better, stop using coff_find_func()
*/
if (sr_s()) {
coff_symbol *symb = coff_find_func(shoe.coff, shoe.pc);
if (symb && strcmp(symb->name, "SetUpTimeK") == 0) {
if (random() & 1)
counter += 0x500;
}
}
return counter >> 8;
}
case VIA_T2C_LO: {
@ -641,6 +680,11 @@ static void via_write_reg(const uint8_t vianum, const uint8_t reg, const uint8_t
handle_pram_state_change();
}
if ((vianum == 2) &&
(via->ddrb & V2POWEROFF_MASK) &&
!(via->regb_output & V2POWEROFF_MASK))
_via_poweroff();
break;
}
@ -652,9 +696,14 @@ static void via_write_reg(const uint8_t vianum, const uint8_t reg, const uint8_t
break;
}
case VIA_DDRB:
case VIA_DDRB: {
via->ddrb = data;
if ((vianum == 2) &&
(via->ddrb & V2POWEROFF_MASK) &&
!(via->regb_output & V2POWEROFF_MASK))
_via_poweroff();
break;
}
case VIA_DDRA:
via->ddra = data;
@ -717,7 +766,7 @@ void via_write_raw (void)
via_write_reg(vianum, reg+1, (uint8_t)shoe.physical_dat, now);
}
else
assert("Writing multiple bytes to the same VIA register!");
assert(!"Writing multiple bytes to the same VIA register!");
pthread_mutex_unlock(&shoe.via_cpu_lock);
}

View File

@ -145,7 +145,7 @@ uint32_t nubus_video_read_func(const uint32_t rawaddr, const uint32_t size,
const uint32_t addr = rawaddr & 0x00ffffff;
// ROM and control registers
if ((addr >> 20) == 0xf) {
if sunlikely((addr >> 20) == 0xf) {
slog("nubus_video_read_func: got a read to 0x%08x sz=%u\n", rawaddr, size);
@ -172,7 +172,7 @@ uint32_t nubus_video_read_func(const uint32_t rawaddr, const uint32_t size,
// Else, this is video ram
uint32_t i, result = 0;
if (addr < (ctx->pixels * 4)) {
if slikely(addr < (ctx->pixels * 4)) {
for (i=0; i<size; i++)
result = (result << 8) | ((uint8_t*)ctx->direct_buf)[addr + i];
}
@ -234,7 +234,7 @@ void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size,
uint32_t i;
// ROM and control registers
if ((addr >> 20) == 0xf) {
if sunlikely((addr >> 20) == 0xf) {
slog("nubus_video_write_func: got a write to 0x%08x sz=%u data=0x%x\n", rawaddr, size, data);
@ -340,7 +340,7 @@ void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size,
// Else, this is video ram
if (addr < (ctx->pixels * 4)) {
if slikely(addr < (ctx->pixels * 4)) {
uint32_t mydata, myaddr;
for (myaddr = addr + size, mydata = data; addr < myaddr; ) {
((uint8_t*)ctx->direct_buf)[--myaddr] = mydata & 0xff;

View File

@ -10,16 +10,16 @@ int main (int argc, char **argv)
uint32_t i;
if (argc != 3) {
printf("usage ./rom_to_c video_rom.bin video_rom.c\n");
printf("usage ./rom_to_c video|ethernet rom.bin rom.c\n");
return 0;
}
assert(in = fopen(argv[1], "rb"));
assert(out = fopen(argv[2], "w"));
assert(in = fopen(argv[2], "rb"));
assert(out = fopen(argv[3], "w"));
assert(fread(rom, 4096, 1, in) == 1);
fprintf(out, "static uint8_t _video_rom[4096] = {\n\t");
fprintf(out, "static uint8_t _%s_rom[4096] = {\n\t", argv[1]);
for (i=0; i<4095; i++) {
fprintf(out, "0x%02x, ", rom[i]);
if ((i % 8) == 7)

View File

@ -1,6 +1,6 @@
CC = clang
CFLAGS = -O0 -ggdb -flto -Wno-deprecated-declarations
CFLAGS = -O3 -ggdb -flto -Wno-deprecated-declarations
LFLAGS = -L ../intermediates -lshoebill_core -framework GLUT -framework OpenGL -ledit
all: debugger

View File

@ -42,6 +42,7 @@ struct dbg_state_t {
uint64_t breakpoint_counter;
dbg_breakpoint_t *breakpoints;
_Bool trace;
uint32_t slow_factor;
char *ring;
uint32_t ring_i, ring_len;
@ -84,7 +85,7 @@ void printregs()
print_mmu_rp(shoe.crp);
printf("tc: e=%u sre=%u fcl=%u ps=%u is=%u (tia=%u tib=%u tic=%u tid=%u)\n",
tc_enable(), tc_sre(), tc_fcl(), tc_ps(), tc_is(), tc_tia(), tc_tib(), tc_tic(), tc_tid());
_tc_enable(), _tc_sre(), tc_fcl(), _tc_ps(), _tc_is(), tc_tia(), tc_tib(), tc_tic(), tc_tid());
printf("\n");
}
@ -394,6 +395,8 @@ void verb_continue_handler (const char *line)
{
dbg_state.running = 1;
while (dbg_state.running) {
if (dbg_state.slow_factor)
usleep(dbg_state.slow_factor);
stepper();
}
print_pc();
@ -412,6 +415,13 @@ void verb_reset_handler (const char *line)
shoe.pool = NULL;
}
void verb_slow_handler (const char *line)
{
const uint64_t usecs = strtoul(line, NULL, 0);
printf("Slow factor %u -> %u\n", dbg_state.slow_factor, (uint32_t)usecs);
dbg_state.slow_factor = usecs;
}
struct verb_handler_table_t {
const char *name;
void (*func)(const char *);
@ -430,6 +440,7 @@ struct verb_handler_table_t {
{"trace", verb_trace_toggle_handler},
{"x", verb_examine_handler},
{"reset", verb_reset_handler},
{"slow", verb_slow_handler},
};
void execute_verb (const char *line)
@ -839,19 +850,21 @@ int main (int argc, char **argv)
*/
config.debug_mode = 1;
config.aux_verbose = 1;
config.aux_verbose = 0;
config.ram_size = 16 * 1024 * 1024;
config.aux_kernel_path = "/unix";
config.rom_path = "../priv/macii.rom";
config.rom_path = "../../../shoebill_priv/macii.rom";
config.scsi_devices[0].path = "../priv/aux3.0.1.img";
config.scsi_devices[0].path = "../../../shoebill_priv/root3.img";
//config.scsi_devices[1].path = "../priv/marathon.img";
/*dbg_state.ring_len = 256 * 1024 * 1024;
dbg_state.ring = malloc(dbg_state.ring_len);
dbg_state.ring_i = 0;*/
shoebill_validate_or_zap_pram(config.pram, 1);
if (!shoebill_initialize(&config)) {
printf("%s\n", config.error_msg);
return 0;
@ -864,6 +877,9 @@ int main (int argc, char **argv)
640, // 1024,
480); // 768,
// uint8_t ethernet_addr[6] = {0x22, 0x33, 0x55, 0x77, 0xbb, 0xdd};
// shoebill_install_ethernet_card(&config, 13, ethernet_addr);
// Start the VIA timer thread
shoebill_start();

View File

@ -283,6 +283,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_LINK_OBJC_RUNTIME = NO;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
@ -322,6 +323,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_LINK_OBJC_RUNTIME = NO;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;

View File

@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2013-2014 Peter Rutenbar</string>
<string>Copyright © 2013-2015 Peter Rutenbar</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.0.4</string>
<string>0.0.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.0.4</string>
<string>0.0.5</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSMainNibFile</key>

View File

@ -25,6 +25,7 @@
#import "shoeAppDelegate.h"
#import "shoeApplication.h"
#import "shoePreferencesWindowController.h"
@implementation shoeAppDelegate
@ -39,8 +40,8 @@
[defaults setInteger:NSOnState forKey:@"verboseState"];
[defaults setInteger:16 forKey:@"memorySize"];
[defaults setInteger:640 forKey:@"screenWidth"];
[defaults setInteger:480 forKey:@"screenHeight"];
// [defaults setInteger:640 forKey:@"screenWidth"];
// [defaults setInteger:480 forKey:@"screenHeight"];
for (i=0; i<7; i++)
[defaults setObject:@"" forKey:[NSString stringWithFormat:@"scsiPath%u", i]];
@ -50,6 +51,7 @@
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
uint32_t i;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL isInitialized = [defaults boolForKey:@"defaultsInitialized"];
@ -57,13 +59,33 @@
if (!isInitialized)
[self createFirstTimeUserDefaults];
// Going from 0.0.1 to 0.0.2 leaves rootKernelPath uninitialized
// < 0.0.2 leaves rootKernelPath uninitialized
if ([defaults objectForKey:@"rootKernelPath"] == nil)
[defaults setObject:@"/unix" forKey:@"rootKernelPath"];
// 0.0.1-2 leave pramData uninitialized
// < 0.0.3 leaves pramData uninitialized
if ([defaults objectForKey:@"pramData"] == nil)
[((shoeApplication*)NSApp) zapPram:defaults ptr:nil];
// < 0.0.5 leaves ethernet settings uninitialized
if ([defaults objectForKey:@"tapPathE"] == nil) {
uint8_t mac[6];
generateMACAddr(mac);
[defaults setObject:[NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]
forKey:@"macAddressE"];
[defaults setObject:@"/dev/tap0" forKey:@"tapPathE"];
[defaults setInteger:0 forKey:@"ethernetEnabledE"];
for (i=0; i<4; i++) {
[defaults setInteger:640 forKey:[NSString stringWithFormat:@"screenWidth%u", i]];
[defaults setInteger:480 forKey:[NSString stringWithFormat:@"screenHeight%u", i]];
[defaults setInteger:0 forKey:[NSString stringWithFormat:@"screenEnabled%u", i]];
}
[defaults setInteger:1 forKey:@"screenEnabled0"];
}
[defaults synchronize];
}

View File

@ -46,6 +46,14 @@ struct shoe_app_pram_data_t
BOOL doCaptureMouse, doCaptureKeys;
BOOL isRunning;
shoebill_config_t config;
char *tapPath;
uint8_t mac[6];
int tap_fd;
BOOL ethEnabled, tap_fd_valid;
struct {
uint16_t height, width, enabled;
} screens[4];
}

View File

@ -26,6 +26,7 @@
#import "shoeApplication.h"
#import "shoeScreenWindow.h"
#import "shoeScreenWindowController.h"
#import "shoePreferencesWindowController.h"
#include <ctype.h>
@implementation shoeApplication
@ -215,7 +216,7 @@
}
- (BOOL) fetchUserDefaults:(uint16_t*)height width:(uint16_t*)width
- (BOOL) fetchUserDefaults
{
uint32_t i;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
@ -239,14 +240,22 @@
if ((memsize < 1) || (memsize > 1024))
memsize = 8;
NSInteger screenHeightValue = [defaults integerForKey:@"screenHeight"];
NSInteger screenWidthValue = [defaults integerForKey:@"screenWidth"];
for (i=0; i<4; i++) {
NSInteger height = [defaults integerForKey:[NSString stringWithFormat:@"screenHeight%u", i]];
NSInteger width = [defaults integerForKey:[NSString stringWithFormat:@"screenWidth%u", i]];
NSInteger enabled = [defaults integerForKey:[NSString stringWithFormat:@"screenEnabled%u", i]];
if ((screenHeightValue < 342) || (screenHeightValue > 0xffff))
screenHeightValue = 480;
if ((screenWidthValue < 512) || (screenWidthValue > 0xffff))
screenWidthValue = 640;
if ((height < 342) || (height > 0xffff))
height = 480;
if ((width < 512) || (width > 0xffff))
width = 640;
screens[i].width = (uint16_t)width;
screens[i].height = (uint16_t)height;
screens[i].enabled = (uint16_t)enabled;
}
for (i=0; i<7; i++) {
@ -277,8 +286,23 @@
if (memcmp(config.pram+0xc, "NuMc", 4) != 0)
[self zapPram:defaults ptr:config.pram];
*width = screenWidthValue;
*height = screenHeightValue;
NSString *defaultTapPath = [defaults objectForKey:@"tapPathE"];
NSString *defaultMacAddr = [defaults objectForKey:@"macAddressE"];
ethEnabled = [defaults integerForKey:@"ethernetEnabledE"];
if (ethEnabled) {
if (tap_fd_valid && strcmp(tapPath, [defaultTapPath UTF8String]) != 0) {
close(tap_fd);
tap_fd_valid = 0;
}
if (tapPath)
free(tapPath);
tapPath = strdup([defaultTapPath UTF8String]);
if (!(parseMACAddr([defaultMacAddr UTF8String], mac))) {
[self complain:@"Bad MAC addr"];
ethEnabled = 0;
return NO;
}
}
return YES;
}
@ -346,12 +370,12 @@ void pram_callback (void *param, const uint8_t addr, const uint8_t byte)
if (isRunning)
return;
uint16_t width, height;
uint32_t i;
bzero(&config, sizeof(shoebill_config_t));
[self fetchUserDefaults:&height width:&width];
if (![self fetchUserDefaults])
return ;
self->pram = calloc(1, sizeof(struct shoe_app_pram_data_t));
memcpy(self->pram, config.pram, 256);
@ -371,7 +395,33 @@ void pram_callback (void *param, const uint8_t addr, const uint8_t byte)
return ;
}
[self createScreenWindow:9 height:height width:width];
for (i=0; i<4; i++) {
if (screens[i].enabled)
[self createScreenWindow:(9+i) height:screens[i].height width:screens[i].width];
}
if (ethEnabled) {
if (!tap_fd_valid) {
tap_fd = open(tapPath, O_RDWR | O_NOFOLLOW);
if (tap_fd == -1) {
NSAlert *theAlert = [NSAlert
alertWithMessageText:nil
defaultButton:nil
alternateButton:nil
otherButton:nil
informativeTextWithFormat:@"Couldn't open tap device (errno = %d)", errno
];
[theAlert runModal];
return ;
}
tap_fd_valid = 1;
}
if (!shoebill_install_ethernet_card(&config, 13, mac, tap_fd)) {
[self complain:[NSString stringWithFormat:@"%s", config.error_msg]];
return ;
}
}
shoebill_start();

View File

@ -27,10 +27,17 @@
@interface shoePreferencesWindowController : NSWindowController {
IBOutlet __weak NSButton *apply, *cancel, *applyAndRun, *verbose;
IBOutlet __weak NSButton *apply, *cancel, *applyAndRun, *verbose, *ethernetEnabled;
IBOutlet __weak NSTextField *kernelPath, *romPath, *memorySize;
IBOutlet __weak NSTextField *scsiPath0, *scsiPath1, *scsiPath2, *scsiPath3, *scsiPath4, *scsiPath5, *scsiPath6;
IBOutlet __weak NSTextField *screenHeight, *screenWidth;
IBOutlet __weak NSTextField *macAddress, *tapPath;
IBOutlet __weak NSTextField *screenHeight1, *screenWidth1;
IBOutlet __weak NSTextField *screenHeight2, *screenWidth2;
IBOutlet __weak NSTextField *screenHeight3, *screenWidth3;
IBOutlet __weak NSTextField *screenHeight4, *screenWidth4;
IBOutlet __weak NSButton *enableScreen1, *enableScreen2, *enableScreen3, *enableScreen4;
}
@ -40,3 +47,6 @@
- (IBAction)browsePressed:(id)sender;
@end
void generateMACAddr (uint8_t *mac);
_Bool parseMACAddr (const char *str, uint8_t *mac);

View File

@ -25,6 +25,7 @@
#import "shoePreferencesWindowController.h"
#import "shoeApplication.h"
#include <ctype.h>
@implementation shoePreferencesWindowController
@ -35,6 +36,14 @@
- (void)windowDidLoad
{
uint32_t i;
NSTextField *screenWidths[4] = {
screenWidth1, screenWidth2, screenWidth3, screenWidth4};
NSTextField *screenHeights[4] = {
screenHeight1, screenHeight2, screenHeight3, screenHeight4};
NSButton *screenEnableds[4] = {
enableScreen1, enableScreen2, enableScreen3, enableScreen4};
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *rootKernelPathStr = [defaults objectForKey:@"rootKernelPath"];
@ -71,21 +80,28 @@
if (scsiPath5Str) [scsiPath5 setStringValue:scsiPath5Str];
if (scsiPath6Str) [scsiPath6 setStringValue:scsiPath6Str];
NSInteger screenHeightValue = [defaults integerForKey:@"screenHeight"];
NSInteger screenWidthValue = [defaults integerForKey:@"screenWidth"];
if ((screenHeightValue < 342) || (screenHeightValue > 0xffff)) {
screenHeightValue = 480;
[defaults setInteger:screenHeightValue forKey:@"screenHeight"];
for (i=0; i<4; i++) {
NSInteger height = [defaults integerForKey:[NSString stringWithFormat:@"screenHeight%u", i]];
NSInteger width = [defaults integerForKey:[NSString stringWithFormat:@"screenWidth%u", i]];
NSInteger enabled = [defaults integerForKey:[NSString stringWithFormat:@"screenEnabled%u", i]];
if ((height < 342) || (height > 0xffff))
height = 480;
if ((width < 342) || (width > 0xffff))
width = 640;
[screenHeights[i] setStringValue:[NSString stringWithFormat:@"%u", (uint32_t)height]];
[screenWidths[i] setStringValue:[NSString stringWithFormat:@"%u", (uint32_t)width]];
[screenEnableds[i] setState:enabled];
}
NSString *tapPathStr = [defaults objectForKey:@"tapPathE"];
NSString *macAddressStr = [defaults objectForKey:@"macAddressE"];
NSInteger ethernetEnabledState = [defaults integerForKey:@"ethernetEnabledE"];
if ((screenWidthValue < 512) || (screenWidthValue > 0xffff)) {
screenWidthValue = 640;
[defaults setInteger:screenWidthValue forKey:@"screenWidth"];
}
[screenWidth setStringValue:[NSString stringWithFormat:@"%u", (uint32_t)screenWidthValue]];
[screenHeight setStringValue:[NSString stringWithFormat:@"%u", (uint32_t)screenHeightValue]];
[tapPath setStringValue:tapPathStr];
[macAddress setStringValue:macAddressStr];
[ethernetEnabled setIntegerValue:ethernetEnabledState];
[defaults synchronize];
}
@ -134,8 +150,27 @@
[field setStringValue: [url path]];
}
- (void) complain:(NSString*)str
{
NSAlert *theAlert = [NSAlert
alertWithMessageText:nil
defaultButton:nil
alternateButton:nil
otherButton:nil
informativeTextWithFormat:@"%@", str
];
[theAlert runModal];
}
- (IBAction)applyPressed:(id)sender
{
uint32_t i;
NSTextField *screenWidths[4] = {
screenWidth1, screenWidth2, screenWidth3, screenWidth4};
NSTextField *screenHeights[4] = {
screenHeight1, screenHeight2, screenHeight3, screenHeight4};
NSButton *screenEnableds[4] = {
enableScreen1, enableScreen2, enableScreen3, enableScreen4};
NSString *rootKernelPathStr = [kernelPath stringValue];
NSString *romPathStr = [romPath stringValue];
@ -150,11 +185,21 @@
NSString *scsiPath5Str = [scsiPath5 stringValue];
NSString *scsiPath6Str = [scsiPath6 stringValue];
NSInteger screenHeightValue = [screenHeight integerValue];
NSInteger screenWidthValue = [screenWidth integerValue];
NSString *macAddressStr = [macAddress stringValue];
NSString *tapPathStr = [tapPath stringValue];
NSInteger ethernetEnabledState = [ethernetEnabled state];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
uint8_t mac[6];
if (!parseMACAddr ([macAddressStr UTF8String], mac)) {
[self complain:@"Bad MAC address"];
}
else {
[macAddress setStringValue:[NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]];
}
[defaults setObject:rootKernelPathStr forKey:@"rootKernelPath"];
[defaults setObject:romPathStr forKey:@"romPath"];
[defaults setInteger:verboseState forKey:@"verboseState"];
@ -168,8 +213,24 @@
[defaults setObject:scsiPath5Str forKey:@"scsiPath5"];
[defaults setObject:scsiPath6Str forKey:@"scsiPath6"];
[defaults setInteger:screenHeightValue forKey:@"screenHeight"];
[defaults setInteger:screenWidthValue forKey:@"screenWidth"];
for (i=0; i<4; i++) {
NSInteger height = [screenHeights[i] integerValue];
NSInteger width = [screenWidths[i] integerValue];
NSInteger enabled = [screenEnableds[i] state];
if ((height < 342) || (height > 0xffff))
height = 480;
if ((width < 342) || (width > 0xffff))
width = 640;
[defaults setInteger:height forKey:[NSString stringWithFormat:@"screenHeight%u", i]];
[defaults setInteger:width forKey:[NSString stringWithFormat:@"screenWidth%u", i]];
[defaults setInteger:enabled forKey:[NSString stringWithFormat:@"screenEnabled%u", i]];
}
[defaults setObject:macAddressStr forKey:@"macAddressE"];
[defaults setObject:tapPathStr forKey:@"tapPathE"];
[defaults setInteger:ethernetEnabledState forKey:@"ethernetEnabledE"];
[defaults synchronize];
}
@ -192,5 +253,63 @@
[shoeApp zapPram:[NSUserDefaults standardUserDefaults] ptr:nil];
}
void generateMACAddr (uint8_t *mac)
{
srandom((unsigned)(random() ^ time(NULL)));
/* Generate a MAC address in the range of the original EtherTalk card */
mac[0] = 0x02;
mac[1] = 0x60;
mac[2] = 0x8c;
mac[3] = random() & 0x07;
mac[4] = random() & 0xff;
mac[5] = random() & 0xff;
}
_Bool parseMACAddr (const char *str, uint8_t *mac)
{
uint32_t i, nibbles = 0;
uint8_t allowed[256];
memset(allowed, 30, 256);
for (i=0; i<256; i++)
if (isspace(i))
allowed[i] = 20;
allowed[':'] = 20;
allowed['-'] = 20;
for (i=0; i<10; i++)
allowed['0' + i] = i;
for (i=0; i<6; i++) {
allowed['a' + i] = 10 + i;
allowed['A' + i] = 10 + i;
}
for (i=0; str[i]; i++) {
const uint8_t v = allowed[str[i]];
if (v == 30)
return 0;
else if (v == 20)
continue;
if (nibbles >= 12)
return 0;
mac[nibbles/2] <<= 4;
mac[nibbles/2] |= v;
nibbles++;
}
return (nibbles == 12);
}
-(IBAction)newMacAddrPressed:(id)sender
{
uint8_t mac[6];
generateMACAddr(mac);
[macAddress setStringValue:[NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]];
}
@end

View File

@ -1,17 +1,29 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13D65" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="7706" systemVersion="14F27" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="7706"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="shoePreferencesWindowController">
<connections>
<outlet property="enableScreen1" destination="JSa-Bw-xDM" id="3Vr-kl-5To"/>
<outlet property="enableScreen2" destination="QR4-Cc-AkE" id="An0-V4-7Gg"/>
<outlet property="enableScreen3" destination="C6X-Zw-psD" id="Ipx-9O-5jD"/>
<outlet property="enableScreen4" destination="isQ-0Q-gQ4" id="4rO-YL-FaT"/>
<outlet property="ethernetEnabled" destination="GCJ-G0-drE" id="urw-x8-B7H"/>
<outlet property="kernelPath" destination="zU0-5O-afD" id="Q3V-Ly-Y6B"/>
<outlet property="macAddress" destination="UAs-x7-p28" id="PTo-JO-bHU"/>
<outlet property="memorySize" destination="uvm-gd-pCd" id="zzI-jI-ZUW"/>
<outlet property="romPath" destination="LoN-Nd-9cy" id="R3k-vY-TPo"/>
<outlet property="screenHeight" destination="Wyt-jg-xmk" id="Sq6-IJ-xbQ"/>
<outlet property="screenWidth" destination="EMf-gC-m9T" id="xxW-Ji-t7R"/>
<outlet property="screenHeight1" destination="Wyt-jg-xmk" id="dCS-jW-MMh"/>
<outlet property="screenHeight2" destination="IPj-pY-K2b" id="cnW-fh-y05"/>
<outlet property="screenHeight3" destination="tqh-iM-5GM" id="sF2-HA-acz"/>
<outlet property="screenHeight4" destination="3aP-6m-As4" id="fsH-cL-DLg"/>
<outlet property="screenWidth1" destination="EMf-gC-m9T" id="GSA-cX-c70"/>
<outlet property="screenWidth2" destination="B2c-pG-rIH" id="1BQ-0g-PMw"/>
<outlet property="screenWidth3" destination="cQO-ri-LxM" id="fBQ-VU-X4L"/>
<outlet property="screenWidth4" destination="VvE-c8-mBx" id="acc-3d-WMa"/>
<outlet property="scsiPath0" destination="nhQ-gw-2di" id="Ayi-Wk-Nhf"/>
<outlet property="scsiPath1" destination="8th-va-hXP" id="xTk-Kd-9v2"/>
<outlet property="scsiPath2" destination="RTT-NZ-Tte" id="w7D-05-cvN"/>
@ -19,34 +31,33 @@
<outlet property="scsiPath4" destination="Biz-iI-IiP" id="gbh-Jl-dxV"/>
<outlet property="scsiPath5" destination="GE2-3P-G1I" id="ohD-Fj-EX9"/>
<outlet property="scsiPath6" destination="cy8-jg-woV" id="QoH-Z0-e8d"/>
<outlet property="tapPath" destination="Wvc-cC-QWO" id="kuK-DA-ui3"/>
<outlet property="verbose" destination="fkL-RE-iRz" id="uba-U2-Zkh"/>
<outlet property="window" destination="rKy-wc-8AE" id="sYz-fH-ohd"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="rKy-wc-8AE">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="498" height="433"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="878"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="4Fm-p8-6h9">
<rect key="frame" x="0.0" y="0.0" width="498" height="433"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tabView fixedFrame="YES" drawsBackground="NO" initialItem="Ffn-1Z-2rp" translatesAutoresizingMaskIntoConstraints="NO" id="i29-bb-k7Y">
<rect key="frame" x="13" y="33" width="472" height="394"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<font key="font" metaFont="system"/>
<tabViewItems>
<tabViewItem label="General" identifier="1" id="Ffn-1Z-2rp">
<view key="view" ambiguous="YES" id="BF8-Dm-rF5">
<view key="view" id="BF8-Dm-rF5">
<rect key="frame" x="10" y="33" width="452" height="348"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oVj-nA-5GP">
<rect key="frame" x="11" y="314" width="81" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="Rom Path:" usesSingleLineMode="YES" id="7qD-i1-FXI">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -55,7 +66,6 @@
</textField>
<button identifier="romPathBrowse" verticalHuggingPriority="750" fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="fjl-Jg-nIF">
<rect key="frame" x="358" y="303" width="97" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Browse..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ITb-nX-hmP">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -66,7 +76,6 @@
</button>
<textField identifier="romPath" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LoN-Nd-9cy">
<rect key="frame" x="98" y="292" width="258" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="macii.rom" drawsBackground="YES" id="IvC-yQ-qdn">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -75,7 +84,6 @@
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RDI-wU-bdg">
<rect key="frame" x="2" y="267" width="90" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="Memory (MB):" usesSingleLineMode="YES" id="8mu-le-9YC">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -84,61 +92,14 @@
</textField>
<textField identifier="memorySize" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uvm-gd-pCd">
<rect key="frame" x="98" y="262" width="42" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="8" placeholderString="8" drawsBackground="YES" id="I5v-kb-eCo">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tgt-1x-QT0">
<rect key="frame" x="2" y="210" width="90" height="42"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="right" title="Screen Resolution:" id="9bl-WA-bhb">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JNe-0k-g4e">
<rect key="frame" x="146" y="224" width="14" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="center" title="x" id="9cf-Xq-tuu">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aSg-xG-o1t">
<rect key="frame" x="223" y="223" width="59" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="left" title="pixels" id="D5V-Zm-Grd">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField identifier="widthBox" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EMf-gC-m9T">
<rect key="frame" x="98" y="220" width="43" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="width" placeholderString="width" drawsBackground="YES" id="sbq-WW-C05">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField identifier="heightBox" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wyt-jg-xmk">
<rect key="frame" x="168" y="220" width="49" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="height" placeholderString="height" drawsBackground="YES" id="qvE-Bk-NDl">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fNZ-zo-4uj">
<rect key="frame" x="7" y="10" width="103" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Zap PRAM" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="EGV-fk-y4d">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -147,6 +108,223 @@
<action selector="zapPramPressed:" target="-2" id="9N7-dY-Fl6"/>
</connections>
</button>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0nJ-ho-P1P">
<rect key="frame" x="11" y="235" width="81" height="17"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="Kernel Path:" usesSingleLineMode="YES" id="Wdx-2C-yGA">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField identifier="kernelPath" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zU0-5O-afD">
<rect key="frame" x="98" y="232" width="325" height="22"/>
<string key="toolTip">The path to the kernel on the root image. If you don't know what this is, just use "/unix" (Note: the root image needs to be at SCSI ID 0)</string>
<textFieldCell key="cell" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="/unix" drawsBackground="YES" id="0MQ-1P-9gJ">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button identifier="verbose" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fkL-RE-iRz">
<rect key="frame" x="283" y="18" width="142" height="18"/>
<string key="toolTip">Verbose mode causes A/UX to print diagnostic info during boot, and it will also run fsck to repair the root filesystem if necessary.</string>
<buttonCell key="cell" type="check" title="A/UX Verbose Boot" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="htQ-zH-VRv">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
</view>
</tabViewItem>
<tabViewItem label="Screens" identifier="" id="3o8-Ma-LAk">
<view key="view" id="Zdy-ik-svz">
<rect key="frame" x="10" y="33" width="452" height="348"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tgt-1x-QT0">
<rect key="frame" x="186" y="312" width="125" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="right" title="Screen Resolution:" id="9bl-WA-bhb">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ld1-xq-pdG">
<rect key="frame" x="186" y="287" width="47" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="right" title="Width" id="QBW-rk-c7E">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JNe-0k-g4e">
<rect key="frame" x="241" y="259" width="14" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="center" title="x" id="9cf-Xq-tuu">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aSg-xG-o1t">
<rect key="frame" x="317" y="259" width="59" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="left" title="pixels" id="D5V-Zm-Grd">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField identifier="width1" toolTip="width" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="EMf-gC-m9T">
<rect key="frame" x="192" y="256" width="43" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="width" placeholderString="width" drawsBackground="YES" id="sbq-WW-C05">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField identifier="height1" toolTip="height" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wyt-jg-xmk">
<rect key="frame" x="262" y="256" width="49" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="height" placeholderString="height" drawsBackground="YES" id="qvE-Bk-NDl">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button identifier="verbose" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JSa-Bw-xDM">
<rect key="frame" x="57" y="258" width="129" height="18"/>
<string key="toolTip">Verbose mode causes A/UX to print diagnostic info during boot, and it will also run fsck to repair the root filesystem if necessary.</string>
<buttonCell key="cell" type="check" title="Enable Screen 1" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="azN-j2-txA">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button identifier="verbose" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QR4-Cc-AkE">
<rect key="frame" x="57" y="228" width="129" height="18"/>
<string key="toolTip">Verbose mode causes A/UX to print diagnostic info during boot, and it will also run fsck to repair the root filesystem if necessary.</string>
<buttonCell key="cell" type="check" title="Enable Screen 2" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Zqf-mb-br4">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button identifier="verbose" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="C6X-Zw-psD">
<rect key="frame" x="57" y="198" width="129" height="18"/>
<string key="toolTip">Verbose mode causes A/UX to print diagnostic info during boot, and it will also run fsck to repair the root filesystem if necessary.</string>
<buttonCell key="cell" type="check" title="Enable Screen 3" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Cfv-ZG-aBO">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G8E-Jw-aPd">
<rect key="frame" x="241" y="229" width="14" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="center" title="x" id="1RP-Cp-YFY">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8hd-at-UXU">
<rect key="frame" x="317" y="229" width="59" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="left" title="pixels" id="2DF-kS-r5B">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField identifier="width2" toolTip="width" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="B2c-pG-rIH">
<rect key="frame" x="192" y="226" width="43" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="width" placeholderString="width" drawsBackground="YES" id="DMe-fk-aJx">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField identifier="height2" toolTip="height" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="IPj-pY-K2b">
<rect key="frame" x="262" y="226" width="49" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="height" placeholderString="height" drawsBackground="YES" id="3F9-jB-hfl">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uAk-QS-Kpu">
<rect key="frame" x="241" y="199" width="14" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="center" title="x" id="XrI-eJ-Xmq">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="a0D-DN-Abg">
<rect key="frame" x="317" y="199" width="59" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="left" title="pixels" id="V3B-61-meh">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField identifier="width3" toolTip="width" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cQO-ri-LxM">
<rect key="frame" x="192" y="196" width="43" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="width" placeholderString="width" drawsBackground="YES" id="5Rx-30-P1a">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField identifier="height3" toolTip="height" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tqh-iM-5GM">
<rect key="frame" x="262" y="196" width="49" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="height" placeholderString="height" drawsBackground="YES" id="PdC-tw-Mou">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="WMg-rd-urO">
<rect key="frame" x="241" y="169" width="14" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="center" title="x" id="r21-SX-0ht">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NDL-uY-GIk">
<rect key="frame" x="317" y="169" width="59" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="left" title="pixels" id="gKj-k6-3XK">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField identifier="width4" toolTip="width" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VvE-c8-mBx">
<rect key="frame" x="192" y="166" width="43" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="width" placeholderString="width" drawsBackground="YES" id="rfI-7T-Vc2">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField identifier="height4" toolTip="height" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3aP-6m-As4">
<rect key="frame" x="262" y="166" width="49" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="height" placeholderString="height" drawsBackground="YES" id="56I-cY-cml">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bgh-Ds-kMn">
<rect key="frame" x="260" y="287" width="47" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="right" title="Height" id="Ato-zm-vpN">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<button identifier="verbose" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="isQ-0Q-gQ4">
<rect key="frame" x="57" y="168" width="129" height="18"/>
<string key="toolTip">Verbose mode causes A/UX to print diagnostic info during boot, and it will also run fsck to repair the root filesystem if necessary.</string>
<buttonCell key="cell" type="check" title="Enable Screen 4" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="dNj-R0-mIT">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
</view>
</tabViewItem>
@ -157,7 +335,6 @@
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dA0-AE-SsA">
<rect key="frame" x="1" y="321" width="72" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="SCSI ID 0" usesSingleLineMode="YES" id="YYd-8o-kqe">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -166,7 +343,6 @@
</textField>
<button identifier="scsiPath0Browse" verticalHuggingPriority="750" fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="BUV-3F-sRD">
<rect key="frame" x="353" y="310" width="97" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Browse..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Ekq-OL-WH9">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -177,7 +353,6 @@
</button>
<textField identifier="scsiPath0" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nhQ-gw-2di">
<rect key="frame" x="79" y="299" width="272" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="None" drawsBackground="YES" id="4NZ-tu-sNu">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -186,7 +361,6 @@
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Gjz-Nn-CkC">
<rect key="frame" x="1" y="274" width="72" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="SCSI ID 1" usesSingleLineMode="YES" id="oPB-iw-Fuy">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -195,7 +369,6 @@
</textField>
<button identifier="scsiPath1Browse" verticalHuggingPriority="750" fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="0OE-Ny-sRU">
<rect key="frame" x="353" y="263" width="97" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Browse..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="iRT-nY-bQx">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -206,7 +379,6 @@
</button>
<textField identifier="scsiPath1" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8th-va-hXP">
<rect key="frame" x="79" y="252" width="272" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="None" drawsBackground="YES" id="wM4-Hu-6dD">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -215,7 +387,6 @@
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="17i-H8-woP">
<rect key="frame" x="1" y="227" width="72" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="SCSI ID 2" usesSingleLineMode="YES" id="rWu-qs-tIH">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -224,7 +395,6 @@
</textField>
<button identifier="scsiPath2Browse" verticalHuggingPriority="750" fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="OS6-vm-18P">
<rect key="frame" x="353" y="216" width="97" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Browse..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ojq-kT-7Hz">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -235,7 +405,6 @@
</button>
<textField identifier="scsiPath2" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RTT-NZ-Tte">
<rect key="frame" x="79" y="205" width="272" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="None" drawsBackground="YES" id="bx9-L2-52p">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -244,7 +413,6 @@
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zeV-Os-yjZ">
<rect key="frame" x="1" y="180" width="72" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="SCSI ID 3" usesSingleLineMode="YES" id="4Ir-Qy-6TG">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -253,7 +421,6 @@
</textField>
<button identifier="scsiPath3Browse" verticalHuggingPriority="750" fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="hyG-x9-NBA">
<rect key="frame" x="353" y="169" width="97" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Browse..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Toc-PB-8FO">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -264,7 +431,6 @@
</button>
<textField identifier="scsiPath3" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pKG-3S-zID">
<rect key="frame" x="79" y="158" width="272" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="None" drawsBackground="YES" id="Ksz-dn-t4g">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -273,7 +439,6 @@
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Rpv-lh-1BC">
<rect key="frame" x="1" y="133" width="72" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="SCSI ID 4" usesSingleLineMode="YES" id="RSB-J8-WHv">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -282,7 +447,6 @@
</textField>
<button identifier="scsiPath4Browse" verticalHuggingPriority="750" fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="FUw-LT-FRg">
<rect key="frame" x="353" y="122" width="97" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Browse..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="CDZ-hc-2Kz">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -293,7 +457,6 @@
</button>
<textField identifier="scsiPath4" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Biz-iI-IiP">
<rect key="frame" x="79" y="111" width="272" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="None" drawsBackground="YES" id="j2E-vU-3LZ">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -302,7 +465,6 @@
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eGO-wX-v7I">
<rect key="frame" x="1" y="86" width="72" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="SCSI ID 5" usesSingleLineMode="YES" id="lVw-XZ-DkQ">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -311,7 +473,6 @@
</textField>
<button identifier="scsiPath5Browse" verticalHuggingPriority="750" fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="Ur1-2a-9nV">
<rect key="frame" x="353" y="75" width="97" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Browse..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="QW3-hO-eDz">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -322,7 +483,6 @@
</button>
<textField identifier="scsiPath5" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GE2-3P-G1I">
<rect key="frame" x="79" y="64" width="272" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="None" drawsBackground="YES" id="BrK-XM-gcx">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -331,7 +491,6 @@
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="c4H-Kt-ANK">
<rect key="frame" x="1" y="39" width="72" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="SCSI ID 6" usesSingleLineMode="YES" id="NS8-2m-U2B">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -340,7 +499,6 @@
</textField>
<button identifier="scsiPath6Browse" verticalHuggingPriority="750" fixedFrame="YES" tag="9" translatesAutoresizingMaskIntoConstraints="NO" id="Twn-Yd-cyf">
<rect key="frame" x="353" y="28" width="97" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Browse..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="JNl-qq-v8p">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -351,7 +509,6 @@
</button>
<textField identifier="scsiPath6" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cy8-jg-woV">
<rect key="frame" x="79" y="17" width="272" height="39"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingMiddle" truncatesLastVisibleLine="YES" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="None" drawsBackground="YES" id="gZa-0y-cOt">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@ -361,35 +518,56 @@
</subviews>
</view>
</tabViewItem>
<tabViewItem label="Booting" identifier="" id="3o8-Ma-LAk">
<view key="view" id="Zdy-ik-svz">
<tabViewItem label="Ethernet" identifier="" id="npc-ti-4lo">
<view key="view" id="2Hm-kn-wCU">
<rect key="frame" x="10" y="33" width="452" height="348"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0nJ-ho-P1P">
<rect key="frame" x="6" y="315" width="81" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="Kernel Path:" usesSingleLineMode="YES" id="Wdx-2C-yGA">
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oLm-yd-Ca2">
<rect key="frame" x="15" y="272" width="93" height="17"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="MAC Address:" usesSingleLineMode="YES" id="vve-T4-Rce">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField identifier="kernelPath" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zU0-5O-afD">
<rect key="frame" x="93" y="310" width="342" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<string key="toolTip">The path to the kernel on the root image. If you don't know what this is, just use "/unix" (Note: the root image needs to be at SCSI ID 0)</string>
<textFieldCell key="cell" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="/unix" drawsBackground="YES" id="0MQ-1P-9gJ">
<textField identifier="macAddress" toolTip="The MAC address of the emulated ethernet card" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="UAs-x7-p28">
<rect key="frame" x="114" y="269" width="160" height="22"/>
<textFieldCell key="cell" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="AA:AA:AA:AA:AA:AA" placeholderString="01:02:03:04:05:06" drawsBackground="YES" id="2is-7Y-0d2">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button identifier="verbose" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fkL-RE-iRz">
<rect key="frame" x="6" y="271" width="142" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<string key="toolTip">Verbose mode causes A/UX to print diagnostic info during boot, and it will also run fsck to repair the root filesystem if necessary.</string>
<buttonCell key="cell" type="check" title="A/UX Verbose Boot" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="htQ-zH-VRv">
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vp5-0F-Hl5">
<rect key="frame" x="30" y="302" width="78" height="17"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" allowsUndo="NO" alignment="right" title="TAP Device:" usesSingleLineMode="YES" id="QWi-Fs-xtO">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</textFieldCell>
</textField>
<textField identifier="tapPath" toolTip="The path to the TAP device (/dev/tap0 should be fine)" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Wvc-cC-QWO">
<rect key="frame" x="114" y="299" width="313" height="22"/>
<textFieldCell key="cell" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="/dev/tap0" placeholderString="/dev/tap0" drawsBackground="YES" id="Sb8-nl-Q5r">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button toolTip="Generate a new MAC address" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gZ8-0N-f6V">
<rect key="frame" x="276" y="263" width="157" height="32"/>
<buttonCell key="cell" type="push" title="New MAC Address" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="04X-Ao-SYd">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="newMacAddrPressed:" target="-2" id="Lgm-OH-3ff"/>
</connections>
</button>
<button identifier="enableEthernet" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GCJ-G0-drE">
<rect key="frame" x="15" y="218" width="142" height="18"/>
<buttonCell key="cell" type="check" title="Enable Ethernet" bezelStyle="regularSquare" imagePosition="left" inset="2" id="03F-wY-3oH">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
@ -401,7 +579,6 @@
</tabView>
<button identifier="applyAndRun" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="r8k-B7-iXM">
<rect key="frame" x="352" y="5" width="132" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Apply and Run" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="oR1-x8-VgY">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -412,7 +589,6 @@
</button>
<button identifier="cancel" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="T6y-kh-jgH">
<rect key="frame" x="188" y="5" width="82" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Sk4-hr-Ot6">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
@ -426,7 +602,6 @@ Gw
</button>
<button identifier="apply" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZDd-0H-a3B">
<rect key="frame" x="270" y="5" width="82" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Apply" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="bC6-3u-5Op">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>

View File

@ -82,7 +82,7 @@
[[NSRunLoop currentRunLoop] addTimer:timer
forMode:NSEventTrackingRunLoopMode];
[[self window] setTitle:[NSString stringWithFormat:@"Shoebill - Screen 1"]];
[[self window] setTitle:[NSString stringWithFormat:@"Shoebill"]];
[[self window] makeKeyAndOrderFront:nil];
}

View File

@ -104,7 +104,7 @@
shoeApplication *shoeApp = (shoeApplication*)NSApp;
shoeApp->doCaptureMouse = NO;
CGDisplayShowCursor(0);
[self setTitle:@"Shoebill - Screen 1"];
[self setTitle:@"Shoebill"];
}
- (void) captureMouse
@ -113,7 +113,7 @@
shoeApp->doCaptureMouse = YES;
CGDisplayHideCursor(0);
[self warpToCenter];
[self setTitle:@"Shoebill - Screen 1 (Ctrl-click to escape)"];
[self setTitle:@"Shoebill (Ctrl-click to escape)"];
}

View File

@ -8,7 +8,7 @@ for i in adb fpu mc68851 mem via floppy core_api cpu dis; do
files="$files $i.post.c"
done
for i in atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer ethernet sound; do
for i in SoftFloat/softfloat atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer ethernet sound; do
files="$files ../core/$i.c"
done

View File

@ -8,7 +8,7 @@ for i in adb fpu mc68851 mem via floppy core_api cpu dis; do
files="$files $i.post.c"
done
for i in atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer ethernet sound; do
for i in SoftFloat/softfloat atrap_tab coff exception macii_symbols redblack scsi video filesystem alloc_pool toby_frame_buffer ethernet sound; do
files="$files ../core/$i.c"
done
@ -17,6 +17,6 @@ $CC -O1 ../core/decoder_gen.c -o decoder_gen
./decoder_gen dis .
cmd="$CC -O3 -ggdb -flto $files sdl.c -framework OpenGL -framework SDL2 -o shoebill"
cmd="$CC -F/Library/Frameworks -O3 -ggdb -flto $files sdl.c -framework OpenGL -framework SDL2 -o shoebill"
echo $cmd
$cmd

View File

@ -6,4 +6,4 @@ gcc -O1 ..\core\decoder_gen.c -o decoder_gen
decoder_gen inst .
decoder_gen dis .
gcc -O3 -flto -mno-ms-bitfields sdl.c adb.post.c fpu.post.c mc68851.post.c mem.post.c via.post.c floppy.post.c core_api.post.c cpu.post.c dis.post.c ..\core\atrap_tab.c ..\core\coff.c ..\core\exception.c ..\core\macii_symbols.c ..\core\redblack.c ..\core\scsi.c ..\core\video.c ..\core\filesystem.c ..\core\alloc_pool.c ..\core\toby_frame_buffer.c ..\core\ethernet.c ..\core\sound.c -lmingw32 -lopengl32 -lsdl2main -lsdl2 -o shoebill
gcc -O3 -flto -mno-ms-bitfields sdl.c adb.post.c fpu.post.c mc68851.post.c mem.post.c via.post.c floppy.post.c core_api.post.c cpu.post.c dis.post.c ..\core\atrap_tab.c ..\core\coff.c ..\core\exception.c ..\core\macii_symbols.c ..\core\redblack.c ..\core\scsi.c ..\core\video.c ..\core\filesystem.c ..\core\alloc_pool.c ..\core\toby_frame_buffer.c ..\core\ethernet.c ..\core\sound.c ..\core\SoftFloat\softfloat.c -lmingw32 -lopengl32 -lsdl2main -lsdl2 -o shoebill