1 /*
2 * Copyright (C) 2002-2021 The DOSBox Team
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #ifndef DOSBOX_LAZYFLAGS_H
20 #define DOSBOX_LAZYFLAGS_H
21
22 #include "cpu.h"
23
24 #include <cassert>
25
26 // Flag Handling
27 uint32_t get_CF();
28 uint32_t get_AF();
29 uint32_t get_ZF();
30 uint32_t get_SF();
31 uint32_t get_OF();
32 uint32_t get_PF();
33
34 uint32_t FillFlags(void);
35 void FillFlagsNoCFOF(void);
36 void DestroyConditionFlags(void);
37
38 #ifndef DOSBOX_REGS_H
39 #include "regs.h"
40 #endif
41
42 struct LazyFlags {
43 GenReg32 var1 = {};
44 GenReg32 var2 = {};
45 GenReg32 res = {};
46 Bitu type = 0;
47 Bitu prev_type = 0;
48 Bitu oldcf = 0;
49 };
50
51 extern LazyFlags lflags;
52
53 inline constexpr uint8_t &lf_var1b = lflags.var1.byte[BL_INDEX];
54 inline constexpr uint8_t &lf_var2b = lflags.var2.byte[BL_INDEX];
55 inline constexpr uint8_t &lf_resb = lflags.res.byte[BL_INDEX];
56
57 inline constexpr uint16_t &lf_var1w = lflags.var1.word[W_INDEX];
58 inline constexpr uint16_t &lf_var2w = lflags.var2.word[W_INDEX];
59 inline constexpr uint16_t &lf_resw = lflags.res.word[W_INDEX];
60
61 inline constexpr uint32_t &lf_var1d = lflags.var1.dword[DW_INDEX];
62 inline constexpr uint32_t &lf_var2d = lflags.var2.dword[DW_INDEX];
63 inline constexpr uint32_t &lf_resd = lflags.res.dword[DW_INDEX];
64
65 // many places in the code want to shift by "lf_var2b - 1", so this wrapper
66 // catches potential negative shifts.
lf_var2b_minus_one()67 inline uint8_t lf_var2b_minus_one()
68 {
69 assert(lf_var2b > 0);
70 return lf_var2b - 1;
71 }
72
73 // Types of Flag changing instructions
74 enum {
75 t_UNKNOWN=0,
76 t_ADDb,t_ADDw,t_ADDd,
77 t_ORb,t_ORw,t_ORd,
78 t_ADCb,t_ADCw,t_ADCd,
79 t_SBBb,t_SBBw,t_SBBd,
80 t_ANDb,t_ANDw,t_ANDd,
81 t_SUBb,t_SUBw,t_SUBd,
82 t_XORb,t_XORw,t_XORd,
83 t_CMPb,t_CMPw,t_CMPd,
84 t_INCb,t_INCw,t_INCd,
85 t_DECb,t_DECw,t_DECd,
86 t_TESTb,t_TESTw,t_TESTd,
87 t_SHLb,t_SHLw,t_SHLd,
88 t_SHRb,t_SHRw,t_SHRd,
89 t_SARb,t_SARw,t_SARd,
90 t_ROLb,t_ROLw,t_ROLd,
91 t_RORb,t_RORw,t_RORd,
92 t_RCLb,t_RCLw,t_RCLd,
93 t_RCRb,t_RCRw,t_RCRd,
94 t_NEGb,t_NEGw,t_NEGd,
95
96 t_DSHLw,t_DSHLd,
97 t_DSHRw,t_DSHRd,
98 t_MUL,t_DIV,
99 t_NOTDONE,
100 t_LASTFLAG
101 };
102
SETFLAGSb(const uint8_t FLAGB)103 inline void SETFLAGSb(const uint8_t FLAGB)
104 {
105 SETFLAGBIT(OF, get_OF());
106 lflags.type = t_UNKNOWN;
107 CPU_SetFlags(FLAGB, FMASK_NORMAL & 0xff);
108 }
109
SETFLAGSw(const uint16_t FLAGW)110 inline void SETFLAGSw(const uint16_t FLAGW)
111 {
112 lflags.type = t_UNKNOWN;
113 CPU_SetFlagsw(FLAGW);
114 }
115
SETFLAGSd(const uint32_t FLAGD)116 inline void SETFLAGSd(const uint32_t FLAGD)
117 {
118 lflags.type = t_UNKNOWN;
119 CPU_SetFlagsd(FLAGD);
120 }
121
122 #define LoadCF SETFLAGBIT(CF, get_CF());
123 #define LoadZF SETFLAGBIT(ZF, get_ZF());
124 #define LoadSF SETFLAGBIT(SF, get_SF());
125 #define LoadOF SETFLAGBIT(OF, get_OF());
126 #define LoadAF SETFLAGBIT(AF, get_AF());
127
128 #define TFLG_O (get_OF())
129 #define TFLG_NO (!get_OF())
130 #define TFLG_B (get_CF())
131 #define TFLG_NB (!get_CF())
132 #define TFLG_Z (get_ZF())
133 #define TFLG_NZ (!get_ZF())
134 #define TFLG_BE (get_CF() || get_ZF())
135 #define TFLG_NBE (!get_CF() && !get_ZF())
136 #define TFLG_S (get_SF())
137 #define TFLG_NS (!get_SF())
138 #define TFLG_P (get_PF())
139 #define TFLG_NP (!get_PF())
140 #define TFLG_L ((get_SF() != 0) != (get_OF() != 0))
141 #define TFLG_NL ((get_SF() != 0) == (get_OF() != 0))
142 #define TFLG_LE (get_ZF() || ((get_SF() != 0) != (get_OF() != 0)))
143 #define TFLG_NLE (!get_ZF() && ((get_SF() != 0) == (get_OF() != 0)))
144
145 #endif
146