TweetFollow Us on Twitter

68881 Access
Volume Number:4
Issue Number:4
Column Tag:Forth Forum

Direct 68881 Floating Point Access

By Jörg Langowski, MacTutor Editorial Board, Grenoble, France

Being the proud owner of a MacII since the beginning of this year, I was - like so many others - disappointed at the relative slowness of the SANE package. Even with the floating point coprocessor, the speedup is only a factor of 5-10 compared to the Mac SE. The coprocessor itself allows you to go much faster than that, and it is Apple’s SANE implementation that slows down the operations.

The reason for this is, of course, that Apple is trying to guarantee the ‘compatibility’ of the SANE on the MacII with the old SANE implementation. That means that the results are supposed to be the same, down to the least significant bit (or even to the last guard bit?). The 68881 uses different algorithms for calculating transcendental functions than SANE does, therefore some of its built-in operations could not be used and had to be replaced by software. Of course, that slows down things a lot.

As a side note, I’m not at all in favor of such a strategy. Artificially restraining a high performance chip just because its results, although accurate enough, don’t match the old - also accurate - results to the last bit seems a little exaggerated. Stable numerical algorithms should take into account the possibility that the hardware changes slightly and the machine errors are different, and they should be immune against such changes; or at least the new SANE should have had an option built in that uses the 68881 directly! [Amen to that statement! -Ed]

Many of the development systems for the Macintosh now come with the possibility to generate code that supports the floating point coprocessor directly, many others don’t; working with Forth, we don’t have a real problem since we can easily redefine our floating point operators. This month I’ll show you how to do that.

The 68881

Let’s first have a look at the floating point coprocessor itself.

The 68881 is accessed from the 68020 in a special address area. When the 68020 encounters an instruction of the form $Fxxx (previously the F line trap), it will set its function code lines (pins FC0-FC2) all to high, indicating ‘CPU space’. It will then exchange information with the coprocessor’s internal registers to perform the floating point operation requested.

This information exchange occurs automatically, it is part of the 68020’s design; when using the floating point instructions, you don’t notice the communication between the two processors at all. The 68881 appears as an extension to the 68020, just as if we had a new set of registers available, with special instructions operating on them.

The registers FP0-FP7 can each hold one extended precision (80-bit) floating point number, in the format given by the IEEE standard: bits 0-63 contain the mantissa, 64-78 the 15-bit exponent offset by 16383, and bit 79 the sign. The instruction set of the 68881 allows you to do floating point operations on any or between any two of these registers, and transfer data between them, the 68020’s registers and memory.

Mach2’s assembler fully supports all 68881 instructions. The redefinition of the words in the SANE vocabulary is therefore quite straightforward. Register D7 is used by Mach2 as the floating point stack pointer, all we have to do is to transfer floating point numbers from the FP stack to the 68881’s registers, do the FP operation and transfer back the result.

The 68881 expects floating point numbers in a different format than SANE does. In order to keep FP numbers aligned to the boundaries of a 32-bit long word, which speeds up operations, an extended precision number in memory will be 96 bits long instead of 80; there is a 16 bit gap between the 64-bit mantissa and the 16-bit sign and exponent field. Since SANE and the floating point stack in Mach2 use 80 bit numbers, we have to convert their format when we use the coprocessor.

Listing 1 provides the macros f>2, f>1 and 1>f for this purpose. The general format for a binary floating point operation is then

 f>2  
 fop.x  FPn, FPm 
 1>f

where fop.x is an extended format floating point instruction that operates on floating point registers FPn and FPm. The example always uses registers FP0 and FP1. Unary operations are encoded the same way, using only FP0.

In the example, I provided a new vocabulary f68881 that contains redefinitions of the most important SANE operations for the 68881. Of course, the concept can be far extended. We have eight registers at our disposition and can use them to optimize more complicated numerical algorithms, using only assembly language. I might give some examples how to do this in a later column.

For the moment, let’s content ourselves with the speed improvement that we have achieved so far, which is already remarkable. Some simple benchmarks are listed at the end of listing 1, and the results are given here:

( MacII, direct 68881 access, 100000 loops each )

bmark1 2 Secs 18 Ticks ok <0> [0]

bmark2 4 Secs 48 Ticks ok <0> [0]

