1 /*******************************************************
2  *
3  *      Portable (hopefully ;-) 8085A emulator
4  *
5  *      Written by J. Buchmueller for use with MAME
6  *
7  *		Partially based on Z80Em by Marcel De Kogel
8  *
9  *      CPU related macros
10  *
11  *******************************************************/
12 
13 /* Set to 1 for a more exact i8080 emulation */
14 #define I8080_EXACT	1
15 
16 #define SF              0x80
17 #define ZF              0x40
18 #define YF              0x20
19 #define HF              0x10
20 #define XF              0x08
21 #define VF              0x04
22 #define NF              0x02
23 #define CF              0x01
24 
25 #define IM_SID          0x80
26 #define IM_SOD          0x40
27 //#define IM_IEN          0x20
28 #define IM_INTR         0x20 //AT: the 8085 ignores bit 0x20. we move IM_INTR here for compatibility.
29 #define IM_TRAP         0x10
30 //#define IM_INTR         0x08
31 #define IM_IEN          0x08 //AT: RIM returns IEN status on this bit. SIM checks this bit to allow masking RST55-75
32 #define IM_RST75        0x04
33 #define IM_RST65        0x02
34 #define IM_RST55        0x01
35 
36 #define ADDR_TRAP       0x0024
37 #define ADDR_RST55      0x002c
38 #define ADDR_RST65      0x0034
39 #define ADDR_RST75      0x003c
40 #define ADDR_INTR       0x0038
41 
42 #define M_INR(R) ++R; I.AF.b.l=(I.AF.b.l&CF)|ZSP[R]|((R==0x80)?VF:0)|((R&0x0F)?0:HF)
43 #define M_DCR(R) I.AF.b.l=(I.AF.b.l&CF)|NF|((R==0x80)?VF:0)|((R&0x0F)?0:HF); I.AF.b.l|=ZSP[--R]
44 #define M_MVI(R) R=ARG()
45 
46 #define M_ANA(R) I.AF.b.h&=R; I.AF.b.l=ZSP[I.AF.b.h]|HF
47 #define M_ORA(R) I.AF.b.h|=R; I.AF.b.l=ZSP[I.AF.b.h]
48 #define M_XRA(R) I.AF.b.h^=R; I.AF.b.l=ZSP[I.AF.b.h]
49 
50 #define M_RLC { 												\
51 	I.AF.b.h = (I.AF.b.h << 1) | (I.AF.b.h >> 7);				\
52 	I.AF.b.l = (I.AF.b.l & ~(HF+NF+CF)) | (I.AF.b.h & CF);		\
53 }
54 
55 #define M_RRC { 												\
56 	I.AF.b.l = (I.AF.b.l & ~(HF+NF+CF)) | (I.AF.b.h & CF);		\
57 	I.AF.b.h = (I.AF.b.h >> 1) | (I.AF.b.h << 7);				\
58 }
59 
60 #define M_RAL { 												\
61 	int c = I.AF.b.l&CF;										\
62 	I.AF.b.l = (I.AF.b.l & ~(HF+NF+CF)) | (I.AF.b.h >> 7);		\
63 	I.AF.b.h = (I.AF.b.h << 1) | c; 							\
64 }
65 
66 #define M_RAR { 												\
67 	int c = (I.AF.b.l&CF) << 7; 								\
68 	I.AF.b.l = (I.AF.b.l & ~(HF+NF+CF)) | (I.AF.b.h & CF);		\
69 	I.AF.b.h = (I.AF.b.h >> 1) | c; 							\
70 }
71 
72 #if I8080_EXACT
73 #define M_ADD(R) {							\
74 int q = I.AF.b.h+R; 							\
75 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)| 				\
76 		((I.AF.b.h^q^R)&HF)|					\
77 		(((R^I.AF.b.h^SF)&(R^q)&SF)>>5);			\
78 	I.AF.b.h=q; 							\
79 }
80 #else
81 #ifdef X86_ASM
82 #define M_ADD(R)												\
83  asm (															\
84  " addb %2,%0           \n"                                     \
85  " lahf                 \n"                                     \
86  " setob %%al           \n" /* al = 1 if overflow */            \
87  " shlb $2,%%al         \n" /* shift to P/V bit position */     \
88  " andb $0xd1,%%ah      \n" /* sign, zero, half carry, carry */ \
89  " orb %%ah,%%al        \n"                                     \
90  :"=mq" (I.AF.b.h), "=a" (I.AF.b.l)                              \
91  :"q" (R), "0" (I.AF.b.h)                                       \
92  )
93 #else
94 #define M_ADD(R) {												\
95 int q = I.AF.b.h+R; 											\
96 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)| 				\
97 		((I.AF.b.h^q^R)&HF)|									\
98 		(((R^I.AF.b.h^SF)&(R^q)&SF)>>5);						\
99 	I.AF.b.h=q; 												\
100 }
101 #endif
102 #endif
103 
104 #if I8080_EXACT
105 #define M_ADC(R) {						\
106 	int q = I.AF.b.h+R+(I.AF.b.l&CF);			\
107 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)| 			\
108 		((I.AF.b.h^q^R)&HF)|				\
109 		(((R^I.AF.b.h^SF)&(R^q)&SF)>>5);		\
110 	I.AF.b.h=q; 						\
111 }
112 #else
113 #ifdef X86_ASM
114 #define M_ADC(R)												\
115  asm (															\
116  " shrb $1,%%al         \n"                                     \
117  " adcb %2,%0           \n"                                     \
118  " lahf                 \n"                                     \
119  " setob %%al           \n" /* al = 1 if overflow */            \
120  " shlb $2,%%al         \n" /* shift to P/V bit position */     \
121  " andb $0xd1,%%ah      \n" /* sign, zero, half carry, carry */ \
122  " orb %%ah,%%al        \n" /* combine with P/V */              \
123  :"=mq" (I.AF.b.h), "=a" (I.AF.b.l)				\
124  :"q" (R), "a" (I.AF.b.l), "0" (I.AF.b.h)                       \
125  )
126 #else
127 #define M_ADC(R) {						\
128 	int q = I.AF.b.h+R+(I.AF.b.l&CF);			\
129 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)| 			\
130 		((I.AF.b.h^q^R)&HF)|				\
131 		(((R^I.AF.b.h^SF)&(R^q)&SF)>>5);		\
132 	I.AF.b.h=q; 						\
133 }
134 #endif
135 #endif
136 
137 #if I8080_EXACT
138 #define M_SUB(R) {							\
139 	int q = I.AF.b.h-R; 						\
140 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)|NF|				\
141 		((I.AF.b.h^q^R)&HF)|					\
142 		(((R^I.AF.b.h)&(I.AF.b.h^q)&SF)>>5);			\
143 	I.AF.b.h=q; 							\
144 }
145 #else
146 #ifdef X86_ASM
147 #define M_SUB(R)												\
148  asm (															\
149  " subb %2,%0           \n"                                     \
150  " lahf                 \n"                                     \
151  " setob %%al           \n" /* al = 1 if overflow */            \
152  " shlb $2,%%al         \n" /* shift to P/V bit position */     \
153  " andb $0xd1,%%ah      \n" /* sign, zero, half carry, carry */ \
154  " orb $2,%%al          \n" /* set N flag */                    \
155  " orb %%ah,%%al        \n" /* combine with P/V */              \
156  :"=mq" (I.AF.b.h), "=a" (I.AF.b.l)                              \
157  :"q" (R), "0" (I.AF.b.h)                                       \
158  )
159 #else
160 #define M_SUB(R) {												\
161 	int q = I.AF.b.h-R; 										\
162 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)|NF|				\
163 		((I.AF.b.h^q^R)&HF)|									\
164 		(((R^I.AF.b.h)&(I.AF.b.h^q)&SF)>>5);					\
165 	I.AF.b.h=q; 												\
166 }
167 #endif
168 #endif
169 
170 #if I8080_EXACT
171 #define M_SBB(R) {                                              \
172 	int q = I.AF.b.h-R-(I.AF.b.l&CF);			\
173 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)|NF|			\
174 		((I.AF.b.h^q^R)&HF)|				\
175 		(((R^I.AF.b.h)&(I.AF.b.h^q)&SF)>>5);		\
176 	I.AF.b.h=q; 						\
177 }
178 #else
179 #ifdef X86_ASM
180 #define M_SBB(R)						\
181  asm (								\
182  " shrb $1,%%al         \n"                                     \
183  " sbbb %2,%0           \n"                                     \
184  " lahf                 \n"                                     \
185  " setob %%al           \n" /* al = 1 if overflow */            \
186  " shlb $2,%%al         \n" /* shift to P/V bit position */     \
187  " andb $0xd1,%%ah      \n" /* sign, zero, half carry, carry */ \
188  " orb $2,%%al          \n" /* set N flag */                    \
189  " orb %%ah,%%al        \n" /* combine with P/V */              \
190  :"=mq" (I.AF.b.h), "=a" (I.AF.b.l)				\
191  :"q" (R), "a" (I.AF.b.l), "0" (I.AF.b.h)                       \
192  )
193 #else
194 #define M_SBB(R) {                                              \
195 	int q = I.AF.b.h-R-(I.AF.b.l&CF);			\
196 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)|NF|			\
197 		((I.AF.b.h^q^R)&HF)|				\
198 		(((R^I.AF.b.h)&(I.AF.b.h^q)&SF)>>5);		\
199 	I.AF.b.h=q; 						\
200 }
201 #endif
202 #endif
203 
204 #if I8080_EXACT
205 #define M_CMP(R) {                                              	\
206 	int q = I.AF.b.h-R; 						\
207 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)|NF|				\
208 		((I.AF.b.h^q^R)&HF)|					\
209 		(((R^I.AF.b.h)&(I.AF.b.h^q)&SF)>>5);			\
210 }
211 #else
212 #ifdef X86_ASM
213 #define M_CMP(R)												\
214  asm (															\
215  " cmpb %2,%0          \n"                                      \
216  " lahf                \n"                                      \
217  " setob %%al          \n" /* al = 1 if overflow */             \
218  " shlb $2,%%al        \n" /* shift to P/V bit position */      \
219  " andb $0xd1,%%ah     \n" /* sign, zero, half carry, carry */  \
220  " orb $2,%%al         \n" /* set N flag */                     \
221  " orb %%ah,%%al       \n" /* combine with P/V */               \
222  :"=mq" (I.AF.b.h), "=a" (I.AF.b.l)				\
223  :"q" (R), "0" (I.AF.b.h)                                       \
224  )
225 #else
226 #define M_CMP(R) {                                              \
227 	int q = I.AF.b.h-R; 										\
228 	I.AF.b.l=ZSP[q&255]|((q>>8)&CF)|NF|				\
229 		((I.AF.b.h^q^R)&HF)|									\
230 		(((R^I.AF.b.h)&(I.AF.b.h^q)&SF)>>5);					\
231 }
232 #endif
233 #endif
234 
235 #define M_IN													\
236 	I.XX.d=ARG();												\
237 	I.AF.b.h=cpu_readport16(I.XX.d);
238 
239 #define M_OUT													\
240 	I.XX.d=ARG();												\
241 	cpu_writeport16(I.XX.d,I.AF.b.h)
242 
243 #ifdef	X86_ASM
244 #define M_DAD(R)												\
245  asm (															\
246  " andb $0xc4,%1        \n"                                     \
247  " addb %%al,%%cl       \n"                                     \
248  " adcb %%ah,%%ch       \n"                                     \
249  " lahf                 \n"                                     \
250  " andb $0x11,%%ah      \n"                                     \
251  " orb %%ah,%1          \n"                                     \
252  :"=c" (I.HL.d), "=mq" (I.AF.b.l)                                \
253  :"0" (I.HL.d), "1" (I.AF.b.l), "a" (I.R.d)                     \
254  )
255 #else
256 #define M_DAD(R) {                                              \
257 	int q = I.HL.d + I.R.d; 									\
258 	I.AF.b.l = ( I.AF.b.l & ~(HF+CF) ) |						\
259 		( ((I.HL.d^q^I.R.d) >> 8) & HF ) |						\
260 		( (q>>16) & CF );										\
261 	I.HL.w.l = q;												\
262 }
263 #endif
264 
265 #define M_PUSH(R) {                                             \
266 	WM(--I.SP.w.l, I.R.b.h);									\
267 	WM(--I.SP.w.l, I.R.b.l);									\
268 }
269 
270 #define M_POP(R) {												\
271 	I.R.b.l = RM(I.SP.w.l++);									\
272 	I.R.b.h = RM(I.SP.w.l++);									\
273 }
274 
275 #define M_RET(cc)												\
276 {																\
277 	if (cc) 													\
278 	{															\
279 		i8085_ICount -= 6;										\
280 		M_POP(PC);												\
281 		change_pc16(I.PC.d);									\
282 	}															\
283 }
284 
285 #define M_JMP(cc) { 											\
286 	if (cc) {													\
287 		i8085_ICount -= 3;										\
288 		I.PC.w.l = ARG16(); 									\
289 		change_pc16(I.PC.d);									\
290 	} else I.PC.w.l += 2;										\
291 }
292 
293 #define M_CALL(cc)												\
294 {																\
295 	if (cc) 													\
296 	{															\
297 		UINT16 a = ARG16(); 									\
298 		i8085_ICount -= 6;										\
299 		M_PUSH(PC); 											\
300 		I.PC.d = a; 											\
301 		change_pc16(I.PC.d);									\
302 	} else I.PC.w.l += 2;										\
303 }
304 
305 #define M_RST(nn) { 											\
306 	M_PUSH(PC); 												\
307 	I.PC.d = 8 * nn;											\
308 	change_pc16(I.PC.d);										\
309 }
310 
311 #define M_DSUB() {												\
312 	int q = I.HL.b.l-I.BC.b.l;									\
313 	I.AF.b.l=ZS[q&255]|((q>>8)&CF)|NF|							\
314 		((I.HL.b.l^q^I.BC.b.l)&HF)|								\
315 		(((I.BC.b.l^I.HL.b.l)&(I.HL.b.l^q)&SF)>>5);				\
316 	I.HL.b.l=q; 												\
317 	q = I.HL.b.h-I.BC.b.h-(I.AF.b.l&CF);						\
318 	I.AF.b.l=ZS[q&255]|((q>>8)&CF)|NF|							\
319 		((I.HL.b.h^q^I.BC.b.h)&HF)|								\
320 		(((I.BC.b.h^I.HL.b.h)&(I.HL.b.h^q)&SF)>>5);				\
321 	if (I.HL.b.l!=0) I.AF.b.l&=~ZF;								\
322 }
323