]> Git Repo - qemu.git/blame - target-ppc/dfp_helper.c
target-ppc: Introduce DFP Post Processor Utilities
[qemu.git] / target-ppc / dfp_helper.c
CommitLineData
7b0c0d66
TM
1/*
2 * PowerPC Decimal Floating Point (DPF) emulation helpers for QEMU.
3 *
4 * Copyright (c) 2014 IBM Corporation.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "cpu.h"
21#include "exec/helper-proto.h"
22
23#define DECNUMDIGITS 34
24#include "libdecnumber/decContext.h"
25#include "libdecnumber/decNumber.h"
26#include "libdecnumber/dpd/decimal32.h"
27#include "libdecnumber/dpd/decimal64.h"
28#include "libdecnumber/dpd/decimal128.h"
29
30#if defined(HOST_WORDS_BIGENDIAN)
31#define HI_IDX 0
32#define LO_IDX 1
33#else
34#define HI_IDX 1
35#define LO_IDX 0
36#endif
37
38struct PPC_DFP {
39 CPUPPCState *env;
40 uint64_t t64[2], a64[2], b64[2];
41 decNumber t, a, b;
42 decContext context;
43 uint8_t crbf;
44};
45
46static void dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr)
47{
48 enum rounding rnd;
49
50 switch ((fpscr >> 32) & 0x7) {
51 case 0:
52 rnd = DEC_ROUND_HALF_EVEN;
53 break;
54 case 1:
55 rnd = DEC_ROUND_DOWN;
56 break;
57 case 2:
58 rnd = DEC_ROUND_CEILING;
59 break;
60 case 3:
61 rnd = DEC_ROUND_FLOOR;
62 break;
63 case 4:
64 rnd = DEC_ROUND_HALF_UP;
65 break;
66 case 5:
67 rnd = DEC_ROUND_HALF_DOWN;
68 break;
69 case 6:
70 rnd = DEC_ROUND_UP;
71 break;
72 case 7:
73 rnd = DEC_ROUND_05UP;
74 break;
75 default:
76 g_assert_not_reached();
77 }
78
79 decContextSetRounding(context, rnd);
80}
81
82__attribute__ ((unused))
83static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a,
84 uint64_t *b, CPUPPCState *env)
85{
86 decContextDefault(&dfp->context, DEC_INIT_DECIMAL64);
87 dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
88 dfp->env = env;
89
90 if (a) {
91 dfp->a64[0] = *a;
92 decimal64ToNumber((decimal64 *)dfp->a64, &dfp->a);
93 } else {
94 dfp->a64[0] = 0;
95 decNumberZero(&dfp->a);
96 }
97
98 if (b) {
99 dfp->b64[0] = *b;
100 decimal64ToNumber((decimal64 *)dfp->b64, &dfp->b);
101 } else {
102 dfp->b64[0] = 0;
103 decNumberZero(&dfp->b);
104 }
105}
106
107__attribute__ ((unused))
108static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a,
109 uint64_t *b, CPUPPCState *env)
110{
111 decContextDefault(&dfp->context, DEC_INIT_DECIMAL128);
112 dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
113 dfp->env = env;
114
115 if (a) {
116 dfp->a64[0] = a[HI_IDX];
117 dfp->a64[1] = a[LO_IDX];
118 decimal128ToNumber((decimal128 *)dfp->a64, &dfp->a);
119 } else {
120 dfp->a64[0] = dfp->a64[1] = 0;
121 decNumberZero(&dfp->a);
122 }
123
124 if (b) {
125 dfp->b64[0] = b[HI_IDX];
126 dfp->b64[1] = b[LO_IDX];
127 decimal128ToNumber((decimal128 *)dfp->b64, &dfp->b);
128 } else {
129 dfp->b64[0] = dfp->b64[1] = 0;
130 decNumberZero(&dfp->b);
131 }
132}
27722744
TM
133
134#define FP_FX (1ull << FPSCR_FX)
135#define FP_FEX (1ull << FPSCR_FEX)
136#define FP_OX (1ull << FPSCR_OX)
137#define FP_OE (1ull << FPSCR_OE)
138#define FP_UX (1ull << FPSCR_UX)
139#define FP_UE (1ull << FPSCR_UE)
140#define FP_XX (1ull << FPSCR_XX)
141#define FP_XE (1ull << FPSCR_XE)
142#define FP_ZX (1ull << FPSCR_ZX)
143#define FP_ZE (1ull << FPSCR_ZE)
144#define FP_VX (1ull << FPSCR_VX)
145#define FP_VXSNAN (1ull << FPSCR_VXSNAN)
146#define FP_VXISI (1ull << FPSCR_VXISI)
147#define FP_VXIMZ (1ull << FPSCR_VXIMZ)
148#define FP_VXZDZ (1ull << FPSCR_VXZDZ)
149#define FP_VXIDI (1ull << FPSCR_VXIDI)
150#define FP_VXVC (1ull << FPSCR_VXVC)
151#define FP_VXCVI (1ull << FPSCR_VXCVI)
152#define FP_VE (1ull << FPSCR_VE)
153#define FP_FI (1ull << FPSCR_FI)
154
155__attribute__ ((unused))
156static void dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag,
157 uint64_t enabled)
158{
159 dfp->env->fpscr |= (flag | FP_FX);
160 if (dfp->env->fpscr & enabled) {
161 dfp->env->fpscr |= FP_FEX;
162 }
163}
This page took 0.036264 seconds and 4 git commands to generate.