diff --git a/c/execute.c b/c/execute.c index 42a5bd6..41c2435 100644 --- a/c/execute.c +++ b/c/execute.c @@ -315,7 +315,9 @@ void op_f2d(struct vm * vm) void op_f2i(struct vm * vm) { - assert(!"op_f2i"); + float value = operand_stack_pop_f32(vm->current_frame); + int32_t result = (int32_t)value; + operand_stack_push_u32(vm->current_frame, result); } void op_f2l(struct vm * vm) @@ -325,122 +327,189 @@ void op_f2l(struct vm * vm) void op_fadd(struct vm * vm) { - assert(!"op_fadd"); + float value2 = operand_stack_pop_f32(vm->current_frame); + float value1 = operand_stack_pop_f32(vm->current_frame); + float result = value1 + value2; + operand_stack_push_f32(vm->current_frame, result); } void op_faload(struct vm * vm) { - assert(!"op_faload"); + int32_t index = operand_stack_pop_u32(vm->current_frame); + int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + assert(arrayref[0] > 0 && index < arrayref[0]); + int32_t * intarray = (int32_t *)&arrayref[1]; + int32_t value = intarray[index]; + operand_stack_push_u32(vm->current_frame, value); } void op_fastore(struct vm * vm) { - assert(!"op_fastore"); + int32_t value = operand_stack_pop_u32(vm->current_frame); + int32_t index = operand_stack_pop_u32(vm->current_frame); + int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + assert(arrayref[0] > 0 && index < arrayref[0]); + int32_t * intarray = (int32_t *)&arrayref[1]; + intarray[index] = value; } void op_fcmpg(struct vm * vm) { - assert(!"op_fcmpg"); + float value2 = operand_stack_pop_f32(vm->current_frame); + float value1 = operand_stack_pop_f32(vm->current_frame); + bool greater = value1 > value2; + bool equal = value1 == value2; + int32_t value; + if (__builtin_isnan(value1) || __builtin_isnan(value2)) { + value = 1; + } else if (equal) { + value = 0; + } else if (greater) { + value = 1; + } else { // less than + value = -1; + } + operand_stack_push_u32(vm->current_frame, value); } void op_fcmpl(struct vm * vm) { - assert(!"op_fcmpl"); + float value2 = operand_stack_pop_f32(vm->current_frame); + float value1 = operand_stack_pop_f32(vm->current_frame); + bool greater = value1 > value2; + bool equal = value1 == value2; + int32_t value; + if (__builtin_isnan(value1) || __builtin_isnan(value2)) { + value = -1; + } else if (equal) { + value = 0; + } else if (greater) { + value = 1; + } else { // less than + value = -1; + } + operand_stack_push_u32(vm->current_frame, value); } void op_fconst_0(struct vm * vm) { - assert(!"op_fconst_0"); + operand_stack_push_f32(vm->current_frame, 0.0f); } void op_fconst_1(struct vm * vm) { - assert(!"op_fconst_1"); + operand_stack_push_f32(vm->current_frame, 1.0f); } void op_fconst_2(struct vm * vm) { - assert(!"op_fconst_2"); + operand_stack_push_f32(vm->current_frame, 2.0f); } void op_fdiv(struct vm * vm) { - assert(!"op_fdiv"); + float value2 = operand_stack_pop_f32(vm->current_frame); + float value1 = operand_stack_pop_f32(vm->current_frame); + float result = value1 / value2; + operand_stack_push_f32(vm->current_frame, result); } void op_fload(struct vm * vm, uint32_t index) { - assert(!"op_fload"); + uint32_t value = vm->current_frame->local_variable[index]; + operand_stack_push_u32(vm->current_frame, value); } void op_fload_0(struct vm * vm) { - assert(!"op_fload_0"); + uint32_t value = vm->current_frame->local_variable[0]; + operand_stack_push_u32(vm->current_frame, value); } void op_fload_1(struct vm * vm) { - assert(!"op_fload_1"); + uint32_t value = vm->current_frame->local_variable[1]; + operand_stack_push_u32(vm->current_frame, value); } void op_fload_2(struct vm * vm) { - assert(!"op_fload_2"); + uint32_t value = vm->current_frame->local_variable[2]; + operand_stack_push_u32(vm->current_frame, value); } void op_fload_3(struct vm * vm) { - assert(!"op_fload_3"); + uint32_t value = vm->current_frame->local_variable[3]; + operand_stack_push_u32(vm->current_frame, value); } void op_fmul(struct vm * vm) { - assert(!"op_fmul"); + float value2 = operand_stack_pop_f32(vm->current_frame); + float value1 = operand_stack_pop_f32(vm->current_frame); + float result = value1 * value2; + operand_stack_push_f32(vm->current_frame, result); } void op_fneg(struct vm * vm) { - assert(!"op_fneg"); + float value = operand_stack_pop_f32(vm->current_frame); + float result = -value; + operand_stack_push_f32(vm->current_frame, result); } void op_frem(struct vm * vm) { - assert(!"op_frem"); + float value2 = operand_stack_pop_f32(vm->current_frame); + float value1 = operand_stack_pop_f32(vm->current_frame); + float q = value1 / value2; + float result = value1 - (value2 * (float)((int32_t)q)); + operand_stack_push_f32(vm->current_frame, result); } void op_freturn(struct vm * vm) { - assert(!"op_freturn"); + assert(vm->current_frame->return_type == 'F'); + vm_method_return(vm); } void op_fstore(struct vm * vm, uint32_t index) { - assert(!"op_fstore"); + uint32_t value = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[index] = value; } void op_fstore_0(struct vm * vm) { - assert(!"op_fstore_0"); + uint32_t value = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[0] = value; } void op_fstore_1(struct vm * vm) { - assert(!"op_fstore_1"); + uint32_t value = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[1] = value; } void op_fstore_2(struct vm * vm) { - assert(!"op_fstore_2"); + uint32_t value = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[2] = value; } void op_fstore_3(struct vm * vm) { - assert(!"op_fstore_3"); + uint32_t value = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[3] = value; } void op_fsub(struct vm * vm) { - assert(!"op_fsub"); + float value2 = operand_stack_pop_f32(vm->current_frame); + float value1 = operand_stack_pop_f32(vm->current_frame); + float result = value1 - value2; + operand_stack_push_f32(vm->current_frame, result); } void op_getfield(struct vm * vm, uint32_t index) @@ -517,7 +586,9 @@ void op_i2d(struct vm * vm) void op_i2f(struct vm * vm) { - assert(!"op_i2f"); + int32_t value = operand_stack_pop_u32(vm->current_frame); + float result = (float)value; + operand_stack_push_f32(vm->current_frame, result); } void op_i2l(struct vm * vm) @@ -873,8 +944,8 @@ void op_ior(struct vm * vm) void op_irem(struct vm * vm) { - uint32_t value2 = operand_stack_pop_u32(vm->current_frame); - uint32_t value1 = operand_stack_pop_u32(vm->current_frame); + int32_t value2 = operand_stack_pop_u32(vm->current_frame); + int32_t value1 = operand_stack_pop_u32(vm->current_frame); int32_t result = value1 % value2; operand_stack_push_u32(vm->current_frame, result); } @@ -1039,7 +1110,7 @@ void op_ldc(struct vm * vm, uint32_t index) { struct constant * constant = &vm->current_thread.current_class->constant_pool[index - 1]; #ifdef DEBUG - assert(constant->tag == CONSTANT_Integer); + assert(constant->tag == CONSTANT_Integer || constant->tag == CONSTANT_Float); #endif int32_t value = constant->integer.bytes; operand_stack_push_u32(vm->current_frame, value); diff --git a/c/frame.c b/c/frame.c index ebbfe7d..9a5c154 100644 --- a/c/frame.c +++ b/c/frame.c @@ -141,6 +141,7 @@ void vm_method_return(struct vm * vm) vm->current_frame->pc = vm->current_frame->next_pc; switch (old_frame->return_type) { + case 'F': [[fallthrough]]; case 'I': uint32_t value = operand_stack_pop_u32(old_frame); operand_stack_push_u32(vm->current_frame, value); @@ -163,7 +164,7 @@ static void print_vm_stack(struct vm * vm) continue; } int32_t value = vm->current_frame->operand_stack[vm->current_frame->operand_stack_ix - i]; - if (value > 65536) + if (value > 32767 || value < -32768) printf("0x%08x ", value); else printf("%10d ", value); @@ -174,12 +175,12 @@ static void print_vm_stack(struct vm * vm) void vm_execute(struct vm * vm) { while (true) { + assert(vm->current_frame->pc < vm->current_frame->code->code_length); print_vm_stack(vm); decode_print_instruction(vm->current_frame->code->code, vm->current_frame->pc); uint32_t old_pc = vm->current_frame->pc; struct method_info * old_method = vm->current_thread.current_method; decode_execute_instruction(vm, vm->current_frame->code->code, vm->current_frame->pc); - //if (vm->current_frame->pc >= vm->current_frame->code->code_length) { if (vm->frame_stack.ix == 1) { printf("terminate\n"); break; diff --git a/c/frame.h b/c/frame.h index d52cc04..384dbde 100644 --- a/c/frame.h +++ b/c/frame.h @@ -60,5 +60,21 @@ static inline void operand_stack_dup_u32(struct frame * frame) frame->operand_stack_ix++; } +static inline void operand_stack_push_f32(struct frame * frame, float f) +{ + uint32_t value = *((uint32_t *)&f); + frame->operand_stack[frame->operand_stack_ix] = value; + frame->operand_stack_ix++; +} + +static inline float operand_stack_pop_f32(struct frame * frame) +{ + frame->operand_stack_ix--; + uint32_t value = frame->operand_stack[frame->operand_stack_ix]; + frame->operand_stack[frame->operand_stack_ix] = -1; + float f = *((float *)&value); + return f; +} + void vm_static_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info); void vm_method_return(struct vm * vm); diff --git a/p/Float.java b/p/Float.java new file mode 100644 index 0000000..cbce1b2 --- /dev/null +++ b/p/Float.java @@ -0,0 +1,32 @@ +package p; + +class Float { + public static void main() { + test2(); + } + + static float test() { + float a = 1.0f; + float b = a / 3.0f; + float c = b * 2.0f; + float d = c + 5.0f; + float e = d - 0.5f; + float f = -e; + float g = f % 2.0f; + int h = (int)g; + return h; + } + + static float test2() { + float[] arr = {1.0f, 2.1f, 3.2f, 4.3f}; + float sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + } + boolean b = sum < 1.0f; + float i = 0.0f; + if (b) + i = 1.0f; + return i * 4.2f; + } +}