implement double

This commit is contained in:
Zack Buhman 2024-12-25 01:42:24 -06:00
parent eef2c848e8
commit d0edd6b12b
3 changed files with 196 additions and 29 deletions

View File

@ -149,132 +149,225 @@ void op_checkcast(struct vm * vm, uint32_t index)
void op_d2f(struct vm * vm)
{
assert(!"op_d2f");
double value = operand_stack_pop_f64(vm->current_frame);
float result = (float)value;
operand_stack_push_f32(vm->current_frame, result);
}
void op_d2i(struct vm * vm)
{
assert(!"op_d2i");
double value = operand_stack_pop_f64(vm->current_frame);
int32_t result = (int32_t)value;
operand_stack_push_u32(vm->current_frame, result);
}
void op_d2l(struct vm * vm)
{
assert(!"op_d2l");
double value = operand_stack_pop_f64(vm->current_frame);
int64_t result = (int64_t)value;
operand_stack_push_u64(vm->current_frame, result);
}
void op_dadd(struct vm * vm)
{
assert(!"op_dadd");
double value2 = operand_stack_pop_f64(vm->current_frame);
double value1 = operand_stack_pop_f64(vm->current_frame);
double result = value1 + value2;
operand_stack_push_f64(vm->current_frame, result);
}
void op_daload(struct vm * vm)
{
assert(!"op_daload");
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]);
int64_t * longarray = (int64_t *)&arrayref[1];
int64_t value = longarray[index];
operand_stack_push_u64(vm->current_frame, value);
}
void op_dastore(struct vm * vm)
{
assert(!"op_dastore");
int64_t value = operand_stack_pop_u64(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]);
int64_t * longarray = (int64_t *)&arrayref[1];
longarray[index] = value;
}
void op_dcmpg(struct vm * vm)
{
assert(!"op_dcmpg");
double value2 = operand_stack_pop_f64(vm->current_frame);
double value1 = operand_stack_pop_f64(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_dcmpl(struct vm * vm)
{
assert(!"op_dcmpl");
double value2 = operand_stack_pop_f64(vm->current_frame);
double value1 = operand_stack_pop_f64(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_dconst_0(struct vm * vm)
{
assert(!"op_dconst_0");
operand_stack_push_f64(vm->current_frame, 0.0f);
}
void op_dconst_1(struct vm * vm)
{
assert(!"op_dconst_1");
operand_stack_push_f64(vm->current_frame, 1.0f);
}
void op_ddiv(struct vm * vm)
{
assert(!"op_ddiv");
double value2 = operand_stack_pop_f64(vm->current_frame);
double value1 = operand_stack_pop_f64(vm->current_frame);
double result = value1 / value2;
operand_stack_push_f64(vm->current_frame, result);
}
void op_dload(struct vm * vm, uint32_t index)
{
assert(!"op_dload");
uint32_t low = vm->current_frame->local_variable[index];
uint32_t high = vm->current_frame->local_variable[index + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_dload_0(struct vm * vm)
{
assert(!"op_dload_0");
uint32_t low = vm->current_frame->local_variable[0];
uint32_t high = vm->current_frame->local_variable[0 + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_dload_1(struct vm * vm)
{
assert(!"op_dload_1");
uint32_t low = vm->current_frame->local_variable[1];
uint32_t high = vm->current_frame->local_variable[1 + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_dload_2(struct vm * vm)
{
assert(!"op_dload_2");
uint32_t low = vm->current_frame->local_variable[2];
uint32_t high = vm->current_frame->local_variable[2 + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_dload_3(struct vm * vm)
{
assert(!"op_dload_3");
uint32_t low = vm->current_frame->local_variable[3];
uint32_t high = vm->current_frame->local_variable[3 + 1];
operand_stack_push_u32(vm->current_frame, low);
operand_stack_push_u32(vm->current_frame, high);
}
void op_dmul(struct vm * vm)
{
assert(!"op_dmul");
double value2 = operand_stack_pop_f64(vm->current_frame);
double value1 = operand_stack_pop_f64(vm->current_frame);
double result = value1 * value2;
operand_stack_push_f64(vm->current_frame, result);
}
void op_dneg(struct vm * vm)
{
assert(!"op_dneg");
double value = operand_stack_pop_f64(vm->current_frame);
double result = -value;
operand_stack_push_f64(vm->current_frame, result);
}
void op_drem(struct vm * vm)
{
assert(!"op_drem");
double value2 = operand_stack_pop_f64(vm->current_frame);
double value1 = operand_stack_pop_f64(vm->current_frame);
double q = value1 / value2;
double result = value1 - (value2 * (double)((int64_t)q));
operand_stack_push_f64(vm->current_frame, result);
}
void op_dreturn(struct vm * vm)
{
assert(!"op_dreturn");
assert(vm->current_frame->return_type == 'D');
vm_method_return(vm);
}
void op_dstore(struct vm * vm, uint32_t index)
{
assert(!"op_dstore");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[index + 1] = high;
vm->current_frame->local_variable[index] = low;
}
void op_dstore_0(struct vm * vm)
{
assert(!"op_dstore_0");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[0 + 1] = high;
vm->current_frame->local_variable[0] = low;
}
void op_dstore_1(struct vm * vm)
{
assert(!"op_dstore_1");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[1 + 1] = high;
vm->current_frame->local_variable[1] = low;
}
void op_dstore_2(struct vm * vm)
{
assert(!"op_dstore_2");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[2 + 1] = high;
vm->current_frame->local_variable[2] = low;
}
void op_dstore_3(struct vm * vm)
{
assert(!"op_dstore_3");
uint32_t high = operand_stack_pop_u32(vm->current_frame);
uint32_t low = operand_stack_pop_u32(vm->current_frame);
vm->current_frame->local_variable[3 + 1] = high;
vm->current_frame->local_variable[3] = low;
}
void op_dsub(struct vm * vm)
{
assert(!"op_dsub");
double value2 = operand_stack_pop_f64(vm->current_frame);
double value1 = operand_stack_pop_f64(vm->current_frame);
double result = value1 - value2;
operand_stack_push_f64(vm->current_frame, result);
}
void op_dup(struct vm * vm)
@ -309,7 +402,9 @@ void op_dup_x2(struct vm * vm)
void op_f2d(struct vm * vm)
{
assert(!"op_f2d");
float value = operand_stack_pop_f32(vm->current_frame);
double result = (double)value;
operand_stack_push_f64(vm->current_frame, result);
}
void op_f2i(struct vm * vm)
@ -589,7 +684,9 @@ void op_i2c(struct vm * vm)
void op_i2d(struct vm * vm)
{
assert(!"op_i2d");
int32_t value = operand_stack_pop_u32(vm->current_frame);
double result = (double)value;
operand_stack_push_f64(vm->current_frame, result);
}
void op_i2f(struct vm * vm)
@ -1092,7 +1189,9 @@ void op_jsr_w(struct vm * vm, int32_t branch)
void op_l2d(struct vm * vm)
{
assert(!"op_l2d");
int64_t value = operand_stack_pop_u64(vm->current_frame);
double result = (double)value;
operand_stack_push_f64(vm->current_frame, result);
}
void op_l2f(struct vm * vm)

View File

@ -127,6 +127,26 @@ static inline uint64_t operand_stack_pop_u64(struct frame * frame)
return value;
}
static inline void operand_stack_push_f64(struct frame * frame, double f)
{
uint64_t value = *((uint64_t *)&f);
frame->operand_stack[frame->operand_stack_ix] = (uint32_t)(value >> 0);
frame->operand_stack_ix++;
frame->operand_stack[frame->operand_stack_ix] = (uint32_t)(value >> 32);
frame->operand_stack_ix++;
}
static inline double operand_stack_pop_f64(struct frame * frame)
{
frame->operand_stack_ix--;
uint64_t high = frame->operand_stack[frame->operand_stack_ix];
frame->operand_stack_ix--;
uint64_t low = frame->operand_stack[frame->operand_stack_ix];
uint64_t value = (high << 32) | (low << 0);
double f = *((double *)&value);
return f;
}
bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry);
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);

48
p/Double.java Normal file
View File

@ -0,0 +1,48 @@
package p;
class Double {
public static void main() {
test();
test2();
test3(3.0);
}
static double test() {
double a = 1.0;
double b = a / 3.0;
double c = b * 2.0;
double d = c + 5.0;
double e = d - 0.5;
double f = -e;
double g = f % 2.0;
int h = (int)g;
return h;
}
static double test2() {
double[] arr = {1.0, 2.1, 3.2, 4.3};
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
boolean b = sum < 1.0;
double i = 0.0;
if (b)
i = 1.0;
return i * 4.2;
}
static double test3(double n) {
float a = (float)n;
int b = (int)n;
long c = (long)n;
char d = (char)n;
double e = (double)a;
double f = (double)b;
double g = (double)c;
double h = (double)d;
return e * f * g * h;
}
}