File: Word.c

package info (click to toggle)
mlton 20041109-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 18,212 kB
  • ctags: 58,085
  • sloc: ansic: 10,386; makefile: 1,178; sh: 1,139; pascal: 256; asm: 97
file content (115 lines) | stat: -rw-r--r-- 3,306 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "platform.h"

/*
 * We have to be very careful implementing WordS_quot and WordS_rem using / and %
 * because C allows
 *  "The direction of truncation for / and the sign of the result for % are
 *   machine-dependent for negative operands, ..." (K&R p. 41) (See also p. 205.)
 * On the other hand, the SML Basis library spec is completely nailed down.
 * On x86, gcc implements / and % using idiv, which fortunately does have the
 * same semantics as the SML Basis library.  However, gcc's optimizer sometimes
 * takes advantage of the flexibility in the C spec when one of the arguments
 * is a constant, producing incorrect results.  So, we have two options:
 *
 * Put them in a separate file, all by themselves, without a static inline, and
 * use / and % where we know gcc's optimer can't hurt us.
 * OR
 * Use inline assembler.
 *
 * We've gone for the first option because of simplicity, and because
 * quot and rem are only used with the C codegen.  If you really want
 * speed, you could try inline assembler.
 *
 * To get this working on another architecture, you need to check how gcc
 * implements / and %.
 */

#ifndef DEBUG
#define DEBUG FALSE
#endif

#if ! (defined (__i386__) || defined (__ppc__) || defined (__sparc__))
#error check that C {/,%} correctly implement {quot,rem} from the basis library
#endif

#define coerce(f, t)				\
	t f##_to##t (f x) {			\
		return (t)x;			\
	}

#define bothCoerce(from, to)			\
	coerce (Word##S##from, Word##to)	\
	coerce (Word##U##from, Word##to)

#define binary(kind, name, op)						\
	Word##kind Word##kind##_##name (Word##kind w1, Word##kind w2) {	\
		return w1 op w2;					\
	}

#define bothBinary(size, name, op)		\
	binary (S##size, name, op)		\
	binary (U##size, name, op)

#define compare(kind, name, op)						\
	Bool Word##kind##_##name (Word##kind w1, Word##kind w2) {	\
		return w1 op w2;					\
	}

#define bothCompare(size, name, op)		\
	compare (S##size, name, op)		\
	compare (U##size, name, op)

#define unary(kind,name, op)				\
	Word##kind Word##kind##_##name (Word##kind w) {	\
		return op w;				\
	}

#define shift(kind, name, op)						\
	Word##kind Word##kind##_##name (Word##kind w1, Word w2) {	\
		return w1 op w2;					\
	}

#define all(size)						\
	binary (size, add, +)					\
	binary (size, andb, &)					\
	compare (size, equal, ==)				\
	bothCompare (size, ge, >=)				\
	bothCompare (size, gt, >)				\
	bothCompare (size, le, <=)				\
	shift (size, lshift, <<)				\
	bothCompare (size, lt, <)				\
	bothBinary (size, mul, *)				\
	unary (size, neg, -)					\
	unary (size, notb, ~)					\
	binary (size, orb, |)					\
	bothBinary (size, quot, /)				\
	bothBinary (size, rem, %)				\
	Word##size Word##size##_rol (Word##size w1, Word w2) {	\
		return (w1 >> (size - w2)) | (w1 << w2);	\
	}							\
	Word##size Word##size##_ror (Word##size w1, Word w2) {	\
		return (w1 >> w2) | (w1 << (size - w2));	\
	}							\
	shift (S##size, rshift, >>)				\
	shift (U##size, rshift, >>)				\
	binary (size, sub, -)					\
	binary (size, xorb, ^)					\
	bothCoerce (size, 64)					\
	bothCoerce (size, 32)					\
	bothCoerce (size, 16)					\
	bothCoerce (size, 8)

all (8)
all (16)
all (32)
all (64)

#undef coerce
#undef bothCoerce
#undef binary
#undef bothBinary
#undef compare
#undef bothCompare
#undef unary
#undef shift
#undef all