diff --git a/Makefile b/Makefile index 923ae72..e04200b 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ CC ?= gcc ARCH = -m32 CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protector -std=c2x -g CFLAGS += -DDEBUG -#CFLAGS += -DDEBUG_PRINT +CFLAGS += -DDEBUG_PRINT OPT ?= -O0 DEPFLAGS = -MMD -MP diff --git a/c/decode.c b/c/decode.c index 2686c5c..f90203b 100644 --- a/c/decode.c +++ b/c/decode.c @@ -82,11 +82,22 @@ static inline int32_t aligned_s4(const void * buf) #define TABLESWITCH_NEXT_PC \ (args + (3 * 4) + ((highbyte - lowbyte + 1) * 4)) -#define LOOKUPSWITCH_ARGS assert(false); +#define LOOKUPSWITCH_ARGS \ + uint32_t args = ((pc + 1) + 3) & (~3); \ + int32_t defaultbyte = aligned_s4(&code[args + 0]); \ + int32_t npairs = aligned_s4(&code[args + 4]); \ + const int32_t * table = (const int32_t *)&code[args + 8]; -#define LOOKUPSWITCH_PRINT_ARGS() +#define LOOKUPSWITCH_PRINT_ARGS() \ + do { \ + for (int i = 0; i < npairs; i++) { \ + debugf(" %d: %d\n", aligned_s4(&table[i * 2]), aligned_s4(&table[i * 2 + 1])); \ + } \ + debugf("default: %d\n", defaultbyte); \ + } while (0); -#define LOOKUPSWITCH_NEXT_PC 0 +#define LOOKUPSWITCH_NEXT_PC \ + (args + (2 * 4) + (npairs * 2 * 4)) #define WIDE_ARGS assert(false); diff --git a/c/decode.inc.c b/c/decode.inc.c index 2823d7d..1841c8a 100644 --- a/c/decode.inc.c +++ b/c/decode.inc.c @@ -2165,7 +2165,7 @@ void decode_execute_instruction(struct vm * vm, const uint8_t * code, uint32_t p { LOOKUPSWITCH_ARGS; vm->current_frame->next_pc = LOOKUPSWITCH_NEXT_PC; - op_lookupswitch(vm); + op_lookupswitch(vm, defaultbyte, npairs, table); break; } case 172: // ireturn diff --git a/c/execute.c b/c/execute.c index 4e51114..38c5c78 100644 --- a/c/execute.c +++ b/c/execute.c @@ -1467,9 +1467,18 @@ void op_lneg(struct vm * vm) operand_stack_push_u64(vm->current_frame, result); } -void op_lookupswitch(struct vm * vm) +void op_lookupswitch(struct vm * vm, int32_t defaultbyte, int32_t npairs, const int32_t * table) { - assert(!"op_lookupswitch"); + int32_t key = operand_stack_pop_u32(vm->current_frame); + for (int i = 0; i < npairs; i++) { + int32_t match = BE_BSWAP32(table[i * 2]); + if (key == match) { + int32_t offset = BE_BSWAP32(table[i * 2 + 1]); + vm->current_frame->pc = vm->current_frame->pc + offset; + return; + } + } + vm->current_frame->pc = vm->current_frame->pc + defaultbyte; } void op_lor(struct vm * vm) diff --git a/c/execute.h b/c/execute.h index 4bf72a3..79f7cf7 100644 --- a/c/execute.h +++ b/c/execute.h @@ -177,7 +177,7 @@ void op_lload_2(struct vm * vm); void op_lload_3(struct vm * vm); void op_lmul(struct vm * vm); void op_lneg(struct vm * vm); -void op_lookupswitch(struct vm * vm); +void op_lookupswitch(struct vm * vm, int32_t defaultbyte, int32_t npairs, const int32_t * table); void op_lor(struct vm * vm); void op_lrem(struct vm * vm); void op_lreturn(struct vm * vm); diff --git a/main.bin b/main.bin deleted file mode 100755 index d3e8978..0000000 Binary files a/main.bin and /dev/null differ diff --git a/opcodes.ods b/opcodes.ods index 7e19be4..f75c31b 100644 Binary files a/opcodes.ods and b/opcodes.ods differ diff --git a/p/LookupSwitch.java b/p/LookupSwitch.java new file mode 100644 index 0000000..0095bd3 --- /dev/null +++ b/p/LookupSwitch.java @@ -0,0 +1,18 @@ +package p; + +class LookupSwitch { + static int foo(int a) { + switch (a) { + case 1: return 5; + case 10: return 42; + case 100: return 432; + case 1000: return 999; + case 10000: return 9999; + default: return 123; + } + } + + public static void main() { + foo(10); + } +}