bmark3 4 Secs 14 Ticks ok <0> [0]

bmark4 4 Secs 17 Ticks ok <0> [0]

bmark5 4 Secs 14 Ticks ok <0> [0]

( MacII, SANE w/68881, 10000 loops each )

smark1 15 Ticks ok <0> [0]

smark2 37 Secs 12 Ticks ok <0> [0]

smark3 24 Ticks ok <0> [0]

smark4 1 Secs 33 Ticks ok <0> [0]

smark5 1 Secs 33 Ticks ok <0> [0]

( Mac +, SANE, 10000 loops each )

ok <0> [0]

smark1 24 Ticks ok <0> [0]

smark2 181 Secs 54 Ticks ok <0> [0]

smark3 49 Ticks ok <0> [0]

smark4 4 Secs 47 Ticks ok <0> [0]

smark5 5 Secs 14 Ticks ok <0> [0]

For the Mac+, the fnull1 and fnull2 operations had been replaced by simple fdrops. As you see, the speedup going from Mac+ to MacII’s SANE is not so breathtaking: a factor of 6 for the exponential, 4 for addition and subtraction; but when we access the 68881 directly, we gain another factor of 3 for simple addition and multiplication and 78 for the exponential. It is in the calculation of the transcendentals where the 68881 really shines.

Pop up menus

Someone approached me lately on the question of how to do pop up menu selection. Since the technical notes contain only sketchy references to popup menus at the time I write this (e.g. TN156, TN172), I’d like to give you a practical example how to use pop up menus from Mach2 in a simple way.

Listing 2 explains the process. The PopUpMenuSelect trap takes four parameters:

- a handle to the menu to be displayed (32 bits),

- the top and left global coordinate of the point at which to display the menu (2*16 bits),

- the menu item which should be positioned at that point for the default selection.

Although Mach2 knows the trap name, the interface to this routine is not (yet) correct, so we have to redefine it in assembler. Note that the point returned by the @mouse function is in local coordinates, while PopUpMenuSelect expects it in global coordinates.

The example defines a menu using the Mach2 interface; the menu is created with -1 as the insertion parameter (-1 150 mymenu BOUNDS) so that after insertion into the tasks’s menu bar the menu will stay invisible (just as we did for the hierarchical menus). Note that a pop up menu has to be inserted into the menu bar before using it.

The content handler for the default Mach2 window is then rewritten so that on a mouse down event it will select the example pop up menu. The menu handler will just beep a number of times depending on the item selected. dopop activates the new content handler while nopop deactivates it.

Feedback dept.

This letter comes from Vassili Dzuba, Paris:

“In January’s issue ‘Mousehole Report’, Alan Dall put in his wish list the ability to define ‘ghost copies’ of applications. Even without Unix’ capability of defining links, this can be done with a small program using the _Launch trap. This program takes only 1K on the disk. The path name of the application to launch is stored in ‘STR ‘ resource 1000. It’s possible to set the creator and the bundle bit of the ghost to have it share the same icon as the real thing. Of course, double-clicking on a document can then launch the ghost instead of the application, but the slowing down is only marginal.

The program is the following

(using MPW’s assembler):

 INCLUDE‘traps.a’
ghost MAIN
 MOVE.W #0,-(SP) 
 ; the context data (_launch parameter)
 MOVE.L #’STR ‘,-(SP)
 ; 1st parameter of GetResource
 MOVE.W #1000,-(SP)
 ; 2nd parameter of GetResource
 _GetResource
 ; handle to string in (SP)
 TST.L  (SP)
 ; test if null handle (no resource available)
 BEQ.B  exit
 ; if null, go to exit
 MOVE.L (SP),A0
 MOVE.L (A0),(SP)
 ; handle dereferenced
 MOVE.L SP,A0
 ; stack pointer in A0
 _Launch
exit  _ExitToShell
 END

The resource file is something like this (using Rez format):

#include “types.r”
resource ‘STR ‘ (1000) {
 “Sys:myDirectory:MyApp”
};

A ghost can be easily created using a small shell script (assuming the original ghost’s directory being {MPW}dev) which sets up the string resource:

