/
not_gerd_notes
166 lines (116 loc) · 5.45 KB
/
not_gerd_notes
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
not_gerd (no relation to gerd) dropped by #parrot and shared the following
thoughts about the then-current state of M0. I (cotto) have moved them into
this repository to make sure that the worthwhile bits get implemented and that
the pieces that don't get implemented at least won't get dropped accidentally.
As I delete items, I'll either add them to the todo list or delete them
outright. not_gerd did a good job of finding some holes, and everything he
nopasted is at least worth considering, though not everything will go into the
M0 spec and prototypes.
COMENTS ON THE M0 INSTRUCTION SET
Math/numeric ops
----------------
Currently, the math instructions do not respect the difference between signed
and unsigned integers. It is necessary to either add more ops, or to mandate a
two's complement representation (which is for example what LLVM IR does).
Even if two's complement is used, conversion from integer to numeric needs to
differentiate between signed and unsigned, so at least one additional op is
necessary.
Comparison ops are missing as well.
Register ops
------------
The get/set word/byte instructions are insufficient to deal with signed/unsigned
integers of common sizes.
There should be instructions for loading integers of common sizes (8/16/32/64)
into the least-significant part of an I register as well as conversion
operations for sign- and zero-extension (and the inverse conversion).
The conversion could be combined with the get/set instructions, resulting in
instruction like get_u8/set_u8, get_s8/set_s8, ...
------------------------------------------------------------
Second nopaste
------------------------------------------------------------
NOTE: We assume a uniform pointer representation corresponding to the C type
void*. Pointers with different representations are not supported.
add_p
-----
Treat *$2 as a pointer and *$3 as an integer, add *$3 to *$2 and store the
result in *$1.
sub_p
-----
Treat *$2 as a pointer and *$3 as an integer, substract *$3 from *$2 and store
the result in *$1.
get_p
-----
Treat *$1 and *$2 as pointers, load a pointer from address *$2 and store it in
*$1. $3 is ignored.
set_p
-----
Treat *$1 and *$2 as pointers, load *$2 and store it at address *$1. $3 is
ignored.
NOTE: For the next two ops, XX is one of 8, 16, 32, 64
get_XX
------
Treat *$2 as a pointer and $3 as an immediate constant indicating the conversion
to be performed, ie one of SIGNED, UNSIGNED, FLOAT.
Load a value of width XX from address *$2 and store the converted value in *$1,
which is treated as either integer or numeric depending on the conversion type.
If the conversion type is SIGNED, the value is sign-extended to the width of I
registers.
If the conversion type is UNSIGNED, the value is zero-extended to the width of I
registers.
If the conversion type is FLOAT, the value is converted to the precision of N
registers.
Valid values for XX in case of FLOAT conversions are 32 for single- and 64 for
double-precision and possibly 16 for half-precision (see
http://www.mathworks.com/matlabcentral/fileexchange/23173 for an
implementation).
If the value is not in range of the register types (eg if I registers have a
width of 32 and the instruction tries to load a 64-bit integer), the register is
set to the nearest representable value, or, in case of out of range
floating-point values, infinity, of correct sign.
If *$2 is not correctly aligned for access of the specified width, the behaviour
is undefined.
set_XX
------
Treats *$1 as a pointer and $3 as an immediate constant indicating the
conversion to be performed, ie one of SIGNED, UNSIGNED, FLOAT.
Loads *$2 and stores the converted value at address *$1.
Conversion behaviour corresponds to get_XX.
------------------------------------------
third nopaste
------------------------------------------
add_p
-----
Treat *$2 as a pointer and *$3 as an integer, add *$3 to *$2 and store the
result in *$1.
sub_p
-----
Treat *$2 as a pointer and *$3 as an integer, substract *$3 from *$2 and store
the result in *$1.
load
----
Treat *$2 as a pointer and $3 as immediate constant indicating the type of the
pointed-to value. Load a value of specified type from address *$2 and store a
corresponding value in *$1, which is treated as either integer or numeric
depending on the value of $3.
The possible values for $3 are the same as the ones for the FFI instructions.
If the type is signed, the value is sign-extended to the width of I registers.
If the type is unsigned, the value is zero-extended to the width of I registers.
If the type is a floating-point type, the value is converted to the precision of
N registers.
If the value is a pointer type, no conversions are necessary as a uniform
pointer representation is assumed.
If the value is not in range of the register types, the register is set to the
nearest representable value of correct sign, or, in case of out of range
floating-point values, infinity.
If *$2 is not correctly aligned for types of specified width, the behaviour is
undefined.
store
-----
Treat *$1 as a pointer and $3 as immediate constant indicating the type of the
pointed-to value. Load a value of specified type from address *$2 and store a
corresponding value in *$1, which is treated as either integer or numeric
depending on the value of $3.
The possible values for $3 are the same as the ones for the FFI instructions.
The conversions correspond to the ones performed by the load instruction.
If *$1 is not correctly aligned for types of specified width, the behaviour is
undefined.