@@ -197,12 +197,18 @@ sub emit_rex_64 {
197
197
}
198
198
}
199
199
200
- # Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
201
200
sub emit_modrm {
202
201
my ($reg , $rm_reg ) = @_ ;
203
202
if ( is_register($reg ) && is_register($rm_reg ) ) {
203
+ # Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
204
204
emit(0xC0 | $reg -> low_bits() << 3 | $rm_reg -> low_bits());
205
205
}
206
+ elsif ( is_register($rm_reg ) ) {
207
+ # Emit a ModR/M byte with an operation subcode in the reg field and
208
+ # a register in the rm_reg field.
209
+ my ($code , $rm_reg ) = @_ ;
210
+ emit(0xC0 | $code << 3 | $rm_reg -> low_bits());
211
+ }
206
212
else {
207
213
die " emit_modrm: don't know what to do with $reg , $rm_reg " ;
208
214
}
@@ -255,6 +261,24 @@ sub _bind {
255
261
$label -> bind ( scalar (@buffer ) );
256
262
}
257
263
264
+ sub _cpuid {
265
+ emit(0x0F);
266
+ emit(0xA2);
267
+ }
268
+
269
+ sub _cqo {
270
+ emit_rex_64();
271
+ emit(0x99);
272
+ }
273
+
274
+ sub _hlt {
275
+ emit(0xF4);
276
+ }
277
+
278
+ sub _int3 {
279
+ emit(0xCC);
280
+ }
281
+
258
282
sub _jmp {
259
283
my ( $label , $distance ) = @_ ;
260
284
@@ -279,6 +303,10 @@ sub _jmp {
279
303
}
280
304
}
281
305
306
+ sub _leave {
307
+ emit(0xC9);
308
+ }
309
+
282
310
sub _movl {
283
311
my ( $dst , $src ) = @_ ;
284
312
if ( is_register($dst ) && is_register($src ) ) {
@@ -351,6 +379,27 @@ sub _repmovsq() {
351
379
emit(0xA5);
352
380
}
353
381
382
+ sub _mul {
383
+ my ($src ) = @_ ;
384
+ emit_rex_64($src );
385
+ emit(0xF7);
386
+ emit_modrm( 0x4, $src );
387
+ }
388
+
389
+ sub _neg {
390
+ my ($dst ) = @_ ;
391
+ emit_rex_64($dst );
392
+ emit(0xF7);
393
+ emit_modrm( 0x3, $dst );
394
+ }
395
+
396
+ sub _negl {
397
+ my ($dst ) = @_ ;
398
+ emit_optional_rex_32($dst );
399
+ emit(0xF7);
400
+ emit_modrm( 0x3, $dst );
401
+ }
402
+
354
403
sub _nop {
355
404
emit(0x90);
356
405
}
0 commit comments