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; } }
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. */ } }