001    // This file is part of the program FRYSK.
002    //
003    // Copyright 2007, Red Hat Inc.
004    //
005    // FRYSK is free software; you can redistribute it and/or modify it
006    // under the terms of the GNU General Public License as published by
007    // the Free Software Foundation; version 2 of the License.
008    //
009    // FRYSK is distributed in the hope that it will be useful, but
010    // WITHOUT ANY WARRANTY; without even the implied warranty of
011    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012    // General Public License for more details.
013    // 
014    // You should have received a copy of the GNU General Public License
015    // along with FRYSK; if not, write to the Free Software Foundation,
016    // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
017    // 
018    // In addition, as a special exception, Red Hat, Inc. gives You the
019    // additional right to link the code of FRYSK with code not covered
020    // under the GNU General Public License ("Non-GPL Code") and to
021    // distribute linked combinations including the two, subject to the
022    // limitations in this paragraph. Non-GPL Code permitted under this
023    // exception must only link to the code of FRYSK through those well
024    // defined interfaces identified in the file named EXCEPTION found in
025    // the source code files (the "Approved Interfaces"). The files of
026    // Non-GPL Code may instantiate templates or use macros or inline
027    // functions from the Approved Interfaces without causing the
028    // resulting work to be covered by the GNU General Public
029    // License. Only Red Hat, Inc. may make changes or additions to the
030    // list of Approved Interfaces. You must obey the GNU General Public
031    // License in all respects for all of the FRYSK code and other code
032    // used in conjunction with FRYSK except the Non-GPL Code covered by
033    // this exception. If you modify this file, you may extend this
034    // exception to your version of the file, but you are not obligated to
035    // do so. If you do not wish to provide this exception without
036    // modification, you must delete this exception statement from your
037    // version and license this file solely under the GPL without
038    // exception.
039    
040    package frysk.value;
041    
042    import inua.eio.ByteOrder;
043    import inua.eio.ByteBuffer;
044    import java.io.PrintWriter;
045    import java.math.BigInteger;
046    
047    /**
048     * Type for a floating-point value.
049     */
050    
051    public class FloatingPointType
052        extends ArithmeticType
053    {    
054            
055        private FloatingPointFormat format;
056            
057        public FloatingPointType(String name, ByteOrder order, int size) {
058            super(name, order, size);
059            
060            switch (size) {
061            case 4: format = FloatingPoint854Format.IEEE32;
062            break;
063            case 8: format = FloatingPoint854Format.IEEE64;
064            break;
065            case 16:format = FloatingPoint854Format.IEEE128;
066            break;
067            case 10:format = FloatingPoint854Format.IEEE80;
068            break;
069            case 12:format = FloatingPoint854Format.IEEE96;
070            break;
071            default:format = FloatingPoint854Format.IEEE64;
072            break;
073            }
074        }
075    
076        public void toPrint(PrintWriter writer, Location location,
077                            ByteBuffer memory, Format format, int indent) {
078            // double-dispatch.
079            format.print(writer, location, this);
080        }
081        
082        /**
083         * Prints value as a hexadecimal float constant. 
084         * eg. double value 9.0 --> 0x1.2p+0
085         */
086        public void printAsHexConstant (PrintWriter writer, Location loc) {
087            byte[] bytes = loc.get(order());
088            FloatingPoint854Format f = (FloatingPoint854Format)format;
089            writer.print(f.getSign(bytes)==0? "":"-");
090            writer.print("0x");
091            writer.print(f.getIntegralOfMantissa(bytes));
092            writer.print('.');
093            writer.print(f.getFraction(bytes).toString(16));
094            writer.print('p');
095            writer.print(f.getBiasedExponent(bytes).intValue() 
096                         - f.getMaxEValue().intValue()/2);
097        }
098        
099        /**
100         * Return the raw bytes as an unsigned integer.
101         */
102        BigInteger getBigInteger(Location location) {
103            return new BigInteger(1, location.get(order()));
104        }
105    
106        void putBigInteger(Location location, BigInteger val) {
107            location.put(order(), val.toByteArray(), 0);
108        }
109    
110        void putBigFloatingPoint(Location location, BigFloatingPoint val) {
111            location.put(order(), this.format.pack(val, this.getSize()), 0);
112        }
113       
114        BigFloatingPoint getBigFloatingPoint(Location location) {
115            return format.unpack(location.get(order()));
116        }
117    
118        BigFloatingPoint bigFloatingPointValue(Location location) {
119            return getBigFloatingPoint(location);
120        }
121    
122        BigInteger bigIntegerValue (Location location) {
123            return getBigFloatingPoint(location).bigIntegerValue();
124        }
125    
126        void assign(Location location, Value v) {
127            BigFloatingPoint f = ((FloatingPointType)v.getType()).bigFloatingPointValue(v.getLocation());
128            location.put(order(), format.pack(f, getSize()), 0);
129        }
130        
131        /* getALUs are double dispatch functions to determine 
132         * the ArithmeticUnit for an operation between two types.
133         */
134        public ArithmeticUnit getALU(Type type, int wordSize) {
135            return type.getALU(this, wordSize);
136        }    
137        public ArithmeticUnit getALU(IntegerType type, int wordSize) {
138            return new FloatingPointUnit(this, wordSize);
139        }    
140        public ArithmeticUnit getALU(FloatingPointType type, int wordSize) {
141            return new FloatingPointUnit(this, type, wordSize);
142        }       
143        public ArithmeticUnit getALU(PointerType type, int wordSize) {
144            throw new RuntimeException("Invalid Pointer Arithmetic");
145        }    
146        // Use for unary operations.
147        public ArithmeticUnit getALU(int wordSize) {
148            return new FloatingPointUnit(this, wordSize);
149        }    
150    }