@@ -19,7 +19,7 @@ All of them are 64 bit wide.
19
19
| ` r8 ` | all | GPR | Call-preserved
20
20
| ` r9 ` | all | GPR | Call-preserved
21
21
| ` r10 ` | all | Frame pointer | System register
22
- | ` r11 ` | from v2 | Stack pointer | System register
22
+ | ` r11 ` | from v1 | Stack pointer | System register
23
23
| ` pc ` | all | Program counter | Hidden register
24
24
25
25
@@ -78,7 +78,7 @@ The following Rust equivalents assume that:
78
78
- ` imm ` is ` u32 `
79
79
- ` off ` is ` u16 `
80
80
81
- ### 32 bit Arithmetic and Logic
81
+ ### Memory Load or 32 bit Arithmetic and Logic
82
82
| opcode (hex / bin) | feature set | assembler mnemonic | Rust equivalent
83
83
| ------------------ | ----------- | ---------------------- | ---------------
84
84
| ` 04 ` / ` 00000100 ` | until v2 | ` add32 dst, imm ` | ` dst = (dst as u32).wrapping_add(imm) as i32 as i64 as u64 `
@@ -90,9 +90,13 @@ The following Rust equivalents assume that:
90
90
| ` 1C ` / ` 00011100 ` | until v2 | ` sub32 dst, src ` | ` dst = (dst as u32).wrapping_sub(src as u32) as i32 as i64 as u64 `
91
91
| ` 1C ` / ` 00011100 ` | from v2 | ` sub32 dst, src ` | ` dst = (dst as u32).wrapping_sub(src as u32) as u64 `
92
92
| ` 24 ` / ` 00100100 ` | until v2 | ` mul32 dst, imm ` | ` dst = (dst as i32).wrapping_mul(imm as i32) as i64 as u64 `
93
+ | ` 24 ` / ` 00100100 ` | from v2 | -- reserved --
93
94
| ` 2C ` / ` 00101100 ` | until v2 | ` mul32 dst, src ` | ` dst = (dst as i32).wrapping_mul(src as i32) as i64 as u64 `
95
+ | ` 2C ` / ` 00101100 ` | from v2 | ` ldxb dst, [src + off] `
94
96
| ` 34 ` / ` 00110100 ` | until v2 | ` div32 dst, imm ` | ` dst = ((dst as u32) / imm) as u64 `
97
+ | ` 34 ` / ` 00110100 ` | from v2 | -- reserved --
95
98
| ` 3C ` / ` 00111100 ` | until v2 | ` div32 dst, src ` | ` dst = ((dst as u32) / (src as u32)) as u64 `
99
+ | ` 3C ` / ` 00111100 ` | from v2 | ` ldxh dst, [src + off] `
96
100
| ` 44 ` / ` 01000100 ` | all | ` or32 dst, imm ` | ` dst = (dst as u32).or(imm) as u64 `
97
101
| ` 4C ` / ` 01001100 ` | all | ` or32 dst, src ` | ` dst = (dst as u32).or(src as u32) as u64 `
98
102
| ` 54 ` / ` 01010100 ` | all | ` and32 dst, imm ` | ` dst = (dst as u32).and(imm) as u64 `
@@ -102,9 +106,13 @@ The following Rust equivalents assume that:
102
106
| ` 74 ` / ` 01110100 ` | all | ` rsh32 dst, imm ` | ` dst = (dst as u32).wrapping_shr(imm) as u64 `
103
107
| ` 7C ` / ` 01111100 ` | all | ` rsh32 dst, src ` | ` dst = (dst as u32).wrapping_shr(src as u32) as u64 `
104
108
| ` 84 ` / ` 10000100 ` | until v2 | ` neg32 dst ` | ` dst = (dst as i32).wrapping_neg() as u32 as u64 `
105
- | ` 8C ` / ` 10001100 ` | | -- reserved --
109
+ | ` 84 ` / ` 10000100 ` | from v2 | -- reserved --
110
+ | ` 8C ` / ` 10001100 ` | until v2 | -- reserved --
111
+ | ` 8C ` / ` 01100001 ` | from v2 | ` ldxw dst, [src + off] `
106
112
| ` 94 ` / ` 10010100 ` | until v2 | ` mod32 dst, imm ` | ` dst = ((dst as u32) % imm) as u64 `
113
+ | ` 94 ` / ` 10010100 ` | from v2 | -- reserved --
107
114
| ` 9C ` / ` 10011100 ` | until v2 | ` mod32 dst, src ` | ` dst = ((dst as u32) % (src as u32)) as u64 `
115
+ | ` 9C ` / ` 01111001 ` | from v2 | ` ldxdw dst, [src + off] `
108
116
| ` A4 ` / ` 10100100 ` | all | ` xor32 dst, imm ` | ` dst = (dst as u32).xor(imm) as u64 `
109
117
| ` AC ` / ` 10101100 ` | all | ` xor32 dst, src ` | ` dst = (dst as u32).xor(src as u32) as u64 `
110
118
| ` B4 ` / ` 10110100 ` | all | ` mov32 dst, imm ` | ` dst = imm as i32 as i64 as u64 `
@@ -113,10 +121,11 @@ The following Rust equivalents assume that:
113
121
| ` C4 ` / ` 11000100 ` | all | ` ash32 dst, imm ` | ` dst = (dst as i32).wrapping_shr(imm) as u32 as u64 `
114
122
| ` CC ` / ` 11001100 ` | all | ` ash32 dst, src ` | ` dst = (dst as i32).wrapping_shr(src as u32) as u32 as u64 `
115
123
| ` D4 ` / ` 11010100 ` | until v2 | ` le dst, imm ` | ` dst = dst as u32 as u64 `
124
+ | ` D4 ` / ` 11010100 ` | from v2 | -- reserved --
116
125
| ` DC ` / ` 11011100 ` | all | ` be dst, imm ` | ` dst = match imm { 16 => (dst as u16).swap_bytes() as u64, 32 => (dst as u32).swap_bytes() as u64, 64 => dst.swap_bytes() } `
117
- | ` E4 ` to ` FC ` | | -- reserved --
126
+ | ` E4 ` to ` FC ` | all | -- reserved --
118
127
119
- ### 64 bit Arithmetic and Logic
128
+ ### Memory Store or 64 bit Arithmetic and Logic
120
129
| opcode (hex / bin) | feature set | assembler mnemonic | Rust equivalent
121
130
| ------------------ | ----------- | ------------------ | ---------------
122
131
| ` 07 ` / ` 00000111 ` | all | ` add64 dst, imm ` | ` dst = dst.wrapping_add(imm as i32 as i64 as u64) `
@@ -125,9 +134,13 @@ The following Rust equivalents assume that:
125
134
| ` 17 ` / ` 00010111 ` | from v2 | ` sub64 dst, imm ` | ` dst = (imm as i32 as i64 as u64).wrapping_sub(dst) `
126
135
| ` 1F ` / ` 00011111 ` | all | ` sub64 dst, src ` | ` dst = dst.wrapping_sub(src) `
127
136
| ` 27 ` / ` 00100111 ` | until v2 | ` mul64 dst, imm ` | ` dst = dst.wrapping_mul(imm as u64) `
137
+ | ` 27 ` / ` 01110010 ` | from v2 | ` stb [dst + off], imm `
128
138
| ` 2F ` / ` 00101111 ` | until v2 | ` mul64 dst, src ` | ` dst = dst.wrapping_mul(src) `
139
+ | ` 2F ` / ` 01110011 ` | from v2 | ` stxb [dst + off], src `
129
140
| ` 37 ` / ` 00110111 ` | until v2 | ` div64 dst, imm ` | ` dst = dst / (imm as u64) `
141
+ | ` 37 ` / ` 01101010 ` | from v2 | ` sth [dst + off], imm `
130
142
| ` 3F ` / ` 00111111 ` | until v2 | ` div64 dst, src ` | ` dst = dst / src `
143
+ | ` 3F ` / ` 01101011 ` | from v2 | ` stxh [dst + off], src `
131
144
| ` 47 ` / ` 01000111 ` | all | ` or64 dst, imm ` | ` dst = dst.or(imm) `
132
145
| ` 4F ` / ` 01001111 ` | all | ` or64 dst, src ` | ` dst = dst.or(src) `
133
146
| ` 57 ` / ` 01010111 ` | all | ` and64 dst, imm ` | ` dst = dst.and(imm) `
@@ -137,18 +150,23 @@ The following Rust equivalents assume that:
137
150
| ` 77 ` / ` 01110111 ` | all | ` rsh64 dst, imm ` | ` dst = dst.wrapping_shr(imm) `
138
151
| ` 7F ` / ` 01111111 ` | all | ` rsh64 dst, src ` | ` dst = dst.wrapping_shr(src as u32) `
139
152
| ` 87 ` / ` 10000111 ` | until v2 | ` neg64 dst ` | ` dst = (dst as i64).wrapping_neg() as u64 `
140
- | ` 8F ` / ` 10001111 ` | | -- reserved --
153
+ | ` 87 ` / ` 01100010 ` | from v2 | ` stw [dst + off], imm `
154
+ | ` 8F ` / ` 10001111 ` | until | -- reserved --
155
+ | ` 8F ` / ` 01100011 ` | from v2 | ` stxw [dst + off], src `
141
156
| ` 97 ` / ` 10010111 ` | until v2 | ` mod64 dst, imm ` | ` dst = dst % (imm as u64) `
157
+ | ` 97 ` / ` 01111010 ` | from v2 | ` stdw [dst + off], imm `
142
158
| ` 9F ` / ` 10011111 ` | until v2 | ` mod64 dst, src ` | ` dst = dst % src `
159
+ | ` 9F ` / ` 01111011 ` | from v2 | ` stxdw [dst + off], src `
143
160
| ` A7 ` / ` 10100111 ` | all | ` xor64 dst, imm ` | ` dst = dst.xor(imm) `
144
161
| ` AF ` / ` 10101111 ` | all | ` xor64 dst, src ` | ` dst = dst.xor(src) `
145
162
| ` B7 ` / ` 10110111 ` | all | ` mov64 dst, imm ` | ` dst = imm as u64 `
146
163
| ` BF ` / ` 10111111 ` | all | ` mov64 dst, src ` | ` dst = src `
147
164
| ` C7 ` / ` 11000111 ` | all | ` ash64 dst, imm ` | ` dst = (dst as i64).wrapping_shr(imm) `
148
165
| ` CF ` / ` 11001111 ` | all | ` ash64 dst, src ` | ` dst = (dst as i64).wrapping_shr(src as u32) `
149
- | ` D7 ` to ` EF ` | | -- reserved --
166
+ | ` D7 ` to ` EF ` | all | -- reserved --
167
+ | ` F7 ` / ` 11110111 ` | until v2 | -- reserved --
150
168
| ` F7 ` / ` 11110111 ` | from v2 | ` hor64 dst, imm ` | ` dst = dst.or((imm as u64).wrapping_shl(32)) `
151
- | ` FF ` / ` 11111111 ` | | -- reserved --
169
+ | ` FF ` / ` 11111111 ` | all | -- reserved --
152
170
153
171
### Product / Quotient / Remainder
154
172
| bit index | when ` 0 ` | when ` 1 `
@@ -165,7 +183,7 @@ The following Rust equivalents assume that:
165
183
166
184
| opcode (hex / bin) | feature set | assembler mnemonic | Rust equivalent
167
185
| ------------------ | ----------- | ------------------ | ---------------
168
- | ` 06 ` to ` 2E ` | | -- reserved --
186
+ | ` 06 ` to ` 2E ` | all | -- reserved --
169
187
| ` 36 ` / ` 00110110 ` | from v2 | ` uhmul64 dst, imm ` | ` dst = (dst as u128).wrapping_mul(imm as u128).wrapping_shr(64) as u64 `
170
188
| ` 3E ` / ` 00111110 ` | from v2 | ` uhmul64 dst, src ` | ` dst = (dst as u128).wrapping_mul(src as u128).wrapping_shr(64) as u64 `
171
189
| ` 46 ` / ` 01000110 ` | from v2 | ` udiv32 dst, imm ` | ` dst = ((dst as u32) / imm) as u64 `
@@ -180,7 +198,7 @@ The following Rust equivalents assume that:
180
198
| ` 8E ` / ` 10001110 ` | from v2 | ` lmul32 dst, src ` | ` dst = (dst as i32).wrapping_mul(src as i32) as u32 as u64 `
181
199
| ` 96 ` / ` 10010110 ` | from v2 | ` lmul64 dst, imm ` | ` dst = dst.wrapping_mul(imm as u64) `
182
200
| ` 9E ` / ` 10011110 ` | from v2 | ` lmul64 dst, src ` | ` dst = dst.wrapping_mul(src) `
183
- | ` A6 ` to ` AE ` | | -- reserved --
201
+ | ` A6 ` to ` AE ` | all | -- reserved --
184
202
| ` B6 ` / ` 10110110 ` | from v2 | ` shmul64 dst, imm ` | ` dst = (dst as i128).wrapping_mul(imm as i32 as i128).wrapping_shr(64) as i64 as u64 `
185
203
| ` BE ` / ` 10111110 ` | from v2 | ` shmul64 dst, src ` | ` dst = (dst as i128).wrapping_mul(src as i64 as i128).wrapping_shr(64) as i64 as u64 `
186
204
| ` C6 ` / ` 11000110 ` | from v2 | ` sdiv32 dst, imm ` | ` dst = ((dst as i32) / (imm as i32)) as u32 as u64 `
@@ -192,7 +210,7 @@ The following Rust equivalents assume that:
192
210
| ` F6 ` / ` 11110110 ` | from v2 | ` srem64 dst, imm ` | ` dst = ((dst as i64) % (imm as i64)) as u64 `
193
211
| ` FE ` / ` 11111110 ` | from v2 | ` srem64 dst, src ` | ` dst = ((dst as i64) % (src as i64)) as u64 `
194
212
195
- ### Memory
213
+ ### Deprecated Memory Load and Store
196
214
197
215
#### Panics
198
216
- Out of bounds: When the memory location is not mapped.
@@ -201,36 +219,36 @@ The following Rust equivalents assume that:
201
219
| opcode (hex / bin) | feature set | assembler mnemonic | Rust equivalent
202
220
| ------------------ | ----------- | ------------------ | ---------------
203
221
| ` 00 ` / ` 00000000 ` | until v2 | ` lddw dst, imm ` | ` dst = dst.or((imm as u64).wrapping_shl(32)) `
204
- | ` 08 ` to ` 10 ` | | -- reserved --
222
+ | ` 08 ` to ` 10 ` | all | -- reserved --
205
223
| ` 18 ` / ` 00011000 ` | until v2 | ` lddw dst, imm ` | ` dst = imm as u64 `
206
- | ` 20 ` to ` F8 ` | | -- reserved --
224
+ | ` 20 ` to ` F8 ` | all | -- reserved --
207
225
208
226
| opcode (hex / bin) | feature set | assembler mnemonic
209
227
| ------------------ | ----------- | ------------------
210
- | ` 01 ` to ` 59 ` | | -- reserved --
211
- | ` 61 ` / ` 01100001 ` | all | ` ldxw dst, [src + off] `
212
- | ` 69 ` / ` 01101001 ` | all | ` ldxh dst, [src + off] `
213
- | ` 71 ` / ` 01110001 ` | all | ` ldxb dst, [src + off] `
214
- | ` 79 ` / ` 01111001 ` | all | ` ldxdw dst, [src + off] `
215
- | ` 81 ` to ` F9 ` | | -- reserved --
228
+ | ` 01 ` to ` 59 ` | all | -- reserved --
229
+ | ` 61 ` / ` 01100001 ` | until v2 | ` ldxw dst, [src + off] `
230
+ | ` 69 ` / ` 01101001 ` | until v2 | ` ldxh dst, [src + off] `
231
+ | ` 71 ` / ` 01110001 ` | until v2 | ` ldxb dst, [src + off] `
232
+ | ` 79 ` / ` 01111001 ` | until v2 | ` ldxdw dst, [src + off] `
233
+ | ` 81 ` to ` F9 ` | all | -- reserved --
216
234
217
235
| opcode (hex / bin) | feature set | assembler mnemonic
218
236
| ------------------ | ----------- | ------------------
219
- | ` 02 ` to ` 5A ` | | -- reserved --
220
- | ` 62 ` / ` 01100010 ` | all | ` stw [dst + off], imm `
221
- | ` 6A ` / ` 01101010 ` | all | ` sth [dst + off], imm `
222
- | ` 72 ` / ` 01110010 ` | all | ` stb [dst + off], imm `
223
- | ` 7A ` / ` 01111010 ` | all | ` stdw [dst + off], imm `
224
- | ` 82 ` to ` FA ` | | -- reserved --
237
+ | ` 02 ` to ` 5A ` | all | -- reserved --
238
+ | ` 62 ` / ` 01100010 ` | until v2 | ` stw [dst + off], imm `
239
+ | ` 6A ` / ` 01101010 ` | until v2 | ` sth [dst + off], imm `
240
+ | ` 72 ` / ` 01110010 ` | until v2 | ` stb [dst + off], imm `
241
+ | ` 7A ` / ` 01111010 ` | until v2 | ` stdw [dst + off], imm `
242
+ | ` 82 ` to ` FA ` | all | -- reserved --
225
243
226
244
| opcode (hex / bin) | feature set | assembler mnemonic
227
245
| ------------------ | ----------- | ------------------
228
- | ` 03 ` to ` 5B ` | | -- reserved --
229
- | ` 63 ` / ` 01100011 ` | all | ` stxw [dst + off], src `
230
- | ` 6B ` / ` 01101011 ` | all | ` stxh [dst + off], src `
231
- | ` 73 ` / ` 01110011 ` | all | ` stxb [dst + off], src `
232
- | ` 7B ` / ` 01111011 ` | all | ` stxdw [dst + off], src `
233
- | ` 83 ` to ` FB ` | | -- reserved --
246
+ | ` 03 ` to ` 5B ` | all | -- reserved --
247
+ | ` 63 ` / ` 01100011 ` | until v2 | ` stxw [dst + off], src `
248
+ | ` 6B ` / ` 01101011 ` | until v2 | ` stxh [dst + off], src `
249
+ | ` 73 ` / ` 01110011 ` | until v2 | ` stxb [dst + off], src `
250
+ | ` 7B ` / ` 01111011 ` | until v2 | ` stxdw [dst + off], src `
251
+ | ` 83 ` to ` FB ` | all | -- reserved --
234
252
235
253
### Control Flow
236
254
@@ -239,24 +257,24 @@ Except that the target location of `callx` is the src register, thus runtime dyn
239
257
240
258
Call instructions (` call ` and ` callx ` but not ` syscall ` ) do:
241
259
- Save the registers ` r6 ` , ` r7 ` , ` r8 ` , ` r9 ` , the frame pointer ` r10 ` and the ` pc ` (pointing at the next instruction)
242
- - If ≤ v1: Add one stack frame size to the frame pointer ` r10 `
243
- - If ≥ v2 : Move the stack pointer ` r11 ` into the frame pointer ` r10 `
260
+ - If < v1: Add one stack frame size to the frame pointer ` r10 `
261
+ - If ≥ v1 : Move the stack pointer ` r11 ` into the frame pointer ` r10 `
244
262
245
263
The ` exit ` (a.k.a. return) instruction does:
246
264
- Restore the registers ` r6 ` , ` r7 ` , ` r8 ` , ` r9 ` , the frame pointer ` r10 ` and the ` pc `
247
265
- Or gracefully terminate the program if there is no stack frame to restore
248
266
249
267
#### Panics
250
- - Out of bounds: When the target location is outside the bytecode if ≤ v1 .
251
- - Out of bounds: When the target location is outside the current function if ≥ v2 and a jump.
252
- - Out of bounds: When the target location is not a registered function if ≥ v2 and a call.
268
+ - Out of bounds: When the target location is outside the bytecode if < v3 .
269
+ - Out of bounds: When the target location is outside the current function if ≥ v3 and a jump.
270
+ - Out of bounds: When the target location is not a registered function if ≥ v3 and a call.
253
271
- Second slot of ` lddw ` : When the target location has opcode ` 0x00 ` .
254
272
- Stack overflow: When one too many nested call happens.
255
273
256
274
| opcode (hex / bin) | feature set | assembler mnemonic | condition Rust equivalent
257
275
| ------------------ | ----------- | -------------------- | -------------------------
258
276
| ` 05 ` / ` 00000101 ` | all | ` ja off ` | ` true `
259
- | ` 0D ` / ` 00001101 ` | | -- reserved --
277
+ | ` 0D ` / ` 00001101 ` | all | -- reserved --
260
278
| ` 15 ` / ` 00010101 ` | all | ` jeq dst, imm, off ` | ` dst == (imm as i32 as i64 as u64) `
261
279
| ` 1D ` / ` 00011101 ` | all | ` jeq dst, src, off ` | ` dst == src `
262
280
| ` 25 ` / ` 00100101 ` | all | ` jgt dst, imm, off ` | ` dst > (imm as i32 as i64 as u64) `
@@ -271,13 +289,14 @@ The `exit` (a.k.a. return) instruction does:
271
289
| ` 6D ` / ` 01101101 ` | all | ` jsgt dst, src, off ` | ` (dst as i64) > (src as i64) `
272
290
| ` 75 ` / ` 01110101 ` | all | ` jsge dst, imm, off ` | ` (dst as i64) >= (imm as i32 as i64) `
273
291
| ` 7D ` / ` 01111101 ` | all | ` jsge dst, src, off ` | ` (dst as i64) >= (src as i64) `
274
- | ` 85 ` / ` 10000101 ` | until v2 | ` call off `
275
- | ` 85 ` / ` 10000101 ` | from v2 | ` syscall src=0, off `
276
- | ` 85 ` / ` 10000101 ` | from v2 | ` call src=1, off `
292
+ | ` 85 ` / ` 10000101 ` | until v3 | ` call imm ` or ` syscall imm `
293
+ | ` 85 ` / ` 10000101 ` | from v3 | ` call off `
277
294
| ` 8D ` / ` 10001101 ` | until v2 | ` callx imm `
278
295
| ` 8D ` / ` 10001101 ` | from v2 | ` callx src `
279
- | ` 95 ` / ` 10010101 ` | all | ` exit `
280
- | ` 9D ` / ` 10011101 ` | | -- reserved --
296
+ | ` 95 ` / ` 10010101 ` | until v3 | ` exit ` or ` return `
297
+ | ` 95 ` / ` 10010101 ` | from v3 | ` syscall imm `
298
+ | ` 9D ` / ` 10011101 ` | until v3 | -- reserved --
299
+ | ` 9D ` / ` 10011101 ` | from v3 | ` exit ` or ` return `
281
300
| ` A5 ` / ` 10100101 ` | all | ` jlt dst, imm, off ` | ` dst < imm as i32 as i64 as u64 `
282
301
| ` AD ` / ` 10101101 ` | all | ` jlt dst, src, off ` | ` dst < src `
283
302
| ` B5 ` / ` 10110101 ` | all | ` jle dst, imm, off ` | ` dst <= imm as i32 as i64 as u64 `
@@ -286,7 +305,7 @@ The `exit` (a.k.a. return) instruction does:
286
305
| ` CD ` / ` 11001101 ` | all | ` jslt dst, src, off ` | ` (dst as i64) < (src as i64) `
287
306
| ` D5 ` / ` 11010101 ` | all | ` jsle dst, imm, off ` | ` (dst as i64) <= (imm as i32 as i64) `
288
307
| ` DD ` / ` 11011101 ` | all | ` jsle dst, src, off ` | ` (dst as i64) <= (src as i64) `
289
- | ` E5 ` to ` FD ` | | -- reserved --
308
+ | ` E5 ` to ` FD ` | all | -- reserved --
290
309
291
310
292
311
Verification
@@ -307,23 +326,34 @@ Verification
307
326
- For all instructions the opcode must be valid
308
327
- Memory write instructions can use ` r10 ` as destination register
309
328
329
+ ### until v1
330
+ - No instruction can use ` r11 ` as destination register
331
+
332
+ ### from v1
333
+ - ` add64 reg, imm ` can use ` r11 ` as destination register
334
+
310
335
### until v2
311
336
- Opcodes from the product / quotient / remainder instruction class are forbiden
337
+ - ` neg32 ` and ` neg64 ` are allowed
312
338
- ` le ` is allowed
339
+ - ` lddw ` (opcodes ` 0x18 ` and ` 0x00 ` ) is allowed
313
340
- ` hor64 ` is forbidden
314
341
- ` callx ` source register is encoded in the imm field
315
- - The targets of ` call ` instructions is checked at runtime not verification time
316
- - The offset of jump instructions must be limited to the range of the bytecode
317
342
318
343
### from v2
319
- - Every function must end in a ` ja ` or ` exit ` instruction
320
- - ` lddw ` (opcodes ` 0x18 ` and ` 0x00 ` ) are forbidden
321
- - ` neg32 ` and ` neg64 ` are forbidden
322
344
- Opcodes from the product / quotient / remainder instruction class are allowed
345
+ - ` neg32 ` and ` neg64 ` are forbidden
323
346
- ` le ` is forbidden
347
+ - ` lddw ` (opcodes ` 0x18 ` and ` 0x00 ` ) is forbidden
324
348
- ` hor64 ` is allowed
325
- - The offset of jump instructions must be limited to the range of the current function
326
349
- ` callx ` source register is encoded in the src field
327
- - The targets of internal calls (` call ` instructions with src ≠ 0) must have been registered at verification time
328
- - The targets of syscalls (` call ` instructions with src = 0) must have been registered at verification time
329
- - ` add64 reg, imm ` can use ` r11 ` as destination register
350
+
351
+ ### until v3
352
+ - The targets of ` call ` instructions (which includes ` syscall ` instructions) are checked at runtime not verification time
353
+ - The offset of jump instructions must be limited to the range of the bytecode
354
+
355
+ ### from v3
356
+ - Every function must end in a ` ja ` or ` exit ` instruction
357
+ - The targets of ` call ` instructions must have been registered at verification time
358
+ - The targets of ` syscall ` instructions must have been registered at verification time
359
+ - The offset of jump instructions must be limited to the range of the current function
0 commit comments