Beispiel #1
0
void outopt(int ch, int count)
{
    if (deadloop) {
	if (ch == '[') deadloop++;
	if (ch == ']') deadloop--;
	return;
    }
    if (ch == '[') {
	if (tape->is_set && tape->v == 0) {
	    deadloop++;
	    return;
	}
    }

    switch(ch)
    {
    case '[': case ']': case '!': case '~': case 'X': case '#':
    case 'I': case 'E':
	if (ch == '!') {
	    flush_tape(1,0);
	    tape->cleaned = tape->is_set = first_run = !disable_init_optim;
	} else if (ch == '~' && enable_optim && !disable_init_optim)
	    flush_tape(1,0);
	else
	    flush_tape(0,0);
	if (ch) outcmd(ch, count);

	/* Loops end with zero */
	if (ch == ']') {
	    tape->is_set = 1;
	    tape->v = 0;
	    tape->cleaned = 1;
	    tape->cleaned_val = tape->v;
	}

	/* I could save the cleaned tape state at the beginning of a loop,
	 * then when we find the matching end loop the two tapes could be
	 * merged to give a tape of known values after the loop ends.
	 * This would not break the pipeline style of this code.
	 *
	 * This would also give states where a cell is known to have one
	 * of two or more different values. */
	return;

    case '.':
	if (tape->is_set) {
	    int c = tape->v;
	    if (bytecell) c &= 0xFF;
	    if (c > 0 && c < 128) {
		add_string(c);

		/* Limit the buffer size. */
		if (sav_str_len >= 128*1024 - (tape->v=='\n')*1024)
		    flush_string();
		break;
	    }
	}
	flush_tape(0,1);
	outcmd(ch, count);
	return;

    case ',':
	flush_tape(0,1);
	clear_cell(tape);
	outcmd(ch, count);
	return;

    case '>': while(count-->0) { if (tape->n == 0) new_n(tape); tape=tape->n; curroff++; } break;
    case '<': while(count-->0) { if (tape->p == 0) new_p(tape); tape=tape->p; curroff--; } break;
    case '+':
	if (be_interface.cells_are_ints || bytecell) {
	    tape->v += count;
	    if (bytecell) tape->v %= 256; /* -255..255 */
	} else {
	    int ov=0, res;
	    res = ov_iadd(tape->v, count, &ov);
	    if (!ov)
		tape->v = res;
	    else {
		flush_tape(0,1);
		clear_cell(tape);
		outcmd(ch, count);
	    }
	}
	break;
    case '-':
	if (be_interface.cells_are_ints || bytecell) {
	    tape->v -= count;
	    if (bytecell) tape->v %= 256; /* -255..255 */
	} else {
	    int ov=0, res;
	    res = ov_isub(tape->v, count, &ov);
	    if (!ov)
		tape->v = res;
	    else {
		flush_tape(0,1);
		clear_cell(tape);
		outcmd(ch, count);
	    }
	}
	break;

    case '=': tape->v = count; tape->is_set = 1; break;

    case 'B':
	flush_tape(0,1);
	if (be_interface.disable_be_optim) be_codegen_failure();
	outcmd(ch, count);
	return;

    case 'M': case 'N': case 'S': case 'T':
	if (ch == 'N') count = -count;
	else if (ch == 'S') count = 1;
	else if (ch == 'T') count = -1;

	if (tape->is_set && tape->v == 0) {
	    tape->is_set = 0 ; tape->v = 0;

	    ch = 'C';
	    if (count == 1) ch = 'V';
	    else if (count == -1) { ch = 'W'; count = -count; }
	    else if (count < 0) { ch = 'D'; count = -count; }
	} else {
	    ch = 'M';
	    if (count == 1) ch = 'S';
	    else if (count == -1) { ch = 'T'; count = -count; }
	    else if (count < 0) { ch = 'N'; count = -count; }
	}

	flush_tape(0,1);
	clear_cell(tape);
	if (be_interface.disable_be_optim) be_codegen_failure();
	outcmd(ch, count);
	return;

    default:
	if (be_interface.disable_be_optim) be_codegen_failure();
	if (ch>=0 && ch<256)
	    fprintf(stderr, "Unknown token in bf2const.c (%d)\n", ch);
	flush_tape(0,0);
	outcmd(ch, count);
	return;
    }
}
Beispiel #2
0
void outopt(int ch, int count)
{
    if (deadloop) {
	if (ch == '[') deadloop++;
	if (ch == ']') deadloop--;
	return;
    }
    if (ch == '[' && enable_mov_optim) {
	if (tape->is_set && tape->v == 0) {
	    deadloop++;
	    return;
	}
    }

    switch(ch)
    {
    default:
	if (ch == '!') {
	    flush_tape(1,0);
	    tape->cleaned = tape->is_set = first_run = !disable_init_optim;
	} else if (ch == '~' && enable_optim && !disable_init_optim)
	    flush_tape(1,0);
	else
	    flush_tape(0,0);
	if (ch) outcmd(ch, count);

	/* Loops end with zero */
	if (ch == ']') {
	    tape->is_set = 1;
	    tape->v = 0;
	    tape->cleaned = 1;
	    tape->cleaned_val = tape->v;
	}

	/* I could save the cleaned tape state at the beginning of a loop,
	 * then when we find the matching end loop the two tapes could be
	 * merged to give a tape of known values after the loop ends.
	 * This would not break the pipeline style of this code.
	 *
	 * This would also give states where a cell is known to have one
	 * of two or more different values. */
	return;

    case '.':
	if (!disable_savestring && enable_be_optim &&
		tape->is_set && tape->v > 0 && tape->v < 128) {
	    add_string(tape->v);

	    if (sav_str_len >= 128*1024) /* Limit the buffer size. */
	    {
		add_string(0);
		outcmd('"', 0);
		sav_str_len = 0;
	    }
	    break;
	}
	flush_tape(0,1);
	outcmd(ch, count);
	return;

    case ',':
	flush_tape(0,1);
	clear_cell(tape);
	outcmd(ch, count);
	return;

    case '>': while(count-->0) { if (tape->n == 0) new_n(tape); tape=tape->n; curroff++; } break;
    case '<': while(count-->0) { if (tape->p == 0) new_p(tape); tape=tape->p; curroff--; } break;
    case '+': tape->v += count; break;
    case '-': tape->v -= count; break;

    case '=': tape->v = count; tape->is_set = 1; break;

    case 'B':
	/* Some BE are not 32 bits, try to avoid cell size mistakes */
	if (!cells_are_ints && (tape->v > 65536 || tape->v < -65536))
	    ;
	else
	if (tape->is_set) {
	    if (bytecell) tape->v %= 256; /* Note: preserves sign but limits range. */
	    reg_known = 1;
	    reg_val = tape->v;
	    break;
	}

	flush_tape(0,1);
	reg_known = 0; reg_val = 0;
	if (enable_be_optim) {
	    outcmd(ch, count);
	} else {
	    outcmd('[', 1);
	}
	return;

    case 'M':
    case 'N':
    case 'S':
    case 'Q':
    case 'm':
    case 'n':
    case 's':
    case 'E':
	if (!reg_known) {
	    flush_tape(0,1);
	    clear_cell(tape);
	    if (enable_be_optim) {
		outcmd(ch, count);
	    } else switch(ch) {
		case 'M': case 'm':
		    outcmd('+', count);
		    break;
		case 'N': case 'n':
		    outcmd('-', count);
		    break;
		case 'S': case 's':
		    outcmd('+', 1);
		    break;
		case 'Q':
		    outcmd('[', 1);
		    outcmd('-', 1);
		    outcmd(']', 1);
		    if (count)
			outcmd('+', count);
		    break;
		case 'E':
		    outcmd(']', 1);
		    break;
	    }
	    return;
	}
	switch(ch) {
	case 'm':
	case 'M':
	    tape->v += reg_val * count;
	    break;
	case 'n':
	case 'N':
	    tape->v -= reg_val * count;
	    break;
	case 's':
	case 'S':
	    tape->v += reg_val;
	    break;

	case 'Q':
	    if (reg_val != 0) {
		tape->v = count;
		tape->is_set = 1;
	    }
	    break;
	}
	if (bytecell) tape->v %= 256; /* Note: preserves sign but limits range. */
    }
}