Canola
0.8.D001
|
00001 // 00002 // canola - canon canola 1614p emulator 00003 // Copyright (C) 2011, 2012 Peter Miller 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License, version 3, as 00007 // published by the Free Software Foundation. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License along 00015 // with this program. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #include <lib/ac/stdio.h> 00019 #include <lib/calculator.h> 00020 00021 // #define OPCODE_DEBUG 1 00022 00023 00024 void 00025 calculator::execute_one_instruction(void) 00026 { 00027 // 00028 // <question> 00029 // How many instructions are executed per second? 00030 // </question> 00031 // 00032 // <question> 00033 // Do all instructions execute at the same speed? 00034 // We already know that PRINT (420ms) and FEED (290ms) take longer 00035 // than other opcodes. 00036 // </question> 00037 // 00038 location::pointer where = next_location(); 00039 opcode_t op = (opcode_t)next_opcode(); 00040 #ifdef OPCODE_DEBUG 00041 fprintf(stderr, "%s: %d: addr %d, op '%s'\n", __FILE__, 00042 __LINE__, address - 1, opcode_name(op).c_str()); 00043 #endif 00044 assert(op < 128); 00045 switch (op) 00046 { 00047 case opcode_zero: 00048 if (address == wrap_address(0) + 1) 00049 { 00050 on_error("no program to execute"); 00051 clock_tick_mode = clock_tick_mode_disabled; 00052 address = 0; 00053 break; 00054 } 00055 00056 // 00057 // <question> 00058 // Does opcode $000 mean "goto 1" or does opcode $000 mean "skip 1"? 00059 // <p> 00060 // How to tell the difference:<br> 00061 // If I use the program bank selector switch, put a program in 00062 // bank I and a second program in bank II, then set the program 00063 // bank selector switch to I+II. When the program is executed, 00064 // at the end of bank I (hitting a $000 opcode) does it goto 00065 // address 1, or does it execute the first opcode in bank II? 00066 // </question> 00067 // 00068 // Here we assume it means the first, rather than the second. 00069 // 00070 address = 0; 00071 break; 00072 00073 case opcode_plus_equals: 00074 case opcode_minus_equals: 00075 case opcode_mul: 00076 case opcode_div: 00077 case opcode_sqrt: 00078 execute_as_normal: 00079 on_opcode_ope(op, where); 00080 break; 00081 00082 case opcode_ent: 00098 #if 1 00099 switch (mstate) 00100 { 00101 case mstate_reset: 00102 break; 00103 00104 case mstate_lhs_digits_before_dot: 00105 case mstate_lhs_digits_after_dot: 00106 mstate = mstate_lhs_complete; 00107 break; 00108 00109 case mstate_lhs_complete: 00110 case mstate_mul: 00111 break; 00112 00113 case mstate_mul_digits_before_dot: 00114 case mstate_mul_digits_after_dot: 00115 mstate = mstate_mul_complete; 00116 break; 00117 00118 case mstate_mul_complete: 00119 break; 00120 00121 default: 00122 break; 00123 } 00124 #endif 00125 clock_tick_mode = clock_tick_mode_entry; 00126 number_of_keys_since_ej = 0; 00127 break; 00128 00129 case opcode_sj: 00146 clock_tick_mode = clock_tick_mode_sj; 00147 // Note: we have yet to read the jump flag byte. 00148 number_of_keys_since_ej = 0; 00149 break; 00150 00151 case opcode_ej: 00169 clock_tick_mode = clock_tick_mode_ej; 00170 // Note: we have yet to read the jump flag byte. 00171 // <question> 00172 // If we have [2] [EJ] {flag} in a program, and execution 00173 // reaches the EJ opcode, does pressing [3] display "3" or "23" 00174 // or something else? 00175 // </question> 00176 number_of_keys_since_ej = 0; 00177 break; 00178 00179 case opcode_mj: 00193 { 00194 unsigned char label = next_opcode(); 00195 if (x_register < 0) 00196 address = find_flag_jump(label); 00197 } 00198 break; 00199 00200 case opcode_uj: 00221 address = find_flag_jump(next_opcode()); 00222 break; 00223 00224 case opcode_fj: 00242 next_opcode(); 00243 break; 00244 00245 case opcode_suj: 00246 { 00247 // <question> 00248 // How deep is the subroutine call stack? 00249 // Or, to ask it another way, can you nest SUJ calls? 00250 // </question> 00251 unsigned char label = next_opcode(); 00252 call_stack.push_back(address); 00253 address = find_subroutine_flag_jump(label); 00254 } 00255 break; 00256 00257 case opcode_sfj: 00258 // Question: What happens when you SUJ to a non-existent SFJ? 00259 next_opcode(); 00260 break; 00261 00262 case opcode_srj: 00263 // Question: What happens when you SRJ but no subroutine was called? 00264 if (call_stack.empty()) 00265 { 00266 on_error("returning from subroutine that was not called"); 00267 clock_tick_mode = clock_tick_mode_disabled; 00268 break; 00269 } 00270 address = call_stack.back(); 00271 call_stack.pop_back(); 00272 break; 00273 00274 case opcode_m1: 00275 case opcode_m2: 00276 case opcode_m3: 00277 case opcode_m4: 00278 case opcode_m5: 00279 case opcode_m6: 00280 case opcode_m7: 00281 case opcode_m8: 00282 case opcode_m9: 00283 case opcode_m10: 00284 case opcode_m11: 00285 case opcode_m12: 00286 case opcode_m13: 00287 case opcode_m14: 00288 case opcode_mm1: 00289 case opcode_mm2: 00290 case opcode_sm3: 00291 case opcode_sm4: 00292 case opcode_sm5: 00293 case opcode_sm6: 00294 case opcode_sm7: 00295 case opcode_sm8: 00296 case opcode_sm9: 00297 case opcode_sm10: 00298 case opcode_sm11: 00299 case opcode_sm12: 00300 case opcode_sm13: 00301 case opcode_sm14: 00302 case opcode_rm1: 00303 case opcode_rm2: 00304 case opcode_rm3: 00305 case opcode_rm4: 00306 case opcode_rm5: 00307 case opcode_rm6: 00308 case opcode_rm7: 00309 case opcode_rm8: 00310 case opcode_rm9: 00311 case opcode_rm10: 00312 case opcode_rm11: 00313 case opcode_rm12: 00314 case opcode_rm13: 00315 case opcode_rm14: 00316 case opcode_clear_indicator: 00317 case opcode_cm1: 00318 case opcode_cm2: 00319 case opcode_cm3: 00320 case opcode_cm4: 00321 case opcode_cm5: 00322 case opcode_cm6: 00323 case opcode_cm7: 00324 case opcode_cm8: 00325 case opcode_cm9: 00326 case opcode_cm10: 00327 case opcode_cm11: 00328 case opcode_cm12: 00329 case opcode_cm13: 00330 case opcode_cm14: 00331 case opcode_dot: 00332 case opcode_rv: 00333 case opcode_right: 00334 case opcode_chg_sign: 00335 goto execute_as_normal; 00336 00337 case opcode_round_down: 00338 // FIXME: should we issue a warning if it isn't a number? 00339 // i.e. 0x70..0x7E 00340 precro_current = 00341 precision_and_rounding 00342 ( 00343 next_opcode() & 15, 00344 precision_and_rounding::round_down 00345 ); 00346 break; 00347 00348 case opcode_round_off: 00349 // FIXME: should we issue a warning if it isn't a number? 00350 // i.e. 0x70..0x7E 00351 precro_current = 00352 precision_and_rounding 00353 ( 00354 next_opcode() & 15, 00355 precision_and_rounding::round_off 00356 ); 00357 break; 00358 00359 case opcode_round_up: 00360 // FIXME: should we issue a warning if it isn't a number? 00361 // i.e. 0x70..0x7E 00362 precro_current = 00363 precision_and_rounding 00364 ( 00365 next_opcode() & 15, 00366 precision_and_rounding::round_up 00367 ); 00368 break; 00369 00370 case opcode_print: 00371 { 00372 display value = x_register.get_display(); 00373 value.set_opcode(op); 00374 update_display_lamps(value); 00375 derived_print(value); 00376 } 00377 break; 00378 00379 case opcode_fd: 00380 derived_feed(); 00381 break; 00382 00383 case opcode_n0: 00384 case opcode_n1: 00385 case opcode_n2: 00386 case opcode_n3: 00387 case opcode_n4: 00388 case opcode_n5: 00389 case opcode_n6: 00390 case opcode_n7: 00391 case opcode_n8: 00392 case opcode_n9: 00393 goto execute_as_normal; 00394 00395 case opcode_n10: 00396 case opcode_n11: 00397 case opcode_n12: 00398 case opcode_n13: 00399 case opcode_n14: 00400 // These opcodes cause an automatic overflow, 00401 // but we let on_opcode_ope generate the overflow. 00402 goto execute_as_normal; 00403 00404 default: 00405 on_error("%03d '%s' can not be executed", address - 1, 00406 opcode_name(op).c_str()); 00407 clock_tick_mode = clock_tick_mode_disabled; 00408 break; 00409 00410 case opcode_extended_c: 00411 case opcode_extended_start: 00412 case opcode_extended_m3_tilde: 00413 case opcode_extended_sm3_tilde: 00414 case opcode_extended_rm3_tilde: 00415 case opcode_extended_cm3_tilde: 00416 case opcode_extended_off: 00417 case opcode_extended_program_print: 00418 case opcode_extended_display_print: 00419 case opcode_extended_paper_feed: 00420 case opcode_extended_rounding_switch_up: 00421 case opcode_extended_rounding_switch_off: 00422 case opcode_extended_rounding_switch_down: 00423 case opcode_extended_decimal_point_selector_0: 00424 case opcode_extended_decimal_point_selector_1: 00425 case opcode_extended_decimal_point_selector_2: 00426 case opcode_extended_decimal_point_selector_3: 00427 case opcode_extended_decimal_point_selector_4: 00428 case opcode_extended_decimal_point_selector_5: 00429 case opcode_extended_decimal_point_selector_6: 00430 case opcode_extended_decimal_point_selector_7: 00431 case opcode_extended_decimal_point_selector_8: 00432 case opcode_extended_decimal_point_selector_9: 00433 case opcode_extended_decimal_point_selector_10: 00434 case opcode_extended_decimal_point_selector_11: 00435 case opcode_extended_decimal_point_selector_12: 00436 case opcode_extended_decimal_point_selector_float: 00437 case opcode_extended_goto_000: 00438 case opcode_extended_goto_001: 00439 case opcode_extended_goto_002: 00440 case opcode_extended_goto_003: 00441 case opcode_extended_goto_004: 00442 case opcode_extended_goto_005: 00443 case opcode_extended_goto_006: 00444 case opcode_extended_goto_007: 00445 case opcode_extended_goto_008: 00446 case opcode_extended_goto_009: 00447 case opcode_extended_goto_010: 00448 case opcode_extended_goto_011: 00449 case opcode_extended_goto_012: 00450 case opcode_extended_goto_013: 00451 case opcode_extended_goto_014: 00452 case opcode_extended_goto_015: 00453 case opcode_extended_goto_100: 00454 case opcode_extended_goto_101: 00455 case opcode_extended_goto_102: 00456 case opcode_extended_goto_103: 00457 case opcode_extended_goto_104: 00458 case opcode_extended_goto_105: 00459 case opcode_extended_goto_106: 00460 case opcode_extended_goto_107: 00461 case opcode_extended_goto_108: 00462 case opcode_extended_goto_109: 00463 case opcode_extended_goto_110: 00464 case opcode_extended_goto_111: 00465 case opcode_extended_goto_112: 00466 case opcode_extended_goto_113: 00467 case opcode_extended_goto_114: 00468 case opcode_extended_goto_115: 00469 case opcode_extended_goto_200: 00470 case opcode_extended_goto_201: 00471 case opcode_extended_goto_202: 00472 case opcode_extended_goto_203: 00473 case opcode_extended_goto_204: 00474 case opcode_extended_goto_205: 00475 case opcode_extended_goto_206: 00476 case opcode_extended_goto_207: 00477 case opcode_extended_goto_208: 00478 case opcode_extended_goto_209: 00479 case opcode_extended_goto_210: 00480 case opcode_extended_goto_211: 00481 case opcode_extended_goto_212: 00482 case opcode_extended_goto_213: 00483 case opcode_extended_goto_214: 00484 case opcode_extended_goto_215: 00485 case opcode_extended_goto_300: 00486 case opcode_extended_goto_301: 00487 case opcode_extended_goto_302: 00488 case opcode_extended_goto_303: 00489 case opcode_extended_goto_304: 00490 case opcode_extended_goto_305: 00491 case opcode_extended_goto_306: 00492 case opcode_extended_goto_307: 00493 case opcode_extended_goto_308: 00494 case opcode_extended_goto_309: 00495 case opcode_extended_goto_310: 00496 case opcode_extended_goto_311: 00497 case opcode_extended_goto_312: 00498 case opcode_extended_goto_313: 00499 case opcode_extended_goto_314: 00500 case opcode_extended_goto_315: 00501 case opcode_extended_goto_400: 00502 case opcode_extended_goto_401: 00503 case opcode_extended_goto_402: 00504 case opcode_extended_goto_403: 00505 case opcode_extended_goto_404: 00506 case opcode_extended_goto_405: 00507 case opcode_extended_goto_406: 00508 case opcode_extended_goto_407: 00509 case opcode_extended_goto_408: 00510 case opcode_extended_goto_409: 00511 case opcode_extended_goto_410: 00512 case opcode_extended_goto_411: 00513 case opcode_extended_goto_412: 00514 case opcode_extended_goto_413: 00515 case opcode_extended_goto_414: 00516 case opcode_extended_goto_415: 00517 case opcode_extended_goto_500: 00518 case opcode_extended_goto_501: 00519 case opcode_extended_goto_502: 00520 case opcode_extended_goto_503: 00521 case opcode_extended_goto_504: 00522 case opcode_extended_goto_505: 00523 case opcode_extended_goto_506: 00524 case opcode_extended_goto_507: 00525 case opcode_extended_goto_508: 00526 case opcode_extended_goto_509: 00527 case opcode_extended_goto_510: 00528 case opcode_extended_goto_511: 00529 case opcode_extended_goto_512: 00530 case opcode_extended_goto_513: 00531 case opcode_extended_goto_514: 00532 case opcode_extended_goto_515: 00533 case opcode_extended_goto_600: 00534 case opcode_extended_goto_601: 00535 case opcode_extended_goto_602: 00536 case opcode_extended_goto_603: 00537 case opcode_extended_goto_604: 00538 case opcode_extended_goto_605: 00539 case opcode_extended_goto_606: 00540 case opcode_extended_goto_607: 00541 case opcode_extended_goto_608: 00542 case opcode_extended_goto_609: 00543 case opcode_extended_goto_610: 00544 case opcode_extended_goto_611: 00545 case opcode_extended_goto_612: 00546 case opcode_extended_goto_613: 00547 case opcode_extended_goto_614: 00548 case opcode_extended_goto_615: 00549 case opcode_extended_goto_700: 00550 case opcode_extended_goto_701: 00551 case opcode_extended_goto_702: 00552 case opcode_extended_goto_703: 00553 case opcode_extended_goto_704: 00554 case opcode_extended_goto_705: 00555 case opcode_extended_goto_706: 00556 case opcode_extended_goto_707: 00557 case opcode_extended_goto_708: 00558 case opcode_extended_goto_709: 00559 case opcode_extended_goto_710: 00560 case opcode_extended_goto_711: 00561 case opcode_extended_goto_712: 00562 case opcode_extended_goto_713: 00563 case opcode_extended_goto_714: 00564 case opcode_extended_goto_715: 00565 assert(!"can't happen"); 00566 break; 00567 } 00568 #ifdef OPCODE_DEBUG 00569 fprintf(stderr, "%s: %d: x = %.18Lg\n", __FILE__, __LINE__, 00570 x_register.get_floating()); 00571 #endif 00572 }