duplicate {MPW}’dev:ghost’ {2}
echo ‘#include “types.r”’n
‘resource ‘’’STR ‘’’ (1000) { “‘{1}’” };’
| rez -a -o {2}

Assuming this script is named ‘summon’, the creation in the current directory of a ghost of MacPaint would be something like:

summon ‘sys:appli ƒ:mac paint’ ‘macpaint.Ghost’

Sincerely yours”

Thank you, Vassili, for this helpful little utility.


Listing 1: direct access 68881 floating point words for Mach2
\ 68881 access, © J. Langowski/MacTutor Jan 1988

only forth also assembler also sane
vocabulary f68881
also f68881 definitions

code f>2
 add.l  #20,d7
 move.l d7,a0
 move.l -(a0),-(a7); move mantissa
 move.l -(a0),-(a7); in two 32-bit chunks
 subq.l #2,a7    ; 16-bit gap
 move.w -(a0),-(a7); move exponent + sign
 fmove.x(a7)+,fp0; transfer from stack to fp0
 move.l -(a0),-(a7); same for fp1...
 move.l -(a0),-(a7)
 subq.l #2,a7
 move.w -(a0),-(a7)
 fmove.x(a7)+,fp1
 add.l  #10,a0 ; a0 points to 2nd fp stack item
 rts
end-code mach

code f>1
 add.l  #10,d7
 move.l d7,a0
 move.l -(a0),-(a7)
 move.l -(a0),-(a7)
 subq.l #2,a7
 move.w -(a0),-(a7)
 fmove.x(a7)+,fp0
 rts
end-code mach

code 1>f
 fmove.xfp0,-(a7)
 move.w (a7)+,(a0)+; transfer exponent + sign
 addq.l #2,a7    ; skip16 bit gap
 move.l (a7)+,(a0)+; transfer mantissa 
 move.l (a7)+,(a0)+; in 2 steps
 sub.l  #10,d7   ; adjust FP stack pointer
 rts
end-code mach

( note: f>1 or f>2 and 1>f should always occur in pairs since 1>f expects 
A0 to point to second floating point stack position; this is assured 
by f>1 and f>2 )

code f+
 f>2
 fadd.x fp1,fp0
 1>f
 rts
end-code

code f-
 f>2
 fsub.x fp1,fp0
 1>f
 rts
end-code

code f/
 f>2
 fdiv.x fp1,fp0
 1>f
 rts
end-code

code f*
 f>2
 fmul.x fp1,fp0
 1>f
 rts
end-code

code fmod
 f>2
 fmod.x fp1,fp0
 1>f
 rts
end-code

code frem
 f>2
 frem.x fp1,fp0
 1>f
 rts
end-code

code fabs
 f>1
 fabs.x fp0
 1>f
 rts
end-code

code facos
 f>1
 facos.xfp0
 1>f
 rts
end-code

code fasin
 f>1
 fasin.xfp0
 1>f
 rts
end-code

code fatan
 f>1
 fatan.xfp0
 1>f
 rts
end-code

code fatanh
 f>1
 fatanh.x fp0
 1>f
 rts
end-code

code fcos
 f>1
 fcos.x fp0
 1>f
 rts
end-code

code fcosh
 f>1
 fcosh.xfp0
 1>f
 rts
end-code

code fe^x
 f>1
 fetox.xfp0
 1>f
 rts
end-code
 
code fe^x-1
 f>1
 fetoxm1.x fp0
 1>f
 rts
end-code

code fgetexp
 f>1
 fgetexp.x fp0
 1>f
 rts
end-code

code fgetman
 f>1
 fgetexp.x fp0
 1>f
 rts
end-code

code fint
 f>1
 fint.x fp0
 1>f
 rts
end-code

code fintrz
 f>1
 fintrz.x fp0
 1>f
 rts
end-code

code fln
 f>1
 flogn.x  fp0
 1>f
 rts
end-code

code fln+1
 f>1
 flognp1.x fp0
 1>f
 rts
end-code

code flog10
 f>1
 flog10.x fp0
 1>f
 rts
end-code

code flog2
 f>1
 flog2.x  fp0
 1>f
 rts
end-code

code fneg
 f>1
 fneg.x fp0
 1>f
 rts
end-code

code fsin
 f>1
 fsin.x fp0
 1>f
 rts
end-code

