home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / CROSSASM / 68ASMSIM.ZIP / simsrc / run.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-09  |  16.2 KB  |  611 lines

  1.  
  2. /***************************** 68000 SIMULATOR ****************************
  3.  
  4. File Name: RUN.C
  5. Version: 1.0
  6.  
  7. This file contains various routines to run a 68000 instruction.  These
  8. routines are :
  9.  
  10.     decode_size(), eff_addr(), runprog(), exec_inst(), exception()
  11.  
  12. ***************************************************************************/
  13.  
  14.  
  15.  
  16. #include <stdio.h>
  17. #include "extern.h"                             /* global declarations */
  18. #include "opcodes.h"                            /* opcode masks for decoding */
  19.                                                         /* the 68000 instructions */
  20.  
  21.  
  22.  
  23. /**************************** int decode_size() ****************************
  24.  
  25.    name       : int decode_size (result)
  26.    parameters : long *result : the appropriate mask for the decoded size
  27.    function   : decodes the size field in the instruction being processed
  28.                   and returns a mask to be used in instruction execution.
  29.                   For example, if the size field was "01" then the mask 
  30.                   returned is WORD.
  31.  
  32. ****************************************************************************/
  33.  
  34.  
  35. int    decode_size (result)
  36. long    *result;
  37. {
  38.     int    bits;
  39.  
  40.     /* the size field is always in bits 6 and 7 of the instruction word */
  41.     bits = (inst >> 6) & 0x0003;
  42.  
  43.     switch (bits) {
  44.         case 0 : *result = BYTE;
  45.              break;
  46.         case 1 : *result = WORD;
  47.              break;
  48.         case 2 : *result = LONG;
  49.              break;
  50.         default : *result = 0;
  51.         }
  52.  
  53.     if (result != 0) 
  54.        return SUCCESS;
  55.     else    
  56.        return FAILURE;
  57.  
  58. }
  59.  
  60.  
  61.  
  62. /**************************** int eff_addr() *******************************
  63.  
  64.    name       : int eff_addr (size, mask, add_times)
  65.    parameters : long size : the appropriate size mask
  66.                 int mask : the effective address modes mask to be used
  67.                 int add_times : tells whether to increment the cycle counter
  68.                       (there are times when we don't want to)
  69.    function   : eff_addr() decodes the effective address field in the current
  70.                   instruction, returns a pointer to the effective address 
  71.                   either in EA1 or EA2, and returns the value at that 
  72.                   location in EV1 or EV2.
  73.  
  74. ****************************************************************************/
  75.  
  76.  
  77. int eff_addr (size, mask, add_times)
  78. long    size;
  79. int    mask;
  80. int    add_times;
  81. {
  82.     int    mode, reg, legal, addr, move_operation;
  83.     int    bwinc, linc;
  84.     long    ext, temp_ext, inc_size, ind_reg, *value, disp;
  85.  
  86.     if (
  87.             ( 
  88.                 ((inst & 0xf000) == 0x1000)
  89.                 || ((inst & 0xf000) == 0x2000)
  90.                 ||    ((inst & 0xf000) == 0x3000)
  91.             ) 
  92.             && (mask == DATA_ALT_ADDR)
  93.         )
  94.         move_operation = TRUE;
  95.     else
  96.         move_operation = FALSE;
  97.  
  98.     if (move_operation)
  99.         addr = (inst >> 6) & 0x003f;
  100.     else
  101.         addr = inst & 0x003f;
  102.     legal = FALSE;
  103.     bwinc = linc = 0;
  104.    if (move_operation)        /* reg and mode are reversed in MOVE dest EA */
  105.         {
  106.         reg = (addr & MODE_MASK) >> 3;
  107.         mode = addr & REG_MASK;
  108.         }
  109.     else
  110.         {
  111.         mode = (addr & MODE_MASK) >> 3;
  112.         reg = addr & REG_MASK;
  113.         }
  114.     switch (mode) {
  115.        case    0 : if (mask & bit_1)
  116.             {
  117.             value = &D[reg];
  118.             bwinc = linc = 0;
  119.             legal = TRUE;
  120.             }
  121.             break;
  122.        case    1 : if (mask & bit_2)
  123.             {
  124.             reg = a_reg(reg);
  125.             value = &A[reg];
  126.             bwinc = linc = 0;
  127.             legal = TRUE;
  128.             }
  129.             break;
  130.        case    2 : if (mask & bit_3)
  131.             {
  132.             reg = a_reg(reg);
  133.             value = (long) &memory[A[reg]];
  134.             bwinc = 4;
  135.             linc = 8;
  136.             legal = TRUE;
  137.             }
  138.             break;
  139.        case    3 : if (mask & bit_4)
  140.             {
  141.             reg = a_reg(reg);
  142.             if (size == BYTE) 
  143.                 inc_size = 1;
  144.             else if (size == WORD)
  145.                 inc_size = 2;
  146.             else inc_size = 4;
  147.             value = (long) &memory[A[reg]];
  148.             A[reg] = A[reg] + inc_size;
  149.             bwinc = 4;
  150.             linc = 8;
  151.             legal = TRUE;
  152.             }
  153.             break;
  154.        case    4 : if (mask & bit_5)
  155.             {
  156.             reg = a_reg(reg);
  157.             if (size == BYTE) 
  158.                 inc_size = 1;
  159.             else if (size == WORD)
  160.                 inc_size = 2;
  161.             else inc_size = 4;
  162.             A[reg] = A[reg] - inc_size;
  163.             value = (long) &memory[A[reg]];
  164.             bwinc = 6;
  165.             linc = 10;
  166.             legal = TRUE;
  167.             }
  168.             break;
  169.        case    5 : if (mask & bit_6)
  170.             {
  171.             reg = a_reg(reg);
  172.             mem_request (&PC, (long) WORD, &ext);
  173.             from_2s_comp (ext, (long) WORD, &ext);
  174.             value = (long) &memory[A[reg] + (ext & WORD)];
  175.             bwinc = 8;
  176.             linc = 12;
  177.             legal = TRUE;
  178.             }
  179.             break;
  180.        case    6 : if (mask & bit_7)
  181.             {
  182.             reg = a_reg(reg);
  183.             /* fetch extension word */
  184.             mem_request (&PC, (long) WORD, &ext);
  185.             disp = ext & 0xff;
  186.             sign_extend (disp, BYTE, &disp);
  187.             from_2s_comp (disp, (long) WORD, &disp);
  188.             /* get index register value */
  189.             if (ext & 0x8000)
  190.                 ind_reg = A[a_reg((ext & 0x7000) >> 12)];
  191.             else
  192.                 ind_reg = D[(ext & 0x7000) >> 12];
  193.             /* get correct length for index register */
  194.             if (!(ext & 0x0800))
  195.                 {
  196.                 sign_extend (ind_reg, WORD, &ind_reg);
  197.                 from_2s_comp (ind_reg, (long) LONG, &ind_reg);
  198.                 }
  199.             value = (long) (&memory[A[reg] + (disp & WORD) + ind_reg]);
  200.             bwinc = 10;
  201.             linc = 14;
  202.             legal = TRUE;
  203.             }
  204.             break;
  205.        case    7 : switch (reg) {
  206.                case    0 : if (mask & bit_8)
  207.                     {
  208.                     mem_request (&PC, (long) WORD, &ext);
  209.                     value = (long) &memory[ext];
  210.                     bwinc = 8;
  211.                     linc = 12;
  212.                     legal = TRUE;
  213.                     }
  214.                     break;
  215.                case    1 : if (mask & bit_9)
  216.                     {
  217.                     mem_request (&PC, (long) WORD, &ext);
  218.                     mem_request (&PC, (long) WORD, &temp_ext);
  219.                     ext = ext * 0xffff + temp_ext;
  220.                     value = (long) &memory[ext & ADDRMASK];
  221.                     bwinc = 12;
  222.                     linc = 16;
  223.                     legal = TRUE;
  224.                     }
  225.                      break;
  226.                case    2 : if (mask & bit_10)
  227.                     {
  228.                     mem_request (&PC, (long) WORD, &ext);
  229.                     from_2s_comp (ext, (long) WORD, &ext);
  230.                     value = (long) &memory[PC + (ext & WORD) - 1];
  231.                     bwinc = 8;
  232.                     linc = 12;
  233.                     legal = TRUE;
  234.                     }
  235.                      break;
  236.                case    3 : if (mask & bit_11)
  237.                     {
  238.                     /* fetch extension word */
  239.                     mem_request (&PC, (long) WORD, &ext);
  240.                     disp = ext & 0xff;
  241.                     sign_extend (disp, BYTE, &disp);
  242.                     from_2s_comp (disp, (long) WORD, &disp);
  243.                     /* get index register value */
  244.                     if (ext & 0x8000)
  245.                        ind_reg = A[a_reg((ext & 0x7000) >> 12)];
  246.                     else
  247.                        ind_reg = D[(ext & 0x7000) >> 12];
  248.                     /* get correct length for index register */
  249.                     if (!(ext & 0x0800))
  250.                         {
  251.                         sign_extend (ind_reg, WORD, &ind_reg);
  252.                         from_2s_comp (ind_reg, (long) LONG, &ind_reg);
  253.                         }
  254.                     ext = ext & 0x00ff;
  255.                     value = (long) (&memory[PC - 1 + (disp & WORD) + ind_reg]);
  256.                     bwinc = 10;
  257.                     linc = 14;
  258.                     legal = TRUE;
  259.                     }
  260.                     break;
  261.                case    4 : if (mask & bit_12)
  262.                     {
  263.                     if ((size == BYTE) || (size == WORD))
  264.                         mem_request (&PC, (long) WORD, &ext);
  265.                     else
  266.                         mem_request (&PC, LONG, &ext);
  267.                     global_temp = ext;
  268.                     value = &global_temp;
  269.                     bwinc = 4;
  270.                     linc = 8;
  271.                     legal = TRUE;
  272.                     }
  273.                     break;
  274.                 }
  275.             break;
  276.     }         /* switch */
  277.  
  278.     if (legal) 
  279.         {
  280.         if (add_times) {
  281.             if (size != LONG) 
  282.                 inc_cyc (bwinc);
  283.             else     
  284.                 inc_cyc (linc);
  285.         }
  286.         if (move_operation)/* choose EA2 in case of MOVE dest effective address */
  287.             {
  288.              EA2 = value;
  289.             value_of (EA2, &EV2, size);
  290.             }
  291.         else
  292.             {
  293.             EA1 = value;
  294.             value_of (EA1, &EV1, size);
  295.             }
  296.         return SUCCESS;
  297.         }
  298.     else
  299.         return FAILURE;       /* return FAILURE if illegal addressing mode */
  300.  
  301. }
  302.  
  303.  
  304.  
  305.  
  306. /**************************** int runprog() *******************************
  307.  
  308.    name       : int runprog ()
  309.    parameters : NONE
  310.    function   : executes a program at PC specified or current PC if not
  311.                   specified.  this function is the outer loop of the 
  312.                   running program.  it handles i/o interrupts, user
  313.                   (keyboard) interrupts, and calls the error routine if an
  314.                   illegal opcode is found.
  315.  
  316.  
  317. ****************************************************************************/
  318.  
  319. int runprog()
  320. {
  321.     int new_pc;
  322.     int i;
  323.     char ch, *pc_str;
  324.  
  325.     printf ("Running the program ...");
  326.     windowLine();
  327.  
  328.     if (wcount > 1)
  329.         {
  330.         pc_str = wordptr[1];
  331.         eval2 (pc_str, &new_pc);
  332.         OLD_PC = PC = new_pc;
  333.         }
  334.  
  335.     errflg = 0;
  336.  
  337.     for (;;)        /* execute instructions until error or break */
  338.         {
  339.  
  340.         exec_inst();        /* execute an instruction */
  341.  
  342.         ch = chk_buf();   /* has a character been hit ? */
  343.         if (ch != '\0')
  344.             switch ((int) ch)
  345.                 {
  346.                 case 3: exit (0);     /* exit simulator if control-c */
  347.                 case 2: save_cursor();
  348.                             scrshow();    /* terminate the 68000 program if control-b */
  349.                             restore_cursor();
  350.                      return (USER_BREAK);
  351.                 }
  352.  
  353.         if (errflg)   /* if illegal opcode in program initiate an exception */
  354.             {
  355.             printf("illegal opcode at loc %04x", WORD & (PC - 1));
  356.             windowLine();
  357.             inc_cyc (34);
  358.             exception (1, 0, READ);
  359.             mem_req (0x10, LONG, &PC);
  360.             save_cursor();
  361.             scrshow();
  362.             restore_cursor();
  363.             return (0);
  364.             }
  365.  
  366.         if (trace) {
  367.             save_cursor();
  368.             scrshow();   /* if trace is on then update the screen */
  369.             restore_cursor();
  370.             }
  371.  
  372.         for (i = 0; i < bpoints; i++)      /* if PC equals a breakpoint, break */
  373.             if (PC == brkpt[i])
  374.                 {
  375.                 printf("break point at %04x", PC);
  376.                 windowLine();
  377.                 save_cursor();
  378.                 scrshow();
  379.                 restore_cursor();
  380.                 return (0);
  381.                 }
  382.         if (sstep) return (0);  /* if single stepping is on then stop running */
  383.  
  384.         OLD_PC = PC;    /* update the OLD_PC */
  385.         }
  386.  
  387. }
  388.  
  389.  
  390.  
  391.  
  392. /**************************** int exec_inst() *****************************
  393.  
  394.    name       : int exec_inst ()
  395.    parameters : NONE
  396.    function   : executes a single instruction at the location pointed 
  397.                   to by PC.  it is called from runprog() and sets the 
  398.                   flag "errflg" if an illegal opcode is detected so 
  399.                   that runprog() terminates.  exec_inst() also takes
  400.                   care of handling the different kinds of exceptions 
  401.                   that may occur.  If an instruction returns a different
  402.                   return code than "SUCCESS" then the appropriate
  403.                   exception is initiated, unless the "exceptions" flag
  404.                   is turned off by the user in which case the exception
  405.                   is not initiated and the program simply terminates and
  406.                   informs the user that an exception condition has occurred.
  407.  
  408.  
  409. ****************************************************************************/
  410.  
  411.  
  412. int exec_inst()
  413. {
  414. int    start, finish, exec_result, i;
  415.  
  416. if ( !(mem_request (&PC, (long) WORD, &inst)) )
  417.    {
  418.     start = offsets[(inst & FIRST_FOUR) >> 12];
  419.     finish = offsets[((inst & FIRST_FOUR) >> 12) + 1] - 1;
  420.     errflg = TRUE;
  421.  
  422.     if ((inst & 0xF000) == 0xA000)    /* unimplemented instruction */
  423.         {
  424.         errflg = FALSE;
  425.         mem_req (0x28, LONG, &PC);
  426.         printf ("'Line A' unimplemented instruction found at location %4x",
  427.             OLD_PC);
  428.         windowLine();
  429.         }
  430.     else
  431.     if ((inst & 0xF000) == 0xF000)    /* unimplemented instruction */
  432.         {
  433.         errflg = FALSE;
  434.         mem_req (0x2C, LONG, &PC);
  435.         printf ("'Line F' unimplemented instruction found at location %4x",
  436.             OLD_PC);
  437.         windowLine();
  438.         }
  439.     else
  440.     for (i = start; i <= finish; i++)
  441.         {
  442.         if ((inst & ~inst_arr[i].mask) == inst_arr[i].val)
  443.             {
  444.             if (trace) {
  445.                 printf ("executing a %s instruction at location %4x",
  446.                     inst_arr[i].name, PC-2);
  447.                 windowLine();
  448.                 }
  449.  
  450.             exec_result = (*(names[i]))();
  451.  
  452.     if (exceptions)
  453.     {
  454.             switch (exec_result)
  455.                 {
  456.                 case SUCCESS  : break;
  457.                 case BAD_INST : inc_cyc (34);    /* load the PC from the illegal */
  458.                                      exception (1, 0, READ);
  459.                                      mem_req (0x10, LONG, &PC);        /* vector */
  460.     printf ("Illegal instruction found at location %4x", OLD_PC);
  461.                                     windowLine();
  462.                                   break;
  463.                 case NO_PRIVILEGE : inc_cyc (34);
  464.                                      exception (1, 0, READ);
  465.                                      mem_req (0x20, LONG, &PC);
  466.     printf ("supervisor privilege violation at location %4x", OLD_PC);
  467.                                     windowLine();
  468.                                   break;
  469.                 case CHK_EXCEPTION : inc_cyc (40);
  470.                                      exception (2, 0, READ);
  471.                                      mem_req (0x18, LONG, &PC);
  472.                                   break;
  473.                 case ILLEGAL_TRAP : inc_cyc (34);
  474.                                      exception (1, 0, READ);
  475.                                      mem_req (0x10, LONG, &PC);
  476.                                   break;
  477.                 case STOP_TRAP : sstep = TRUE;    /* break out of the program */
  478.                                      break;
  479.                 case TRAP_TRAP : inc_cyc (34);
  480.                                      exception (2, 0, READ);
  481.                                      mem_req (128 + (inst & 0x0f) * 4, LONG, &PC);
  482.                                   break;
  483.                 case TRAPV_TRAP : inc_cyc (34);
  484.                                      exception (2, 0, READ);
  485.                                      mem_req (0x1c, LONG, &PC);
  486.                                   break;
  487.                 case DIV_BY_ZERO : inc_cyc (38);
  488.                                      exception (2, 0, READ);
  489.                                      mem_req (0x14, LONG, &PC);
  490.                                   break;
  491.                 }
  492.  
  493.             if (SR & tbit)   /* initiate a trace exception */
  494.                 {
  495.                 inc_cyc (34);
  496.                 exception (1, 0, READ);
  497.                 mem_req (0x24, LONG, &PC);
  498.                 }
  499.     }
  500.     else
  501.     {
  502.             switch (exec_result)
  503.                 {
  504.                 case SUCCESS  : break;
  505.                 case BAD_INST : sstep = TRUE;    /* break out of the program */
  506.     printf ("Illegal instruction found at location %4x. Execution halted", OLD_PC);
  507.                                     windowLine();
  508.                                   break;
  509.                 case NO_PRIVILEGE : sstep = TRUE;    /* break out of the program */
  510.     printf ("supervisor privilege violation at location %4x. Execution halted", OLD_PC);
  511.                                     windowLine();
  512.                                   break;
  513.                 case CHK_EXCEPTION : sstep = TRUE;    /* break out of the program */
  514.     printf ("CHK exception occurred at location %4x. Execution halted", OLD_PC);
  515.                                     windowLine();
  516.                                   break;
  517.                 case ILLEGAL_TRAP : sstep = TRUE;    /* break out of the program */
  518.     printf ("Illegal instruction found at location %4x. Execution halted", OLD_PC);
  519.                                     windowLine();
  520.                                   break;
  521.                 case STOP_TRAP : sstep = TRUE;    /* break out of the program */
  522.     printf ("STOP instruction executed at location %4x. Execution halted", OLD_PC);
  523.                                     windowLine();
  524.                                      break;
  525.                 case TRAP_TRAP : sstep = TRUE;    /* break out of the program */
  526.     printf ("TRAP exception occurred at location %4x. Execution halted", OLD_PC);
  527.                                     windowLine();
  528.                                   break;
  529.                 case TRAPV_TRAP : sstep = TRUE;    /* break out of the program */
  530.     printf ("TRAPV exception occurred at location %4x. Execution halted", OLD_PC);
  531.                                     windowLine();
  532.                                   break;
  533.                 case DIV_BY_ZERO : sstep = TRUE;    /* break out of the program */
  534.     printf ("Divide by zero occurred at location %4x. Execution halted", OLD_PC);
  535.                                     windowLine();
  536.                                   break;
  537.                 }
  538.  
  539.     if (SR & tbit)
  540.         {
  541.         sstep = TRUE;    /* break out of the program */
  542.         printf ("TRACE exception occurred at location %4x. Execution halted", OLD_PC);
  543.         windowLine();
  544.         }
  545.     }
  546.             errflg = FALSE;
  547.             break;
  548.             }
  549.         }
  550.  
  551. }
  552.  
  553. }
  554.  
  555.  
  556.  
  557.  
  558.  
  559. /**************************** int exception () *****************************
  560.  
  561.    name       : int exception (class, loc, r_w)
  562.    parameters : int class : class of exception to be taken
  563.                 long loc : the address referenced in the case of an
  564.                   address or bus error
  565.                 int r_w : in the case of an address or bus error, this
  566.                   tells whether the reference was a read or write 
  567.    function   : initiates exception processing by pushing the appropriate
  568.                   exception stack frame on the system stack and turning 
  569.                   supervisor mode on and trace mode off.
  570.  
  571.  
  572. ****************************************************************************/
  573.  
  574. int    exception(class, loc, r_w)
  575. int    class;
  576. long    loc;
  577. int    r_w;
  578. {
  579.     int    info_word;
  580.  
  581.     if ( (class == 1) || (class == 2))
  582.         {
  583.         A[8] -= 4;        /* create the stack frame for class 1 and 2 exceptions */
  584.         put (&memory[A[8]], OLD_PC, LONG);
  585.         A[8] -= 2;
  586.         put (&memory[A[8]], (long) SR, (long) WORD);
  587.         }
  588.     else
  589.         {                        /* class 0 exception (address or bus error) */
  590.         inc_cyc (50);    /* fifty clock cycles for the address or bus exception */
  591.         A[8] -= 4;                        /* now create the exception stack frame */
  592.         put (&memory[A[8]], OLD_PC, LONG);
  593.         A[8] -= 2;
  594.         put (&memory[A[8]], (long) SR, (long) WORD);
  595.         A[8] -= 2;
  596.         put (&memory[A[8]], (long) inst, (long) WORD);
  597.         A[8] -= 4;
  598.         put (&memory[A[8]], loc, LONG);
  599.         A[8] -= 2;
  600.         info_word = 0x6;
  601.         if (r_w == READ)
  602.             info_word |= 0x10;
  603.         put (&memory[A[8]], (long)0x0016, (long) WORD);/* push information word */
  604.         }
  605.     SR = SR | sbit;            /* force processor into supervisor state */
  606.     SR = SR & ~tbit;            /* turn off trace mode */
  607.  
  608. }
  609.  
  610.  
  611.