/* LU3_command.c Implement messaging and commands in FLISP LU3 systems */ #include "console.h" #include "lu3.h" #include "flispcontrol.h" static int Q; static DATAPATH dp; void setFlispRegisterValue(unsigned char r, unsigned char d) { switch( r ) { case 'a': case 'A': dp.regA.cval = d; break; case 't': case 'T': dp.regT.cval = d; break; case 'x': case 'X': dp.regX.cval = d; break; case 'y': case 'Y': dp.regY.cval = d; break; case 's': case 'S': dp.regSP.cval = d; break; case 'p': case 'P': dp.regPC.cval = d; break; case 'u': case 'U': dp.regTA.cval = d; break; case 'c': case 'C': dp.regCC.cval = d; break; case 'r': case 'R': dp.regR.cval = d; break; case 'i': case 'I': dp.regI.cval = d; break; } } unsigned char getFlispRegisterValue(unsigned char r) { switch( r ) { case 'a': case 'A': return ( dp.regA.cval ); case 't': case 'T': return ( dp.regT.cval ); case 'x': case 'X': return ( dp.regX.cval ); case 'y': case 'Y': return ( dp.regY.cval ); case 's': case 'S': return ( dp.regSP.cval ); case 'p': case 'P': return ( dp.regPC.cval ); case 'u': case 'U': return ( dp.regTA.cval ); case 'c': case 'C': return ( dp.regCC.cval ); case 'r': case 'R': return ( dp.regR.cval ); case 'i': case 'I': return ( dp.regI.cval ); } return 0; } unsigned char translateFlispRegister(unsigned char r) { switch( r ) { case 'a': case 'A': return ( 'A' ); case 't': case 'T': return ( 'T' ); case 'x': case 'X': return ( 'X' ); case 'y': case 'Y': return ( 'Y' ); case 's': case 'S': return ( 'S' ); case 'p': case 'P': return ( 'P' ); case 'u': case 'U': return ( 'U' ); case 'c': case 'C': return ( 'C' ); case 'r': case 'R': return ( 'R' ); case 'i': case 'I': return ( 'I' ); } return 0xFF; } static void refreshDatapath( DATAPATH *d ) { /* copy control signals from LU3-SE to internal data structures */ unsigned char tmp; char vout,cout,nout,zout; d->regT.clrenab = 0; /* always, cannot be used by external logic */ tmp = readIn( 3 ); if( tmp & 1) d->regA.ldenab = 1; else d->regA.ldenab = 0; if( tmp & 2) d->regT.ldenab = 1; else d->regT.ldenab = 0; if( tmp & 4) d->nf = 1; else d->nf = 0; if( tmp & 8) d->regX.ldenab = 1; else d->regX.ldenab = 0; if( tmp & 0x10) d->regY.ldenab = 1; else d->regY.ldenab = 0; if( tmp & 0x20) d->regPC.ldenab = 1; else d->regPC.ldenab = 0; if( tmp & 0x40) d->regSP.incenab = 1; else d->regSP.incenab = 0; if( tmp & 0x80) d->regPC.incenab = 1; else d->regPC.incenab = 0; tmp = readIn( 4 ); if( tmp & 1) d->regSP.ldenab = 1; else d->regSP.ldenab = 0; if( tmp & 2) d->regSP.decenab = 1; else d->regSP.decenab = 0; if( tmp & 4) d->regTA.ldenab = 1; else d->regTA.ldenab = 0; if( tmp & 8) d->regR.ldenab = 1; else d->regR.ldenab = 0; if( tmp & 0x10) d->regCC.ldenab = 1; else d->regCC.ldenab = 0; if( tmp & 0x20) d->regI.ldenab = 1; else d->regI.ldenab = 0; if( tmp & 0x40) d->mainmem.mw = 1; else d->mainmem.mw = 0; if( tmp & 0x80) d->mainmem.mr = 1; else d->mainmem.mr = 0; tmp = readIn( 5 ); if( tmp & 1) d->alu.f0 = 1; else d->alu.f0 = 0; if( tmp & 2) d->alu.f1 = 1; else d->alu.f1 = 0; if( tmp & 4) d->alu.f2 = 1; else d->alu.f2 = 0; if( tmp & 8) d->alu.f3 = 1; else d->alu.f3 = 0; if( tmp & 0x10) d->mux.g14 = 1; else d->mux.g14 = 0; if( tmp & 0x20) d->mux.g13 = 1; else d->mux.g13 = 0; if( tmp & 0x40) d->mux.g12 = 1; else d->mux.g12 = 0; if( tmp & 0x80) d->mux.g9 = 1; else d->mux.g9 = 0; tmp = readIn( 6 ); if( tmp & 1) d->mux.g8 = 1; else d->mux.g8 = 0; if( tmp & 2) d->mux.g7 = 1; else d->mux.g7 = 0; if( tmp & 4) d->mux.g6 = 1; else d->mux.g6 = 0; if( tmp & 8) d->mux.g5 = 1; else d->mux.g5 = 0; if( tmp & 0x10) d->mux.g4 = 1; else d->mux.g4 = 0; if( tmp & 0x20) d->mux.g3 = 1; else d->mux.g3 = 0; if( tmp & 0x40) d->mux.g2 = 1; else d->mux.g2 = 0; if( tmp & 0x80) d->mux.g1 = 1; else d->mux.g1 = 0; tmp = readIn( 7 ); if( tmp & 1) d->regA.oeenab = 1; else d->regA.oeenab = 0; if( tmp & 2) d->regCC.oeenab = 1; else d->regCC.oeenab = 0; if( tmp & 4) d->regPC.oeenab = 1; else d->regPC.oeenab = 0; if( tmp & 8) d->regR.oeenab = 1; else d->regR.oeenab = 0; if( tmp & 0x10) d->regX.oeenab = 1; else d->regX.oeenab = 0; if( tmp & 0x20) d->regSP.oeenab = 1; else d->regSP.oeenab = 0; if( tmp & 0x40) d->regY.oeenab = 1; else d->regY.oeenab = 0; if( tmp & 0x80) d->mux.g0 = 1; else d->mux.g0 = 0; // evaluate conditions cout = 0; vout = 0; zout = 0; nout = 0; if( d->regCC.cval & 8 ) nout = 1; if( d->regCC.cval & 4 ) zout = 1; if( d->regCC.cval & 2 ) vout = 1; if( d->regCC.cval & 1) cout = 1; d->Cond[0]=1; d->Cond[1]=0; d->Cond[2]= zout; d->Cond[3]= !(zout); d->Cond[4]= nout; d->Cond[5]= !(nout); d->Cond[6]= vout; d->Cond[7]= !(vout); d->Cond[8]= cout; d->Cond[9]= !(cout); d->Cond[10]= ((cout)||(vout) ); d->Cond[11]= !((cout)||(vout) ); d->Cond[12]= ((nout)^(vout)); d->Cond[13]= !((nout)^(vout)); d->Cond[14]= (((nout)^(vout))||(zout) ); d->Cond[15]= !(((nout)^(vout))||(zout) ); } static void updateDatapath( DATAPATH *d ) { /* copy cotrol signals from internal data structures to LU3-DV */ unsigned char tmp; unsigned short q; int i; outbusHigh( dp.regA.cval ); outbusLow( dp.regT.cval ); selectOut( 1 ); outbusHigh( dp.regX.cval ); outbusLow( dp.regY.cval ); selectOut( 2 ); outbusHigh( dp.regSP.cval ); outbusLow( dp.regPC.cval ); selectOut( 3 ); outbusHigh( dp.alu.Dval ); outbusLow( dp.alu.Uval ); selectOut( 4 ); outbusHigh( dp.regR.cval ); outbusLow( dp.regTA.cval ); selectOut( 5 ); outbusHigh( dp.regI.cval ); outbusLow( dp.regCC.cval ); selectOut( 6 ); tmp = 0; if( d->regA.ldenab) tmp |= 1; if( d->regT.ldenab) tmp |= 2; if( d->regT.clrenab) tmp |= 4; if( d->regX.ldenab) tmp |= 8; if( d->regY.ldenab) tmp |= 0x10; if( d->regSP.ldenab) tmp |= 0x20; if( d->regSP.incenab) tmp |= 0x40; if( d->regSP.decenab) tmp |= 0x80; outbusHigh( tmp ); tmp = 0; if( d->regPC.ldenab) tmp |= 1; if( d->regPC.incenab) tmp |= 2; if( d->regTA.ldenab) tmp |= 4; if( d->regR.ldenab) tmp |= 8; if( d->regCC.ldenab) tmp |= 0x10; if( d->regI.ldenab) tmp |= 0x20; if( d->mainmem.mw ) tmp |= 0x40; if( d->mainmem.mr ) tmp |= 0x80; outbusLow( tmp ); selectOut( 7 ); tmp = 0; if( d->alu.f0 ) tmp |= 1; if( d->alu.f1 ) tmp |= 2; if( d->alu.f2 ) tmp |= 4; if( d->alu.f3 ) tmp |= 8; if( d->mux.g14 ) tmp |= 0x10; if( d->mux.g13 ) tmp |= 0x20; if( d->mux.g12 ) tmp |= 0x40; if( d->mux.g9 ) tmp |= 0x80; outbusHigh( tmp ); tmp = 0; if( d->mux.g8 ) tmp |= 1; if( d->mux.g7 ) tmp |= 2; if( d->mux.g6 ) tmp |= 4; if( d->mux.g5 ) tmp |= 8; if( d->mux.g4 ) tmp |= 0x10; if( d->mux.g3 ) tmp |= 0x20; if( d->mux.g2 ) tmp |= 0x40; if( d->mux.g1 ) tmp |= 0x80; outbusLow( tmp ); selectOut( 8 ); tmp = 0; if( d->regA.oeenab ) tmp |= 1; if( d->regR.oeenab ) tmp |= 2; if( d->regCC.oeenab ) tmp |= 4; if( d->regX.oeenab ) tmp |= 8; if( d->regY.oeenab ) tmp |= 0x10; if( d->regSP.oeenab ) tmp |= 0x20; if( d->regPC.oeenab ) tmp |= 0x40; if( d->mux.g0 ) tmp |= 0x80; outbusLow( tmp ); selectOut( 9 ); switch( Q ) { case 0: q = 0x100; break; case 1: q = 0x200; break; case 2: q = 0x400; break; case 3: q = 0x800; break; case 4: q = 0x1000; break; case 5: q = 0x2000; break; case 6: q = 0x4000; break; case 7: q = 0x8000; break; case 8: q = 1; break; case 9: q = 2; break; case 10: q = 4; break; case 11: q = 8; break; case 12: q = 0x10; break; case 13: q = 0x20; break; case 14: q = 0x40; break; case 15: q = 0x80; break; default: q = 0; break; } outbusHigh( (q >> 8) ); outbusLow( q & 0xFF ); selectOut( 10 ); tmp = 0; if( d->regI.cval == 0x03 ) tmp |= 1; else if( d->regI.cval == 0x04 ) tmp |= 2; else if( d->regI.cval == 0xDF ) tmp |= 4; else if( d->regI.cval == 0xEF ) tmp |= 8; if( d->regCC.cval & 8 ) /* NFLAG */ tmp |= 0x40; if( d->regCC.cval & 4 ) /* ZFLAG */ tmp |= 0x80; if( d->regCC.cval & 2 ) /* VFLAG */ tmp |= 0x20; if( d->regCC.cval & 1 ) /* CFLAG */ tmp |= 0x10; outbusHigh( tmp ); selectOut( 11 ); if( Q < 8) { outbusLow( 0 ); /* clears Q8-Q15 */ tmp = 1; for( i = 0; i < 8; i++ ) { if (d->Qstate[i]){ outbusHigh( tmp ); break; } tmp = tmp << 1; } }else{ outbusHigh( 0 ); /* clears Q0-Q7 */ tmp = 1; for( i = 8; i < 16; i++ ) { if (d->Qstate[i]){ outbusLow( tmp ); break; } tmp = tmp << 1; } } selectOut(10); updateAddressDisplay( 0 ); updateDataDisplay( 0 ); } int isExternalOpcode( void ) { return ((Q>3)&&( ( dp.regI.cval == 0x03 )||( dp.regI.cval == 0x04 )||( dp.regI.cval == 0xDF )||( dp.regI.cval == 0xEF ))); } void doExternalOpcode( void ) { /* Called from main loop */ refreshDatapath( &dp ); /* read logic from external board */ asynchDatapath( &dp ); /* do asynch operations */ updateDatapath( &dp ); } void updateAll( int all ) { int i; char external_opcode; dp.irq = 0; /* always */ external_opcode = isExternalOpcode(); /* Set Qstate and I-vectors */ for( i = 0; i < 16; i++ ) dp.Qstate[i] = 0; if( Q < 16 ) dp.Qstate[Q] = 1; for( i = 0; i < 256; i++ ) dp.Istate[i] = 0; dp.Istate[ (int) dp.regI.cval ] = 1; if( external_opcode ){ refreshDatapath( &dp ); /* read logic frpm external board */ }else{ asynchControl( &dp ); /* evaluate AND/OR logic */ } asynchDatapath( &dp ); /* do asynch operations */ if( all ) { setAutoAddress( dp.memadd ); updateDatapath( &dp ); } } void doFlispReset( void ) { Q = 0; updateAll(1); } static void singleClk( void ) { int nfflag; nfflag = dp.nf; synchDatapath( &dp ); if( nfflag ) Q = 3; else{ Q++; if( Q > 15) Q = 0; } updateAll(0); } void doFlispNF( void ) { /* 2015-03-08 changed NF functionality from "set NF" to "step to NF" */ do { singleClk(); } while ( Q != 3); // Q = 3; updateAll(1); } void doFlispClk(void) { singleClk(); updateAll(1); } void doStepInstruction( void ) { doFlispNF( ); // Q = 3; /* ? */ // doFlispClk(); // while( Q != 3 ) // { // doFlispClk(); // } } static unsigned char memory[256]; void setMemory(unsigned char add, unsigned char data, DATAPATH *dp) { memory[add] = data; } unsigned char getMemory(unsigned char add, DATAPATH *dp ) { return memory[add]; }