Canola  0.8.D001
lib/calculator/execute_one_instruction.cc
Go to the documentation of this file.
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 }