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