1 /*===========================================================================
2     ASTAT -- ALU/MAC status register
3 ===========================================================================*/
4 
5 /* flag definitions */
6 #define SSFLAG			0x80
7 #define MVFLAG			0x40
8 #define QFLAG			0x20
9 #define SFLAG			0x10
10 #define CFLAG			0x08
11 #define VFLAG			0x04
12 #define NFLAG			0x02
13 #define ZFLAG			0x01
14 
15 /* extracts flags */
16 #define GET_SS			(adsp->astat & SSFLAG)
17 #define GET_MV			(adsp->astat & MVFLAG)
18 #define GET_Q			(adsp->astat &  QFLAG)
19 #define GET_S			(adsp->astat &  SFLAG)
20 #define GET_C			(adsp->astat &  CFLAG)
21 #define GET_V			(adsp->astat &  VFLAG)
22 #define GET_N			(adsp->astat &  NFLAG)
23 #define GET_Z			(adsp->astat &  ZFLAG)
24 
25 /* clears flags */
26 #define CLR_SS			(adsp->astat &= ~SSFLAG)
27 #define CLR_MV			(adsp->astat &= ~MVFLAG)
28 #define CLR_Q			(adsp->astat &=  ~QFLAG)
29 #define CLR_S			(adsp->astat &=  ~SFLAG)
30 #define CLR_C			(adsp->astat &=  ~CFLAG)
31 #define CLR_V			(adsp->astat &=  ~VFLAG)
32 #define CLR_N			(adsp->astat &=  ~NFLAG)
33 #define CLR_Z			(adsp->astat &=  ~ZFLAG)
34 
35 /* sets flags */
36 #define SET_SS			(adsp->astat |= SSFLAG)
37 #define SET_MV			(adsp->astat |= MVFLAG)
38 #define SET_Q			(adsp->astat |=  QFLAG)
39 #define SET_S			(adsp->astat |=  SFLAG)
40 #define SET_C			(adsp->astat |=  CFLAG)
41 #define SET_V			(adsp->astat |=  VFLAG)
42 #define SET_Z			(adsp->astat |=  ZFLAG)
43 #define SET_N			(adsp->astat |=  NFLAG)
44 
45 /* flag clearing; must be done before setting */
46 #define CLR_FLAGS		(adsp->astat &= adsp->astat_clear)
47 
48 /* compute flags */
49 #define CALC_Z(r)		(adsp->astat |= ((r & 0xffff) == 0))
50 #define CALC_N(r)		(adsp->astat |= (r >> 14) & 0x02)
51 #define CALC_V(s,d,r)	(adsp->astat |= ((s ^ d ^ r ^ (r >> 1)) >> 13) & 0x04)
52 #define CALC_C(r)		(adsp->astat |= (r >> 13) & 0x08)
53 #define CALC_C_SUB(r)	(adsp->astat |= (~r >> 13) & 0x08)
54 #define CALC_NZ(r) 		CLR_FLAGS; CALC_N(r); CALC_Z(r)
55 #define CALC_NZV(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r)
56 #define CALC_NZVC(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r); CALC_C(r)
57 #define CALC_NZVC_SUB(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r); CALC_C_SUB(r)
58 
59 /* ADSP-218x constants */
60 static const INT32 constants[] =
61 {
62 	0x0001, 0xfffe, 0x0002, 0xfffd, 0x0004, 0xfffb, 0x0008, 0xfff7,
63 	0x0010, 0xffef, 0x0020, 0xffdf, 0x0040, 0xffbf, 0x0080, 0xff7f,
64 	0x0100, 0xfeff, 0x0200, 0xfdff, 0x0400, 0xfbff, 0x0800, 0xf7ff,
65 	0x1000, 0xefff, 0x2000, 0xdfff, 0x4000, 0xbfff, 0x8000, 0x7fff
66 };
67 
68 
69 
70 /*===========================================================================
71     MSTAT -- ALU/MAC control register
72 ===========================================================================*/
73 
74 /* flag definitions */
75 #define MSTAT_BANK		0x01			/* register bank select */
76 #define MSTAT_REVERSE	0x02			/* bit-reverse addressing enable (DAG1) */
77 #define MSTAT_STICKYV	0x04			/* sticky ALU overflow enable */
78 #define MSTAT_SATURATE	0x08			/* AR saturation mode enable */
79 #define MSTAT_INTEGER	0x10			/* MAC result placement; 0=fractional, 1=integer */
80 #define MSTAT_TIMER		0x20			/* timer enable */
81 #define MSTAT_GOMODE	0x40			/* go mode enable */
82 
83 /* you must call this in order to change MSTAT */
update_mstat(adsp2100_state * adsp)84 INLINE void update_mstat(adsp2100_state *adsp)
85 {
86 	if ((adsp->mstat ^ adsp->mstat_prev) & MSTAT_BANK)
87 	{
88 		ADSPCORE temp = adsp->core;
89 		adsp->core = adsp->alt;
90 		adsp->alt = temp;
91 	}
92 	if ((adsp->mstat ^ adsp->mstat_prev) & MSTAT_TIMER)
93 		if (adsp->timer_fired != NULL)
94                         (*adsp->timer_fired)(adsp, (adsp->mstat & MSTAT_TIMER) != 0);
95 
96         if (adsp->mstat & MSTAT_STICKYV)
97 		adsp->astat_clear = ~(CFLAG | NFLAG | ZFLAG);
98 	else
99 		adsp->astat_clear = ~(CFLAG | VFLAG | NFLAG | ZFLAG);
100 	adsp->mstat_prev = adsp->mstat;
101 }
102 
103 
104 /*===========================================================================
105     SSTAT -- stack status register
106 ===========================================================================*/
107 
108 /* flag definitions */
109 #define PC_EMPTY		0x01			/* PC stack empty */
110 #define PC_OVER			0x02			/* PC stack overflow */
111 #define COUNT_EMPTY		0x04			/* count stack empty */
112 #define COUNT_OVER		0x08			/* count stack overflow */
113 #define STATUS_EMPTY	0x10			/* status stack empty */
114 #define STATUS_OVER		0x20			/* status stack overflow */
115 #define LOOP_EMPTY		0x40			/* loop stack empty */
116 #define LOOP_OVER		0x80			/* loop stack overflow */
117 
118 
119 
120 /*===========================================================================
121     PC stack handlers
122 ===========================================================================*/
123 
pc_stack_top(adsp2100_state * adsp)124 INLINE UINT32 pc_stack_top(adsp2100_state *adsp)
125 {
126 	if (adsp->pc_sp > 0)
127 		return adsp->pc_stack[adsp->pc_sp - 1];
128 	else
129 		return adsp->pc_stack[0];
130 }
131 
set_pc_stack_top(adsp2100_state * adsp,UINT32 top)132 INLINE void set_pc_stack_top(adsp2100_state *adsp, UINT32 top)
133 {
134 	if (adsp->pc_sp > 0)
135 		adsp->pc_stack[adsp->pc_sp - 1] = top;
136 	else
137 		adsp->pc_stack[0] = top;
138 }
139 
pc_stack_push(adsp2100_state * adsp)140 INLINE void pc_stack_push(adsp2100_state *adsp)
141 {
142 	if (adsp->pc_sp < PC_STACK_DEPTH)
143 	{
144 		adsp->pc_stack[adsp->pc_sp] = adsp->pc;
145 		adsp->pc_sp++;
146 		adsp->sstat &= ~PC_EMPTY;
147 	}
148 	else
149 		adsp->sstat |= PC_OVER;
150 }
151 
pc_stack_push_val(adsp2100_state * adsp,UINT32 val)152 INLINE void pc_stack_push_val(adsp2100_state *adsp, UINT32 val)
153 {
154 	if (adsp->pc_sp < PC_STACK_DEPTH)
155 	{
156 		adsp->pc_stack[adsp->pc_sp] = val;
157 		adsp->pc_sp++;
158 		adsp->sstat &= ~PC_EMPTY;
159 	}
160 	else
161 		adsp->sstat |= PC_OVER;
162 }
163 
pc_stack_pop(adsp2100_state * adsp)164 INLINE void pc_stack_pop(adsp2100_state *adsp)
165 {
166 	if (adsp->pc_sp > 0)
167 	{
168 		adsp->pc_sp--;
169 		if (adsp->pc_sp == 0)
170 			adsp->sstat |= PC_EMPTY;
171 	}
172 	adsp->pc = adsp->pc_stack[adsp->pc_sp];
173 }
174 
pc_stack_pop_val(adsp2100_state * adsp)175 INLINE UINT32 pc_stack_pop_val(adsp2100_state *adsp)
176 {
177 	if (adsp->pc_sp > 0)
178 	{
179 		adsp->pc_sp--;
180 		if (adsp->pc_sp == 0)
181 			adsp->sstat |= PC_EMPTY;
182 	}
183 	return adsp->pc_stack[adsp->pc_sp];
184 }
185 
186 
187 /*===========================================================================
188     CNTR stack handlers
189 ===========================================================================*/
190 
cntr_stack_top(adsp2100_state * adsp)191 INLINE UINT32 cntr_stack_top(adsp2100_state *adsp)
192 {
193 	if (adsp->cntr_sp > 0)
194 		return adsp->cntr_stack[adsp->cntr_sp - 1];
195 	else
196 		return adsp->cntr_stack[0];
197 }
198 
cntr_stack_push(adsp2100_state * adsp)199 INLINE void cntr_stack_push(adsp2100_state *adsp)
200 {
201 	if (adsp->cntr_sp < CNTR_STACK_DEPTH)
202 	{
203 		adsp->cntr_stack[adsp->cntr_sp] = adsp->cntr;
204 		adsp->cntr_sp++;
205 		adsp->sstat &= ~COUNT_EMPTY;
206 	}
207 	else
208 		adsp->sstat |= COUNT_OVER;
209 }
210 
cntr_stack_pop(adsp2100_state * adsp)211 INLINE void cntr_stack_pop(adsp2100_state *adsp)
212 {
213 	if (adsp->cntr_sp > 0)
214 	{
215 		adsp->cntr_sp--;
216 		if (adsp->cntr_sp == 0)
217 			adsp->sstat |= COUNT_EMPTY;
218 	}
219 	adsp->cntr = adsp->cntr_stack[adsp->cntr_sp];
220 }
221 
222 
223 /*===========================================================================
224     LOOP stack handlers
225 ===========================================================================*/
226 
loop_stack_top(adsp2100_state * adsp)227 INLINE UINT32 loop_stack_top(adsp2100_state *adsp)
228 {
229 	if (adsp->loop_sp > 0)
230 		return adsp->loop_stack[adsp->loop_sp - 1];
231 	else
232 		return adsp->loop_stack[0];
233 }
234 
loop_stack_push(adsp2100_state * adsp,UINT32 value)235 INLINE void loop_stack_push(adsp2100_state *adsp, UINT32 value)
236 {
237 	if (adsp->loop_sp < LOOP_STACK_DEPTH)
238 	{
239 		adsp->loop_stack[adsp->loop_sp] = value;
240 		adsp->loop_sp++;
241 		adsp->loop = value >> 4;
242 		adsp->loop_condition = value & 15;
243 		adsp->sstat &= ~LOOP_EMPTY;
244 	}
245 	else
246 		adsp->sstat |= LOOP_OVER;
247 }
248 
loop_stack_pop(adsp2100_state * adsp)249 INLINE void loop_stack_pop(adsp2100_state *adsp)
250 {
251 	if (adsp->loop_sp > 0)
252 	{
253 		adsp->loop_sp--;
254 		if (adsp->loop_sp == 0)
255 		{
256 			adsp->loop = 0xffff;
257 			adsp->loop_condition = 0;
258 			adsp->sstat |= LOOP_EMPTY;
259 		}
260 		else
261 		{
262 			adsp->loop = adsp->loop_stack[adsp->loop_sp -1] >> 4;
263 			adsp->loop_condition = adsp->loop_stack[adsp->loop_sp - 1] & 15;
264 		}
265 	}
266 }
267 
268 
269 /*===========================================================================
270     STAT stack handlers
271 ===========================================================================*/
272 
stat_stack_push(adsp2100_state * adsp)273 INLINE void stat_stack_push(adsp2100_state *adsp)
274 {
275 	if (adsp->stat_sp < STAT_STACK_DEPTH)
276 	{
277 		adsp->stat_stack[adsp->stat_sp][0] = adsp->mstat;
278 		adsp->stat_stack[adsp->stat_sp][1] = adsp->imask;
279 		adsp->stat_stack[adsp->stat_sp][2] = adsp->astat;
280 		adsp->stat_sp++;
281 		adsp->sstat &= ~STATUS_EMPTY;
282 	}
283 	else
284 		adsp->sstat |= STATUS_OVER;
285 }
286 
stat_stack_pop(adsp2100_state * adsp)287 INLINE void stat_stack_pop(adsp2100_state *adsp)
288 {
289 	if (adsp->stat_sp > 0)
290 	{
291 		adsp->stat_sp--;
292 		if (adsp->stat_sp == 0)
293 			adsp->sstat |= STATUS_EMPTY;
294 	}
295 	adsp->mstat = adsp->stat_stack[adsp->stat_sp][0];
296 	update_mstat(adsp);
297 	adsp->imask = adsp->stat_stack[adsp->stat_sp][1];
298 	adsp->astat = adsp->stat_stack[adsp->stat_sp][2];
299  	check_irqs(adsp);
300 }
301 
302 
303 
304 /*===========================================================================
305     condition code checking
306 ===========================================================================*/
307 
CONDITION(adsp2100_state * adsp,int c)308 INLINE int CONDITION(adsp2100_state *adsp, int c)
309 {
310 	if (c != 14)
311 		return condition_table[((c) << 8) | adsp->astat];
312 	else if ((INT32)--adsp->cntr > 0)
313 		return 1;
314 	else
315 	{
316 		cntr_stack_pop(adsp);
317 		return 0;
318 	}
319 }
320 
321 
322 
323 /*===========================================================================
324     register writing
325 ===========================================================================*/
326 
update_i(adsp2100_state * adsp,int which)327 INLINE void update_i(adsp2100_state *adsp, int which)
328 {
329 	adsp->base[which] = adsp->i[which] & adsp->lmask[which];
330 }
331 
update_l(adsp2100_state * adsp,int which)332 INLINE void update_l(adsp2100_state *adsp, int which)
333 {
334 	adsp->lmask[which] = mask_table[adsp->l[which] & 0x3fff];
335 	adsp->base[which] = adsp->i[which] & adsp->lmask[which];
336 }
337 
wr_inval(adsp2100_state * adsp,INT32 val)338 static void wr_inval(adsp2100_state *adsp, INT32 val) { logerror( "ADSP %04x: Writing to an invalid register!\n", adsp->ppc ); }
wr_ax0(adsp2100_state * adsp,INT32 val)339 static void wr_ax0(adsp2100_state *adsp, INT32 val)   { adsp->core.ax0.s = val; }
wr_ax1(adsp2100_state * adsp,INT32 val)340 static void wr_ax1(adsp2100_state *adsp, INT32 val)   { adsp->core.ax1.s = val; }
wr_mx0(adsp2100_state * adsp,INT32 val)341 static void wr_mx0(adsp2100_state *adsp, INT32 val)   { adsp->core.mx0.s = val; }
wr_mx1(adsp2100_state * adsp,INT32 val)342 static void wr_mx1(adsp2100_state *adsp, INT32 val)   { adsp->core.mx1.s = val; }
wr_ay0(adsp2100_state * adsp,INT32 val)343 static void wr_ay0(adsp2100_state *adsp, INT32 val)   { adsp->core.ay0.s = val; }
wr_ay1(adsp2100_state * adsp,INT32 val)344 static void wr_ay1(adsp2100_state *adsp, INT32 val)   { adsp->core.ay1.s = val; }
wr_my0(adsp2100_state * adsp,INT32 val)345 static void wr_my0(adsp2100_state *adsp, INT32 val)   { adsp->core.my0.s = val; }
wr_my1(adsp2100_state * adsp,INT32 val)346 static void wr_my1(adsp2100_state *adsp, INT32 val)   { adsp->core.my1.s = val; }
wr_si(adsp2100_state * adsp,INT32 val)347 static void wr_si(adsp2100_state *adsp, INT32 val)    { adsp->core.si.s = val; }
wr_se(adsp2100_state * adsp,INT32 val)348 static void wr_se(adsp2100_state *adsp, INT32 val)    { adsp->core.se.s = (INT8)val; }
wr_ar(adsp2100_state * adsp,INT32 val)349 static void wr_ar(adsp2100_state *adsp, INT32 val)    { adsp->core.ar.s = val; }
wr_mr0(adsp2100_state * adsp,INT32 val)350 static void wr_mr0(adsp2100_state *adsp, INT32 val)   { adsp->core.mr.mrx.mr0.s = val; }
wr_mr1(adsp2100_state * adsp,INT32 val)351 static void wr_mr1(adsp2100_state *adsp, INT32 val)   { adsp->core.mr.mrx.mr1.s = val; adsp->core.mr.mrx.mr2.s = (INT16)val >> 15; }
wr_mr2(adsp2100_state * adsp,INT32 val)352 static void wr_mr2(adsp2100_state *adsp, INT32 val)   { adsp->core.mr.mrx.mr2.s = (INT8)val; }
wr_sr0(adsp2100_state * adsp,INT32 val)353 static void wr_sr0(adsp2100_state *adsp, INT32 val)   { adsp->core.sr.srx.sr0.s = val; }
wr_sr1(adsp2100_state * adsp,INT32 val)354 static void wr_sr1(adsp2100_state *adsp, INT32 val)   { adsp->core.sr.srx.sr1.s = val; }
wr_i0(adsp2100_state * adsp,INT32 val)355 static void wr_i0(adsp2100_state *adsp, INT32 val)    { adsp->i[0] = val & 0x3fff; update_i(adsp, 0); }
wr_i1(adsp2100_state * adsp,INT32 val)356 static void wr_i1(adsp2100_state *adsp, INT32 val)    { adsp->i[1] = val & 0x3fff; update_i(adsp, 1); }
wr_i2(adsp2100_state * adsp,INT32 val)357 static void wr_i2(adsp2100_state *adsp, INT32 val)    { adsp->i[2] = val & 0x3fff; update_i(adsp, 2); }
wr_i3(adsp2100_state * adsp,INT32 val)358 static void wr_i3(adsp2100_state *adsp, INT32 val)    { adsp->i[3] = val & 0x3fff; update_i(adsp, 3); }
wr_i4(adsp2100_state * adsp,INT32 val)359 static void wr_i4(adsp2100_state *adsp, INT32 val)    { adsp->i[4] = val & 0x3fff; update_i(adsp, 4); }
wr_i5(adsp2100_state * adsp,INT32 val)360 static void wr_i5(adsp2100_state *adsp, INT32 val)    { adsp->i[5] = val & 0x3fff; update_i(adsp, 5); }
wr_i6(adsp2100_state * adsp,INT32 val)361 static void wr_i6(adsp2100_state *adsp, INT32 val)    { adsp->i[6] = val & 0x3fff; update_i(adsp, 6); }
wr_i7(adsp2100_state * adsp,INT32 val)362 static void wr_i7(adsp2100_state *adsp, INT32 val)    { adsp->i[7] = val & 0x3fff; update_i(adsp, 7); }
wr_m0(adsp2100_state * adsp,INT32 val)363 static void wr_m0(adsp2100_state *adsp, INT32 val)    { adsp->m[0] = (INT32)(val << 18) >> 18; }
wr_m1(adsp2100_state * adsp,INT32 val)364 static void wr_m1(adsp2100_state *adsp, INT32 val)    { adsp->m[1] = (INT32)(val << 18) >> 18; }
wr_m2(adsp2100_state * adsp,INT32 val)365 static void wr_m2(adsp2100_state *adsp, INT32 val)    { adsp->m[2] = (INT32)(val << 18) >> 18; }
wr_m3(adsp2100_state * adsp,INT32 val)366 static void wr_m3(adsp2100_state *adsp, INT32 val)    { adsp->m[3] = (INT32)(val << 18) >> 18; }
wr_m4(adsp2100_state * adsp,INT32 val)367 static void wr_m4(adsp2100_state *adsp, INT32 val)    { adsp->m[4] = (INT32)(val << 18) >> 18; }
wr_m5(adsp2100_state * adsp,INT32 val)368 static void wr_m5(adsp2100_state *adsp, INT32 val)    { adsp->m[5] = (INT32)(val << 18) >> 18; }
wr_m6(adsp2100_state * adsp,INT32 val)369 static void wr_m6(adsp2100_state *adsp, INT32 val)    { adsp->m[6] = (INT32)(val << 18) >> 18; }
wr_m7(adsp2100_state * adsp,INT32 val)370 static void wr_m7(adsp2100_state *adsp, INT32 val)    { adsp->m[7] = (INT32)(val << 18) >> 18; }
wr_l0(adsp2100_state * adsp,INT32 val)371 static void wr_l0(adsp2100_state *adsp, INT32 val)    { adsp->l[0] = val & 0x3fff; update_l(adsp, 0); }
wr_l1(adsp2100_state * adsp,INT32 val)372 static void wr_l1(adsp2100_state *adsp, INT32 val)    { adsp->l[1] = val & 0x3fff; update_l(adsp, 1); }
wr_l2(adsp2100_state * adsp,INT32 val)373 static void wr_l2(adsp2100_state *adsp, INT32 val)    { adsp->l[2] = val & 0x3fff; update_l(adsp, 2); }
wr_l3(adsp2100_state * adsp,INT32 val)374 static void wr_l3(adsp2100_state *adsp, INT32 val)    { adsp->l[3] = val & 0x3fff; update_l(adsp, 3); }
wr_l4(adsp2100_state * adsp,INT32 val)375 static void wr_l4(adsp2100_state *adsp, INT32 val)    { adsp->l[4] = val & 0x3fff; update_l(adsp, 4); }
wr_l5(adsp2100_state * adsp,INT32 val)376 static void wr_l5(adsp2100_state *adsp, INT32 val)    { adsp->l[5] = val & 0x3fff; update_l(adsp, 5); }
wr_l6(adsp2100_state * adsp,INT32 val)377 static void wr_l6(adsp2100_state *adsp, INT32 val)    { adsp->l[6] = val & 0x3fff; update_l(adsp, 6); }
wr_l7(adsp2100_state * adsp,INT32 val)378 static void wr_l7(adsp2100_state *adsp, INT32 val)    { adsp->l[7] = val & 0x3fff; update_l(adsp, 7); }
wr_astat(adsp2100_state * adsp,INT32 val)379 static void wr_astat(adsp2100_state *adsp, INT32 val) { adsp->astat = val & 0x00ff; }
wr_mstat(adsp2100_state * adsp,INT32 val)380 static void wr_mstat(adsp2100_state *adsp, INT32 val) { adsp->mstat = val & adsp->mstat_mask; update_mstat(adsp); }
wr_imask(adsp2100_state * adsp,INT32 val)381 static void wr_imask(adsp2100_state *adsp, INT32 val) { adsp->imask = val & adsp->imask_mask; check_irqs(adsp); }
wr_icntl(adsp2100_state * adsp,INT32 val)382 static void wr_icntl(adsp2100_state *adsp, INT32 val) { adsp->icntl = val & 0x001f; check_irqs(adsp); }
wr_cntr(adsp2100_state * adsp,INT32 val)383 static void wr_cntr(adsp2100_state *adsp, INT32 val)  { cntr_stack_push(adsp); adsp->cntr = val & 0x3fff; }
wr_sb(adsp2100_state * adsp,INT32 val)384 static void wr_sb(adsp2100_state *adsp, INT32 val)    { adsp->core.sb.s = (INT32)(val << 27) >> 27; }
wr_px(adsp2100_state * adsp,INT32 val)385 static void wr_px(adsp2100_state *adsp, INT32 val)    { adsp->px = val; }
wr_ifc(adsp2100_state * adsp,INT32 val)386 static void wr_ifc(adsp2100_state *adsp, INT32 val)
387 {
388 	adsp->ifc = val;
389 	if (adsp->chip_type >= CHIP_TYPE_ADSP2181)
390 	{
391 		/* clear timer */
392 		if (val & 0x0002) adsp->irq_latch[ADSP2181_IRQ0] = 0;
393 		if (val & 0x0004) adsp->irq_latch[ADSP2181_IRQ1] = 0;
394 		/* clear BDMA */
395 		if (val & 0x0010) adsp->irq_latch[ADSP2181_IRQE] = 0;
396 		if (val & 0x0020) adsp->irq_latch[ADSP2181_SPORT0_RX] = 0;
397 		if (val & 0x0040) adsp->irq_latch[ADSP2181_SPORT0_TX] = 0;
398 		if (val & 0x0080) adsp->irq_latch[ADSP2181_IRQ2] = 0;
399 		/* force timer */
400 		if (val & 0x0200) adsp->irq_latch[ADSP2181_IRQ0] = 1;
401 		if (val & 0x0400) adsp->irq_latch[ADSP2181_IRQ1] = 1;
402 		/* force BDMA */
403 		if (val & 0x1000) adsp->irq_latch[ADSP2181_IRQE] = 1;
404 		if (val & 0x2000) adsp->irq_latch[ADSP2181_SPORT0_RX] = 1;
405 		if (val & 0x4000) adsp->irq_latch[ADSP2181_SPORT0_TX] = 1;
406 		if (val & 0x8000) adsp->irq_latch[ADSP2181_IRQ2] = 1;
407 	}
408 	else
409 	{
410 		/* clear timer */
411 		if (val & 0x002) adsp->irq_latch[ADSP2101_IRQ0] = 0;
412 		if (val & 0x004) adsp->irq_latch[ADSP2101_IRQ1] = 0;
413 		if (val & 0x008) adsp->irq_latch[ADSP2101_SPORT0_RX] = 0;
414 		if (val & 0x010) adsp->irq_latch[ADSP2101_SPORT0_TX] = 0;
415 		if (val & 0x020) adsp->irq_latch[ADSP2101_IRQ2] = 0;
416 		/* set timer */
417 		if (val & 0x080) adsp->irq_latch[ADSP2101_IRQ0] = 1;
418 		if (val & 0x100) adsp->irq_latch[ADSP2101_IRQ1] = 1;
419 		if (val & 0x200) adsp->irq_latch[ADSP2101_SPORT0_RX] = 1;
420 		if (val & 0x400) adsp->irq_latch[ADSP2101_SPORT0_TX] = 1;
421 		if (val & 0x800) adsp->irq_latch[ADSP2101_IRQ2] = 1;
422 	}
423 	check_irqs(adsp);
424 }
wr_tx0(adsp2100_state * adsp,INT32 val)425 static void wr_tx0(adsp2100_state *adsp, INT32 val)	{ if (adsp->sport_tx_callback) (*adsp->sport_tx_callback)(adsp, 0, val); }
wr_tx1(adsp2100_state * adsp,INT32 val)426 static void wr_tx1(adsp2100_state *adsp, INT32 val)	{ if (adsp->sport_tx_callback) (*adsp->sport_tx_callback)(adsp, 1, val); }
wr_owrctr(adsp2100_state * adsp,INT32 val)427 static void wr_owrctr(adsp2100_state *adsp, INT32 val) { adsp->cntr = val & 0x3fff; }
wr_topstack(adsp2100_state * adsp,INT32 val)428 static void wr_topstack(adsp2100_state *adsp, INT32 val) { pc_stack_push_val(adsp, val & 0x3fff); }
429 
430 #define WRITE_REG(adsp,grp,reg,val) ((*wr_reg[grp][reg])(adsp,val))
431 
432 static void (*const wr_reg[4][16])(adsp2100_state*, INT32) =
433 {
434 	{
435 		wr_ax0, wr_ax1, wr_mx0, wr_mx1, wr_ay0, wr_ay1, wr_my0, wr_my1,
436 		wr_si, wr_se, wr_ar, wr_mr0, wr_mr1, wr_mr2, wr_sr0, wr_sr1
437 	},
438 	{
439 		wr_i0, wr_i1, wr_i2, wr_i3, wr_m0, wr_m1, wr_m2, wr_m3,
440 		wr_l0, wr_l1, wr_l2, wr_l3, wr_inval, wr_inval, wr_inval, wr_inval
441 	},
442 	{
443 		wr_i4, wr_i5, wr_i6, wr_i7, wr_m4, wr_m5, wr_m6, wr_m7,
444 		wr_l4, wr_l5, wr_l6, wr_l7, wr_inval, wr_inval, wr_inval, wr_inval
445 	},
446 	{
447 		wr_astat, wr_mstat, wr_inval, wr_imask, wr_icntl, wr_cntr, wr_sb, wr_px,
448 		wr_inval, wr_tx0, wr_inval, wr_tx1, wr_ifc, wr_owrctr, wr_inval, wr_topstack
449 	}
450 };
451 
452 
453 
454 /*===========================================================================
455     register reading
456 ===========================================================================*/
457 
rd_inval(adsp2100_state * adsp)458 static INT32 rd_inval(adsp2100_state *adsp) { logerror( "ADSP %04x: Writing to an invalid register!\n", adsp->ppc ); return 0; }
rd_ax0(adsp2100_state * adsp)459 static INT32 rd_ax0(adsp2100_state *adsp)   { return adsp->core.ax0.s; }
rd_ax1(adsp2100_state * adsp)460 static INT32 rd_ax1(adsp2100_state *adsp)   { return adsp->core.ax1.s; }
rd_mx0(adsp2100_state * adsp)461 static INT32 rd_mx0(adsp2100_state *adsp)   { return adsp->core.mx0.s; }
rd_mx1(adsp2100_state * adsp)462 static INT32 rd_mx1(adsp2100_state *adsp)   { return adsp->core.mx1.s; }
rd_ay0(adsp2100_state * adsp)463 static INT32 rd_ay0(adsp2100_state *adsp)   { return adsp->core.ay0.s; }
rd_ay1(adsp2100_state * adsp)464 static INT32 rd_ay1(adsp2100_state *adsp)   { return adsp->core.ay1.s; }
rd_my0(adsp2100_state * adsp)465 static INT32 rd_my0(adsp2100_state *adsp)   { return adsp->core.my0.s; }
rd_my1(adsp2100_state * adsp)466 static INT32 rd_my1(adsp2100_state *adsp)   { return adsp->core.my1.s; }
rd_si(adsp2100_state * adsp)467 static INT32 rd_si(adsp2100_state *adsp)    { return adsp->core.si.s; }
rd_se(adsp2100_state * adsp)468 static INT32 rd_se(adsp2100_state *adsp)    { return adsp->core.se.s; }
rd_ar(adsp2100_state * adsp)469 static INT32 rd_ar(adsp2100_state *adsp)    { return adsp->core.ar.s; }
rd_mr0(adsp2100_state * adsp)470 static INT32 rd_mr0(adsp2100_state *adsp)   { return adsp->core.mr.mrx.mr0.s; }
rd_mr1(adsp2100_state * adsp)471 static INT32 rd_mr1(adsp2100_state *adsp)   { return adsp->core.mr.mrx.mr1.s; }
rd_mr2(adsp2100_state * adsp)472 static INT32 rd_mr2(adsp2100_state *adsp)   { return adsp->core.mr.mrx.mr2.s; }
rd_sr0(adsp2100_state * adsp)473 static INT32 rd_sr0(adsp2100_state *adsp)   { return adsp->core.sr.srx.sr0.s; }
rd_sr1(adsp2100_state * adsp)474 static INT32 rd_sr1(adsp2100_state *adsp)   { return adsp->core.sr.srx.sr1.s; }
rd_i0(adsp2100_state * adsp)475 static INT32 rd_i0(adsp2100_state *adsp)    { return adsp->i[0]; }
rd_i1(adsp2100_state * adsp)476 static INT32 rd_i1(adsp2100_state *adsp)    { return adsp->i[1]; }
rd_i2(adsp2100_state * adsp)477 static INT32 rd_i2(adsp2100_state *adsp)    { return adsp->i[2]; }
rd_i3(adsp2100_state * adsp)478 static INT32 rd_i3(adsp2100_state *adsp)    { return adsp->i[3]; }
rd_i4(adsp2100_state * adsp)479 static INT32 rd_i4(adsp2100_state *adsp)    { return adsp->i[4]; }
rd_i5(adsp2100_state * adsp)480 static INT32 rd_i5(adsp2100_state *adsp)    { return adsp->i[5]; }
rd_i6(adsp2100_state * adsp)481 static INT32 rd_i6(adsp2100_state *adsp)    { return adsp->i[6]; }
rd_i7(adsp2100_state * adsp)482 static INT32 rd_i7(adsp2100_state *adsp)    { return adsp->i[7]; }
rd_m0(adsp2100_state * adsp)483 static INT32 rd_m0(adsp2100_state *adsp)    { return adsp->m[0]; }
rd_m1(adsp2100_state * adsp)484 static INT32 rd_m1(adsp2100_state *adsp)    { return adsp->m[1]; }
rd_m2(adsp2100_state * adsp)485 static INT32 rd_m2(adsp2100_state *adsp)    { return adsp->m[2]; }
rd_m3(adsp2100_state * adsp)486 static INT32 rd_m3(adsp2100_state *adsp)    { return adsp->m[3]; }
rd_m4(adsp2100_state * adsp)487 static INT32 rd_m4(adsp2100_state *adsp)    { return adsp->m[4]; }
rd_m5(adsp2100_state * adsp)488 static INT32 rd_m5(adsp2100_state *adsp)    { return adsp->m[5]; }
rd_m6(adsp2100_state * adsp)489 static INT32 rd_m6(adsp2100_state *adsp)    { return adsp->m[6]; }
rd_m7(adsp2100_state * adsp)490 static INT32 rd_m7(adsp2100_state *adsp)    { return adsp->m[7]; }
rd_l0(adsp2100_state * adsp)491 static INT32 rd_l0(adsp2100_state *adsp)    { return adsp->l[0]; }
rd_l1(adsp2100_state * adsp)492 static INT32 rd_l1(adsp2100_state *adsp)    { return adsp->l[1]; }
rd_l2(adsp2100_state * adsp)493 static INT32 rd_l2(adsp2100_state *adsp)    { return adsp->l[2]; }
rd_l3(adsp2100_state * adsp)494 static INT32 rd_l3(adsp2100_state *adsp)    { return adsp->l[3]; }
rd_l4(adsp2100_state * adsp)495 static INT32 rd_l4(adsp2100_state *adsp)    { return adsp->l[4]; }
rd_l5(adsp2100_state * adsp)496 static INT32 rd_l5(adsp2100_state *adsp)    { return adsp->l[5]; }
rd_l6(adsp2100_state * adsp)497 static INT32 rd_l6(adsp2100_state *adsp)    { return adsp->l[6]; }
rd_l7(adsp2100_state * adsp)498 static INT32 rd_l7(adsp2100_state *adsp)    { return adsp->l[7]; }
rd_astat(adsp2100_state * adsp)499 static INT32 rd_astat(adsp2100_state *adsp) { return adsp->astat; }
rd_mstat(adsp2100_state * adsp)500 static INT32 rd_mstat(adsp2100_state *adsp) { return adsp->mstat; }
rd_sstat(adsp2100_state * adsp)501 static INT32 rd_sstat(adsp2100_state *adsp) { return adsp->sstat; }
rd_imask(adsp2100_state * adsp)502 static INT32 rd_imask(adsp2100_state *adsp) { return adsp->imask; }
rd_icntl(adsp2100_state * adsp)503 static INT32 rd_icntl(adsp2100_state *adsp) { return adsp->icntl; }
rd_cntr(adsp2100_state * adsp)504 static INT32 rd_cntr(adsp2100_state *adsp)  { return adsp->cntr; }
rd_sb(adsp2100_state * adsp)505 static INT32 rd_sb(adsp2100_state *adsp)    { return adsp->core.sb.s; }
rd_px(adsp2100_state * adsp)506 static INT32 rd_px(adsp2100_state *adsp)    { return adsp->px; }
rd_rx0(adsp2100_state * adsp)507 static INT32 rd_rx0(adsp2100_state *adsp)	{ if (adsp->sport_rx_callback) return (*adsp->sport_rx_callback)(adsp, 0); else return 0; }
rd_rx1(adsp2100_state * adsp)508 static INT32 rd_rx1(adsp2100_state *adsp)	{ if (adsp->sport_rx_callback) return (*adsp->sport_rx_callback)(adsp, 1); else return 0; }
rd_stacktop(adsp2100_state * adsp)509 static INT32 rd_stacktop(adsp2100_state *adsp)	{ return pc_stack_pop_val(adsp); }
510 
511 #define READ_REG(adsp,grp,reg) ((*rd_reg[grp][reg])(adsp))
512 
513 static INT32 (*const rd_reg[4][16])(adsp2100_state *adsp) =
514 {
515 	{
516 		rd_ax0, rd_ax1, rd_mx0, rd_mx1, rd_ay0, rd_ay1, rd_my0, rd_my1,
517 		rd_si, rd_se, rd_ar, rd_mr0, rd_mr1, rd_mr2, rd_sr0, rd_sr1
518 	},
519 	{
520 		rd_i0, rd_i1, rd_i2, rd_i3, rd_m0, rd_m1, rd_m2, rd_m3,
521 		rd_l0, rd_l1, rd_l2, rd_l3, rd_inval, rd_inval, rd_inval, rd_inval
522 	},
523 	{
524 		rd_i4, rd_i5, rd_i6, rd_i7, rd_m4, rd_m5, rd_m6, rd_m7,
525 		rd_l4, rd_l5, rd_l6, rd_l7, rd_inval, rd_inval, rd_inval, rd_inval
526 	},
527 	{
528 		rd_astat, rd_mstat, rd_sstat, rd_imask, rd_icntl, rd_cntr, rd_sb, rd_px,
529 		rd_rx0, rd_inval, rd_rx1, rd_inval, rd_inval, rd_inval, rd_inval, rd_stacktop
530 	}
531 };
532 
533 
534 
535 /*===========================================================================
536     Modulus addressing logic
537 ===========================================================================*/
538 
modify_address(adsp2100_state * adsp,UINT32 ireg,UINT32 mreg)539 INLINE void modify_address(adsp2100_state *adsp, UINT32 ireg, UINT32 mreg)
540 {
541 	UINT32 base = adsp->base[ireg];
542 	UINT32 i = adsp->i[ireg];
543 	UINT32 l = adsp->l[ireg];
544 
545 	i += adsp->m[mreg];
546 	if (i < base) i += l;
547 	else if (i >= base + l) i -= l;
548 	adsp->i[ireg] = i;
549 }
550 
551 
552 
553 /*===========================================================================
554     Data memory accessors
555 ===========================================================================*/
556 
data_write_dag1(adsp2100_state * adsp,UINT32 op,INT32 val)557 INLINE void data_write_dag1(adsp2100_state *adsp, UINT32 op, INT32 val)
558 {
559 	UINT32 ireg = (op >> 2) & 3;
560 	UINT32 mreg = op & 3;
561 	UINT32 base = adsp->base[ireg];
562 	UINT32 i = adsp->i[ireg];
563 	UINT32 l = adsp->l[ireg];
564 
565 	if ( adsp->mstat & MSTAT_REVERSE )
566 	{
567 		UINT32 ir = reverse_table[ i & 0x3fff ];
568 		WWORD_DATA(adsp, ir, val);
569 	}
570 	else
571 		WWORD_DATA(adsp, i, val);
572 
573 	i += adsp->m[mreg];
574 	if (i < base) i += l;
575 	else if (i >= base + l) i -= l;
576 	adsp->i[ireg] = i;
577 }
578 
579 
data_read_dag1(adsp2100_state * adsp,UINT32 op)580 INLINE UINT32 data_read_dag1(adsp2100_state *adsp, UINT32 op)
581 {
582 	UINT32 ireg = (op >> 2) & 3;
583 	UINT32 mreg = op & 3;
584 	UINT32 base = adsp->base[ireg];
585 	UINT32 i = adsp->i[ireg];
586 	UINT32 l = adsp->l[ireg];
587 	UINT32 res;
588 
589 	if (adsp->mstat & MSTAT_REVERSE)
590 	{
591 		UINT32 ir = reverse_table[i & 0x3fff];
592 		res = RWORD_DATA(adsp, ir);
593 	}
594 	else
595 		res = RWORD_DATA(adsp, i);
596 
597 	i += adsp->m[mreg];
598 	if (i < base) i += l;
599 	else if (i >= base + l) i -= l;
600 	adsp->i[ireg] = i;
601 
602 	return res;
603 }
604 
data_write_dag2(adsp2100_state * adsp,UINT32 op,INT32 val)605 INLINE void data_write_dag2(adsp2100_state *adsp, UINT32 op, INT32 val)
606 {
607 	UINT32 ireg = 4 + ((op >> 2) & 3);
608 	UINT32 mreg = 4 + (op & 3);
609 	UINT32 base = adsp->base[ireg];
610 	UINT32 i = adsp->i[ireg];
611 	UINT32 l = adsp->l[ireg];
612 
613 	WWORD_DATA(adsp, i, val);
614 
615 	i += adsp->m[mreg];
616 	if (i < base) i += l;
617 	else if (i >= base + l) i -= l;
618 	adsp->i[ireg] = i;
619 }
620 
621 
data_read_dag2(adsp2100_state * adsp,UINT32 op)622 INLINE UINT32 data_read_dag2(adsp2100_state *adsp, UINT32 op)
623 {
624 	UINT32 ireg = 4 + ((op >> 2) & 3);
625 	UINT32 mreg = 4 + (op & 3);
626 	UINT32 base = adsp->base[ireg];
627 	UINT32 i = adsp->i[ireg];
628 	UINT32 l = adsp->l[ireg];
629 
630 	UINT32 res = RWORD_DATA(adsp, i);
631 
632 	i += adsp->m[mreg];
633 	if (i < base) i += l;
634 	else if (i >= base + l) i -= l;
635 	adsp->i[ireg] = i;
636 
637 	return res;
638 }
639 
640 /*===========================================================================
641     Program memory accessors
642 ===========================================================================*/
643 
pgm_write_dag2(adsp2100_state * adsp,UINT32 op,INT32 val)644 INLINE void pgm_write_dag2(adsp2100_state *adsp, UINT32 op, INT32 val)
645 {
646 	UINT32 ireg = 4 + ((op >> 2) & 3);
647 	UINT32 mreg = 4 + (op & 3);
648 	UINT32 base = adsp->base[ireg];
649 	UINT32 i = adsp->i[ireg];
650 	UINT32 l = adsp->l[ireg];
651 
652 	WWORD_PGM(adsp, i, (val << 8) | adsp->px);
653 
654 	i += adsp->m[mreg];
655 	if (i < base) i += l;
656 	else if (i >= base + l) i -= l;
657 	adsp->i[ireg] = i;
658 }
659 
660 
pgm_read_dag2(adsp2100_state * adsp,UINT32 op)661 INLINE UINT32 pgm_read_dag2(adsp2100_state *adsp, UINT32 op)
662 {
663 	UINT32 ireg = 4 + ((op >> 2) & 3);
664 	UINT32 mreg = 4 + (op & 3);
665 	UINT32 base = adsp->base[ireg];
666 	UINT32 i = adsp->i[ireg];
667 	UINT32 l = adsp->l[ireg];
668 	UINT32 res;
669 
670 	res = RWORD_PGM(adsp, i);
671 	adsp->px = res;
672 	res >>= 8;
673 
674 	i += adsp->m[mreg];
675 	if (i < base) i += l;
676 	else if (i >= base + l) i -= l;
677 	adsp->i[ireg] = i;
678 
679 	return res;
680 }
681 
682 
683 
684 /*===========================================================================
685     register reading
686 ===========================================================================*/
687 
688 #define ALU_GETXREG_UNSIGNED(a,x) (*(UINT16 *)(a)->alu_xregs[x])
689 #define ALU_GETYREG_UNSIGNED(a,y) (*(UINT16 *)(a)->alu_yregs[y])
690 
691 #define MAC_GETXREG_UNSIGNED(a,x) (*(UINT16 *)(a)->mac_xregs[x])
692 #define MAC_GETXREG_SIGNED(a,x)   (*( INT16 *)(a)->mac_xregs[x])
693 #define MAC_GETYREG_UNSIGNED(a,y) (*(UINT16 *)(a)->mac_yregs[y])
694 #define MAC_GETYREG_SIGNED(a,y)   (*( INT16 *)(a)->mac_yregs[y])
695 
696 #define SHIFT_GETXREG_UNSIGNED(a,x) (*(UINT16 *)(a)->shift_xregs[x])
697 #define SHIFT_GETXREG_SIGNED(a,x)   (*( INT16 *)(a)->shift_xregs[x])
698 
699 
700 
701 /*===========================================================================
702     ALU operations (result in AR)
703 ===========================================================================*/
704 
alu_op_ar(adsp2100_state * adsp,int op)705 static void alu_op_ar(adsp2100_state *adsp, int op)
706 {
707 	INT32 xop = (op >> 8) & 7;
708 	INT32 yop = (op >> 11) & 3;
709 	INT32 res;
710 
711 	switch (op & (15<<13))  /*JB*/
712 	{
713 		case 0x00<<13:
714 			/* Y                Clear when y = 0 */
715 			res = ALU_GETYREG_UNSIGNED(adsp, yop);
716 			CALC_NZ(res);
717 			break;
718 		case 0x01<<13:
719 			/* Y + 1            PASS 1 when y = 0 */
720 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
721 			res = yop + 1;
722 			CALC_NZ(res);
723 			if (yop == 0x7fff) SET_V;
724 			else if (yop == 0xffff) SET_C;
725 			break;
726 		case 0x02<<13:
727 			/* X + Y + C */
728 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
729 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
730 			yop += GET_C >> 3;
731 			res = xop + yop;
732 			CALC_NZVC(xop, yop, res);
733 			break;
734 		case 0x03<<13:
735 			/* X + Y            X when y = 0 */
736 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
737 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
738 			res = xop + yop;
739 			CALC_NZVC(xop, yop, res);
740 			break;
741 		case 0x04<<13:
742 			/* NOT Y */
743 			res = ALU_GETYREG_UNSIGNED(adsp, yop) ^ 0xffff;
744 			CALC_NZ(res);
745 			break;
746 		case 0x05<<13:
747 			/* -Y */
748 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
749 			res = -yop;
750 			CALC_NZ(res);
751 			if (yop == 0x8000) SET_V;
752 			if (yop == 0x0000) SET_C;
753 			break;
754 		case 0x06<<13:
755 			/* X - Y + C - 1    X + C - 1 when y = 0 */
756 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
757 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
758 			res = xop - yop + (GET_C >> 3) - 1;
759 			CALC_NZVC_SUB(xop, yop, res);
760 			break;
761 		case 0x07<<13:
762 			/* X - Y */
763 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
764 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
765 			res = xop - yop;
766 			CALC_NZVC_SUB(xop, yop, res);
767 			break;
768 		case 0x08<<13:
769 			/* Y - 1            PASS -1 when y = 0 */
770 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
771 			res = yop - 1;
772 			CALC_NZ(res);
773 			if (yop == 0x8000) SET_V;
774 			else if (yop == 0x0000) SET_C;
775 			break;
776 		case 0x09<<13:
777 			/* Y - X            -X when y = 0 */
778 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
779 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
780 			res = yop - xop;
781 			CALC_NZVC_SUB(yop, xop, res);
782 			break;
783 		case 0x0a<<13:
784 			/* Y - X + C - 1    -X + C - 1 when y = 0 */
785 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
786 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
787 			res = yop - xop + (GET_C >> 3) - 1;
788 			CALC_NZVC_SUB(yop, xop, res);
789 			break;
790 		case 0x0b<<13:
791 			/* NOT X */
792 			res = ALU_GETXREG_UNSIGNED(adsp, xop) ^ 0xffff;
793 			CALC_NZ(res);
794 			break;
795 		case 0x0c<<13:
796 			/* X AND Y */
797 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
798 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
799 			res = xop & yop;
800 			CALC_NZ(res);
801 			break;
802 		case 0x0d<<13:
803 			/* X OR Y */
804 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
805 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
806 			res = xop | yop;
807 			CALC_NZ(res);
808 			break;
809 		case 0x0e<<13:
810 			/* X XOR Y */
811 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
812 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
813 			res = xop ^ yop;
814 			CALC_NZ(res);
815 			break;
816 		case 0x0f<<13:
817 			/* ABS X */
818 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
819 			res = (xop & 0x8000) ? -xop : xop;
820 			if (xop == 0) SET_Z;
821 			if (xop == 0x8000) SET_N, SET_V;
822 			CLR_S;
823 			if (xop & 0x8000) SET_S;
824 			break;
825 		default:
826 			res = 0;	/* just to keep the compiler happy */
827 			break;
828 	}
829 
830 	/* saturate */
831 	if ((adsp->mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
832 
833 	/* set the final value */
834 	adsp->core.ar.u = res;
835 }
836 
837 
838 
839 /*===========================================================================
840     ALU operations (result in AR, constant yop)
841 ===========================================================================*/
842 
alu_op_ar_const(adsp2100_state * adsp,int op)843 static void alu_op_ar_const(adsp2100_state *adsp, int op)
844 {
845 	INT32 xop = (op >> 8) & 7;
846 	INT32 yop = constants[((op >> 5) & 0x07) | ((op >> 8) & 0x18)];
847 	INT32 res;
848 
849 	switch (op & (15<<13))  /*JB*/
850 	{
851 		case 0x00<<13:
852 			/* Y                Clear when y = 0 */
853 			res = yop;
854 			CALC_NZ(res);
855 			break;
856 		case 0x01<<13:
857 			/* Y + 1            PASS 1 when y = 0 */
858 			res = yop + 1;
859 			CALC_NZ(res);
860 			if (yop == 0x7fff) SET_V;
861 			else if (yop == 0xffff) SET_C;
862 			break;
863 		case 0x02<<13:
864 			/* X + Y + C */
865 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
866 			yop += GET_C >> 3;
867 			res = xop + yop;
868 			CALC_NZVC(xop, yop, res);
869 			break;
870 		case 0x03<<13:
871 			/* X + Y            X when y = 0 */
872 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
873 			res = xop + yop;
874 			CALC_NZVC(xop, yop, res);
875 			break;
876 		case 0x04<<13:
877 			/* NOT Y */
878 			res = yop ^ 0xffff;
879 			CALC_NZ(res);
880 			break;
881 		case 0x05<<13:
882 			/* -Y */
883 			res = -yop;
884 			CALC_NZ(res);
885 			if (yop == 0x8000) SET_V;
886 			if (yop == 0x0000) SET_C;
887 			break;
888 		case 0x06<<13:
889 			/* X - Y + C - 1    X + C - 1 when y = 0 */
890 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
891 			res = xop - yop + (GET_C >> 3) - 1;
892 			CALC_NZVC_SUB(xop, yop, res);
893 			break;
894 		case 0x07<<13:
895 			/* X - Y */
896 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
897 			res = xop - yop;
898 			CALC_NZVC_SUB(xop, yop, res);
899 			break;
900 		case 0x08<<13:
901 			/* Y - 1            PASS -1 when y = 0 */
902 			res = yop - 1;
903 			CALC_NZ(res);
904 			if (yop == 0x8000) SET_V;
905 			else if (yop == 0x0000) SET_C;
906 			break;
907 		case 0x09<<13:
908 			/* Y - X            -X when y = 0 */
909 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
910 			res = yop - xop;
911 			CALC_NZVC_SUB(yop, xop, res);
912 			break;
913 		case 0x0a<<13:
914 			/* Y - X + C - 1    -X + C - 1 when y = 0 */
915 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
916 			res = yop - xop + (GET_C >> 3) - 1;
917 			CALC_NZVC_SUB(yop, xop, res);
918 			break;
919 		case 0x0b<<13:
920 			/* NOT X */
921 			res = ALU_GETXREG_UNSIGNED(adsp, xop) ^ 0xffff;
922 			CALC_NZ(res);
923 			break;
924 		case 0x0c<<13:
925 			/* X AND Y */
926 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
927 			res = xop & yop;
928 			CALC_NZ(res);
929 			break;
930 		case 0x0d<<13:
931 			/* X OR Y */
932 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
933 			res = xop | yop;
934 			CALC_NZ(res);
935 			break;
936 		case 0x0e<<13:
937 			/* X XOR Y */
938 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
939 			res = xop ^ yop;
940 			CALC_NZ(res);
941 			break;
942 		case 0x0f<<13:
943 			/* ABS X */
944 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
945 			res = (xop & 0x8000) ? -xop : xop;
946 			if (xop == 0) SET_Z;
947 			if (xop == 0x8000) SET_N, SET_V;
948 			CLR_S;
949 			if (xop & 0x8000) SET_S;
950 			break;
951 		default:
952 			res = 0;	/* just to keep the compiler happy */
953 			break;
954 	}
955 
956 	/* saturate */
957 	if ((adsp->mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
958 
959 	/* set the final value */
960 	adsp->core.ar.u = res;
961 }
962 
963 
964 
965 /*===========================================================================
966     ALU operations (result in AF)
967 ===========================================================================*/
968 
alu_op_af(adsp2100_state * adsp,int op)969 static void alu_op_af(adsp2100_state *adsp, int op)
970 {
971 	INT32 xop = (op >> 8) & 7;
972 	INT32 yop = (op >> 11) & 3;
973 	INT32 res;
974 
975 	switch (op & (15<<13))  /*JB*/
976 	{
977 		case 0x00<<13:
978 			/* Y                Clear when y = 0 */
979 			res = ALU_GETYREG_UNSIGNED(adsp, yop);
980 			CALC_NZ(res);
981 			break;
982 		case 0x01<<13:
983 			/* Y + 1            PASS 1 when y = 0 */
984 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
985 			res = yop + 1;
986 			CALC_NZ(res);
987 			if (yop == 0x7fff) SET_V;
988 			else if (yop == 0xffff) SET_C;
989 			break;
990 		case 0x02<<13:
991 			/* X + Y + C */
992 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
993 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
994 			yop += GET_C >> 3;
995 			res = xop + yop;
996 			CALC_NZVC(xop, yop, res);
997 			break;
998 		case 0x03<<13:
999 			/* X + Y            X when y = 0 */
1000 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1001 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1002 			res = xop + yop;
1003 			CALC_NZVC(xop, yop, res);
1004 			break;
1005 		case 0x04<<13:
1006 			/* NOT Y */
1007 			res = ALU_GETYREG_UNSIGNED(adsp, yop) ^ 0xffff;
1008 			CALC_NZ(res);
1009 			break;
1010 		case 0x05<<13:
1011 			/* -Y */
1012 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1013 			res = -yop;
1014 			CALC_NZ(res);
1015 			if (yop == 0x8000) SET_V;
1016 			if (yop == 0x0000) SET_C;
1017 			break;
1018 		case 0x06<<13:
1019 			/* X - Y + C - 1    X + C - 1 when y = 0 */
1020 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1021 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1022 			res = xop - yop + (GET_C >> 3) - 1;
1023 			CALC_NZVC_SUB(xop, yop, res);
1024 			break;
1025 		case 0x07<<13:
1026 			/* X - Y */
1027 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1028 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1029 			res = xop - yop;
1030 			CALC_NZVC_SUB(xop, yop, res);
1031 			break;
1032 		case 0x08<<13:
1033 			/* Y - 1            PASS -1 when y = 0 */
1034 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1035 			res = yop - 1;
1036 			CALC_NZ(res);
1037 			if (yop == 0x8000) SET_V;
1038 			else if (yop == 0x0000) SET_C;
1039 			break;
1040 		case 0x09<<13:
1041 			/* Y - X            -X when y = 0 */
1042 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1043 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1044 			res = yop - xop;
1045 			CALC_NZVC_SUB(yop, xop, res);
1046 			break;
1047 		case 0x0a<<13:
1048 			/* Y - X + C - 1    -X + C - 1 when y = 0 */
1049 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1050 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1051 			res = yop - xop + (GET_C >> 3) - 1;
1052 			CALC_NZVC_SUB(yop, xop, res);
1053 			break;
1054 		case 0x0b<<13:
1055 			/* NOT X */
1056 			res = ALU_GETXREG_UNSIGNED(adsp, xop) ^ 0xffff;
1057 			CALC_NZ(res);
1058 			break;
1059 		case 0x0c<<13:
1060 			/* X AND Y */
1061 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1062 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1063 			res = xop & yop;
1064 			CALC_NZ(res);
1065 			break;
1066 		case 0x0d<<13:
1067 			/* X OR Y */
1068 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1069 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1070 			res = xop | yop;
1071 			CALC_NZ(res);
1072 			break;
1073 		case 0x0e<<13:
1074 			/* X XOR Y */
1075 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1076 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1077 			res = xop ^ yop;
1078 			CALC_NZ(res);
1079 			break;
1080 		case 0x0f<<13:
1081 			/* ABS X */
1082 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1083 			res = (xop & 0x8000) ? -xop : xop;
1084 			if (xop == 0) SET_Z;
1085 			if (xop == 0x8000) SET_N, SET_V;
1086 			CLR_S;
1087 			if (xop & 0x8000) SET_S;
1088 			break;
1089 		default:
1090 			res = 0;	/* just to keep the compiler happy */
1091 			break;
1092 	}
1093 
1094 	/* set the final value */
1095 	adsp->core.af.u = res;
1096 }
1097 
1098 
1099 
1100 /*===========================================================================
1101     ALU operations (result in AF, constant yop)
1102 ===========================================================================*/
1103 
alu_op_af_const(adsp2100_state * adsp,int op)1104 static void alu_op_af_const(adsp2100_state *adsp, int op)
1105 {
1106 	INT32 xop = (op >> 8) & 7;
1107 	INT32 yop = constants[((op >> 5) & 0x07) | ((op >> 8) & 0x18)];
1108 	INT32 res;
1109 
1110 	switch (op & (15<<13))  /*JB*/
1111 	{
1112 		case 0x00<<13:
1113 			/* Y                Clear when y = 0 */
1114 			res = yop;
1115 			CALC_NZ(res);
1116 			break;
1117 		case 0x01<<13:
1118 			/* Y + 1            PASS 1 when y = 0 */
1119 			res = yop + 1;
1120 			CALC_NZ(res);
1121 			if (yop == 0x7fff) SET_V;
1122 			else if (yop == 0xffff) SET_C;
1123 			break;
1124 		case 0x02<<13:
1125 			/* X + Y + C */
1126 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1127 			yop += GET_C >> 3;
1128 			res = xop + yop;
1129 			CALC_NZVC(xop, yop, res);
1130 			break;
1131 		case 0x03<<13:
1132 			/* X + Y            X when y = 0 */
1133 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1134 			res = xop + yop;
1135 			CALC_NZVC(xop, yop, res);
1136 			break;
1137 		case 0x04<<13:
1138 			/* NOT Y */
1139 			res = yop ^ 0xffff;
1140 			CALC_NZ(res);
1141 			break;
1142 		case 0x05<<13:
1143 			/* -Y */
1144 			res = -yop;
1145 			CALC_NZ(res);
1146 			if (yop == 0x8000) SET_V;
1147 			if (yop == 0x0000) SET_C;
1148 			break;
1149 		case 0x06<<13:
1150 			/* X - Y + C - 1    X + C - 1 when y = 0 */
1151 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1152 			res = xop - yop + (GET_C >> 3) - 1;
1153 			CALC_NZVC_SUB(xop, yop, res);
1154 			break;
1155 		case 0x07<<13:
1156 			/* X - Y */
1157 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1158 			res = xop - yop;
1159 			CALC_NZVC_SUB(xop, yop, res);
1160 			break;
1161 		case 0x08<<13:
1162 			/* Y - 1            PASS -1 when y = 0 */
1163 			res = yop - 1;
1164 			CALC_NZ(res);
1165 			if (yop == 0x8000) SET_V;
1166 			else if (yop == 0x0000) SET_C;
1167 			break;
1168 		case 0x09<<13:
1169 			/* Y - X            -X when y = 0 */
1170 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1171 			res = yop - xop;
1172 			CALC_NZVC_SUB(yop, xop, res);
1173 			break;
1174 		case 0x0a<<13:
1175 			/* Y - X + C - 1    -X + C - 1 when y = 0 */
1176 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1177 			res = yop - xop + (GET_C >> 3) - 1;
1178 			CALC_NZVC_SUB(yop, xop, res);
1179 			break;
1180 		case 0x0b<<13:
1181 			/* NOT X */
1182 			res = ALU_GETXREG_UNSIGNED(adsp, xop) ^ 0xffff;
1183 			CALC_NZ(res);
1184 			break;
1185 		case 0x0c<<13:
1186 			/* X AND Y */
1187 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1188 			res = xop & yop;
1189 			CALC_NZ(res);
1190 			break;
1191 		case 0x0d<<13:
1192 			/* X OR Y */
1193 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1194 			res = xop | yop;
1195 			CALC_NZ(res);
1196 			break;
1197 		case 0x0e<<13:
1198 			/* X XOR Y */
1199 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1200 			res = xop ^ yop;
1201 			CALC_NZ(res);
1202 			break;
1203 		case 0x0f<<13:
1204 			/* ABS X */
1205 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1206 			res = (xop & 0x8000) ? -xop : xop;
1207 			if (xop == 0) SET_Z;
1208 			if (xop == 0x8000) SET_N, SET_V;
1209 			CLR_S;
1210 			if (xop & 0x8000) SET_S;
1211 			break;
1212 		default:
1213 			res = 0;	/* just to keep the compiler happy */
1214 			break;
1215 	}
1216 
1217 	/* set the final value */
1218 	adsp->core.af.u = res;
1219 }
1220 
1221 
1222 
1223 /*===========================================================================
1224     ALU operations (no result)
1225 ===========================================================================*/
1226 
alu_op_none(adsp2100_state * adsp,int op)1227 static void alu_op_none(adsp2100_state *adsp, int op)
1228 {
1229 	INT32 xop = (op >> 8) & 7;
1230 	INT32 yop = (op >> 11) & 3;
1231 	INT32 res;
1232 
1233 	switch (op & (15<<13))  /*JB*/
1234 	{
1235 		case 0x00<<13:
1236 			/* Y                Clear when y = 0 */
1237 			res = ALU_GETYREG_UNSIGNED(adsp, yop);
1238 			CALC_NZ(res);
1239 			break;
1240 		case 0x01<<13:
1241 			/* Y + 1            PASS 1 when y = 0 */
1242 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1243 			res = yop + 1;
1244 			CALC_NZ(res);
1245 			if (yop == 0x7fff) SET_V;
1246 			else if (yop == 0xffff) SET_C;
1247 			break;
1248 		case 0x02<<13:
1249 			/* X + Y + C */
1250 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1251 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1252 			yop += GET_C >> 3;
1253 			res = xop + yop;
1254 			CALC_NZVC(xop, yop, res);
1255 			break;
1256 		case 0x03<<13:
1257 			/* X + Y            X when y = 0 */
1258 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1259 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1260 			res = xop + yop;
1261 			CALC_NZVC(xop, yop, res);
1262 			break;
1263 		case 0x04<<13:
1264 			/* NOT Y */
1265 			res = ALU_GETYREG_UNSIGNED(adsp, yop) ^ 0xffff;
1266 			CALC_NZ(res);
1267 			break;
1268 		case 0x05<<13:
1269 			/* -Y */
1270 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1271 			res = -yop;
1272 			CALC_NZ(res);
1273 			if (yop == 0x8000) SET_V;
1274 			if (yop == 0x0000) SET_C;
1275 			break;
1276 		case 0x06<<13:
1277 			/* X - Y + C - 1    X + C - 1 when y = 0 */
1278 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1279 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1280 			res = xop - yop + (GET_C >> 3) - 1;
1281 			CALC_NZVC_SUB(xop, yop, res);
1282 			break;
1283 		case 0x07<<13:
1284 			/* X - Y */
1285 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1286 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1287 			res = xop - yop;
1288 			CALC_NZVC_SUB(xop, yop, res);
1289 			break;
1290 		case 0x08<<13:
1291 			/* Y - 1            PASS -1 when y = 0 */
1292 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1293 			res = yop - 1;
1294 			CALC_NZ(res);
1295 			if (yop == 0x8000) SET_V;
1296 			else if (yop == 0x0000) SET_C;
1297 			break;
1298 		case 0x09<<13:
1299 			/* Y - X            -X when y = 0 */
1300 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1301 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1302 			res = yop - xop;
1303 			CALC_NZVC_SUB(yop, xop, res);
1304 			break;
1305 		case 0x0a<<13:
1306 			/* Y - X + C - 1    -X + C - 1 when y = 0 */
1307 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1308 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1309 			res = yop - xop + (GET_C >> 3) - 1;
1310 			CALC_NZVC_SUB(yop, xop, res);
1311 			break;
1312 		case 0x0b<<13:
1313 			/* NOT X */
1314 			res = ALU_GETXREG_UNSIGNED(adsp, xop) ^ 0xffff;
1315 			CALC_NZ(res);
1316 			break;
1317 		case 0x0c<<13:
1318 			/* X AND Y */
1319 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1320 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1321 			res = xop & yop;
1322 			CALC_NZ(res);
1323 			break;
1324 		case 0x0d<<13:
1325 			/* X OR Y */
1326 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1327 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1328 			res = xop | yop;
1329 			CALC_NZ(res);
1330 			break;
1331 		case 0x0e<<13:
1332 			/* X XOR Y */
1333 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1334 			yop = ALU_GETYREG_UNSIGNED(adsp, yop);
1335 			res = xop ^ yop;
1336 			CALC_NZ(res);
1337 			break;
1338 		case 0x0f<<13:
1339 			/* ABS X */
1340 			xop = ALU_GETXREG_UNSIGNED(adsp, xop);
1341 			res = (xop & 0x8000) ? -xop : xop;
1342 			if (xop == 0) SET_Z;
1343 			if (xop == 0x8000) SET_N, SET_V;
1344 			CLR_S;
1345 			if (xop & 0x8000) SET_S;
1346 			break;
1347 	}
1348 }
1349 
1350 
1351 
1352 /*===========================================================================
1353     MAC operations (result in MR)
1354 ===========================================================================*/
1355 
mac_op_mr(adsp2100_state * adsp,int op)1356 static void mac_op_mr(adsp2100_state *adsp, int op)
1357 {
1358 	INT8 shift = ((adsp->mstat & MSTAT_INTEGER) >> 4) ^ 1;
1359 	INT32 xop = (op >> 8) & 7;
1360 	INT32 yop = (op >> 11) & 3;
1361 	INT32 temp;
1362 	INT64 res;
1363 
1364 	switch (op & (15<<13))	/*JB*/
1365 	{
1366 		case 0x00<<13:
1367 			/* no-op */
1368 			return;
1369 		case 0x01<<13:
1370 			/* X * Y (RND) */
1371 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1372 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1373 			temp = (xop * yop) << shift;
1374 			res = (INT64)temp;
1375 #if 0
1376 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1377 			else res += (res & 0x8000) << 1;
1378 #else
1379 			temp &= 0xffff;
1380 			res += 0x8000;
1381 			if ( temp == 0x8000 )
1382 				res &= ~((UINT64)0x10000);
1383 #endif
1384 			break;
1385 		case 0x02<<13:
1386 			/* MR + X * Y (RND) */
1387 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1388 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1389 			temp = (xop * yop) << shift;
1390 			res = adsp->core.mr.mr + (INT64)temp;
1391 #if 0
1392 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1393 			else res += (res & 0x8000) << 1;
1394 #else
1395 			temp &= 0xffff;
1396 			res += 0x8000;
1397 			if ( temp == 0x8000 )
1398 				res &= ~((UINT64)0x10000);
1399 #endif
1400 			break;
1401 		case 0x03<<13:
1402 			/* MR - X * Y (RND) */
1403 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1404 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1405 			temp = (xop * yop) << shift;
1406 			res = adsp->core.mr.mr - (INT64)temp;
1407 #if 0
1408 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1409 			else res += (res & 0x8000) << 1;
1410 #else
1411 			temp &= 0xffff;
1412 			res += 0x8000;
1413 			if ( temp == 0x8000 )
1414 				res &= ~((UINT64)0x10000);
1415 #endif
1416 			break;
1417 		case 0x04<<13:
1418 			/* X * Y (SS)       Clear when y = 0 */
1419 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1420 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1421 			temp = (xop * yop) << shift;
1422 			res = (INT64)temp;
1423 			break;
1424 		case 0x05<<13:
1425 			/* X * Y (SU) */
1426 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1427 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1428 			temp = (xop * yop) << shift;
1429 			res = (INT64)temp;
1430 			break;
1431 		case 0x06<<13:
1432 			/* X * Y (US) */
1433 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1434 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1435 			temp = (xop * yop) << shift;
1436 			res = (INT64)temp;
1437 			break;
1438 		case 0x07<<13:
1439 			/* X * Y (UU) */
1440 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1441 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1442 			temp = (xop * yop) << shift;
1443 			res = (INT64)temp;
1444 			break;
1445 		case 0x08<<13:
1446 			/* MR + X * Y (SS) */
1447 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1448 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1449 			temp = (xop * yop) << shift;
1450 			res = adsp->core.mr.mr + (INT64)temp;
1451 			break;
1452 		case 0x09<<13:
1453 			/* MR + X * Y (SU) */
1454 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1455 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1456 			temp = (xop * yop) << shift;
1457 			res = adsp->core.mr.mr + (INT64)temp;
1458 			break;
1459 		case 0x0a<<13:
1460 			/* MR + X * Y (US) */
1461 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1462 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1463 			temp = (xop * yop) << shift;
1464 			res = adsp->core.mr.mr + (INT64)temp;
1465 			break;
1466 		case 0x0b<<13:
1467 			/* MR + X * Y (UU) */
1468 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1469 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1470 			temp = (xop * yop) << shift;
1471 			res = adsp->core.mr.mr + (INT64)temp;
1472 			break;
1473 		case 0x0c<<13:
1474 			/* MR - X * Y (SS) */
1475 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1476 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1477 			temp = (xop * yop) << shift;
1478 			res = adsp->core.mr.mr - (INT64)temp;
1479 			break;
1480 		case 0x0d<<13:
1481 			/* MR - X * Y (SU) */
1482 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1483 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1484 			temp = (xop * yop) << shift;
1485 			res = adsp->core.mr.mr - (INT64)temp;
1486 			break;
1487 		case 0x0e<<13:
1488 			/* MR - X * Y (US) */
1489 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1490 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1491 			temp = (xop * yop) << shift;
1492 			res = adsp->core.mr.mr - (INT64)temp;
1493 			break;
1494 		case 0x0f<<13:
1495 			/* MR - X * Y (UU) */
1496 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1497 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1498 			temp = (xop * yop) << shift;
1499 			res = adsp->core.mr.mr - (INT64)temp;
1500 			break;
1501 		default:
1502 			res = 0;	/* just to keep the compiler happy */
1503 			break;
1504 	}
1505 
1506 	/* set the final value */
1507 	temp = (res >> 31) & 0x1ff;
1508 	CLR_MV;
1509 	if (temp != 0x000 && temp != 0x1ff) SET_MV;
1510 	adsp->core.mr.mr = res;
1511 }
1512 
1513 
1514 
1515 /*===========================================================================
1516     MAC operations (result in MR, yop == xop)
1517 ===========================================================================*/
1518 
mac_op_mr_xop(adsp2100_state * adsp,int op)1519 static void mac_op_mr_xop(adsp2100_state *adsp, int op)
1520 {
1521 	INT8 shift = ((adsp->mstat & MSTAT_INTEGER) >> 4) ^ 1;
1522 	INT32 xop = (op >> 8) & 7;
1523 	INT32 temp;
1524 	INT64 res;
1525 
1526 	switch (op & (15<<13))	/*JB*/
1527 	{
1528 		case 0x00<<13:
1529 			/* no-op */
1530 			return;
1531 		case 0x01<<13:
1532 			/* X * Y (RND) */
1533 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1534 			temp = (xop * xop) << shift;
1535 			res = (INT64)temp;
1536 #if 0
1537 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1538 			else res += (res & 0x8000) << 1;
1539 #else
1540 			temp &= 0xffff;
1541 			res += 0x8000;
1542 			if ( temp == 0x8000 )
1543 				res &= ~((UINT64)0x10000);
1544 #endif
1545 			break;
1546 		case 0x02<<13:
1547 			/* MR + X * Y (RND) */
1548 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1549 			temp = (xop * xop) << shift;
1550 			res = adsp->core.mr.mr + (INT64)temp;
1551 #if 0
1552 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1553 			else res += (res & 0x8000) << 1;
1554 #else
1555 			temp &= 0xffff;
1556 			res += 0x8000;
1557 			if ( temp == 0x8000 )
1558 				res &= ~((UINT64)0x10000);
1559 #endif
1560 			break;
1561 		case 0x03<<13:
1562 			/* MR - X * Y (RND) */
1563 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1564 			temp = (xop * xop) << shift;
1565 			res = adsp->core.mr.mr - (INT64)temp;
1566 #if 0
1567 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1568 			else res += (res & 0x8000) << 1;
1569 #else
1570 			temp &= 0xffff;
1571 			res += 0x8000;
1572 			if ( temp == 0x8000 )
1573 				res &= ~((UINT64)0x10000);
1574 #endif
1575 			break;
1576 		case 0x04<<13:
1577 			/* X * Y (SS)       Clear when y = 0 */
1578 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1579 			temp = (xop * xop) << shift;
1580 			res = (INT64)temp;
1581 			break;
1582 		case 0x05<<13:
1583 			/* X * Y (SU) */
1584 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1585 			temp = (xop * xop) << shift;
1586 			res = (INT64)temp;
1587 			break;
1588 		case 0x06<<13:
1589 			/* X * Y (US) */
1590 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1591 			temp = (xop * xop) << shift;
1592 			res = (INT64)temp;
1593 			break;
1594 		case 0x07<<13:
1595 			/* X * Y (UU) */
1596 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1597 			temp = (xop * xop) << shift;
1598 			res = (INT64)temp;
1599 			break;
1600 		case 0x08<<13:
1601 			/* MR + X * Y (SS) */
1602 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1603 			temp = (xop * xop) << shift;
1604 			res = adsp->core.mr.mr + (INT64)temp;
1605 			break;
1606 		case 0x09<<13:
1607 			/* MR + X * Y (SU) */
1608 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1609 			temp = (xop * xop) << shift;
1610 			res = adsp->core.mr.mr + (INT64)temp;
1611 			break;
1612 		case 0x0a<<13:
1613 			/* MR + X * Y (US) */
1614 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1615 			temp = (xop * xop) << shift;
1616 			res = adsp->core.mr.mr + (INT64)temp;
1617 			break;
1618 		case 0x0b<<13:
1619 			/* MR + X * Y (UU) */
1620 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1621 			temp = (xop * xop) << shift;
1622 			res = adsp->core.mr.mr + (INT64)temp;
1623 			break;
1624 		case 0x0c<<13:
1625 			/* MR - X * Y (SS) */
1626 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1627 			temp = (xop * xop) << shift;
1628 			res = adsp->core.mr.mr - (INT64)temp;
1629 			break;
1630 		case 0x0d<<13:
1631 			/* MR - X * Y (SU) */
1632 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1633 			temp = (xop * xop) << shift;
1634 			res = adsp->core.mr.mr - (INT64)temp;
1635 			break;
1636 		case 0x0e<<13:
1637 			/* MR - X * Y (US) */
1638 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1639 			temp = (xop * xop) << shift;
1640 			res = adsp->core.mr.mr - (INT64)temp;
1641 			break;
1642 		case 0x0f<<13:
1643 			/* MR - X * Y (UU) */
1644 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1645 			temp = (xop * xop) << shift;
1646 			res = adsp->core.mr.mr - (INT64)temp;
1647 			break;
1648 		default:
1649 			res = 0;	/* just to keep the compiler happy */
1650 			break;
1651 	}
1652 
1653 	/* set the final value */
1654 	temp = (res >> 31) & 0x1ff;
1655 	CLR_MV;
1656 	if (temp != 0x000 && temp != 0x1ff) SET_MV;
1657 	adsp->core.mr.mr = res;
1658 }
1659 
1660 
1661 
1662 /*===========================================================================
1663     MAC operations (result in MF)
1664 ===========================================================================*/
1665 
mac_op_mf(adsp2100_state * adsp,int op)1666 static void mac_op_mf(adsp2100_state *adsp, int op)
1667 {
1668 	INT8 shift = ((adsp->mstat & MSTAT_INTEGER) >> 4) ^ 1;
1669 	INT32 xop = (op >> 8) & 7;
1670 	INT32 yop = (op >> 11) & 3;
1671 	INT32 temp;
1672 	INT64 res;
1673 
1674 	switch (op & (15<<13))	/*JB*/
1675 	{
1676 		case 0x00<<13:
1677 			/* no-op */
1678 			return;
1679 		case 0x01<<13:
1680 			/* X * Y (RND) */
1681 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1682 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1683 			temp = (xop * yop) << shift;
1684 			res = (INT64)temp;
1685 #if 0
1686 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1687 			else res += (res & 0x8000) << 1;
1688 #else
1689 			temp &= 0xffff;
1690 			res += 0x8000;
1691 			if ( temp == 0x8000 )
1692 				res &= ~((UINT64)0x10000);
1693 #endif
1694 			break;
1695 		case 0x02<<13:
1696 			/* MR + X * Y (RND) */
1697 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1698 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1699 			temp = (xop * yop) << shift;
1700 			res = adsp->core.mr.mr + (INT64)temp;
1701 #if 0
1702 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1703 			else res += (res & 0x8000) << 1;
1704 #else
1705 			temp &= 0xffff;
1706 			res += 0x8000;
1707 			if ( temp == 0x8000 )
1708 				res &= ~((UINT64)0x10000);
1709 #endif
1710 			break;
1711 		case 0x03<<13:
1712 			/* MR - X * Y (RND) */
1713 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1714 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1715 			temp = (xop * yop) << shift;
1716 			res = adsp->core.mr.mr - (INT64)temp;
1717 #if 0
1718 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1719 			else res += (res & 0x8000) << 1;
1720 #else
1721 			temp &= 0xffff;
1722 			res += 0x8000;
1723 			if ( temp == 0x8000 )
1724 				res &= ~((UINT64)0x10000);
1725 #endif
1726 			break;
1727 		case 0x04<<13:
1728 			/* X * Y (SS)       Clear when y = 0 */
1729 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1730 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1731 			temp = (xop * yop) << shift;
1732 			res = (INT64)temp;
1733 			break;
1734 		case 0x05<<13:
1735 			/* X * Y (SU) */
1736 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1737 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1738 			temp = (xop * yop) << shift;
1739 			res = (INT64)temp;
1740 			break;
1741 		case 0x06<<13:
1742 			/* X * Y (US) */
1743 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1744 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1745 			temp = (xop * yop) << shift;
1746 			res = (INT64)temp;
1747 			break;
1748 		case 0x07<<13:
1749 			/* X * Y (UU) */
1750 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1751 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1752 			temp = (xop * yop) << shift;
1753 			res = (INT64)temp;
1754 			break;
1755 		case 0x08<<13:
1756 			/* MR + X * Y (SS) */
1757 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1758 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1759 			temp = (xop * yop) << shift;
1760 			res = adsp->core.mr.mr + (INT64)temp;
1761 			break;
1762 		case 0x09<<13:
1763 			/* MR + X * Y (SU) */
1764 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1765 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1766 			temp = (xop * yop) << shift;
1767 			res = adsp->core.mr.mr + (INT64)temp;
1768 			break;
1769 		case 0x0a<<13:
1770 			/* MR + X * Y (US) */
1771 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1772 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1773 			temp = (xop * yop) << shift;
1774 			res = adsp->core.mr.mr + (INT64)temp;
1775 			break;
1776 		case 0x0b<<13:
1777 			/* MR + X * Y (UU) */
1778 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1779 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1780 			temp = (xop * yop) << shift;
1781 			res = adsp->core.mr.mr + (INT64)temp;
1782 			break;
1783 		case 0x0c<<13:
1784 			/* MR - X * Y (SS) */
1785 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1786 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1787 			temp = (xop * yop) << shift;
1788 			res = adsp->core.mr.mr - (INT64)temp;
1789 			break;
1790 		case 0x0d<<13:
1791 			/* MR - X * Y (SU) */
1792 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1793 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1794 			temp = (xop * yop) << shift;
1795 			res = adsp->core.mr.mr - (INT64)temp;
1796 			break;
1797 		case 0x0e<<13:
1798 			/* MR - X * Y (US) */
1799 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1800 			yop = MAC_GETYREG_SIGNED(adsp, yop);
1801 			temp = (xop * yop) << shift;
1802 			res = adsp->core.mr.mr - (INT64)temp;
1803 			break;
1804 		case 0x0f<<13:
1805 			/* MR - X * Y (UU) */
1806 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1807 			yop = MAC_GETYREG_UNSIGNED(adsp, yop);
1808 			temp = (xop * yop) << shift;
1809 			res = adsp->core.mr.mr - (INT64)temp;
1810 			break;
1811 		default:
1812 			res = 0;	/* just to keep the compiler happy */
1813 			break;
1814 	}
1815 
1816 	/* set the final value */
1817 	adsp->core.mf.u = (UINT32)res >> 16;
1818 }
1819 
1820 
1821 
1822 /*===========================================================================
1823     MAC operations (result in MF, yop == xop)
1824 ===========================================================================*/
1825 
mac_op_mf_xop(adsp2100_state * adsp,int op)1826 static void mac_op_mf_xop(adsp2100_state *adsp, int op)
1827 {
1828 	INT8 shift = ((adsp->mstat & MSTAT_INTEGER) >> 4) ^ 1;
1829 	INT32 xop = (op >> 8) & 7;
1830 	INT32 temp;
1831 	INT64 res;
1832 
1833 	switch (op & (15<<13))	/*JB*/
1834 	{
1835 		case 0x00<<13:
1836 			/* no-op */
1837 			return;
1838 		case 0x01<<13:
1839 			/* X * Y (RND) */
1840 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1841 			temp = (xop * xop) << shift;
1842 			res = (INT64)temp;
1843 #if 0
1844 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1845 			else res += (res & 0x8000) << 1;
1846 #else
1847 			temp &= 0xffff;
1848 			res += 0x8000;
1849 			if ( temp == 0x8000 )
1850 				res &= ~((UINT64)0x10000);
1851 #endif
1852 			break;
1853 		case 0x02<<13:
1854 			/* MR + X * Y (RND) */
1855 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1856 			temp = (xop * xop) << shift;
1857 			res = adsp->core.mr.mr + (INT64)temp;
1858 #if 0
1859 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1860 			else res += (res & 0x8000) << 1;
1861 #else
1862 			temp &= 0xffff;
1863 			res += 0x8000;
1864 			if ( temp == 0x8000 )
1865 				res &= ~((UINT64)0x10000);
1866 #endif
1867 			break;
1868 		case 0x03<<13:
1869 			/* MR - X * Y (RND) */
1870 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1871 			temp = (xop * xop) << shift;
1872 			res = adsp->core.mr.mr - (INT64)temp;
1873 #if 0
1874 			if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
1875 			else res += (res & 0x8000) << 1;
1876 #else
1877 			temp &= 0xffff;
1878 			res += 0x8000;
1879 			if ( temp == 0x8000 )
1880 				res &= ~((UINT64)0x10000);
1881 #endif
1882 			break;
1883 		case 0x04<<13:
1884 			/* X * Y (SS)       Clear when y = 0 */
1885 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1886 			temp = (xop * xop) << shift;
1887 			res = (INT64)temp;
1888 			break;
1889 		case 0x05<<13:
1890 			/* X * Y (SU) */
1891 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1892 			temp = (xop * xop) << shift;
1893 			res = (INT64)temp;
1894 			break;
1895 		case 0x06<<13:
1896 			/* X * Y (US) */
1897 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1898 			temp = (xop * xop) << shift;
1899 			res = (INT64)temp;
1900 			break;
1901 		case 0x07<<13:
1902 			/* X * Y (UU) */
1903 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1904 			temp = (xop * xop) << shift;
1905 			res = (INT64)temp;
1906 			break;
1907 		case 0x08<<13:
1908 			/* MR + X * Y (SS) */
1909 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1910 			temp = (xop * xop) << shift;
1911 			res = adsp->core.mr.mr + (INT64)temp;
1912 			break;
1913 		case 0x09<<13:
1914 			/* MR + X * Y (SU) */
1915 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1916 			temp = (xop * xop) << shift;
1917 			res = adsp->core.mr.mr + (INT64)temp;
1918 			break;
1919 		case 0x0a<<13:
1920 			/* MR + X * Y (US) */
1921 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1922 			temp = (xop * xop) << shift;
1923 			res = adsp->core.mr.mr + (INT64)temp;
1924 			break;
1925 		case 0x0b<<13:
1926 			/* MR + X * Y (UU) */
1927 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1928 			temp = (xop * xop) << shift;
1929 			res = adsp->core.mr.mr + (INT64)temp;
1930 			break;
1931 		case 0x0c<<13:
1932 			/* MR - X * Y (SS) */
1933 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1934 			temp = (xop * xop) << shift;
1935 			res = adsp->core.mr.mr - (INT64)temp;
1936 			break;
1937 		case 0x0d<<13:
1938 			/* MR - X * Y (SU) */
1939 			xop = MAC_GETXREG_SIGNED(adsp, xop);
1940 			temp = (xop * xop) << shift;
1941 			res = adsp->core.mr.mr - (INT64)temp;
1942 			break;
1943 		case 0x0e<<13:
1944 			/* MR - X * Y (US) */
1945 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1946 			temp = (xop * xop) << shift;
1947 			res = adsp->core.mr.mr - (INT64)temp;
1948 			break;
1949 		case 0x0f<<13:
1950 			/* MR - X * Y (UU) */
1951 			xop = MAC_GETXREG_UNSIGNED(adsp, xop);
1952 			temp = (xop * xop) << shift;
1953 			res = adsp->core.mr.mr - (INT64)temp;
1954 			break;
1955 		default:
1956 			res = 0;	/* just to keep the compiler happy */
1957 			break;
1958 	}
1959 
1960 	/* set the final value */
1961 	adsp->core.mf.u = (UINT32)res >> 16;
1962 }
1963 
1964 
1965 
1966 /*===========================================================================
1967     SHIFT operations (result in SR/SE/SB)
1968 ===========================================================================*/
1969 
shift_op(adsp2100_state * adsp,int op)1970 static void shift_op(adsp2100_state *adsp, int op)
1971 {
1972 	INT8 sc = adsp->core.se.s;
1973 	INT32 xop = (op >> 8) & 7;
1974 	UINT32 res;
1975 
1976 	switch (op & (15<<11))	/*JB*/
1977 	{
1978 		case 0x00<<11:
1979 			/* LSHIFT (HI) */
1980 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop) << 16;
1981 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
1982 			else res = (sc > -32) ? ((UINT32)xop >> -sc) : 0;
1983 			adsp->core.sr.sr = res;
1984 			break;
1985 		case 0x01<<11:
1986 			/* LSHIFT (HI, OR) */
1987 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop) << 16;
1988 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
1989 			else res = (sc > -32) ? ((UINT32)xop >> -sc) : 0;
1990 			adsp->core.sr.sr |= res;
1991 			break;
1992 		case 0x02<<11:
1993 			/* LSHIFT (LO) */
1994 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop);
1995 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
1996 			else res = (sc > -32) ? (xop >> -sc) : 0;
1997 			adsp->core.sr.sr = res;
1998 			break;
1999 		case 0x03<<11:
2000 			/* LSHIFT (LO, OR) */
2001 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop);
2002 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2003 			else res = (sc > -32) ? (xop >> -sc) : 0;
2004 			adsp->core.sr.sr |= res;
2005 			break;
2006 		case 0x04<<11:
2007 			/* ASHIFT (HI) */
2008 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2009 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2010 			else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
2011 			adsp->core.sr.sr = res;
2012 			break;
2013 		case 0x05<<11:
2014 			/* ASHIFT (HI, OR) */
2015 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2016 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2017 			else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
2018 			adsp->core.sr.sr |= res;
2019 			break;
2020 		case 0x06<<11:
2021 			/* ASHIFT (LO) */
2022 			xop = SHIFT_GETXREG_SIGNED(adsp, xop);
2023 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2024 			else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
2025 			adsp->core.sr.sr = res;
2026 			break;
2027 		case 0x07<<11:
2028 			/* ASHIFT (LO, OR) */
2029 			xop = SHIFT_GETXREG_SIGNED(adsp, xop);
2030 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2031 			else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
2032 			adsp->core.sr.sr |= res;
2033 			break;
2034 		case 0x08<<11:
2035 			/* NORM (HI) */
2036 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2037 			if (sc > 0)
2038 			{
2039 				xop = ((UINT32)xop >> 1) | ((adsp->astat & CFLAG) << 28);
2040 				res = xop >> (sc - 1);
2041 			}
2042 			else res = (sc > -32) ? (xop << -sc) : 0;
2043 			adsp->core.sr.sr = res;
2044 			break;
2045 		case 0x09<<11:
2046 			/* NORM (HI, OR) */
2047 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2048 			if (sc > 0)
2049 			{
2050 				xop = ((UINT32)xop >> 1) | ((adsp->astat & CFLAG) << 28);
2051 				res = xop >> (sc - 1);
2052 			}
2053 			else res = (sc > -32) ? (xop << -sc) : 0;
2054 			adsp->core.sr.sr |= res;
2055 			break;
2056 		case 0x0a<<11:
2057 			/* NORM (LO) */
2058 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop);
2059 			if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
2060 			else res = (sc > -32) ? (xop << -sc) : 0;
2061 			adsp->core.sr.sr = res;
2062 			break;
2063 		case 0x0b<<11:
2064 			/* NORM (LO, OR) */
2065 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop);
2066 			if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
2067 			else res = (sc > -32) ? (xop << -sc) : 0;
2068 			adsp->core.sr.sr |= res;
2069 			break;
2070 		case 0x0c<<11:
2071 			/* EXP (HI) */
2072 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2073 			res = 0;
2074 			if (xop < 0)
2075 			{
2076 				SET_SS;
2077 				while ((xop & 0x40000000) != 0) res++, xop <<= 1;
2078 			}
2079 			else
2080 			{
2081 				CLR_SS;
2082 				xop |= 0x8000;
2083 				while ((xop & 0x40000000) == 0) res++, xop <<= 1;
2084 			}
2085 			adsp->core.se.s = -res;
2086 			break;
2087 		case 0x0d<<11:
2088 			/* EXP (HIX) */
2089 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2090 			if (GET_V)
2091 			{
2092 				adsp->core.se.s = 1;
2093 				if (xop < 0) CLR_SS;
2094 				else SET_SS;
2095 			}
2096 			else
2097 			{
2098 				res = 0;
2099 				if (xop < 0)
2100 				{
2101 					SET_SS;
2102 					while ((xop & 0x40000000) != 0) res++, xop <<= 1;
2103 				}
2104 				else
2105 				{
2106 					CLR_SS;
2107 					xop |= 0x8000;
2108 					while ((xop & 0x40000000) == 0) res++, xop <<= 1;
2109 				}
2110 				adsp->core.se.s = -res;
2111 			}
2112 			break;
2113 		case 0x0e<<11:
2114 			/* EXP (LO) */
2115 			if (adsp->core.se.s == -15)
2116 			{
2117 				xop = SHIFT_GETXREG_SIGNED(adsp, xop);
2118 				res = 15;
2119 				if (GET_SS)
2120 					while ((xop & 0x8000) != 0) res++, xop <<= 1;
2121 				else
2122 				{
2123 					xop = (xop << 1) | 1;
2124 					while ((xop & 0x10000) == 0) res++, xop <<= 1;
2125 				}
2126 				adsp->core.se.s = -res;
2127 			}
2128 			break;
2129 		case 0x0f<<11:
2130 			/* EXPADJ */
2131 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2132 			res = 0;
2133 			if (xop < 0)
2134 				while ((xop & 0x40000000) != 0) res++, xop <<= 1;
2135 			else
2136 			{
2137 				xop |= 0x8000;
2138 				while ((xop & 0x40000000) == 0) res++, xop <<= 1;
2139 			}
2140 			if (res < -adsp->core.sb.s)
2141 				adsp->core.sb.s = -res;
2142 			break;
2143 	}
2144 }
2145 
2146 
2147 
2148 /*===========================================================================
2149     Immediate SHIFT operations (result in SR/SE/SB)
2150 ===========================================================================*/
2151 
shift_op_imm(adsp2100_state * adsp,int op)2152 static void shift_op_imm(adsp2100_state *adsp, int op)
2153 {
2154 	INT8 sc = (INT8)op;
2155 	INT32 xop = (op >> 8) & 7;
2156 	UINT32 res;
2157 
2158 	switch (op & (15<<11))	/*JB*/
2159 	{
2160 		case 0x00<<11:
2161 			/* LSHIFT (HI) */
2162 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop) << 16;
2163 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2164 			else res = (sc > -32) ? ((UINT32)xop >> -sc) : 0;
2165 			adsp->core.sr.sr = res;
2166 			break;
2167 		case 0x01<<11:
2168 			/* LSHIFT (HI, OR) */
2169 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop) << 16;
2170 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2171 			else res = (sc > -32) ? ((UINT32)xop >> -sc) : 0;
2172 			adsp->core.sr.sr |= res;
2173 			break;
2174 		case 0x02<<11:
2175 			/* LSHIFT (LO) */
2176 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop);
2177 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2178 			else res = (sc > -32) ? (xop >> -sc) : 0;
2179 			adsp->core.sr.sr = res;
2180 			break;
2181 		case 0x03<<11:
2182 			/* LSHIFT (LO, OR) */
2183 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop);
2184 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2185 			else res = (sc > -32) ? (xop >> -sc) : 0;
2186 			adsp->core.sr.sr |= res;
2187 			break;
2188 		case 0x04<<11:
2189 			/* ASHIFT (HI) */
2190 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2191 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2192 			else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
2193 			adsp->core.sr.sr = res;
2194 			break;
2195 		case 0x05<<11:
2196 			/* ASHIFT (HI, OR) */
2197 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2198 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2199 			else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
2200 			adsp->core.sr.sr |= res;
2201 			break;
2202 		case 0x06<<11:
2203 			/* ASHIFT (LO) */
2204 			xop = SHIFT_GETXREG_SIGNED(adsp, xop);
2205 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2206 			else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
2207 			adsp->core.sr.sr = res;
2208 			break;
2209 		case 0x07<<11:
2210 			/* ASHIFT (LO, OR) */
2211 			xop = SHIFT_GETXREG_SIGNED(adsp, xop);
2212 			if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
2213 			else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
2214 			adsp->core.sr.sr |= res;
2215 			break;
2216 		case 0x08<<11:
2217 			/* NORM (HI) */
2218 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2219 			if (sc > 0)
2220 			{
2221 				xop = ((UINT32)xop >> 1) | ((adsp->astat & CFLAG) << 28);
2222 				res = xop >> (sc - 1);
2223 			}
2224 			else res = (sc > -32) ? (xop << -sc) : 0;
2225 			adsp->core.sr.sr = res;
2226 			break;
2227 		case 0x09<<11:
2228 			/* NORM (HI, OR) */
2229 			xop = SHIFT_GETXREG_SIGNED(adsp, xop) << 16;
2230 			if (sc > 0)
2231 			{
2232 				xop = ((UINT32)xop >> 1) | ((adsp->astat & CFLAG) << 28);
2233 				res = xop >> (sc - 1);
2234 			}
2235 			else res = (sc > -32) ? (xop << -sc) : 0;
2236 			adsp->core.sr.sr |= res;
2237 			break;
2238 		case 0x0a<<11:
2239 			/* NORM (LO) */
2240 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop);
2241 			if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
2242 			else res = (sc > -32) ? (xop << -sc) : 0;
2243 			adsp->core.sr.sr = res;
2244 			break;
2245 		case 0x0b<<11:
2246 			/* NORM (LO, OR) */
2247 			xop = SHIFT_GETXREG_UNSIGNED(adsp, xop);
2248 			if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
2249 			else res = (sc > -32) ? (xop << -sc) : 0;
2250 			adsp->core.sr.sr |= res;
2251 			break;
2252 	}
2253 }
2254