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

  1.  
  2. /***************************** 68000 SIMULATOR ****************************
  3.  
  4. File Name: UTILS.C
  5. Version: 1.0
  6.  
  7. This file contains various routines to aid in executing a 68000 instruction
  8.  
  9. The routines are :  
  10.  
  11.    to_2s_comp, from_2s_comp, sign_extend, inc_cyc, eff_addr_code, 
  12.    a_reg, mem_put, mem_req, mem_request, put, value_of, cc_update, 
  13.    and check_condition.
  14.  
  15. ***************************************************************************/
  16.  
  17.  
  18.  
  19. #include <stdio.h>
  20. #include "extern.h"         /* contains global declarations */
  21.  
  22.  
  23.  
  24. /**************************** int to_2s_comp () ****************************
  25.  
  26.    name       : int to_2s_comp (number, size, result)
  27.    parameters : long number : the number to be converted to 2's compliment
  28.                 long size : the size of the operation
  29.                 long *result : the result of the conversion
  30.    function   : to_2s_comp() converts a number to 2's compliment notation.
  31.  
  32.  
  33. ****************************************************************************/
  34.  
  35. int    to_2s_comp (number, size, result)
  36. long    number, size, *result;
  37. {
  38.  
  39. if (size == LONG)
  40.     {
  41.     if (number < 0)
  42.         *result = ~number - 1;
  43.     else
  44.         *result = number;
  45.     }
  46. if (size == WORD)
  47.     {
  48.     if (number < 0)
  49.         *result = (~(number & WORD) & WORD) - 1;
  50.     else
  51.         *result = number;
  52.     }
  53. if (size == BYTE)
  54.     {
  55.     if (number < 0)
  56.         *result = (~(number & BYTE) & BYTE) - 1;
  57.     else
  58.         *result = number;
  59.     }
  60.  
  61. return SUCCESS;
  62.  
  63. }
  64.  
  65.  
  66.  
  67.  
  68. /**************************** int from_2s_comp () **************************
  69.  
  70.    name       : int from_2s_comp (number, size, result)
  71.    parameters : long number : the number to be converted to 2's compliment
  72.                 long size : the size of the operation
  73.                 long *result : the result of the conversion
  74.    function   : from_2s_comp() converts a number from 2's compliment 
  75.                   notation to the "C" language format so that operations
  76.                   may be performed on it.
  77.  
  78.  
  79. ****************************************************************************/
  80.  
  81.  
  82. int    from_2s_comp (number, size, result)
  83. long    number, size, *result;
  84. {
  85.  
  86. if (size == LONG)
  87.     {
  88.     if (number & 0x80000000)
  89.         {
  90.         *result = ~number + 1;
  91.         *result = -*result;
  92.         }
  93.     else
  94.         *result = number;
  95.     }
  96. if (size == WORD)
  97.     {
  98.     if (number & 0x8000)
  99.         {
  100.         *result = (~number + 1) & WORD;
  101.         *result = -*result;
  102.         }
  103.     else
  104.         *result = number;
  105.     }
  106. if (size == BYTE)
  107.     {
  108.     if (number & 0x80)
  109.         {
  110.         *result = (~number + 1) & BYTE;
  111.         *result = -*result;
  112.         }
  113.     else
  114.         *result = number;
  115.     }
  116.  
  117. return SUCCESS;
  118.  
  119. }
  120.  
  121.  
  122.  
  123. /**************************** int sign_extend () ***************************
  124.  
  125.    name       : int sign_extend (number, size_from, result)
  126.    parameters : int number : the number to sign extended
  127.                 long size_from : the size of the source
  128.                 long *result : the result of the sign extension
  129.    function   : sign_extend() sign-extends a number from byte to word or
  130.                   from word to long.
  131.  
  132.  
  133. ****************************************************************************/
  134.  
  135. int    sign_extend (number, size_from, result)
  136. int    number;
  137. long    size_from;
  138. long    *result;
  139. {
  140.  
  141.     *result = number & size_from;
  142.     if ((size_from == WORD) && (number & 0x8000))
  143.         *result |= 0xffff0000;
  144.     if ((size_from == BYTE) && (number & 0x80))
  145.         *result |= 0xff00;
  146.  
  147.     return SUCCESS;
  148.  
  149. }
  150.  
  151.  
  152.  
  153.  
  154. /**************************** int inc_cyc () *******************************
  155.  
  156.    name       : int inc_cyc (num)
  157.    parameters : int num : number of cycles to increment the cycle counter.
  158.    function   : inc_cyc() increments the machine cycle counter by 'num'.
  159.  
  160.  
  161. ****************************************************************************/
  162.  
  163. int inc_cyc (num)
  164. int    num;
  165. {
  166.  
  167.    cycles = cycles + num;
  168.  
  169. }
  170.  
  171.  
  172.  
  173. /**************************** int eff_addr_code () *************************
  174.  
  175.    name       : int eff_addr_code (inst, start)
  176.    parameters : int inst : the instruction word
  177.                 int start : the start bit of the effective address field
  178.    function   : returns the number of the addressing mode contained in 
  179.                   the effective address field of the instruction.  This
  180.                   number is used in calculating the execution time for 
  181.                   many functions.
  182.  
  183.  
  184. ****************************************************************************/
  185.  
  186. int    eff_addr_code (inst, start)
  187. int    inst;
  188. int    start;
  189. {
  190.     int    mode, reg;
  191.  
  192.     inst = (inst >> start);
  193.     reg = inst & 0x07;
  194.     mode = (inst >> 3) & 0x07;
  195.  
  196.     if (mode != 7) return (mode);
  197.  
  198.     switch (reg) {
  199.         case 0x00 : return (7);
  200.                    break;
  201.         case 0x01 : return (8);
  202.                    break;
  203.         case 0x02 : return (9);
  204.                    break;
  205.         case 0x03 : return (10);
  206.                    break;
  207.         case 0x04 : return (11);
  208.                    break;
  209.         default   : return (12);
  210.                    break;
  211.         }
  212.  
  213.     return -1;
  214.  
  215. }
  216.  
  217.  
  218.  
  219.  
  220. /**************************** int a_reg () *********************************
  221.  
  222.    name       : int a_reg (reg_num)
  223.    parameters : int reg_num : the address register number to be processed
  224.    function   : a_reg() allows both the SSP and USP to act as A[7].  It
  225.                   returns the value '8' if the supervisor bit is set and
  226.                   the reg_num input was '7'.  Otherwise, it returns the
  227.                   reg_num without change.
  228.  
  229.  
  230. ****************************************************************************/
  231.  
  232. int    a_reg (reg_num)
  233. int    reg_num;
  234. {
  235.  
  236.     if ((reg_num == 7) && (SR & sbit))
  237.         return 8;
  238.     else
  239.         return reg_num;
  240.  
  241. }
  242.  
  243.  
  244.  
  245. /**************************** int mem_put() ********************************
  246.  
  247.    name       : int mem_put(data, loc, size)
  248.    parameters : long data : the data to be placed in memory
  249.                 int loc   : the location to place the data
  250.                 long size : the appropriate size mask for the operation
  251.    function   : mem_put() puts data in main memory.  It acts as the "memory
  252.                   management unit" in that it checks for out-of-bound
  253.                   virtual addresses and odd memory accesses on long and
  254.                   word operations and performs the appropriate traps in
  255.                   the cases where there is a violation.  Theoretically,
  256.                   this is the only place in the simulator where the main
  257.                   memory should be written to.
  258.  
  259. ****************************************************************************/
  260.  
  261. int    mem_put (data, loc, size)
  262. long    data;
  263. int    loc;
  264. long    size;
  265. {
  266.  
  267. /* check for odd location reference on word and longword writes */
  268. /* if there is a violation, initiate an address exception */
  269. if ((loc % 2 != 0) && (size != BYTE))       
  270.     {
  271.     /* generate an address error */
  272.     printf ("Address exception at location %4x", OLD_PC);
  273.     windowLine();
  274.     printf ("  was writing to location %4x", loc);
  275.     windowLine();
  276.     mem_req (0xc, LONG, &PC);
  277.     exception (0, (long) loc, WRITE);
  278.     return (FAILURE);
  279.     }
  280.  
  281. /* check for virtual-address out-of-bounds condition.  If there is a */
  282. /* violation, initiate a bus error */
  283. if ((loc < 0) || (loc > MEMSIZE))
  284.     {            /* generate a bus error */
  285.     printf ("Bus Error: Address out of virtual memory space ");
  286.     printf ("at location %4x", OLD_PC);
  287.     windowLine();
  288.     printf ("  was writing to location %4x", loc);
  289.     windowLine();
  290.     mem_req (0x8, LONG, &PC);
  291.     exception (0, (long) loc, WRITE);
  292.     return (FAILURE);
  293.     }
  294.  
  295. /* if everything is okay then perform the write according to size */
  296. if (size == BYTE)
  297.     memory[loc] = data & BYTE;
  298. else if (size == WORD)
  299.     {
  300.     memory[loc] = (data >> 8) & BYTE;
  301.     memory[loc+1] = data & BYTE;
  302.     }
  303. else if (size == LONG)
  304.     {
  305.     memory[loc] = (data >> 24) & BYTE;
  306.     memory[loc+1] = (data >> 16) & BYTE;
  307.     memory[loc+2] = (data >> 8) & BYTE;
  308.     memory[loc+3] = data & BYTE;
  309.     }
  310.  
  311. return SUCCESS;
  312.  
  313. }
  314.  
  315.  
  316.  
  317.  
  318. /**************************** int mem_req() ********************************
  319.  
  320.    name       : int mem_req(loc, size, result)
  321.    parameters : int loc : the memory location to read data from
  322.                 long size : the appropriate size mask for the operation
  323.                 long *result : a pointer to the longword location  
  324.                       to store the result in
  325.    function   : mem_req() returns the contents of a location in main 
  326.                   memory.  It acts as the "memory management unit" in 
  327.                   that it checks for out-of-bound virtual addresses and 
  328.                   odd memory accesses on long and word operations and 
  329.                   performs the appropriate traps in the cases where there 
  330.                   is a violation.  Theoretically, this is the only function
  331.                   in the simulator where the main memory should be read
  332.                   from.
  333.  
  334. ****************************************************************************/
  335.  
  336. int    mem_req (loc, size, result)
  337. int    loc;
  338. long    size;
  339. long    *result;
  340. {
  341. long    temp;
  342.  
  343. /* check for odd location reference on word and longword reads. */
  344. /* If there is a violation, initiate an address exception */
  345. if ((loc % 2 != 0) && (size != BYTE))
  346.     {
  347.     /* generate an address error */
  348.     errflg = FALSE;
  349.     printf ("Address exception at location %4x", OLD_PC);
  350.     windowLine();
  351.     printf ("  was reading from location %4x", loc);
  352.     windowLine();
  353.     mem_req (0xc, LONG, &PC);
  354.     exception (0, (long) loc, READ);
  355.     return (FAILURE);
  356.     }
  357.  
  358. /* check for virtual-address out-of-bounds condition.  If there is a */
  359. /* violation, initiate a bus error */
  360. if ((loc < 0) || (loc > MEMSIZE))
  361.     {
  362.     /* generate a bus error */
  363.     errflg = FALSE;
  364.     printf ("Bus Error: Address out of virtual memory space ");
  365.     printf ("at location %4x", OLD_PC);
  366.     windowLine();
  367.     printf ("  was reading from location %4x", loc);
  368.     windowLine();
  369.     mem_req (0x8, LONG, &PC);
  370.     exception (0, (long) loc, READ);
  371.     return (FAILURE);
  372.     }
  373.  
  374. /* if everything is okay then perform the read according to size */
  375. temp = memory[loc] & BYTE;
  376. if (size != BYTE)
  377.     {
  378.     temp = (temp << 8) | (memory[loc + 1] & BYTE);
  379.     if (size != WORD)
  380.         {
  381.         temp = (temp << 8) | (memory[loc + 2] & BYTE);
  382.         temp = (temp << 8) | (memory[loc + 3] & BYTE);
  383.         }
  384.     }
  385. *result = temp;
  386.  
  387. return SUCCESS;
  388.  
  389. }
  390.  
  391.  
  392.  
  393.  
  394. /**************************** int mem_request() ****************************
  395.  
  396.    name       : int mem_request (loc, size, result)
  397.    parameters : int *loc : the memory location to read data from
  398.                 long size : the appropriate size mask for the operation
  399.                 long *result : a pointer to the longword location  
  400.                       to store the result in
  401.    function   : mem_request() is another "level" of main-memory access.
  402.                   It performs the task of calling the functin mem_req()
  403.                   (above) using "WORD" for the size mask if the simulator
  404.                   wants a byte from main memory.  Also, it increments
  405.                   the location pointer passed to it.  This is to 
  406.                   facilitate easy opcode and operand fetch operations
  407.                   where the program counter needs to be incremented.
  408.  
  409.                   Therefore, in the simulator, "mem_req()" requests data
  410.                   from main memory, and "mem_request()" does the same but
  411.                   also increments the location pointer.  Note that 
  412.                   mem_request() requires a pointer to an int as the first
  413.                   parameter.
  414.  
  415. ****************************************************************************/
  416.  
  417. int    mem_request (loc, size, result)
  418. int    *loc;
  419. long    size;
  420. long    *result;
  421. {
  422.     int    req_result;
  423.  
  424.     if (size == LONG)
  425.         req_result = mem_req (*loc, LONG, result);
  426.     else
  427.         req_result = mem_req (*loc, (long) WORD, result);
  428.  
  429.     if (size == BYTE)
  430.         *result = *result & 0xff;
  431.  
  432.     if (!req_result)
  433.         if (size == LONG)
  434.             *loc += 4;
  435.         else
  436.             *loc += 2;
  437.  
  438.     return req_result;
  439.  
  440. }
  441.  
  442.  
  443.  
  444.  
  445. /**************************** int put() ************************************
  446.  
  447.    name       : int put (dest, source, size)
  448.    parameters : long *dest : the destination to move data to
  449.                 long source : the data to move
  450.                 long size : the appropriate size mask for the operation
  451.    function   : put() performs the task of putting the result of some
  452.                   operation into a destination location "according to 
  453.                   size".  This means that the bits of the destination
  454.                   that are in excess to the size of the operation are not
  455.                   affected.  This function provides a general-purpose
  456.                   mechanism for putting the result of an operation in 
  457.                   the destination, no matter whether the destination is
  458.                   a memory location or a 68000 register.  The data is
  459.                   placed in the destination correctly and the rest of
  460.                   the bits in a register are left alone.
  461.  
  462. ****************************************************************************/
  463.  
  464. int    put (dest, source, size)
  465. long    *dest, source, size;
  466.  
  467. {
  468.  
  469.     if (( (int)dest >= (int)&memory[0]) &&
  470.             ((int)dest <= (int)&memory[MEMSIZE]))
  471.         mem_put (source, (int) ((int)dest - (int)&memory[0]), size);
  472.     else
  473.         *dest = (source & size) | (*dest & ~size);
  474.  
  475. }
  476.  
  477.  
  478.  
  479.  
  480. /**************************** int value_of() *******************************
  481.  
  482.    name       : int value_of (EA, EV, size)
  483.    parameters : long *EA : the location of the data to be evaluated
  484.                 long *EV : the location of the result
  485.                 long size : the appropriate size mask
  486.    function   : value_of() returns the value of the location referenced
  487.                   regardless of whether it is a virtual memory location
  488.                   or a 68000 register location.  The "C" language stores
  489.                   the bytes in an integer in the reverse-order that we 
  490.                   store the bytes in virtual memory, so this function
  491.                   provides a general way of finding the value at a 
  492.                   location.
  493.  
  494. ****************************************************************************/
  495.  
  496.  
  497. int    value_of (EA, EV, size)
  498. long    *EA, *EV, size;
  499. {
  500.  
  501.     if (((int)EA < (int)&memory[0]) || ((int)EA > (int)&memory[MEMSIZE]))
  502.         *EV = *EA & size;
  503.     else
  504.         mem_req ( (int) ((int)EA - (int)&memory[0]), size, EV);
  505.  
  506. }
  507.  
  508.  
  509.  
  510.  
  511. /**************************** int cc_update() *****************************
  512.  
  513.    name       : int cc_update (x, n, z, v, c, source, dest, result, size, r)
  514.    parameters : int x, n, z, v, c : the codes for actions that should be
  515.                     taken to compute the different condition codes.
  516.                 long source : the source operand for the instruction
  517.                 long dest : the destination operand for the instruction
  518.                 long result : the result of the instruction
  519.                 long size : the size of the instruction
  520.                 int r : the shift count for shift and rotate instructions
  521.    function   : updates the five condition codes according to the codes
  522.                   passed as parameters.  each of the condition codes
  523.                   has a number of ways it can be calculated, and the 
  524.                   appropriate method of computation is passed as the 
  525.                   parameter for that condition code.  The source, dest, and
  526.                   result operands contain the source, destination, and
  527.                   result of the instruction requesting updating the 
  528.                   condition codes.  Also, for shift and rotate instructions
  529.                   the shift count needs to be passed.
  530.  
  531.                   The details of the different ways to calculate condition
  532.                   codes are contained in Appendix A of the 68000 
  533.                   Programmer's Reference Manual.
  534.  
  535. ****************************************************************************/
  536.  
  537.  
  538. int    cc_update (x, n, z, v, c, source, dest, result, size, r)
  539. int    x, n, z, v, c;
  540. long    source, dest, result;
  541. long    size;
  542. int    r;
  543. {
  544. int    x_bit, n_bit, z_bit, v_bit, c_bit;
  545. long    Rm, Dm, Sm;
  546. long    count, temp1, temp2, m;
  547.  
  548. /* assign the bits to their variables here */
  549. x_bit = SR & xbit;
  550. n_bit = SR & nbit;
  551. z_bit = SR & zbit;
  552. v_bit = SR & vbit;
  553. c_bit = SR & cbit;
  554.  
  555. source &= size;
  556. dest &= size;
  557. result &= size;
  558.  
  559. if (size == BYTE)
  560.             {
  561.             m = 7;
  562.            Sm = source & 0x0080;
  563.            Rm = result & 0x0080;
  564.            Dm = dest & 0x0080;
  565.             };
  566. if (size == WORD)
  567.             {
  568.             m = 15;
  569.            Sm = source & 0x8000;
  570.            Rm = result & 0x8000;
  571.            Dm = dest & 0x8000;
  572.             };
  573. if (size == LONG)
  574.             {
  575.             m = 31;
  576.            Sm = source & 0x80000000;
  577.            Rm = result & 0x80000000;
  578.            Dm = dest & 0x80000000;
  579.             };
  580.  
  581. /* calculate each of the five condition codes according to the requested */
  582. /* method of calculation */
  583. switch (n) {
  584.     case N_A : break;             /* n_bit not affected */
  585.     case GEN : n_bit = (Rm) ? TRUE : FALSE;
  586.            break;
  587.     case UND : n_bit = !n_bit;        /* undefined result */
  588.            break;
  589.     }
  590. switch (z) {
  591.     case N_A : break;            /* z_bit not affected */
  592.     case UND : z_bit = !z_bit;        /* z_bit undefined */
  593.            break;
  594.     case GEN : z_bit = (result == 0) ? TRUE : FALSE;
  595.            break;
  596.     case CASE_1 : z_bit = (z_bit && (result == 0)) ? TRUE : FALSE;
  597.           break;
  598.     };
  599. switch (v) {
  600.     case N_A : break;            /* v_bit not affected */
  601.     case ZER : v_bit = 0;
  602.            break;
  603.     case UND : v_bit = !v_bit;        /* v_bit not defined */
  604.            break;
  605.     case CASE_1 : v_bit = ((Sm && Dm && !Rm) || (!Sm && !Dm && Rm)) ? 
  606.             TRUE : FALSE;
  607.               break;
  608.     case CASE_2 : v_bit = ((!Sm && Dm && !Rm) || (Sm && !Dm && Rm)) ? 
  609.             TRUE : FALSE;
  610.               break;
  611.     case CASE_3 : v_bit = (Dm && Rm) ? TRUE : FALSE;
  612.               break;
  613.     };
  614. switch (c) {
  615.     case N_A : break;            /* c_bit not affected */
  616.     case UND : c_bit = !c_bit;            /* c_bit undefined  */
  617.            break;
  618.     case ZER : c_bit = 0;
  619.            break;
  620.     case CASE_1 : c_bit = x_bit;
  621.               break;
  622.     case CASE_2 : c_bit = ((dest >> (r-1)) & 1) ? TRUE : FALSE;
  623.               break;
  624.     case CASE_3 : c_bit = ((dest >> (m-r+1)) & 1) ? TRUE : FALSE;
  625.               break;
  626.     case CASE_4 : c_bit = (Dm || Rm) ? TRUE : FALSE;
  627.               break;
  628.     case CASE_5 : c_bit = ((Sm && Dm) || (!Rm && Dm) || (Sm && !Rm)) ? 
  629.             TRUE : FALSE;
  630.               break;
  631.     case CASE_6 : c_bit = ((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm)) ? 
  632.             TRUE : FALSE;
  633.               break;
  634.     };
  635. switch (x) {
  636.     case N_A : break;             /* X condition code not affected */
  637.     case GEN : x_bit = c_bit;        /* general case */
  638.            break;
  639.     };
  640.  
  641. /* set SR according to results */
  642. SR = SR & 0xffe0;                            /* clear the condition codes */
  643. if (x_bit) SR = SR | xbit;
  644. if (n_bit) SR = SR | nbit;
  645. if (z_bit) SR = SR | zbit;
  646. if (v_bit) SR = SR | vbit;
  647. if (c_bit) SR = SR | cbit;
  648.  
  649. return SUCCESS;
  650.  
  651. }
  652.  
  653.  
  654.  
  655.  
  656. /**************************** int check_condition() ************************
  657.  
  658.    name       : int check_condition (condition)
  659.    parameters : int condition : the condition to be checked
  660.    function   : check_condition() checks for the truth of a certain 
  661.                   condition and returns the result.  The possible conditions
  662.                   are encoded in DEF.H and can be seen in the switch()
  663.                   statement below.
  664.  
  665. ****************************************************************************/
  666.  
  667.  
  668. int    check_condition (condition)
  669. int    condition;
  670. {
  671. int    result;
  672.  
  673. result = FALSE;
  674. switch (condition)
  675.     {
  676.     case T : result = 1;                /* true */
  677.            break;
  678.     case F : result = 0;                /* false */
  679.            break;
  680.     case HI : result = !(SR & cbit) && !(SR && zbit);    /* high */
  681.            break;
  682.     case LS : result = (SR & cbit) || (SR & zbit);    /* low or same */
  683.            break;
  684.     case CC : result = !(SR & cbit);        /* carry clear */
  685.            break;
  686.     case CS : result = (SR & cbit);        /* carry set */
  687.            break;
  688.     case NE : result = !(SR & zbit);        /* not equal */
  689.            break;
  690.     case EQ : result = (SR & zbit);        /* equal */
  691.            break;
  692.     case VC : result = !(SR & vbit);        /* overflow clear */
  693.            break;
  694.     case VS : result = (SR & cbit);        /* overflow set */
  695.            break;
  696.     case PL : result = !(SR & nbit);        /* plus */
  697.            break;
  698.     case MI : result = (SR & nbit);                /* minus */
  699.            break;
  700.     case GE : result = ((SR & nbit) && (SR & vbit)) ||
  701.           (!(SR & nbit) && !(SR & vbit));          /* greater or equal */  
  702.            break;
  703.     case LT : result = ((SR & nbit) && !(SR & vbit))    /* less than */
  704.           || (!(SR & nbit) && (SR & vbit));
  705.            break;
  706.     case GT : result = ((SR & nbit) && (SR & vbit) && !(SR & zbit)) 
  707.           || (!(SR & nbit) && !(SR & vbit) && (SR & zbit)); /* greater than */
  708.            break;
  709.     case LE : result = ((SR & nbit) && !(SR & vbit))    /* less or equal */
  710.           || (!(SR & nbit) && (SR & vbit)) || (SR & zbit);
  711.             break;
  712.     }
  713. return result;
  714.  
  715. }
  716.  
  717.  
  718.