code fsinh
 f>1
 fsinh.x  fp0
 1>f
 rts
end-code

code fsqrt
 f>1
 fsqrt.x  fp0
 1>f
 rts
end-code

code ftan
 f>1
 ftan.x fp0
 1>f
 rts
end-code

code ftanh
 f>1
 ftanh.x  fp0
 1>f
 rts
end-code

code f10^x
 f>1
 ftentox.x fp0
 1>f
 rts
end-code

code f2^x
 f>1
 ftwotox.x fp0
 1>f
 rts
end-code

fp

also forth definitions
code fnull1
 f>1
 1>f
 rts
end-code

code fnull2
 f>2
 1>f
 rts
end-code

: bmark1 counter 1.0 
 100000 0 do fdup fnull1 fdrop loop 
timer fdrop ;

: bmark2 counter 4.3352 
 100000 0 do fdup fe^x fdrop loop 
timer fdrop ;

: bmark3 counter 
 3.5 4.5 100000 0 do fover fover fnull2 fdrop loop 
timer fdrop fdrop ;

: bmark4 counter 
 3.5 4.5 100000 0 do fover fover f+ fdrop loop 
timer fdrop fdrop ;

: bmark5 counter 
 3.5 4.5 100000 0 do fover fover f* fdrop loop 
timer fdrop fdrop ;

also sane

: smark1 counter 
 1.0 10000 0 do fdup fnull1 fdrop loop 
timer fdrop ;

: smark2 counter 
 4.3352 10000 0 do fdup fe^x fdrop loop 
timer fdrop ;

: smark3 counter 
 3.5 4.5 10000 0 do fover fover fnull2 fdrop loop 
timer fdrop fdrop ;

: smark4 counter 
 3.5 4.5 10000 0 do fover fover f+ fdrop loop 
timer fdrop fdrop ;

: smark5 counter 
 3.5 4.5 10000 0 do fover fover f* fdrop loop 
timer fdrop fdrop ;
Listing 2: Pop up menus
\ popup menu interface from Forth
\ © J. Langowski/MacTutor Jan 1988

\ FUNCTION PopUpMenuSelect 
\ (menu: MenuHandle; top, left, popUpItem: INTEGER):
\LONGINT;
\  INLINE $A80B;

