home *** CD-ROM | disk | FTP | other *** search
-
- /*
- Status word functions
-
- */
-
- #include "centry.h"
-
- extern s16 lastcmp, lastval;
-
- extern u8 st_o, st_c, st_p;
-
- /************************************************************************/
-
- u16 statusto9900(void);
- void T9900tostatus(u16 stat);
-
- #ifdef __9900__
-
- /*
- Set lae, preserve C and O
- */
- s16 INLINE setst_lae(s16 val)
- {
- lastcmp=0;
- lastval=val;
- return val;
- }
-
-
- /*
- Set lae, preserve C and O (BYTE)
- */
- s8 INLINE setst_byte_laep(s8 val)
- {
- #if defined(GNU_X86_ASM) || defined(FAST_X86_STATUS)
-
- status &= ~ST_P;
- asm(
- "\t or %0,%0\n"
- "\t jpe 1f\n"
- "\t orb $0x4,status+1\n"
- "\t1:\n"
- :
- : "r" (val)
- );
-
- lastval=val;
- lastcmp=0;
- return val;
-
- #else
-
- #if 0
- /*
- Parity checking using XOR.
- Logic: 0^0 == 0 (even # one bits)
- 1^1 == 0 (even # one bits)
- 1^0 == 1
- 0^1 == 1 (odd # one bits)
- Just XOR the bits over each other until
- we have one bit representing the parity.
- */
- u8 a,b,c;
-
- a = ((val & 0xaa) >> 1) ^ (val & 0x55);
- /* a = 0?0?0?0? */
- b = ((a & 0x44) >> 2) ^ (a & 0x11);
- /* b = 000?000? */
- c = ((b & 0x20) >> 4) ^ (a & 0x2);
- /* c = 0000000? */
-
- #elif 0
- /* Perhaps we don't need all the ands if we shift it all to the end. */
- u8 a,b,c;
-
- a = (val >> 4) ^ val;
- b = (a >> 2) ^ a;
- c = (b >> 1) ^ b;
- c &= 1;
-
- #elif 0
- /* halve the work. it's easy to set up an array of parity bits for
- the nybbles 0 through 15. */
- static u8 parity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
- u8 c;
-
- c = (parity[(val & 0xf)] ^ parity[(val >> 4)]) & 1;
-
- #elif 1
-
- /* notice the bitmap formed by the parity[] array above == 0x6996 */
- u8 c;
-
- /* uhoh -- this is functionally equivalent to a "copyrighted"
- algorithm by Tom Brouwer in ti4linux, but I derived it myself. */
-
- #define PARITY(b) \
- (( (0x6996 >> ((b) & 0xf) ) ^ \
- (0x6996 >> (((b) >> 4) & 0xf) )) & 1)
-
- c = PARITY(val);
-
- #endif
-
- #if defined(GNU_X86_ASM) || defined(FAST_X86_STATUS)
- if (c)
- status |= ST_P; /* odd parity */
- else
- status &= ~ST_P;
- #else
- st_p = c;
- #endif
-
- lastval=val;
- lastcmp=0;
-
- return val;
-
- #endif
- }
-
- /*
- For COC, CZC, and TB
- */
- void INLINE setst_e(u16 val,u16 to)
- {
- if (val==to){ lastcmp=lastval=0; }
- else { if (lastcmp==lastval) lastval++; }
- }
-
-
- #if defined(FAST_X86_STATUS)
-
- #define I86_CF 1
- #define I86_OF (1<<11)
- #define I86_PF (1<<2)
-
- u8 i86_to_9900[I86_OF+I86_CF+I86_PF+1];
-
- /* One-time setup of i86_to_9900 array.
- For each entry corresponding to some combination of bits set
- in the x86 status flag, we set the corresponding entry to
- the 9900 status flag value. */
-
- void setup_status(void)
- {
- int i;
-
- memset(i86_to_9900,0x00,sizeof(i86_to_9900));
- for (i=0; i<sizeof(i86_to_9900); i++)
- {
- if (i&I86_CF)
- i86_to_9900[i]|=0x10;
- if (i&I86_OF)
- i86_to_9900[i]|=0x8;
- if (!(i&I86_PF))
- i86_to_9900[i]|=0x4;
- }
- }
-
- #endif
-
- /*
- Set laeco for add, preserve none
- */
- u16 INLINE setst_add_laeco(u16 dst,u16 src)
- {
- #if !defined(GNU_X86_ASM) && !defined(FAST_X86_STATUS)
-
- u16 res = dst + src;
-
- st_c = (((dst & src) & 0x8000) ||
- (((dst & 0x8000) ^ (src & 0x8000)) && !(res & 0x8000))) != 0;
-
- st_o = (((~dst & ~src & res) | (dst & src & ~res)) & 0x8000) != 0;
-
- #elif !defined(FAST_X86_STATUS)
-
- register u16 res=dst;
-
- status&=~(ST_C|ST_O);
- asm(
- "\t addw %1,%0\n"
- "\t pushf\n"
- "\t jno 1f\n"
- "\t orb $0x8,status+1\n"
- "\t1: popf\n"
- "\t jnc 2f\n"
- "\t orb $0x10,status+1\n"
- "\t2:\n"
- : "=r" (res)
- : "g" (src), "0" (dst)
- );
-
- #else // FAST_X86_STATUS
-
- register u16 res=dst;
- register u32 flags;
- register u8 tmp;
-
- status&=~(ST_C|ST_O);
- asm(
- "\t addw %1,%0\n"
- "\t pushf\n"
- "\t popl %3\n"
- "\t andl $2049,%3\n"
- "\t movb i86_to_9900(%3),%4\n"
- "\t orb %4,status+1\n"
- : "=r" (res)
- : "g" (src), "0" (dst), "r" (flags), "r" (tmp)
- );
- #endif
-
- lastval=res;
- lastcmp=0;
-
- return res;
- }
-
-
- /*
- Set laeco for subtract, preserve none
- */
- u16 INLINE setst_sub_laeco(u16 dst,u16 src)
- {
- #if !defined(GNU_X86_ASM) && !defined(FAST_X86_STATUS)
-
- u16 res = setst_add_laeco(dst, 1+~src);
- st_c |= (src==0 || src==0x8000); // the inverse + increment ==> carry
-
- #elif !defined(FAST_X86_STATUS)
-
- register u16 res=dst;
-
- status&=~(ST_C|ST_O);
- asm(
- "\t negw %0\n"
- "\t jnz 3f\n"
- "\t orb $0x10,status+1\n"
- "3:\t addw %1,%0\n"
- "\t pushf\n"
- "\t jno 1f\n"
- "\t orb $0x8,status+1\n"
- "\t1: popf\n"
- "\t jnc 2f\n"
- "\t orb $0x10,status+1\n"
- "\t2:\n"
-
- : "=r" (res)
- : "g" (dst), "0" (src)
- );
-
-
- #else // FAST_X86_STATUS
-
- register u16 res=dst;
- register u32 flags;
- register u8 tmp;
-
- status&=~(ST_C|ST_O);
- asm(
- "\t negw %0\n"
- "\t jnz 3f\n"
- "\t orb $0x10,status+1\n"
- "3:\t addw %1,%0\n"
-
- "\t pushf\n"
- "\t popl %3\n"
- "\t andl $2049,%3\n"
- "\t movb i86_to_9900(%3),%4\n"
- "\t orb %4,status+1\n"
-
- : "=r" (res)
- : "g" (dst), "0" (src), "r" (flags), "r" (tmp)
- );
- #endif
-
-
- lastval=res;
- lastcmp=0;
-
- return res;
- }
-
-
- /*
- Set laeco for add, preserve none (BYTE)
- */
- s8 INLINE setst_addbyte_laecop(s8 dst,s8 src)
- {
- #if !defined(GNU_X86_ASM) && !defined(FAST_X86_STATUS)
-
- s8 res = dst + src;
-
- st_c = (((dst & src) & 0x80) ||
- (((dst & 0x80) ^ (src & 0x80)) && !(res & 0x80))) != 0;
-
- st_o = (((~dst & ~src & res) | (dst & src & ~res)) & 0x80) != 0;
-
- st_p = (PARITY(res));
-
- #elif !defined(FAST_X86_STATUS)
-
- register s8 res=dst;
-
- status&=~(ST_C|ST_O|ST_P);
- asm(
- "\t addb %1,%0\n"
-
- "\t pushf\n"
- "\t jno 1f\n"
- "\t orb $0x8,status+1\n"
- "\t1: popf\n"
- "\t pushf\n"
- "\t jnc 2f\n"
- "\t orb $0x10,status+1\n"
- "\t2:\n"
- "\t popf\n"
- "\t jpe 3f\n"
- "\t orb $0x4,status+1\n"
- "\t3:\n"
-
- : "=r" (res)
- : "g" (src), "0" (dst)
- );
-
- #else // FAST_X86_STATUS
-
- register s8 res=dst;
- register u32 flags;
- register u8 tmp;
-
- status&=~(ST_C|ST_O|ST_P);
- asm(
- "\t addb %1,%0\n"
-
- "\t pushf\n"
- "\t popl %3\n"
- "\t andl $2053,%3\n"
- "\t movb i86_to_9900(%3),%4\n"
- "\t orb %4,status+1\n"
-
- : "=r" (res)
- : "g" (src), "0" (dst), "r" (flags), "r" (tmp)
- );
-
- #endif
-
- lastval=(s16)res;
- lastcmp=0;
-
- return res;
- }
-
-
- /*
- Set laeco for subtract, preserve none (BYTE)
- */
- s8 INLINE setst_subbyte_laecop(s8 dst,s8 src)
- {
- #if !defined(GNU_X86_ASM) && !defined(FAST_X86_STATUS)
-
- s8 res = setst_addbyte_laecop(dst, 1+~src);
- st_c |= (src==0 || (u8)src==0x80); // the inverse + increment ==> carry
-
- #elif !defined(FAST_X86_STATUS)
- register s8 res=dst;
- register u32 flags;
- register u8 tmp;
-
- status&=~(ST_C|ST_O|ST_P);
- asm(
- "\t negb %0\n"
- "\t jnz 3f\n"
- "\t orb $0x10,status+1\n"
- "\t3:\t addb %1,%0\n"
- "\t pushf\n"
- "\t jno 1f\n"
- "\t orb $0x8,status+1\n"
- "\t1: popf\n"
- "\t pushf\n"
- "\t jnc 2f\n"
- "\t orb $0x10,status+1\n"
- "\t2:\n"
- "\t popf\n"
- "\t jpe 3f\n"
- "\t orb $0x4,status+1\n"
- "\t3:\n"
-
- : "=rb" (res)
- : "g" (dst), "0" (src)
- );
-
-
- #else // FAST_X86_STATUS
-
- register s8 res=dst;
- register u32 flags;
- register u8 tmp;
-
- status&=~(ST_C|ST_O|ST_P);
- asm(
- "\t negb %0\n"
- "\t jnz 3f\n"
- "\t orb $0x10,status+1\n"
- "3:\t addb %1,%0\n"
-
- "\t pushf\n"
- "\t popl %3\n"
- "\t andl $2053,%3\n"
- "\t movb i86_to_9900(%3),%4\n"
- "\t orb %4,status+1\n"
-
- : "=r" (res)
- : "g" (dst), "0" (src), "r" (flags), "r" (tmp)
- );
-
- #endif
-
- lastval=(s16)res;
- lastcmp=0;
-
- return res;
- }
-
-
- /*
- For ABS
- */
- u16 INLINE setst_o(u16 val)
- {
- #if defined(GNU_X86_ASM) || defined(FAST_X86_STATUS)
- status = (status & ~ST_O) | ((val == 0x8000) ? ST_O : 0);
- #else
- st_o = (val==0x8000);
- #endif
- return val;
- }
-
-
- /*
- For NEG
- */
- u16 INLINE setst_laeo(u16 val)
- {
- setst_o(val);
- lastval=val;
- lastcmp=0;
- return val;
- }
-
- #endif
-
- /************************************************************************/
- #include "cexit.h"
-
-