1// -*- mode:c++ -*-
2
3// Copyright (c) 2015 Riscv Developers
4// Copyright (c) 2016-2017 The University of Virginia
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are
9// met: redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer;
11// redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution;
14// neither the name of the copyright holders nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Authors: Alec Roelke
31
32////////////////////////////////////////////////////////////////////
33//
34// Floating point operation instructions
35//
36def template FloatExecute {{
37    Fault %(class_name)s::execute(ExecContext *xc,
38        Trace::InstRecord *traceData) const
39    {
40        Fault fault = NoFault;
41
42        %(op_decl)s;
43        %(op_rd)s;
44        if (fault == NoFault) {
45            switch (ROUND_MODE) {
46            case 0x0:
47                std::fesetround(FE_TONEAREST);
48                break;
49            case 0x1:
50                std::fesetround(FE_TOWARDZERO);
51                break;
52            case 0x2:
53                std::fesetround(FE_DOWNWARD);
54                break;
55            case 0x3:
56                std::fesetround(FE_UPWARD);
57                break;
58            case 0x4:
59                // Round to nearest, ties to max magnitude not implemented
60                fault = make_shared<IllegalFrmFault>(ROUND_MODE, machInst);
61                break;
62            case 0x7: {
63                uint8_t frm = xc->readMiscReg(MISCREG_FRM);
64                switch (frm) {
65                case 0x0:
66                    std::fesetround(FE_TONEAREST);
67                    break;
68                case 0x1:
69                    std::fesetround(FE_TOWARDZERO);
70                    break;
71                case 0x2:
72                    std::fesetround(FE_DOWNWARD);
73                    break;
74                case 0x3:
75                    std::fesetround(FE_UPWARD);
76                    break;
77                case 0x4:
78                    // Round to nearest, ties to max magnitude not implemented
79                    fault = make_shared<IllegalFrmFault>(ROUND_MODE, machInst);
80                    break;
81                default:
82                    fault = std::make_shared<IllegalFrmFault>(frm, machInst);
83                    break;
84                }
85                break;
86            }
87            default:
88                fault = std::make_shared<IllegalFrmFault>(ROUND_MODE,
89                                                          machInst);
90                break;
91            }
92
93            if (fault == NoFault) {
94                RegVal FFLAGS = xc->readMiscReg(MISCREG_FFLAGS);
95                std::feclearexcept(FE_ALL_EXCEPT);
96                %(code)s;
97                if (std::fetestexcept(FE_INEXACT)) {
98                    FFLAGS |= FloatInexact;
99                }
100                if (std::fetestexcept(FE_UNDERFLOW)) {
101                    FFLAGS |= FloatUnderflow;
102                }
103                if (std::fetestexcept(FE_OVERFLOW)) {
104                    FFLAGS |= FloatOverflow;
105                }
106                if (std::fetestexcept(FE_DIVBYZERO)) {
107                    FFLAGS |= FloatDivZero;
108                }
109                if (std::fetestexcept(FE_INVALID)) {
110                    FFLAGS |= FloatInvalid;
111                }
112                xc->setMiscReg(MISCREG_FFLAGS, FFLAGS);
113            }
114
115            if (fault == NoFault) {
116                %(op_wb)s;
117            }
118        }
119        return fault;
120    }
121}};
122
123def format FPROp(code, *opt_flags) {{
124    iop = InstObjParams(name, Name, 'RegOp', code, opt_flags)
125    header_output = BasicDeclare.subst(iop)
126    decoder_output = BasicConstructor.subst(iop)
127    decode_block = BasicDecode.subst(iop)
128    exec_output = FloatExecute.subst(iop)
129}};
130