Subversion Repositories Shiroi

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 nishi 1
/* ova.c
2
 *
3
 * Not an egg -- overflow arithmetic. 16 and 32 bit.
4
 *
5
 * Designed to work with both gcc and hi-tech C. This is then meant
6
 * to allow operation of AM9511 emulation with hi-tech C natively
7
 * on z80 platform. There are faster ways, but we want to be able
8
 * to validate the code against a real AM9511A, as long as some of
9
 * those chips are still operational.
10
 *
11
 * Because this code is meant to be (potentially) used with
12
 * hi-tech C, and other very old environments, external names are
13
 * unique to 5 characters (6 with prepended '_').
14
 */
15
 
16
#include <stdio.h>
17
 
18
#include "ova.h"
19
#include "types.h"
20
 
21
#define USE_MUL16
22
 
23
/* Constant 1, good for 16, 32 and 64 bit
24
 */
25
static unsigned char one[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
26
 
27
/* Return overflow flag after add16().
28
 *
29
 * Overflow is detected by sign bits of the arguments and result.
30
 * This can be done after the add (or subtract) is done. That is
31
 * why add and subtract return carry, and leave overflow to a
32
 * separate function.
33
 */
34
int oadd16(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
35
	unsigned char sa, sb, sc;
36
	int overflow = 0;
37
 
38
	sa = pa[1] & 0x80;
39
	sb = pb[1] & 0x80;
40
	sc = pc[1] & 0x80;
41
	if((sa == 0x00) && (sb == 0x00) && (sc == 0x80)) overflow = 1;
42
	if((sa == 0x80) && (sb == 0x80) && (sc == 0x00)) overflow = 1;
43
	return overflow;
44
}
45
 
46
/* Return overflow flag after add32().
47
 */
48
int oadd32(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
49
	unsigned char sa, sb, sc;
50
	int overflow = 0;
51
 
52
	sa = pa[3] & 0x80;
53
	sb = pb[3] & 0x80;
54
	sc = pc[3] & 0x80;
55
	if((sa == 0x00) && (sb == 0x00) && (sc == 0x80)) overflow = 1;
56
	if((sa == 0x80) && (sb == 0x80) && (sc == 0x00)) overflow = 1;
57
	return overflow;
58
}
59
 
60
/* Return overflow flag after sub16().
61
 */
62
int osub16(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
63
	unsigned char sa, sb, sc;
64
	int overflow = 0;
65
 
66
	sa = pa[1] & 0x80;
67
	sb = pb[1] & 0x80;
68
	sc = pc[1] & 0x80;
69
	if((sa == 0x00) && (sb == 0x80) && (sc == 0x80)) overflow = 1;
70
	if((sa == 0x80) && (sb == 0x00) && (sc == 0x00)) overflow = 1;
71
	return overflow;
72
}
73
 
74
/* Return overflow after sub32().
75
 */
76
int osub32(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
77
	unsigned char sa, sb, sc;
78
	int overflow = 0;
79
 
80
	sa = pa[3] & 0x80;
81
	sb = pb[3] & 0x80;
82
	sc = pc[3] & 0x80;
83
	if((sa == 0x00) && (sb == 0x80) && (sc == 0x80)) overflow = 1;
84
	if((sa == 0x80) && (sb == 0x00) && (sc == 0x00)) overflow = 1;
85
	return overflow;
86
}
87
 
88
/* 16 bit add, returns carry.
89
 *
90
 * All parameters are little endian.
91
 */
92
int add16(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
93
	uint16 a, b, c;
94
	int carry;
95
 
96
	a = pa[0] | (pa[1] << 8);
97
	b = pb[0] | (pb[1] << 8);
98
	c = a + b;
99
	carry = (c < a) || (c < b);
100
	pc[0] = c;
101
	pc[1] = c >> 8;
102
	return carry;
103
}
104
 
105
/* 32 bit add, returns carry. Uses add16().
106
 */
107
int add32(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
108
	unsigned char *pah, *pbh, *pch;
109
	int carry, c2;
110
 
111
	pah = pa + 2;
112
	pbh = pb + 2;
113
	pch = pc + 2;
114
 
115
	carry = add16(pa, pb, pc);
116
	if(!carry) {
117
		carry = add16(pah, pbh, pch);
118
		return carry;
119
	}
120
 
121
	carry = add16(one, pbh, pch);
122
	c2 = add16(pch, pah, pch);
123
	return carry || c2;
124
}
125
 
126
/* 64 bit add, returns carry. Uses add32().
127
 *
128
 * This supports 32x32->64 bit multiply.
129
 */
130
static int add64(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
131
	unsigned char *pah, *pbh, *pch;
132
	int carry, c2;
133
 
134
	pah = pa + 4;
135
	pbh = pb + 4;
136
	pch = pc + 4;
137
 
138
	carry = add32(pa, pb, pc);
139
	if(!carry) {
140
		carry = add32(pah, pbh, pch);
141
		return carry;
142
	}
143
 
144
	carry = add32(one, pbh, pch);
145
	c2 = add32(pch, pah, pch);
146
	return carry || c2;
147
}
148
 
149
/* 16 bit 2's complement, return 1 if 0x8000
150
 */
151
int cm16(unsigned char* pa, unsigned char* pb) {
152
	uint16 a, b;
153
	int r = 0;
154
 
155
	a = pa[0] | (pa[1] << 8);
156
	if(a == 0x8000) {
157
		b = a;
158
		r = 1;
159
	} else {
160
		b = ~a;
161
		++b;
162
	}
163
	pb[0] = b;
164
	pb[1] = b >> 8;
165
	return r;
166
}
167
 
168
/* 32 bit 2's complement, return 1 if 0x80000000
169
 */
170
int cm32(unsigned char* pa, unsigned char* pb) {
171
	uint16 a, ah, b, bh;
172
	int r = 0;
173
 
174
	a = pa[0] | (pa[1] << 8);
175
	ah = pa[2] | (pa[3] << 8);
176
	if((a == 0x0000) && (ah == 0x8000)) {
177
		b = a;
178
		bh = ah;
179
		r = 1;
180
	} else {
181
		b = ~a;
182
		bh = ~ah;
183
		if(++b == 0) ++bh;
184
	}
185
	pb[0] = b;
186
	pb[1] = b >> 8;
187
	pb[2] = bh;
188
	pb[3] = bh >> 8;
189
	return r;
190
}
191
 
192
/* 64 bit 2's complement, return 1 if 0x8000 0000 0000 0000
193
 */
194
static int cm64(unsigned char* pa, unsigned char* pb) {
195
	if(pa[7] == 0x80)
196
		if((pa[0] | pa[1] | pa[2] | pa[3] | pa[4] | pa[5] | pa[6]) == 0) {
197
			pb[0] = pb[1] = pb[2] = pb[3] = pb[4] = pb[5] = pb[6] = 0;
198
			pb[7] = 0x80;
199
			return 1;
200
		}
201
 
202
	pb[0] = ~pa[0];
203
	pb[1] = ~pa[1];
204
	pb[2] = ~pa[2];
205
	pb[3] = ~pa[3];
206
	pb[4] = ~pa[4];
207
	pb[5] = ~pa[5];
208
	pb[6] = ~pa[6];
209
	pb[7] = ~pa[7];
210
	add64(pb, one, pb);
211
	return 0;
212
}
213
 
214
/* 16 bit subtract. Return 1 if carry.
215
 */
216
int sub16(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
217
	uint16 a, b, c;
218
	int carry;
219
 
220
	a = pa[0] | (pa[1] << 8);
221
	b = pb[0] | (pb[1] << 8);
222
	c = a - b;
223
	if(a == 0x8000) carry = 1;
224
	else
225
		carry = a < b;
226
	pc[0] = c;
227
	pc[1] = c >> 8;
228
	return carry;
229
}
230
 
231
/* 32 subtract. Return carry.
232
 */
233
int sub32(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
234
	unsigned char *pah, *pbh, *pch;
235
	int carry, c2;
236
 
237
	pah = pa + 2;
238
	pbh = pb + 2;
239
	pch = pc + 2;
240
 
241
	carry = sub16(pa, pb, pc);
242
	if(!carry) {
243
		carry = sub16(pah, pbh, pch);
244
		return carry;
245
	}
246
 
247
	carry = sub16(pah, one, pch);
248
	c2 = sub16(pch, pbh, pch);
249
	return carry || c2;
250
}
251
 
252
/* 16x16 giving 32 bit multiplication
253
 *
254
 * We break it down into 8x8 giving 16 bit
255
 *
256
 *                                   [mHigh mLow]
257
 *                                 * [nHigh nLow]
258
 *                                   ------------
259
 *                   [mHigh * nLow] [mLow * nLow]
260
 * + [mHigh * nHigh] [mLow * nHigh]
261
 *   --------------------------------------------
262
 */
263
 
264
#ifndef USE_MUL16
265
/* Multiply 8x8->16 bit result. Hopefully, we have hardware
266
 * which does this. The Z80 does not. But most of its successors
267
 * do, and most gcc platforms do.
268
 */
269
static uint16 mul8(unsigned char m, unsigned char n) { return m * n; }
270
#endif
271
 
272
/* Multiply 16x16->32
273
 *
274
 * r may be one or both of the operands
275
 */
276
static void mul16(unsigned char* m, unsigned char* n, unsigned char* r) {
277
#ifdef USE_MUL16
278
	/* If we have 16x16->32 multiply, use it.
279
	 */
280
	uint32 a, b, c;
281
 
282
	a = m[0] + (m[1] << 8);
283
	b = n[0] + (n[1] << 8);
284
	c = a * b;
285
	r[0] = c & 0xff;
286
	r[1] = (c >> 8) & 0xff;
287
	r[2] = (c >> 16) & 0xff;
288
	r[3] = (c >> 24) & 0xff;
289
#else
290
	/* Build 16x16->32 from 8x8->16 bit multiply
291
	 */
292
	unsigned char mLow = m[0];
293
	unsigned char mHigh = m[1];
294
 
295
	unsigned char nLow = n[0];
296
	unsigned char nHigh = n[1];
297
 
298
	uint16 mLow_nLow = mul8(mLow, nLow);
299
	uint16 mHigh_nLow = mul8(mHigh, nLow);
300
	uint16 mLow_nHigh = mul8(mLow, nHigh);
301
	uint16 mHigh_nHigh = mul8(mHigh, nHigh);
302
 
303
	uint16 a;
304
	int carry;
305
	unsigned char r2[4], r3[4], r4[4];
306
	int i;
307
 
308
	for(i = 0; i < 4; ++i) r2[i] = r3[i] = r[4] = 0;
309
 
310
	/* r2:
311
	 *
312
	 * 3
313
	 * 2
314
	 * 1 | mLow_nLow
315
	 * 0 |
316
	 */
317
	r2[0] = mLow_nLow & 0xff;
318
	r2[1] = (mLow_nLow >> 8) & 0xff;
319
 
320
	/* r3:
321
	 *
322
	 * 3
323
	 * 2 | mHigh_nLow + mLow_nHigh
324
	 * 1 |
325
	 * 0
326
	 */
327
	carry = add16((unsigned char*)&mHigh_nLow, (unsigned char*)&mLow_nHigh, r3 + 1);
328
 
329
	/* r4:
330
	 *
331
	 * 3 | mHigh_nHigh (+ carry)
332
	 * 2 |
333
	 * 1
334
	 * 0
335
	 */
336
	a = mHigh_nHigh + carry;
337
	r4[2] = a & 0xff;
338
	r4[3] = (a >> 8) & 0xff;
339
 
340
	/* r = r2 + r3
341
	 */
342
	add32(r2, r3, r);
343
 
344
	/* r = r + r4 */
345
	add32(r, r4, r);
346
#endif
347
}
348
 
349
/* 16 bit multiply, lower. Uses mul16(). Returns overflow.
350
 * (1 if high 16 is non-zero).
351
 */
352
int mull16(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
353
	unsigned char r[4];
354
	unsigned char a[2], b[2];
355
	int s, o;
356
 
357
	if(((pa[0] == 0x00) && (pa[1] == 0x80)) || ((pb[0] == 0x00) && (pb[1] == 0x80))) {
358
		pc[0] = 0x00;
359
		pc[1] = 0x80;
360
		return 1;
361
	}
362
 
363
	/* We know that neither operand is 0x8000, so change sign will
364
	 * work.
365
	 */
366
	s = 0;
367
	if(pa[1] & 0x80) {
368
		s ^= 1;
369
		cm16(pa, a);
370
	} else {
371
		a[0] = pa[0];
372
		a[1] = pa[1];
373
	}
374
	if(pb[1] & 0x80) {
375
		s ^= 1;
376
		cm16(pb, b);
377
	} else {
378
		b[0] = pb[0];
379
		b[1] = pb[1];
380
	}
381
 
382
	mul16(a, b, r);
383
 
384
	o = (r[2] | r[3]) != 0;
385
 
386
	if(s) o |= cm32(r, r);
387
 
388
	pc[0] = r[0];
389
	pc[1] = r[1];
390
 
391
	return o;
392
}
393
 
394
/* 16 bit multiply, upper. Uses mul16(). returns overflow.
395
 */
396
int mulu16(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
397
	unsigned char r[4];
398
	unsigned char a[2], b[2];
399
	int s, o;
400
 
401
	if(((pa[0] == 0x00) && (pa[1] == 0x80)) || ((pb[0] == 0x00) && (pb[1] == 0x80))) {
402
		pc[0] = 0x00;
403
		pc[1] = 0x80;
404
		return 1;
405
	}
406
 
407
	s = 0;
408
	if(pa[1] & 0x80) {
409
		s ^= 1;
410
		cm16(pa, a);
411
	} else {
412
		a[0] = pa[0];
413
		a[1] = pa[1];
414
	}
415
	if(pb[1] & 0x80) {
416
		s ^= 1;
417
		cm16(pb, b);
418
	} else {
419
		b[0] = pb[0];
420
		b[1] = pb[1];
421
	}
422
 
423
	mul16(a, b, r);
424
 
425
	o = 0;
426
	if(s) o = cm32(r, r);
427
 
428
	pc[0] = r[2];
429
	pc[1] = r[3];
430
 
431
	return o;
432
}
433
 
434
/* 16 bit division.
435
 *
436
 * Eventually, I will put my own code in here... but, the objective
437
 * is to have the emulator running.
438
 */
439
int div16(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
440
	int16 a, b, c;
441
	int r = 0;
442
 
443
	a = pa[0] | (pa[1] << 8);
444
	b = pb[0] | (pb[1] << 8);
445
	if(b == 0) {
446
		c = b;
447
		r = 1;
448
	} else
449
		c = a / b;
450
	pc[0] = c & 0xff;
451
	pc[1] = (c >> 8) & 0xff;
452
	return r;
453
}
454
 
455
/* 32 bit division.
456
 *
457
 * Eventually, I will put my own code in here... but, the objective
458
 * is to have the emulator running.
459
 */
460
int div32(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
461
	int32 a, b, c;
462
	int r = 0;
463
 
464
	a = pa[0] | (pa[1] << 8) | (pa[2] << 16) | (pa[3] << 24);
465
	b = pb[0] | (pb[1] << 8) | (pb[2] << 16) | (pb[3] << 24);
466
	if(b == 0) {
467
		c = b;
468
		r = 1;
469
	} else
470
		c = a / b;
471
	pc[0] = c & 0xff;
472
	pc[1] = (c >> 8) & 0xff;
473
	pc[2] = (c >> 16) & 0xff;
474
	pc[3] = (c >> 24) & 0xff;
475
	return r;
476
}
477
 
478
/* 32x32->64 multiply
479
 */
480
static void mul32(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
481
	unsigned char *pah, *pal;
482
	unsigned char *pbh, *pbl;
483
 
484
	unsigned char r0[8];
485
	unsigned char r1[8];
486
	unsigned char r2[8];
487
	unsigned char r3[8];
488
 
489
	int i;
490
 
491
	for(i = 0; i < 8; ++i) pc[i] = r0[i] = r1[i] = r2[i] = r3[i] = 0;
492
 
493
	pal = pa;
494
	pah = pa + 2;
495
	pbl = pb;
496
	pbh = pb + 2;
497
 
498
	mul16(pbl, pal, r0);
499
	mul16(pbl, pah, r1 + 2);
500
	mul16(pbh, pal, r2 + 2);
501
	mul16(pbh, pah, r3 + 4);
502
	add64(r0, r1, pc);
503
	add64(pc, r2, r0);
504
	add64(r0, r3, pc);
505
}
506
 
507
int mull32(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
508
	unsigned char r[8];
509
	unsigned char a[4], b[4];
510
	int s, o;
511
 
512
	if(((pa[0] == 0x00) && (pa[1] == 0x00) && (pa[2] == 0x00) && (pa[3] == 0x80)) || ((pb[0] == 0x00) && (pb[1] == 0x00) && (pa[2] == 0x00) && (pa[3] == 0x80))) {
513
		pc[0] = 0x00;
514
		pc[1] = 0x00;
515
		pc[2] = 0x00;
516
		pc[3] = 0x80;
517
		return 1;
518
	}
519
 
520
	s = 0;
521
	if(pa[3] & 0x80) {
522
		s ^= 1;
523
		cm32(pa, a);
524
	} else {
525
		a[0] = pa[0];
526
		a[1] = pa[1];
527
		a[2] = pa[2];
528
		a[3] = pa[3];
529
	}
530
	if(pb[3] & 0x80) {
531
		s ^= 1;
532
		cm32(pb, b);
533
	} else {
534
		b[0] = pb[0];
535
		b[1] = pb[1];
536
		b[2] = pb[2];
537
		b[3] = pb[3];
538
	}
539
 
540
	mul32(a, b, r);
541
 
542
	o = (r[4] | r[5] | r[6] | r[7]) != 0;
543
 
544
	if(s) o |= cm64(r, r);
545
 
546
	pc[0] = r[0];
547
	pc[1] = r[1];
548
	pc[2] = r[2];
549
	pc[3] = r[3];
550
 
551
	return o;
552
}
553
 
554
int mulu32(unsigned char* pa, unsigned char* pb, unsigned char* pc) {
555
	unsigned char r[8];
556
	unsigned char a[4], b[4];
557
	int s, o;
558
 
559
	if(((pa[0] == 0x00) && (pa[1] == 0x00) && (pa[2] == 0x00) && (pa[3] == 0x80)) || ((pb[0] == 0x00) && (pb[1] == 0x00) && (pa[2] == 0x00) && (pa[3] == 0x80))) {
560
		pc[0] = 0x00;
561
		pc[1] = 0x00;
562
		pc[2] = 0x00;
563
		pc[3] = 0x80;
564
		return 1;
565
	}
566
 
567
	s = 0;
568
	if(pa[3] & 0x80) {
569
		s ^= 1;
570
		cm32(pa, a);
571
	} else {
572
		a[0] = pa[0];
573
		a[1] = pa[1];
574
		a[2] = pa[2];
575
		a[3] = pa[3];
576
	}
577
	if(pb[3] & 0x80) {
578
		s ^= 1;
579
		cm32(pb, b);
580
	} else {
581
		b[0] = pb[0];
582
		b[1] = pb[1];
583
		b[2] = pb[2];
584
		b[3] = pb[3];
585
	}
586
 
587
	mul32(a, b, r);
588
 
589
	o = 0;
590
	if(s) o = cm64(r, r);
591
 
592
	pc[0] = r[4];
593
	pc[1] = r[5];
594
	pc[2] = r[6];
595
	pc[3] = r[7];
596
 
597
	return o;
598
}
599
 
600
/*
601
	  16B,16B (32-bit multiplicand)
602
	* 16B,16B (32-bit multiplier)
603
-----------------
604
	  16B,16B (32-bit partial product)
605
+     16B,16B     (32-bit partial product)
606
+     16B,16B     (32-bit partial product)
607
+ 16B,16B         (32-bit partial product)
608
=================
609
  16B,16B,16B,16B (64-bit product)
610
 
611
*/