target/whirl.c
static void generate_jump_inst(WhirlCodeSegment *segment, RingState *state) {
    Inst *inst = segment->inst;

    // Put our jump destination in the PC register so that when we
    // reach the jump table, we know where to jump to
    if (inst->jmp.type == REG) {
        move_to_reg(segment, state, inst->jmp.reg);
        generate_math_command(segment, state, MATH_LOAD);
        move_back_from_reg(segment, state, inst->jmp.reg);
        move_to_reg(segment, state, PC_REG_NUM);
        generate_math_command(segment, state, MATH_STORE);
        move_back_from_reg(segment, state, PC_REG_NUM);
    }
    else {
        move_to_reg(segment, state, PC_REG_NUM);
        set_mem(segment, state, inst->jmp.imm);
        move_back_from_reg(segment, state, PC_REG_NUM);
    }

    // Set the current memory position to the location of the jump table,
    // which should be at the end of the program
    if (segment->next != NULL) {
        set_mem(segment, state, segment->next->total_code_len + 1);
    }
    else {
        set_mem(segment, state, 1);
    }

    // Unconditional jump, just load the address and store a 1 in the cell
    if (inst->op == JMP) {
        generate_op_command(segment, state, OP_LOAD);
        generate_math_command(segment, state, MATH_LOAD);
        generate_math_command(segment, state, MATH_EQUAL);
        generate_math_command(segment, state, MATH_STORE);
    }
    // Otherwise, we have to do an actual comparison and save the result in
    // the first memory cell
    else {
        generate_op_command(segment, state, OP_ONE);

        if (inst->src.type == REG) {
            for (unsigned i = 0; i < inst->src.reg + REG_START_POS; i++) {
                generate_op_command(segment, state, OP_DADD);
            }
            generate_math_command(segment, state, MATH_LOAD);
            for (int i = inst->src.reg + REG_START_POS; i < EXTRA_TMP1; i++) {
                generate_op_command(segment, state, OP_DADD);
            }
            generate_math_command(segment, state, MATH_STORE);
        }
        else {
            for (int i = 0; i < EXTRA_TMP1; i++) {
                generate_op_command(segment, state, OP_DADD);
            }
            set_mem(segment, state, inst->src.imm);
        }
        generate_op_command(segment, state, OP_DADD);
        generate_op_command(segment, state, OP_STORE);
        generate_math_command(segment, state, MATH_LOAD);
        generate_math_command(segment, state, MATH_NEG);
        generate_math_command(segment, state, MATH_STORE);
        generate_op_command(segment, state, OP_LOAD);
        generate_op_command(segment, state, OP_DADD);
        generate_math_command(segment, state, MATH_LOAD);

        for (unsigned i = EXTRA_TMP1; i > inst->dst.reg + REG_START_POS; i--) {
            generate_op_command(segment, state, OP_DADD);
        }

        switch (inst->op) {
            case JEQ: case JNE:
                generate_math_command(segment, state, MATH_EQUAL);
                break;
            case JLT: case JGE:
                generate_math_command(segment, state, MATH_GREATER);
                break;
            case JGT: case JLE:
                generate_math_command(segment, state, MATH_LESS);
                break;
            default:
                assert(false);
                break;
        }

        if (inst->op == JNE || inst->op == JGE || inst->op == JLE) {
            generate_math_command(segment, state, MATH_NOT);
        }

        for (int i = inst->dst.reg + REG_START_POS; i > 0; i--) {
            generate_op_command(segment, state, OP_DADD);
        }

        generate_op_command(segment, state, OP_LOAD);
        generate_math_command(segment, state, MATH_STORE);
    }

    // These last two commands do the jump, and set the rings clockwise. The rings
    // must be clockwise, because the jump table code assumes that the rings will
    // be clockwise, and it'll execute the wrong instructions otherwise
    set_math_ring_clockwise(segment, state);
    do_op_command_clockwise(segment, state, OP_IF);
}
// Generates the code for an ELVM jump instruction. We don't actually jump to
// our final destination here, we jump to the end of the program where there is
// a jump table that we will use
Generates the code for an ELVM jump instruction. We don't actually jump to
our final destination here, we jump to the end of the program where there is
a jump table that we will use
Generates the code for an ELVM jump instruction . We don ' t actually jump to our final destination here we jump to the end of the program where there is a jump table that we will use
static void generate_jump_inst(WhirlCodeSegment *segment, RingState *state) {
    Inst *inst = segment->inst;
    if (inst->jmp.type == REG) {
        move_to_reg(segment, state, inst->jmp.reg);
        generate_math_command(segment, state, MATH_LOAD);
        move_back_from_reg(segment, state, inst->jmp.reg);
        move_to_reg(segment, state, PC_REG_NUM);
        generate_math_command(segment, state, MATH_STORE);
        move_back_from_reg(segment, state, PC_REG_NUM);
    }
    else {
        move_to_reg(segment, state, PC_REG_NUM);
        set_mem(segment, state, inst->jmp.imm);
        move_back_from_reg(segment, state, PC_REG_NUM);
    }
    if (segment->next != NULL) {
        set_mem(segment, state, segment->next->total_code_len + 1);
    }
    else {
        set_mem(segment, state, 1);
    }
    if (inst->op == JMP) {
        generate_op_command(segment, state, OP_LOAD);
        generate_math_command(segment, state, MATH_LOAD);
        generate_math_command(segment, state, MATH_EQUAL);
        generate_math_command(segment, state, MATH_STORE);
    }
    else {
        generate_op_command(segment, state, OP_ONE);
        if (inst->src.type == REG) {
            for (unsigned i = 0; i < inst->src.reg + REG_START_POS; i++) {
                generate_op_command(segment, state, OP_DADD);
            }
            generate_math_command(segment, state, MATH_LOAD);
            for (int i = inst->src.reg + REG_START_POS; i < EXTRA_TMP1; i++) {
                generate_op_command(segment, state, OP_DADD);
            }
            generate_math_command(segment, state, MATH_STORE);
        }
        else {
            for (int i = 0; i < EXTRA_TMP1; i++) {
                generate_op_command(segment, state, OP_DADD);
            }
            set_mem(segment, state, inst->src.imm);
        }
        generate_op_command(segment, state, OP_DADD);
        generate_op_command(segment, state, OP_STORE);
        generate_math_command(segment, state, MATH_LOAD);
        generate_math_command(segment, state, MATH_NEG);
        generate_math_command(segment, state, MATH_STORE);
        generate_op_command(segment, state, OP_LOAD);
        generate_op_command(segment, state, OP_DADD);
        generate_math_command(segment, state, MATH_LOAD);
        for (unsigned i = EXTRA_TMP1; i > inst->dst.reg + REG_START_POS; i--) {
            generate_op_command(segment, state, OP_DADD);
        }
        switch (inst->op) {
            case JEQ: case JNE:
                generate_math_command(segment, state, MATH_EQUAL);
                break;
            case JLT: case JGE:
                generate_math_command(segment, state, MATH_GREATER);
                break;
            case JGT: case JLE:
                generate_math_command(segment, state, MATH_LESS);
                break;
            default:
                assert(false);
                break;
        }
        if (inst->op == JNE || inst->op == JGE || inst->op == JLE) {
            generate_math_command(segment, state, MATH_NOT);
        }
        for (int i = inst->dst.reg + REG_START_POS; i > 0; i--) {
            generate_op_command(segment, state, OP_DADD);
        }
        generate_op_command(segment, state, OP_LOAD);
        generate_math_command(segment, state, MATH_STORE);
    }
    set_math_ring_clockwise(segment, state);
    do_op_command_clockwise(segment, state, OP_IF);
}
static void generate_jump_inst ( WhirlCodeSegment * segment , RingState * state ) { Inst * inst = segment -> inst ; if ( inst -> jmp . type == REG ) { move_to_reg ( segment , state , inst -> jmp . reg ) ; generate_math_command ( segment , state , MATH_LOAD ) ; move_back_from_reg ( segment , state , inst -> jmp . reg ) ; move_to_reg ( segment , state , PC_REG_NUM ) ; generate_math_command ( segment , state , MATH_STORE ) ; move_back_from_reg ( segment , state , PC_REG_NUM ) ; } else { move_to_reg ( segment , state , PC_REG_NUM ) ; set_mem ( segment , state , inst -> jmp . imm ) ; move_back_from_reg ( segment , state , PC_REG_NUM ) ; } if ( segment -> next != NULL ) { set_mem ( segment , state , segment -> next -> total_code_len + 1 ) ; } else { set_mem ( segment , state , 1 ) ; } if ( inst -> op == JMP ) { generate_op_command ( segment , state , OP_LOAD ) ; generate_math_command ( segment , state , MATH_LOAD ) ; generate_math_command ( segment , state , MATH_EQUAL ) ; generate_math_command ( segment , state , MATH_STORE ) ; } else { generate_op_command ( segment , state , OP_ONE ) ; if ( inst -> src . type == REG ) { for ( unsigned i = 0 ; i < inst -> src . reg + REG_START_POS ; i ++ ) { generate_op_command ( segment , state , OP_DADD ) ; } generate_math_command ( segment , state , MATH_LOAD ) ; for ( int i = inst -> src . reg + REG_START_POS ; i < EXTRA_TMP1 ; i ++ ) { generate_op_command ( segment , state , OP_DADD ) ; } generate_math_command ( segment , state , MATH_STORE ) ; } else { for ( int i = 0 ; i < EXTRA_TMP1 ; i ++ ) { generate_op_command ( segment , state , OP_DADD ) ; } set_mem ( segment , state , inst -> src . imm ) ; } generate_op_command ( segment , state , OP_DADD ) ; generate_op_command ( segment , state , OP_STORE ) ; generate_math_command ( segment , state , MATH_LOAD ) ; generate_math_command ( segment , state , MATH_NEG ) ; generate_math_command ( segment , state , MATH_STORE ) ; generate_op_command ( segment , state , OP_LOAD ) ; generate_op_command ( segment , state , OP_DADD ) ; generate_math_command ( segment , state , MATH_LOAD ) ; for ( unsigned i = EXTRA_TMP1 ; i > inst -> dst . reg + REG_START_POS ; i -- ) { generate_op_command ( segment , state , OP_DADD ) ; } switch ( inst -> op ) { case JEQ : case JNE : generate_math_command ( segment , state , MATH_EQUAL ) ; break ; case JLT : case JGE : generate_math_command ( segment , state , MATH_GREATER ) ; break ; case JGT : case JLE : generate_math_command ( segment , state , MATH_LESS ) ; break ; default : assert ( false ) ; break ; } if ( inst -> op == JNE || inst -> op == JGE || inst -> op == JLE ) { generate_math_command ( segment , state , MATH_NOT ) ; } for ( int i = inst -> dst . reg + REG_START_POS ; i > 0 ; i -- ) { generate_op_command ( segment , state , OP_DADD ) ; } generate_op_command ( segment , state , OP_LOAD ) ; generate_math_command ( segment , state , MATH_STORE ) ; } set_math_ring_clockwise ( segment , state ) ; do_op_command_clockwise ( segment , state , OP_IF ) ; }
Generates the code for an ELVM jump instruction.
Generates the code for an ELVM jump instruction .
// Put our jump destination in the PC register so that when we // reach the jump table, we know where to jump to // Set the current memory position to the location of the jump table, // which should be at the end of the program // Unconditional jump, just load the address and store a 1 in the cell // Otherwise, we have to do an actual comparison and save the result in // the first memory cell // These last two commands do the jump, and set the rings clockwise. The rings // must be clockwise, because the jump table code assumes that the rings will // be clockwise, and it'll execute the wrong instructions otherwise