@@ -20,26 +20,47 @@ typedef enum {
20
20
i_iconst_3 = 0x6 ,
21
21
i_iconst_4 = 0x7 ,
22
22
i_iconst_5 = 0x8 ,
23
+ i_lconst_0 = 0x9 ,
24
+ i_lconst_1 = 0xa ,
23
25
i_bipush = 0x10 ,
24
26
i_sipush = 0x11 ,
25
27
i_ldc = 0x12 ,
28
+ i_ldc2_w = 0x14 ,
26
29
i_iload = 0x15 ,
30
+ i_lload = 0x16 ,
27
31
i_iload_0 = 0x1a ,
28
32
i_iload_1 = 0x1b ,
29
33
i_iload_2 = 0x1c ,
30
34
i_iload_3 = 0x1d ,
35
+ i_lload_0 = 0x1e ,
36
+ i_lload_1 = 0x1f ,
37
+ i_lload_2 = 0x20 ,
38
+ i_lload_3 = 0x21 ,
31
39
i_istore = 0x36 ,
40
+ i_lstore = 0x37 ,
32
41
i_istore_0 = 0x3b ,
33
42
i_istore_1 = 0x3c ,
34
43
i_istore_2 = 0x3d ,
35
44
i_istore_3 = 0x3e ,
45
+ i_lstore_0 = 0x3f ,
46
+ i_lstore_1 = 0x40 ,
47
+ i_lstore_2 = 0x41 ,
48
+ i_lstore_3 = 0x42 ,
36
49
i_iadd = 0x60 ,
50
+ i_ladd = 0x61 ,
37
51
i_isub = 0x64 ,
52
+ i_lsub = 0x65 ,
38
53
i_imul = 0x68 ,
54
+ i_lmul = 0x69 ,
39
55
i_idiv = 0x6c ,
56
+ i_ldiv = 0x6d ,
40
57
i_irem = 0x70 ,
58
+ i_lrem = 0x71 ,
41
59
i_ineg = 0x74 ,
42
60
i_iinc = 0x84 ,
61
+ i_i2l = 0x85 ,
62
+ i_l2i = 0x88 ,
63
+ i_lcmp = 0x94 ,
43
64
i_ifeq = 0x99 ,
44
65
i_ifne = 0x9a ,
45
66
i_iflt = 0x9b ,
@@ -54,6 +75,7 @@ typedef enum {
54
75
i_if_icmple = 0xa4 ,
55
76
i_goto = 0xa7 ,
56
77
i_ireturn = 0xac ,
78
+ i_lreturn = 0xad ,
57
79
i_return = 0xb1 ,
58
80
i_getstatic = 0xb2 ,
59
81
i_invokevirtual = 0xb6 ,
@@ -128,10 +150,10 @@ static inline void ineg(stack_frame_t *op_stack)
128
150
129
151
static inline void invokevirtual (stack_frame_t * op_stack )
130
152
{
131
- int32_t op = pop_int (op_stack );
153
+ int64_t op = pop_int (op_stack );
132
154
133
155
/* FIXME: the implement is not correct. */
134
- printf ("%d \n" , op );
156
+ printf ("%ld \n" , op );
135
157
}
136
158
137
159
static inline void iconst (stack_frame_t * op_stack , uint8_t current )
@@ -183,6 +205,18 @@ stack_entry_t *execute(method_t *method,
183
205
return ret ;
184
206
}
185
207
208
+ /* Return long from method */
209
+ case i_lreturn : {
210
+ stack_entry_t * ret = malloc (sizeof (stack_entry_t ));
211
+ ret -> entry .long_value = (int64_t ) pop_int (op_stack );
212
+ ret -> type = STACK_ENTRY_LONG ;
213
+
214
+ free (op_stack -> store );
215
+ free (op_stack );
216
+
217
+ return ret ;
218
+ }
219
+
186
220
/* Return void from method */
187
221
case i_return : {
188
222
stack_entry_t * ret = malloc (sizeof (stack_entry_t ));
@@ -211,6 +245,9 @@ stack_entry_t *execute(method_t *method,
211
245
case STACK_ENTRY_INT :
212
246
push_int (op_stack , exec_res -> entry .int_value );
213
247
break ;
248
+ case STACK_ENTRY_LONG :
249
+ push_long (op_stack , exec_res -> entry .long_value );
250
+ break ;
214
251
case STACK_ENTRY_NONE :
215
252
/* nothing */
216
253
break ;
@@ -223,6 +260,20 @@ stack_entry_t *execute(method_t *method,
223
260
break ;
224
261
}
225
262
263
+ /* Compare long */
264
+ case i_lcmp : {
265
+ int64_t op1 = pop_int (op_stack ), op2 = pop_int (op_stack );
266
+ if (op1 < op2 ) {
267
+ push_int (op_stack , 1 );
268
+ } else if (op1 == op2 ) {
269
+ push_int (op_stack , 0 );
270
+ } else {
271
+ push_int (op_stack , -1 );
272
+ }
273
+ pc += 1 ;
274
+ break ;
275
+ }
276
+
226
277
/* Branch if int comparison with zero succeeds: if equals */
227
278
case i_ifeq : {
228
279
uint8_t param1 = code_buf [pc + 1 ], param2 = code_buf [pc + 2 ];
@@ -393,6 +444,56 @@ stack_entry_t *execute(method_t *method,
393
444
break ;
394
445
}
395
446
447
+ /* Push long or double from run-time constant pool (wide index) */
448
+ case i_ldc2_w : {
449
+ uint8_t param1 = code_buf [pc + 1 ], param2 = code_buf [pc + 2 ];
450
+ uint16_t index = ((param1 << 8 ) | param2 );
451
+
452
+ uint64_t high = ((CONSTANT_LongOrDouble_info * ) get_constant (
453
+ & clazz -> constant_pool , index )
454
+ -> info )
455
+ -> high_bytes ;
456
+ uint64_t low = ((CONSTANT_LongOrDouble_info * ) get_constant (
457
+ & clazz -> constant_pool , index )
458
+ -> info )
459
+ -> low_bytes ;
460
+ int64_t value = high << 32 | low ;
461
+ push_long (op_stack , value );
462
+ pc += 3 ;
463
+ break ;
464
+ }
465
+
466
+ /* Load long from local variable */
467
+ case i_lload : {
468
+ int32_t param = code_buf [pc + 1 ];
469
+ int64_t loaded ;
470
+ loaded = locals [param ].entry .long_value ;
471
+ push_long (op_stack , loaded );
472
+
473
+ pc += 2 ;
474
+ break ;
475
+ }
476
+
477
+ /* FIXME: this implementation has some bugs.
478
+ * In standard JVM, one stack entry only store four
479
+ * bytes data, so in some method descriptor (e.g (JJ)V)
480
+ * the long value will store in locals[0] and locals[2]
481
+ * rather than locals[0] and locals[1].
482
+ */
483
+ /* Load long from local variable */
484
+ case i_lload_0 :
485
+ case i_lload_1 :
486
+ case i_lload_2 :
487
+ case i_lload_3 : {
488
+ int64_t param = current - i_lload_0 ;
489
+ int64_t loaded ;
490
+ loaded = locals [param ].entry .long_value ;
491
+ push_long (op_stack , loaded );
492
+
493
+ pc += 1 ;
494
+ break ;
495
+ }
496
+
396
497
/* Load int from local variable */
397
498
case i_iload_0 :
398
499
case i_iload_1 :
@@ -419,6 +520,31 @@ stack_entry_t *execute(method_t *method,
419
520
break ;
420
521
}
421
522
523
+ /* Store long into local variable */
524
+ case i_lstore : {
525
+ int32_t param = code_buf [pc + 1 ];
526
+ int64_t stored = pop_int (op_stack );
527
+ locals [param ].entry .long_value = stored ;
528
+ locals [param ].type = STACK_ENTRY_LONG ;
529
+
530
+ pc += 2 ;
531
+ break ;
532
+ }
533
+
534
+ /* Store long into local variable */
535
+ case i_lstore_0 :
536
+ case i_lstore_1 :
537
+ case i_lstore_2 :
538
+ case i_lstore_3 : {
539
+ int32_t param = current - i_lstore_0 ;
540
+ int64_t stored = pop_int (op_stack );
541
+ locals [param ].entry .long_value = stored ;
542
+ locals [param ].type = STACK_ENTRY_LONG ;
543
+
544
+ pc += 1 ;
545
+ break ;
546
+ }
547
+
422
548
/* Store int into local variable */
423
549
case i_istore : {
424
550
int32_t param = code_buf [pc + 1 ];
@@ -451,6 +577,24 @@ stack_entry_t *execute(method_t *method,
451
577
break ;
452
578
}
453
579
580
+ /* Convert int to long */
581
+ case i_i2l : {
582
+ int32_t stored = pop_int (op_stack );
583
+ push_long (op_stack , (int64_t ) stored );
584
+
585
+ pc += 1 ;
586
+ break ;
587
+ }
588
+
589
+ /* Convert int to char */
590
+ case i_l2i : {
591
+ int64_t stored = pop_int (op_stack );
592
+ push_int (op_stack , (int32_t ) stored );
593
+
594
+ pc += 1 ;
595
+ break ;
596
+ }
597
+
454
598
/* Push byte */
455
599
case i_bipush :
456
600
bipush (op_stack , pc , code_buf );
@@ -463,31 +607,81 @@ stack_entry_t *execute(method_t *method,
463
607
pc += 1 ;
464
608
break ;
465
609
610
+ /* Add long */
611
+ case i_ladd : {
612
+ int64_t op1 = pop_int (op_stack );
613
+ int64_t op2 = pop_int (op_stack );
614
+
615
+ push_long (op_stack , op1 + op2 );
616
+ pc += 1 ;
617
+ break ;
618
+ }
619
+
466
620
/* Subtract int */
467
621
case i_isub :
468
622
isub (op_stack );
469
623
pc += 1 ;
470
624
break ;
471
625
626
+ /* Subtract long */
627
+ case i_lsub : {
628
+ int64_t op1 = pop_int (op_stack );
629
+ int64_t op2 = pop_int (op_stack );
630
+
631
+ push_long (op_stack , op2 - op1 );
632
+ pc += 1 ;
633
+ break ;
634
+ }
635
+
472
636
/* Multiply int */
473
637
case i_imul :
474
638
imul (op_stack );
475
639
pc += 1 ;
476
640
break ;
477
641
642
+ /* Multiply long */
643
+ case i_lmul : {
644
+ int64_t op1 = pop_int (op_stack );
645
+ int64_t op2 = pop_int (op_stack );
646
+
647
+ push_long (op_stack , op1 * op2 );
648
+ pc += 1 ;
649
+ break ;
650
+ }
651
+
478
652
/* Divide int */
479
653
case i_idiv :
480
654
idiv (op_stack );
481
655
pc += 1 ;
482
656
break ;
483
657
658
+ /* Divide long */
659
+ case i_ldiv : {
660
+ int64_t op1 = pop_int (op_stack );
661
+ int64_t op2 = pop_int (op_stack );
662
+
663
+ push_long (op_stack , op2 / op1 );
664
+ pc += 1 ;
665
+ break ;
666
+ }
667
+
484
668
/* Remainder int */
485
669
case i_irem :
486
670
irem (op_stack );
487
671
pc += 1 ;
488
672
break ;
489
673
490
- /* Negate int */
674
+ /* Remainder long */
675
+ case i_lrem : {
676
+ int64_t op1 = pop_int (op_stack );
677
+ int64_t op2 = pop_int (op_stack );
678
+
679
+ push_long (op_stack , op2 % op1 );
680
+ pc += 1 ;
681
+ break ;
682
+ }
683
+
684
+ /* Negate int */
491
685
case i_ineg :
492
686
ineg (op_stack );
493
687
pc += 1 ;
@@ -517,6 +711,14 @@ stack_entry_t *execute(method_t *method,
517
711
pc += 1 ;
518
712
break ;
519
713
714
+ /* Push long constant */
715
+ case i_lconst_0 :
716
+ case i_lconst_1 : {
717
+ push_long (op_stack , current - i_lconst_0 );
718
+ pc += 1 ;
719
+ break ;
720
+ }
721
+
520
722
/* Push short */
521
723
case i_sipush :
522
724
sipush (op_stack , pc , code_buf );
0 commit comments