code popup ( hMenu top left item# | menuID item  -- )
 exg  d4,a7
 clr.l  -(a7)
 move.l 12(a6),-(a7) \ handle
 move.w 10(a6),-(a7) \ top
 move.w 6(a6),-(a7)\ left
 move.w 2(a6),-(a7)\ item
 adda.l #16,A6
 _popupmenuselect
 clr.l  d0
 clr.l  d1
 move.w (a7)+,d0
 move.w (a7)+,d1
 exg  d4,a7
 move.l d0,-(a6)
 move.l d1,-(a6)
 rts
end-code

CODE  @MOUSE
    SUBQ.L    #4,A6
    MOVE.L    A6,-(A7)
    _GETMOUSE
    RTS
END-CODE

CODE unpack
 MOVE.L (A6),D0
 CLR.L  D1
 MOVE.W D0,D1
 CLR.W  D0
 SWAP.W D0
 MOVE.L D0,(A6)
 MOVE.L D1,-(A6)
 RTS
END-CODE MACH

108 user taskmenubar
152 user content-hook

NEW.MENU myMenu
“ TestMenu” myMenu TITLE
-1 150 myMenu BOUNDS \ invisible menu
“ Item 1;Item 2;Item 3” myMenu ITEMS

taskmenubar @ mymenu add
call drawmenubar

: beep 
 ?dup if 
 0 do 5 call sysbeep loop 
 then
;

: content-handler { | pt -- }
 @mouse -> pt
 ^ pt call localtoglobal
 mymenu @
 pt unpack
 1
 popup
 beep drop
 run-content
;

: dopop [‘] content-handler content-hook ! ;
: nopop [‘] run-content content-hook ! ;
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Live Home 3D Pro 3.6.2 - $49.99
Live Home 3D Pro is powerful yet intuitive home design software that lets you build the house of your dreams right on your Mac, iPhone or iPad. It has every feature of Live Home 3D, plus some... Read more
RapidWeaver 8.2 - Create template-based...
RapidWeaver is a next-generation Web design application to help you easily create professional-looking Web sites in minutes. No knowledge of complex code is required, RapidWeaver will take care of... Read more
Opera 60.0.3255.109 - High-performance W...
Opera is a fast and secure browser trusted by millions of users. With the intuitive interface, Speed Dial and visual bookmarks for organizing favorite sites, news feature with fresh, relevant content... Read more
DEVONthink Pro 3.0beta2 - Knowledge base...
DEVONthink Pro is your essential assistant for today's world, where almost everything is digital. From shopping receipts to important research papers, your life often fills your hard drive in the... Read more
Tunnelblick 3.7.9 - GUI for OpenVPN.
Tunnelblick is a free, open source graphic user interface for OpenVPN on OS X. It provides easy control of OpenVPN client and/or server connections. It comes as a ready-to-use application with all... Read more
Carbon Copy Cloner 5.1.9 - Easy-to-use b...
Carbon Copy Cloner backups are better than ordinary backups. Suppose the unthinkable happens while you're under deadline to finish a project: your Mac is unresponsive and all you hear is an ominous,... Read more
Dropbox 73.4.118 - Cloud backup and sync...
Dropbox is an application that creates a special Finder folder that automatically syncs online and between your computers. It allows you to both backup files and keeps them up-to-date between systems... Read more
Postbox 6.1.18 - Powerful and flexible e...
Postbox is a new email application that helps you organize your work life and get stuff done. It has all the elegance and simplicity of Apple Mail, but with more power and flexibility to manage even... Read more
Wireshark 3.0.2 - Network protocol analy...
Wireshark is one of the world's foremost network protocol analyzers, and is the standard in many parts of the industry. It is the continuation of a project that started in 1998. Hundreds of... Read more
BetterTouchTool 2.856 - Customize multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more

AFK Arena guide - Everything you need to...
Ok, so if you're like me, you've been playing (and sometimes waiting) your way through AFK Arena, only to learn there's a lot more to it than there appears on the surface. There's guilds, a PvP arena, and all sorts of other systems and game modes... | Read more »
Explore an epic fantasy world in MMORPG...
Webzen have just announced the official launch date for its stunning MMORPG ‘MU Origin 2’ which will arrive for iOS and Android on May 28th. It will be the second spinoff from the classic PC-based MU Online, and it looks to further refine the... | Read more »
Solar Explorer: New Dawn guide - Tips an...
Solar Explorer: New Dawn is a lunar lander game that really ratchets the intensity up to 11. With all of the asteroids flying around as you fly around at seemingly breakneck speeds, it can be easy to feel overwhelmed bythe whole thing. | Read more »
The Dalaran Heist - How Hearthstone...
I am someone who wrote Hearthstone off a while ago. It was hard not to try and stick with it. The game has incredible production values and a core of really great talent working on the game continuously to keep it feeling fresh and fun (full... | Read more »
Steam Link App - Everything You Need to...
Steam Link has finally released for iOS! That’s right, you can play your epic backlog of PC games on the go now. Well… sort of. While the Steam Link app was announced seemingly ages ago, it only got actual approval for release last night. Check out... | Read more »
Pre-register now for endless superhero r...
Talking Tom Hero Dash is set to take the ever-popular Talking Tom and Friends franchise in a brand new direction as it opens pre-registration to players worldwide. Not only does it promise to be a beautifully rendered, fast-paced, action-packed... | Read more »
AFK Arena - Guild Wars guide
Ok, so if you're like me, you've been playing (and sometimes waiting) your way through AFK Arena, only to learn there's a lot more to it than there appears on the surface. There's guilds, a PvP arena, and all sorts of other systems and game modes... | Read more »
Superhero-themed Talking Tom Hero Dash i...
One of the exciting releases that we’re looking forward to is Talking Tom Hero Dash, an upcoming superhero-themed runner created by Outfit7. This new game is an action-packed endless runner that takes you on an epic adventure to assemble the... | Read more »
Kingdom Rush Vengeance Update Guide 2 -...
Kingdom Rush: Vengeance just got updated once again to add more content to the game. This addition, called The Frozen Nightmare, adds three new levels, five new enemies, two new heroes, and some new achievements. | Read more »
Save the world with SCIENCE in the upcom...
Previous versions of space colonization game TerraGenesis encouraged you to explore the galaxy and settle its planets. The eagerly-awaited 5.0 update will try to smash them to bits. Yep, with a new "world killers" setting, you can unleash... | Read more »

Price Scanner via MacPrices.net

12″ 1.2GHz MacBooks on sale for $999, $300 of...
Amazon has current-generation 12″ 1.2GHz Retina MacBooks on sale for $300 off Apple’s MSRP. Shipping is free: 12″ 1.2GHz Space Gray MacBook: $999.99 $300 off MSRP 12″ 1.2GHz Silver MacBook: $999.99 $... Read more
Here’s how to save $200 on Apple’s new 8-Core...
Apple has released details of their Education discount associated with the new 2019 15″ 6-Core and 8-Core MacBook Pros. Take $200 off the price of the new 8-Core model (now $2599) and $150 off the 15... Read more
Price drops! 2018 15″ 2.2GHz 6-Core MacBook P...
Amazon has dropped prices on clearance 2018 15″ 2.2GHz 6-Core Touch Bar MacBook Pros by $300 with models now available for $2099. These are the same models sold by Apple in their retail and online... Read more
Apple drops prices on 2018 13″ 2.3GHz Quad-Co...
Apple has dropped prices on Certified Refurbished 2018 13″ 2.3GHz 4-Core Touch Bar MacBook Pros with prices now starting at $1489. Apple’s one-year warranty is included, shipping is free, and each... Read more
Apple drops prices on 2018 Certified Refurbis...
Apple has dropped prices on clearance 2018 15″ 6-Core Touch Bar MacBook Pro, Certified Refurbished, with models available starting at only $1999. Each model features a new outer case, shipping is... Read more
Price drops! Clearance 2018 13″ Quad Core Mac...
Amazon has dropped prices on 2018 13″ Apple Quad-Core MacBook Pros with models now available for $250 off original MSRP. Shipping is free. Select Amazon as the seller, rather than a third-party, to... Read more
How Much Is ‘Solace’ Of Mind Worth When Buyin...
COMMENTARY: 05.22.19- Smartphone cases give us peace of mind by providing ample protection for such a fragile gadget and the sky’s the limit as far as choices go with a plethora of brands, styles,... Read more
Get a 13″ Touch Bar MacBook Pro for the lowes...
Apple has Certified Refurbished 2017 13″ 3.1GHz Dual-Core i5 Touch Bar MacBook Pros available starting at $1439, ranging up to $390 off original MSRP. Each MacBook features a new outer case, shipping... Read more
Apple adds new 15″ 8-Core MacBook Pro to line...
Apple has added a new 15″ MacBook Pro to its lineup featuring a 9th generation 2.3GHz 8-Core Intel i9 processor, 16GB of RAM, a 512GB SSD, and a Radeon Pro 560X with 4GB of GDDR5 memory for $2799.... Read more
21″ 2.3GHz iMac available for $999 at B&H...
B&H Photo has the 2018 21″ 2.3GHz Apple iMac on sale for $100 off MSRP. This is the same model offering by Apple in their retail and online stores. Shipping is free: – 21″ 2.3GHz iMac (MMQA2LL/A... Read more

Jobs Board

Best Buy *Apple* Computing Master - Best Bu...
**690427BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Location Number:** 000860-Charlottesville-Store **Job Description:** **What Read more
*Apple* Mobile Master - Best Buy (United Sta...
**696430BR** **Job Title:** Apple Mobile Master **Job Category:** Store Associates **Location Number:** 001012-Bismarck-Store **Job Description:** **What does a Best Read more
Manager - *Apple* Team - SHI International...
…opportunity available in the Hardware & Advanced Solutions Department as the Manager of the Apple Team The Manager must be familiar with all aspects of Apple Read more
Best Buy *Apple* Computing Master - Best Bu...
**696375BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Location Number:** 000203-North Austin-Store **Job Description:** **What does a Read more
Geek Squad *Apple* Master Consultation Agen...
**696286BR** **Job Title:** Geek Squad Apple Master Consultation Agent **Job Category:** Services/Installation/Repair **Location Number:** 000172-Rivergate-Store Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.