home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / 9900st.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  7.4 KB  |  458 lines

  1.  
  2. /*
  3.     Status word functions
  4.  
  5. */
  6.  
  7. #include "centry.h"
  8.  
  9. extern s16 lastcmp, lastval;
  10.  
  11. extern u8 st_o, st_c, st_p;
  12.  
  13. /************************************************************************/
  14.  
  15. u16 statusto9900(void);
  16. void T9900tostatus(u16 stat);
  17.  
  18. #ifdef __9900__
  19.  
  20. /*
  21.     Set lae, preserve C and O
  22. */
  23. s16 INLINE setst_lae(s16 val)
  24. {
  25.     lastcmp=0;
  26.     lastval=val;
  27.     return val;
  28. }
  29.  
  30.  
  31. /*
  32.     Set lae, preserve C and O (BYTE)
  33. */
  34. s8 INLINE setst_byte_laep(s8 val)
  35. {
  36. #if defined(GNU_X86_ASM) || defined(FAST_X86_STATUS)
  37.  
  38.     status &= ~ST_P;
  39.     asm(
  40.         "\t or %0,%0\n"
  41.         "\t jpe 1f\n"
  42.         "\t    orb $0x4,status+1\n"
  43.         "\t1:\n"
  44.         : 
  45.         : "r" (val)
  46.     );
  47.     
  48.     lastval=val;
  49.     lastcmp=0;
  50.     return val;
  51.  
  52. #else
  53.  
  54.   #if 0
  55.     /*
  56.         Parity checking using XOR.  
  57.         Logic:  0^0 == 0 (even # one bits) 
  58.                 1^1 == 0 (even # one bits) 
  59.                 1^0 == 1
  60.                 0^1 == 1 (odd # one bits) 
  61.         Just XOR the bits over each other until
  62.         we have one bit representing the parity.
  63.     */
  64.     u8 a,b,c;
  65.  
  66.     a = ((val & 0xaa) >> 1) ^ (val & 0x55);
  67.     /* a = 0?0?0?0? */
  68.     b = ((a & 0x44) >> 2) ^ (a & 0x11);
  69.     /* b = 000?000? */
  70.     c = ((b & 0x20) >> 4) ^ (a & 0x2);
  71.     /* c = 0000000? */
  72.  
  73.   #elif 0
  74.     /*  Perhaps we don't need all the ands if we shift it all to the end. */
  75.     u8 a,b,c;
  76.     
  77.     a = (val >> 4) ^ val;
  78.     b = (a >> 2) ^ a;
  79.     c = (b >> 1) ^ b;
  80.     c &= 1;
  81.  
  82.   #elif 0
  83.     /* halve the work.  it's easy to set up an array of parity bits for
  84.         the nybbles 0 through 15. */
  85.     static u8 parity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
  86.     u8 c;
  87.     
  88.     c = (parity[(val & 0xf)] ^ parity[(val >> 4)]) & 1;
  89.  
  90.   #elif 1
  91.  
  92.     /* notice the bitmap formed by the parity[] array above == 0x6996 */    
  93.     u8 c;
  94.     
  95.     /*  uhoh -- this is functionally equivalent to a "copyrighted" 
  96.         algorithm by Tom Brouwer in ti4linux, but I derived it myself. */
  97.         
  98.     #define PARITY(b) \
  99.         (( (0x6996 >> ((b) & 0xf) ) ^ \
  100.         (0x6996 >> (((b) >> 4) & 0xf) )) & 1)
  101.         
  102.     c  = PARITY(val);
  103.         
  104.   #endif
  105.  
  106.   #if defined(GNU_X86_ASM) || defined(FAST_X86_STATUS)
  107.     if (c)
  108.         status |= ST_P;        /* odd parity */
  109.     else
  110.         status &= ~ST_P;
  111.   #else
  112.       st_p = c;
  113.   #endif
  114.  
  115.     lastval=val;
  116.     lastcmp=0;
  117.     
  118.     return val;
  119.  
  120. #endif
  121. }
  122.  
  123. /*
  124.     For COC, CZC, and TB
  125. */
  126. void INLINE setst_e(u16 val,u16 to)
  127. {
  128.     if (val==to){ lastcmp=lastval=0; }
  129.     else        { if (lastcmp==lastval) lastval++; }
  130. }
  131.  
  132.  
  133. #if defined(FAST_X86_STATUS)
  134.  
  135. #define I86_CF 1
  136. #define I86_OF (1<<11)
  137. #define I86_PF (1<<2)
  138.  
  139. u8 i86_to_9900[I86_OF+I86_CF+I86_PF+1];
  140.  
  141. /*    One-time setup of i86_to_9900 array.
  142.     For each entry corresponding to some combination of bits set 
  143.     in the x86 status flag,    we set the corresponding entry to
  144.     the 9900 status flag value. */
  145.  
  146. void setup_status(void)
  147. {
  148.     int    i;
  149.  
  150.     memset(i86_to_9900,0x00,sizeof(i86_to_9900));
  151.     for (i=0; i<sizeof(i86_to_9900); i++)
  152.     {
  153.         if (i&I86_CF)
  154.             i86_to_9900[i]|=0x10;
  155.         if (i&I86_OF)
  156.             i86_to_9900[i]|=0x8;
  157.         if (!(i&I86_PF))
  158.             i86_to_9900[i]|=0x4;
  159.     }
  160. }
  161.  
  162. #endif
  163.  
  164. /*
  165.     Set laeco for add, preserve none
  166. */
  167. u16 INLINE setst_add_laeco(u16 dst,u16 src)
  168. {
  169. #if !defined(GNU_X86_ASM) && !defined(FAST_X86_STATUS)
  170.  
  171.     u16 res = dst + src;
  172.     
  173.     st_c = (((dst & src) & 0x8000) || 
  174.         (((dst & 0x8000) ^ (src & 0x8000)) && !(res & 0x8000))) != 0;
  175.         
  176.     st_o = (((~dst & ~src & res) | (dst & src & ~res)) & 0x8000) != 0;
  177.  
  178. #elif !defined(FAST_X86_STATUS)
  179.  
  180.     register u16 res=dst;
  181.  
  182.     status&=~(ST_C|ST_O);
  183.     asm(
  184.         "\t addw %1,%0\n"
  185.         "\t pushf\n"
  186.         "\t jno 1f\n"
  187.         "\t orb $0x8,status+1\n"
  188.         "\t1: popf\n"
  189.         "\t jnc 2f\n"
  190.         "\t orb $0x10,status+1\n"
  191.         "\t2:\n"
  192.         : "=r" (res)
  193.         : "g" (src), "0" (dst)
  194.         );
  195.  
  196. #else    // FAST_X86_STATUS
  197.  
  198.     register u16 res=dst;
  199.     register u32 flags;
  200.     register u8 tmp;
  201.  
  202.     status&=~(ST_C|ST_O);
  203.     asm(
  204.         "\t addw %1,%0\n"
  205.         "\t pushf\n"
  206.         "\t popl %3\n"
  207.         "\t andl $2049,%3\n"
  208.         "\t movb i86_to_9900(%3),%4\n"
  209.         "\t orb %4,status+1\n"
  210.         : "=r" (res)
  211.         : "g" (src), "0" (dst), "r" (flags), "r" (tmp)
  212.         );
  213. #endif
  214.  
  215.     lastval=res;
  216.     lastcmp=0;
  217.  
  218.     return res;
  219. }
  220.  
  221.  
  222. /*
  223.     Set laeco for subtract, preserve none
  224. */
  225. u16 INLINE setst_sub_laeco(u16 dst,u16 src)
  226. {
  227. #if !defined(GNU_X86_ASM) && !defined(FAST_X86_STATUS)
  228.  
  229.     u16 res = setst_add_laeco(dst, 1+~src);
  230.     st_c |= (src==0 || src==0x8000);    // the inverse + increment ==> carry
  231.  
  232. #elif !defined(FAST_X86_STATUS)
  233.  
  234.     register u16 res=dst;
  235.  
  236.     status&=~(ST_C|ST_O);
  237.     asm(
  238.         "\t negw %0\n"
  239.         "\t jnz 3f\n"
  240.         "\t orb $0x10,status+1\n"
  241.         "3:\t addw %1,%0\n"
  242.         "\t pushf\n"
  243.         "\t jno 1f\n"
  244.         "\t orb $0x8,status+1\n"
  245.         "\t1: popf\n"
  246.         "\t jnc 2f\n"
  247.         "\t orb $0x10,status+1\n"
  248.         "\t2:\n"
  249.         
  250.         : "=r" (res)
  251.         : "g" (dst), "0" (src)
  252.     );
  253.  
  254.  
  255. #else    // FAST_X86_STATUS
  256.  
  257.     register u16 res=dst;
  258.     register u32 flags;
  259.     register u8 tmp;
  260.  
  261.     status&=~(ST_C|ST_O);
  262.     asm(
  263.         "\t negw %0\n"
  264.         "\t jnz 3f\n"
  265.         "\t orb $0x10,status+1\n"
  266.         "3:\t addw %1,%0\n"
  267.  
  268.         "\t pushf\n"
  269.         "\t popl %3\n"
  270.         "\t andl $2049,%3\n"
  271.         "\t movb i86_to_9900(%3),%4\n"
  272.         "\t orb %4,status+1\n"
  273.         
  274.         : "=r" (res)
  275.         : "g" (dst), "0" (src), "r" (flags), "r" (tmp)
  276.     );
  277. #endif
  278.  
  279.  
  280.     lastval=res;
  281.     lastcmp=0;
  282.  
  283.     return res;
  284. }
  285.  
  286.  
  287. /*
  288.     Set laeco for add, preserve none (BYTE)
  289. */
  290. s8 INLINE setst_addbyte_laecop(s8 dst,s8 src)
  291. {
  292. #if !defined(GNU_X86_ASM) && !defined(FAST_X86_STATUS)
  293.  
  294.     s8 res = dst + src;
  295.     
  296.     st_c = (((dst & src) & 0x80) || 
  297.         (((dst & 0x80) ^ (src & 0x80)) && !(res & 0x80))) != 0;
  298.         
  299.     st_o = (((~dst & ~src & res) | (dst & src & ~res)) & 0x80) != 0;
  300.         
  301.     st_p = (PARITY(res));
  302.         
  303. #elif !defined(FAST_X86_STATUS)
  304.  
  305.     register s8 res=dst;
  306.  
  307.     status&=~(ST_C|ST_O|ST_P);
  308.     asm(
  309.         "\t addb %1,%0\n"
  310.         
  311.         "\t pushf\n"
  312.         "\t jno 1f\n"
  313.         "\t orb $0x8,status+1\n"
  314.         "\t1: popf\n"
  315.         "\t pushf\n"
  316.         "\t jnc 2f\n"
  317.         "\t orb $0x10,status+1\n"
  318.         "\t2:\n"
  319.         "\t popf\n"
  320.         "\t jpe 3f\n"
  321.         "\t orb $0x4,status+1\n"
  322.         "\t3:\n"
  323.         
  324.         : "=r" (res)
  325.         : "g" (src), "0" (dst)
  326.     );
  327.  
  328. #else    // FAST_X86_STATUS
  329.  
  330.     register s8 res=dst;
  331.     register u32 flags;
  332.     register u8 tmp;
  333.  
  334.     status&=~(ST_C|ST_O|ST_P);
  335.     asm(
  336.         "\t addb %1,%0\n"
  337.         
  338.         "\t pushf\n"
  339.         "\t popl %3\n"
  340.         "\t andl $2053,%3\n"
  341.         "\t movb i86_to_9900(%3),%4\n"
  342.         "\t orb %4,status+1\n"
  343.                 
  344.         : "=r" (res)
  345.         : "g" (src), "0" (dst), "r" (flags), "r" (tmp)
  346.     );
  347.  
  348. #endif
  349.  
  350.     lastval=(s16)res;
  351.     lastcmp=0;
  352.     
  353.     return res;
  354. }
  355.  
  356.  
  357. /*
  358.     Set laeco for subtract, preserve none (BYTE)
  359. */
  360. s8 INLINE setst_subbyte_laecop(s8 dst,s8 src)
  361. {
  362. #if !defined(GNU_X86_ASM) && !defined(FAST_X86_STATUS)
  363.     
  364.     s8 res = setst_addbyte_laecop(dst, 1+~src);
  365.     st_c |= (src==0 || (u8)src==0x80);    // the inverse + increment ==> carry
  366.         
  367. #elif !defined(FAST_X86_STATUS)
  368.     register s8 res=dst;
  369.     register u32 flags;
  370.     register u8 tmp;
  371.  
  372.     status&=~(ST_C|ST_O|ST_P);
  373.     asm(
  374.         "\t negb %0\n"
  375.         "\t jnz 3f\n"
  376.         "\t orb $0x10,status+1\n"
  377.         "\t3:\t addb %1,%0\n"
  378.         "\t pushf\n"
  379.         "\t jno 1f\n"
  380.         "\t orb $0x8,status+1\n"
  381.         "\t1: popf\n"
  382.         "\t pushf\n"
  383.         "\t jnc 2f\n"
  384.         "\t orb $0x10,status+1\n"
  385.         "\t2:\n"
  386.         "\t popf\n"
  387.         "\t jpe 3f\n"
  388.         "\t orb $0x4,status+1\n"
  389.         "\t3:\n"
  390.  
  391.         : "=rb" (res)
  392.         : "g" (dst), "0" (src)
  393.     );
  394.  
  395.  
  396. #else    // FAST_X86_STATUS
  397.  
  398.     register s8 res=dst;
  399.     register u32 flags;
  400.     register u8 tmp;
  401.  
  402.     status&=~(ST_C|ST_O|ST_P);
  403.     asm(
  404.         "\t negb %0\n"
  405.         "\t jnz 3f\n"
  406.         "\t orb $0x10,status+1\n"
  407.         "3:\t addb %1,%0\n"
  408.         
  409.         "\t pushf\n"
  410.         "\t popl %3\n"
  411.         "\t andl $2053,%3\n"
  412.         "\t movb i86_to_9900(%3),%4\n"
  413.         "\t orb %4,status+1\n"
  414.  
  415.         : "=r" (res)
  416.         : "g" (dst), "0" (src), "r" (flags), "r" (tmp)
  417.     );
  418.  
  419. #endif
  420.  
  421.     lastval=(s16)res;
  422.     lastcmp=0;
  423.     
  424.     return res;
  425. }
  426.  
  427.  
  428. /*
  429.     For ABS
  430. */
  431. u16 INLINE setst_o(u16 val)
  432. {
  433. #if defined(GNU_X86_ASM) || defined(FAST_X86_STATUS)
  434.     status = (status & ~ST_O) | ((val == 0x8000) ? ST_O : 0);
  435. #else
  436.     st_o = (val==0x8000);
  437. #endif
  438.     return val;
  439. }
  440.  
  441.  
  442. /*
  443.     For NEG
  444. */
  445. u16 INLINE setst_laeo(u16 val)
  446. {
  447.     setst_o(val);
  448.     lastval=val;
  449.     lastcmp=0;
  450.     return val;
  451. }
  452.  
  453. #endif
  454.  
  455. /************************************************************************/
  456. #include "cexit.h"
  457.  
  458.