home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / utilities / virtual / !Virtual / c / control next >
Encoding:
Text File  |  1993-03-07  |  27.5 KB  |  1,064 lines

  1. /* includes */
  2. #include "swis.h"
  3. #include "swiv.h"
  4. #include "wimp.h"
  5.  
  6. #include "virtual.h"
  7. #include "lib.h"
  8. #include "pager.h"
  9. #include "output.h"
  10. #include "asm.h"
  11. #include "poll.h"
  12.  
  13. #include "xswis.h"      /* Some RO3 swis */
  14.  
  15. /* constants */
  16. #define DEBUG
  17.  
  18. #define N_bit 0x80000000
  19. #define Z_bit 0x40000000
  20. #define C_bit 0x20000000
  21. #define V_bit 0x10000000
  22. #define PSW_bits 0xF0000000
  23.  
  24. static int * const swivec=(int*)8;
  25.  
  26. /* errors */
  27. #define ERR(x) ((struct Error *)(x))
  28. static char BadMemory[] = { "XXXXNo memory at this address" };
  29. static char Failed[] = { "XXXXMisc Virtual swi failed" };
  30. static char NotAllowed[] = { "XXXXThis swi not allowed under virtual" };
  31.  
  32. /* module wrapping */
  33.  struct Error *Cinit(private **p) /* */
  34. { /* called with C stack a 1K bit out of svcstack. */
  35.   struct Error *err;
  36.   if (!*p)
  37.     *p=alloc(sizeof(private));
  38.   (*p)->uses = 0;
  39.   (*p)->w = 0;
  40.   worksemaphore = 1;
  41.   err = swix(OS_CallEvery,IN(R0|R1|R2),15,&OurCallEvery,*p);
  42.   if (err)
  43.     free(*p),*p=0;
  44.   return err;
  45. }
  46.  
  47.  struct Error *Cfinish(private **p)
  48. { /* called with C stack a 1K bit out of svcstack. */
  49.   /* should check (*p)->uses */
  50.   return swix(OS_RemoveTickerEvent,IN(R0|R1),&OurCallEvery,*p);
  51. }
  52.  
  53.  struct Error *CDoPhysical(int task, int addr, int len, int k[3],private *priv) 
  54. { /* called with C stack a 1K bit out of svcstack. */
  55.   WKSP *w=priv->w;
  56.   RANGE r;
  57.   if (w->ourtask!=task)
  58.     return 0;
  59.   r = Locate(w,addr,addr+len);
  60.   k[0]=r.start; k[1]=r.end; k[2]=w->pagefile;  
  61.   return 0;
  62. }
  63.  
  64.  
  65. /* ******************** mode changers */
  66.  void ClaimVVecs(WKSP *w) 
  67. { int oldswi;
  68.   workptr=w;
  69.   swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),2,&VPrefetchAbort,&w->OldPrefetchAbort);
  70.   swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),3,&VDataAbort,&w->OldDataAbort);
  71.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),7,&VCallBack,w,&w->regs,
  72.                                    &w->OldCallBack,&w->OldCallBackR12,&w->OldCallBackRegs);
  73.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&VError,&w->errnum,&w->errPC);
  74.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&VUpCall,w);
  75.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&VExit,w);
  76.   oldswi=*swivec;
  77.   if (oldswi>>24==0xEA)
  78.     ; /* B */
  79.   oldswi=8+(int)swivec+(oldswi<<8>>6);
  80.   w->OldSWIV=oldswi;
  81.   workOldSWIV=oldswi;
  82.   *swivec=(int)&VSWIV-8-(int)swivec>>2|0xEA000000;
  83. }
  84.  
  85.  void ReleaseVVecs(WKSP *w) 
  86. {
  87.   *swivec=w->OldSWIV-8-(int)swivec>>2|0xEA000000;
  88.   swi(OS_ChangeEnvironment,IN(R0|R1),2,w->OldPrefetchAbort);
  89.   swi(OS_ChangeEnvironment,IN(R0|R1),3,w->OldDataAbort);
  90.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),7,w->OldCallBack,w->OldCallBackR12,w->OldCallBackRegs);
  91.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
  92.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
  93.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
  94. }
  95.  
  96.  void ClaimExtVecs( WKSP *w ) 
  97. { swi(OS_Claim,IN(R0|R1|R2),3,&ExtWriteC,w);
  98.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&ExtError,w,&w->errPC);
  99.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&ExtUpCall,w);
  100.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&ExtExit,w);
  101. }
  102.  
  103.  void ReleaseExtVecs( WKSP *w ) 
  104. { swi(OS_Release,IN(R0|R1|R2),3,&ExtWriteC,w);
  105.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
  106.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
  107.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
  108. }
  109.  
  110.  void Virtual(WKSP *w) 
  111. {
  112.   virtualmem(w);
  113.   ClaimVVecs(w);
  114. }
  115.  
  116.  void Normal(WKSP *w) 
  117. {
  118.   ReleaseVVecs(w);
  119.   normalmem(w);
  120. }
  121.  
  122.  void V2Ext( WKSP *w ) 
  123. {
  124.   ReleaseVVecs(w);
  125.   ClaimExtVecs(w);
  126. }
  127.  
  128.  void Ext2V( WKSP *w ) 
  129. {
  130.   ReleaseExtVecs(w);
  131.   ClaimVVecs(w);
  132. }
  133.  
  134.  void Ext2Norm( WKSP *w) 
  135. {
  136.   ReleaseExtVecs(w);
  137.   normalmem(w);
  138. }
  139.  
  140.  void Norm2Ext( WKSP *w) 
  141. {
  142.   virtualmem(w);
  143.   ClaimExtVecs(w);
  144. }
  145.  
  146.  
  147. /* ******************** Virtual mode handlers */
  148.  WKSP *CVWantAddr(WKSP *w, int start, int len) 
  149. {
  150.   if (len<0)
  151.     start += len, len= -len;
  152.   if (w->regs[15]&3)
  153.   { Normal(w);
  154.     printf("***** CWantAddr called from non-user mode. Disaster! *****\n");
  155.     RealDoOff(w);
  156.   }
  157.   if (!WriteRange(w,start,start+len))
  158.   { Normal(w);
  159.     printf("***** CWantAddr can't get desired area: %08x+%08x****\n",start,len);
  160.     RealDoOff(w);
  161.   }
  162.   return w;
  163. }
  164.  
  165.  void doeschand(WKSP *w,int n) 
  166. { w->EscapeCondition = n;
  167.   if (w->Escape)
  168.   { Normal(w);
  169.     printf("(should call escape handler at %08x)",w->Escape);
  170.     Virtual(w);
  171.   }
  172. }
  173.  
  174.  WKSP *CVCallBack(WKSP *w) 
  175. { Normal(w);
  176.   Poll(w);
  177.   Virtual(w);
  178.   if (1==w->EscapeCondition)
  179.     doeschand(w,2);
  180.   worksemaphore=1;      /* Ready to reenable when we exit */
  181.   return w;
  182. }
  183.  
  184.  WKSP *CVSWIV(WKSP *w,int instr) 
  185. {
  186.   int *r=w->regs;
  187.   char s[256];
  188.   struct Error *err=0;
  189.   int psw,i;
  190.   int swinum=instr&~(XOS_Bit|0xFF000000);
  191.   r[15]&=~V_bit;
  192. #if 0
  193.     Normal(w);
  194.     swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
  195.     printf("Swi %s PC=%08x ",s,r[15]);
  196.     for (i=0;i<=14;i++)
  197.       printf("R%d=%08x ",i,r[i]);
  198.     printf("...");
  199.     Virtual(w);
  200. #endif
  201.   switch(swinum) {
  202.   /* input/output */
  203.    case OS_WriteC: 
  204.     outc(w,r[0]);
  205.     break;
  206.   
  207.    case OS_Write0: 
  208.     { char *p;
  209.       ReadRange(w,r[0],r[0]+1);
  210.       for (p=(char *)r[0];*p;p++)
  211.       { ReadPtr(w,(int)p);
  212.         outc(w,*p);
  213.       }
  214.       r[0]=(int)++p;
  215.     }
  216.     break;
  217.   
  218.    case OS_WriteS: 
  219.     { char *p=(char *)(r[15]&~0xfc000003);
  220.       char *q=p;
  221.       for (;*p;p++)
  222.       { ReadPtr(w,(int)p);
  223.         outc(w,*p);
  224.       }
  225.       r[15]+=(((p+1)-q)|3)+1;
  226.     }
  227.     break;
  228.   
  229.    case OS_WriteN: 
  230.     { int n;
  231.       for ( n=0; n<r[1]; n++ )
  232.       { ReadPtr(w,r[0]+n);
  233.         outc(w,((char *)r[0])[n]);
  234.       }
  235.     }
  236.     break;
  237.   
  238.    case OS_NewLine: 
  239.     outc(w,'\r'); outc(w,'\n');
  240.     break;
  241.   
  242.    case OS_ReadC: 
  243.     r[0]=getc(w);
  244.     if (-1==r[0])
  245.     { r[0] = 27;
  246.       r[15]|=C_bit;
  247.     }
  248.     else
  249.       r[15]&=~C_bit;
  250.     if (1==w->EscapeCondition)
  251.       doeschand(w,2);
  252.     break;
  253.   
  254.    case OS_ReadLine: 
  255.     { char buf[256];
  256.       int n=0,c;
  257.       r[15]&=~C_bit;
  258.       for (;;)
  259.       { c=getc(w);
  260.         switch (c)
  261.         {
  262.            case 13: case 10: 
  263.             buf[n]=13;
  264.             break;
  265.           
  266.            case 27: case -1: 
  267.             r[15]|=C_bit;
  268.             break;
  269.           
  270.            case 127: case 8: 
  271.             if (n>0)
  272.             { outc(w,127); n--; }
  273.             else
  274.               outc(w,7);
  275.             continue;
  276.           
  277.            case 21: 
  278.             while (n>0)
  279.             { outc(w,127); n--; }
  280.             continue;
  281.           
  282.            default: 
  283.             if (r[2]<=c && c<=r[3])
  284.             { if (n<r[1]-1 && n<255)
  285.               { buf[n++]=c;
  286.                 outc(w,c);
  287.               }
  288.               else
  289.                 outc(w,7);
  290.             }
  291.             else
  292.               outc(w,7);
  293.             continue;
  294.           
  295.         }
  296.         outc(w,'\r'); outc(w,'\n');
  297.         break;
  298.       }
  299.       WriteRange(w,r[0],r[0]+n+1);
  300.       memcpy((void *)r[0],buf,n+1);
  301.       r[1]=n;
  302.     }
  303.     if (1==w->EscapeCondition)
  304.       doeschand(w,2);
  305.     break;
  306.   
  307.   
  308.    case OS_Byte: 
  309.     switch (r[0])
  310.     { default: goto uk;
  311.       case 0:           /* display os version */
  312.         Normal(w);
  313.         err = swix(OS_Byte,IN(R0|R1)|OUT(R1),0,r[1],&r[1]);
  314.         Virtual(w);
  315.         break;
  316.       case 2:           /* switch input streams */
  317.         Normal(w);
  318.         printf("(FX 2,%d)",r[1]);
  319.         Virtual(w);
  320.         break;
  321.       case 3:           /* switch output streams */
  322.         Normal(w);
  323.         printf("(FX 3,%d)",r[1]);
  324.         Virtual(w);
  325.         break;
  326.       case 15:          /* clear input or all buffers */
  327.         break;
  328.       case 21:          /* clear specific buffer */
  329.         break;
  330.       case 124:         /* clear esc cond immed */
  331.         w->EscapeCondition = 0;
  332.         break;
  333.       case 125:         /* cause esc cond */
  334.         doeschand(w,2);
  335.         break;
  336.       case 126:         /* acknowledge escape cond */
  337.         r[1]=w->EscapeCondition?0xff:0;
  338.         if (w->EscapeCondition)
  339.           doeschand(w,0);
  340.         break;
  341.       case 160:
  342.       case 161:
  343.         err = swix(OS_Byte,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
  344.         break;
  345.       case 0xDA:        /* Read/write bytes in VDU queue */
  346.         r[1]=0;
  347.         break;
  348.       case 0xDC:        /* Read/write escape character */
  349.         { int old = w->EscapeChar;
  350.           w->EscapeChar = (w->EscapeChar&r[2])^r[1];
  351.           r[1] = old;
  352.           break;
  353.         }
  354.       case 0xE5:      /* Read/write escape char enable */
  355.         { int old = w->EscapeCharEnable;
  356.           w->EscapeCharEnable = (w->EscapeCharEnable&r[2])^r[1];
  357.           r[1] = old;
  358.           break;
  359.         }
  360.     }
  361.     break;
  362.   
  363.    case OS_SerialOp: 
  364.     err = ERR(&NotAllowed);
  365.     break;
  366.   
  367.    case OS_Word: 
  368.     switch (r[0])
  369.     { default: goto uk;
  370.       case 1: case 2: case 3: case 4: case 14:
  371.         WriteRange(w, r[1],r[1]+256);
  372.         err = swix(OS_Word,IN(R0|R1),r[0],r[1]);
  373.         break;
  374.     }
  375.     break;
  376.   
  377.    case OS_ReadUnsigned: 
  378.     ReadRange(w,r[1],r[1]+256);
  379.     err = swix(OS_ReadUnsigned,IN(R0|R1|R2)|OUT(R1|R2),r[0],r[1],r[2],&r[1],&r[2]);
  380.     break;
  381.   
  382.    case OS_EnterOS: 
  383.     Normal(w);
  384.     printf("***OS_EnterOS (ignored) from %08x ****\n",r[15]);
  385.     Virtual(w);
  386.     break;
  387.   
  388.    case OS_IntOff: 
  389.     Normal(w);
  390.     printf("***OS_IntOff (ignored) from %08x ****\n",r[15]);
  391.     Virtual(w);
  392.     break;
  393.   
  394.    case OS_IntOn: 
  395.     Normal(w);
  396.     printf("***OS_IntOn (ignored) from %08x ****\n",r[15]);
  397.     Virtual(w);
  398.     break;
  399.   
  400.    case OS_Exit: 
  401.     Normal(w);
  402.     printf("***OS_Exit from %08x ****\n",r[15]);
  403.     Virtual(w);
  404.     if (-1==w->Exit)
  405.     { Normal(w);
  406.       RealDoOff(w);
  407.     }
  408.     r[15] = w->Exit;
  409.     r[12] = w->ExitR12;
  410.     break;
  411.   
  412.    case OS_GenerateError: 
  413.     { char buf[264];
  414.       Normal(w);
  415.       FromMem(w,r[0],&buf,sizeof(buf));
  416.       printf("***GenerateError: PC=%08x %d %s\n",r[15],((int *)&buf)[0],&buf+4);
  417.       Virtual(w);
  418.     }
  419.     getc(w);
  420.     err = (void *)r[0];
  421.     break;
  422.   
  423.    case OS_ChangeEnvironment: 
  424.     switch (r[0])
  425.     { int t;
  426.   #define ifswap(x,y) ((x)?((t)=(x),(x)=(y),(y)=(t)):((x)=(y)))
  427.       default: goto uk;
  428.       case 0: ifswap(r[1],w->MemoryLimit); break;
  429.       case 1: ifswap(r[1],w->UndefinedInstruction); break;
  430.       case 2: ifswap(r[1],w->PrefetchAbort); break;
  431.       case 3: ifswap(r[1],w->DataAbort); break;
  432.       case 4: ifswap(r[1],w->AddressException); break;
  433.       case 5: ifswap(r[1],w->OtherExceptions); break;
  434.       case 6: ifswap(r[1],w->Error); ifswap(r[2],w->ErrorR0); ifswap(r[3],w->ErrorBuf); break;
  435.       case 7: ifswap(r[1],w->CallBack); ifswap(r[2],w->CallBackR12); ifswap(r[3],w->CallBackBuf); break;
  436.       case 8: ifswap(r[1],w->BreakPoint); ifswap(r[2],w->BreakPointR12); ifswap(r[3],w->BreakPointBuf); break;
  437.       case 9: ifswap(r[1],w->Escape); ifswap(r[2],w->EscapeR12); break;
  438.       case 10: ifswap(r[1],w->Event); ifswap(r[2],w->EventR12); break;
  439.       case 11: ifswap(r[1],w->Exit); ifswap(r[2],w->ExitR12); break;
  440.       case 12: ifswap(r[1],w->UnusedSWI); ifswap(r[2],w->UnusedSWIR12); break;
  441.       case 13: ifswap(r[1],w->ExceptionRegs); break;
  442.       case 14: ifswap(r[1],w->ApplicationSpace); break;
  443.       case 15: ifswap(r[1],w->CurrentlyActiveObject); break;
  444.       case 16: ifswap(r[1],w->UpCall); ifswap(r[2],w->UpCallR12); break;
  445.     }
  446.     break;
  447.   
  448.    case OS_SetEnv: 
  449.     { int t;
  450.       ifswap(r[0],w->Exit);
  451.       ifswap(r[1],w->MemoryLimit);
  452.       ifswap(r[2],w->ApplicationSpace);
  453.       ifswap(r[4],w->UndefinedInstruction);
  454.       ifswap(r[5],w->PrefetchAbort);
  455.       ifswap(r[6],w->DataAbort);
  456.       ifswap(r[7],w->AddressException);
  457.     }
  458.     break;
  459.   
  460.    case OS_GetEnv: 
  461.     r[0]=(int)&w->command;
  462.     r[1]=w->MemoryLimit;
  463.     r[2]=(int)&w->starttime;
  464.     break;
  465.   
  466.    case OS_ReadVarVal: 
  467.     ReadRange(w,r[0],r[0]+256);
  468.     if (r[2]>=0)
  469.       WriteRange(w,r[1],r[1]+r[2]);
  470.     err = swix(OS_ReadVarVal,IN(R0|R1|R2|R3|R4)|OUT(R2|R3|R4),r[0],r[1],r[2],r[3],r[4],&r[2],&r[3],&r[4]);
  471.     break;
  472.   
  473.    case OS_Module: 
  474.     switch (r[0])
  475.     { default: goto uk;
  476.       case 6:
  477.         Normal(w);
  478.         err = swix(OS_Module,IN(R0|R3)|OUT(R2),r[0],r[3],&r[2]);
  479.         Virtual(w);
  480.         break;
  481.       case 7:
  482.         Normal(w);
  483.         err = swix(OS_Module,IN(R0|R2),r[0],r[2]);
  484.         Virtual(w);
  485.         break;
  486.       case 18:
  487.         ReadRange(w,r[1],r[1]+256);
  488.         err = swix(OS_Module,IN(R0|R1)|OUT(R1|R2|R3|R4|R5),
  489.                         r[0],r[1],&r[1],&r[2],&r[3],&r[4],&r[5]);
  490.         break;
  491.     }
  492.     break;
  493.   
  494. #ifndef SharedCLibrary_LibInitAPCS_R
  495. #define SharedCLibrary_LibInitAPCS_R 0x80681
  496. #endif
  497.    case SharedCLibrary_LibInitAPCS_R: 
  498.     ReadRange(w,r[0],r[0]+256);
  499.     WriteRange(w,r[1],r[1]+32768);
  500.     err = swix(SharedCLibrary_LibInitAPCS_R,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(R0|R1|R2|R6),
  501.         r[0],r[1],r[2],r[3],r[4],r[5],r[6],&r[0],&r[1],&r[2],&r[6]);
  502.     break;
  503.   
  504.    case DDEUtils_SetCLSize: 
  505.     Normal(w);
  506.     free(w->DDECL);
  507.     w->DDECLSize = r[0];
  508.     w->DDECL = alloc(r[0]);
  509.     Virtual(w);
  510.     break;
  511.   
  512.    case DDEUtils_SetCL: 
  513.     Normal(w);
  514.     FromMem(w,r[0],w->DDECL,w->DDECLSize);
  515.     Virtual(w);
  516.     break;
  517.   
  518.    case DDEUtils_GetCLSize: 
  519.     r[0] = w->DDECLSize;
  520.     break;
  521.   
  522. #ifndef DDEUtils_GetCL
  523. #define DDEUtils_GetCL 0x42584
  524. #endif
  525.    case DDEUtils_GetCL: 
  526.     Normal(w);
  527.     ToMem(w,w->DDECL,r[0],w->DDECLSize);
  528.     Virtual(w);
  529.     break;
  530.   
  531.    case DDEUtils_ThrowbackStart: 
  532.     Normal(w);
  533.     err = swix(DDEUtils_ThrowbackStart,0);
  534.     Virtual(w);
  535.     break;
  536.   
  537.    case DDEUtils_ThrowbackSend: 
  538.     { char file[256];
  539.       char msg[256];
  540.       Normal(w);
  541.       FromMem(w,r[2],&file,sizeof(file));
  542.       if (r[0])
  543.         FromMem(w,r[5],&msg,sizeof(msg));
  544.       err = swix(DDEUtils_ThrowbackSend,IN(R0|R2|R3|R4|R5),r[0],file,r[3],r[4],msg);
  545.       Virtual(w);
  546.       break;
  547.     }
  548.   
  549.    case DDEUtils_ThrowbackEnd: 
  550.     Normal(w);
  551.     err = swix(DDEUtils_ThrowbackEnd,0);
  552.     Virtual(w);
  553.     break;
  554.   
  555.    case MessageTrans_Lookup: case MessageTrans_ErrorLookup:
  556.     ReadRange(w,r[1],r[1]+256);
  557.     if (r[2])
  558.       WriteRange(w,r[2],r[2]+r[3]);
  559.     err = swix(swinum,IN(R0|R1|R2|R3|R4|R5|R6|R7)|OUT(R0|R2|R3),
  560.         r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],&r[0],&r[2],&r[3]);
  561.     break;
  562.   
  563.    case Wimp_ReadSysInfo: 
  564.     err = swix(Wimp_ReadSysInfo,IN(R0)|OUT(R0),r[0],&r[0]);
  565.     break;
  566.   
  567.    case FPEmulator_Version: 
  568.     err = swix(FPEmulator_Version,OUT(R0),&r[0]);
  569.     break;
  570.   
  571.    case Territory_ReadCurrentTimeZone: 
  572.     err = swix(Territory_ReadCurrentTimeZone,OUT(R0|R1),&r[0],&r[1]);
  573.     break;
  574.   
  575.    case Territory_ReadTimeZones: 
  576.     err = swix(Territory_ReadTimeZones,IN(R0)|OUT(R0|R1|R2|R3),r[0],&r[0],&r[1],&r[2],&r[3]);
  577.     break;
  578.   
  579.    case Territory_ConvertTimeToOrdinals: 
  580.     ReadRange(w,r[1],r[1]+5);
  581.     WriteRange(w,r[2],r[2]+32);
  582.     err = swix(Territory_ConvertTimeToOrdinals,IN(R0|R1|R2),r[0],r[1],r[2]);
  583.     break;
  584.   
  585.    case Wimp_SlotSize: 
  586.     swi(Wimp_SlotSize,IN(R0|R1),OUT(R1|R2),-1,r[1],&r[1],&r[2]);
  587.     if (r[0]!=-1)
  588.     { w->ApplicationSpace = r[0];
  589.       w->MemoryLimit = r[0];
  590.     }
  591.     r[0]=w->ApplicationSpace;
  592.     break;
  593.   
  594.   /* filesystem swis */
  595.    case OS_Find: 
  596.     if (!r[0])
  597.     { Normal(w);
  598.       err = swix(OS_Find,IN(R0|R1)|OUT(PSW),r[0],r[1],&psw);
  599.       Virtual(w);
  600.     }
  601.     else
  602.     { char name[256];
  603.       char path[256];
  604.       Normal(w);
  605.       FromMem(w,r[1],name,sizeof(name));
  606.       if ((r[0]&3)==1 || (r[0]&3)==2)
  607.         FromMem(w,r[2],path,sizeof(path));
  608.       err = swix(OS_Find,IN(R0|R1|R2)|OUT(PSW|R0),r[0],name,path,&psw,&r[0]);
  609.       Virtual(w);
  610.     }
  611.     break;
  612.   
  613.    case OS_BGet: case OS_BPut: case OS_Args: 
  614.     Normal(w);
  615.     err=swix(swinum,IN(R0|R1|R2)|OUT(PSW|R0|R1|R2),r[0],r[1],r[2],&psw,&r[0],&r[1],&r[2]);
  616.     r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  617.     Virtual(w);
  618.     break;
  619.   
  620.    case OS_GBPB: 
  621.     Normal(w);
  622.     if (1<=r[0] && r[0]<=4)
  623.     { /* read/write variety */
  624.       while (r[3]>0)
  625.       { RANGE k = Physical(w,r[2],r[2]+r[3]);
  626.         int p = k.start;
  627.         int l = k.end-k.start;
  628.         int q,m;
  629.         err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R2|R3|R4),r[0],r[1],p,l,r[4],&psw,&q,&m,&r[4]);
  630.         r[2]+=q-p;
  631.         r[3]-=l-m;
  632.         if (err || m)
  633.           break;
  634.     } }
  635.     else if (5<=r[0] && r[0]<=8)
  636.     { char buf[2048];
  637.       FromMem(w,r[2],&buf,sizeof(buf));
  638.       err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R3|R4),r[0],buf,r[2],r[3],r[4],&psw,&r[3],&r[4]);
  639.       ToMem(w,&buf,r[2],sizeof(buf));
  640.     }
  641.     else if (9<=r[0] && r[0]<=12)
  642.     { char dirname[256];
  643.       char wild[256];
  644.       RANGE k;
  645.       FromMem(w,r[1],&dirname,sizeof(dirname));
  646.       if (r[6])
  647.         FromMem(w,r[6],&wild,sizeof(wild));
  648.       k = Physical(w,r[2],r[2]+r[5]);
  649.       err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(PSW|R3|R4),
  650.         r[0],dirname,k.start,r[3],r[4],k.end-k.start,r[6]?wild:0,
  651.         &psw,&r[3],&r[4]);
  652.     }
  653.     else
  654.     { Virtual(w);
  655.       goto uk;
  656.     }
  657.     r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  658.     Virtual(w);
  659.     break;
  660.   
  661.    case OS_File: 
  662.     Normal(w);
  663.     switch(r[0])
  664.     { default: Virtual(w); goto uk;
  665.       case 5: case 13: case 15: case 17:        /* read cat info */
  666.       case 20: case 21: case 22: case 23:
  667.       { int h;
  668.         char path[256];
  669.         char name[256];
  670.         FromMem(w,r[1],name,sizeof(name));
  671.         if (r[0]==13 || r[0]==15 || r[0]==21 || r[0]==22)
  672.           FromMem(w,r[4],path,sizeof(path));
  673.         err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5|R6),r[0],name,path,
  674.                                         &r[0],&r[2],&r[3],&r[4],&r[5],&h);
  675.         if (20<=r[0] && r[0]<=23)
  676.           r[6]=h;
  677.         break;
  678.       }
  679.       case 1: case 2: case 3: case 4: case 9: case 18:  /* Write cat info */
  680.       case 6:           /* Delete */
  681.       case 7: case 11:  /* Create */
  682.       case 8:           /* Create directory */
  683.       { char name[256];
  684.         FromMem(w,r[1],name,sizeof(name));
  685.         err = swix(OS_File,IN(R0|R1|R2|R3|R4|R5)|OUT(R0|R2|R3|R4|R5),r[0],name,r[2],r[3],r[4],r[5],
  686.                                         &r[0],&r[2],&r[3],&r[4],&r[5]);
  687.         break;
  688.       }
  689.       case 12: case 14: case 16: case 255:      /* load */
  690.       { int h;
  691.         char path[256];
  692.         char name[256];
  693.         RANGE k;
  694.         int l,m,q;
  695.         int p=(r[3]&0xFF)?-1:r[2];
  696.         int t = r[0]==255?0:r[0]==12?1:r[0]==14?2:r[0]==16?3:0;
  697.         FromMem(w,r[1],name,sizeof(name));
  698.         if (t==1 || t==2)
  699.           FromMem(w,r[4],path,sizeof(path));
  700.         err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5),"\x05\x0D\x0F\x11"[t],name,path,
  701.                                         &r[0],&r[2],&r[3],&r[4],&r[5]);
  702.         if (err)
  703.           break;
  704.         err = swix(OS_Find,IN(R0|R1|R2)|OUT(R0),0x4C+t,name,path,&h);
  705.         if (err)
  706.           break;
  707.         if (p==-1)
  708.           p = r[2];
  709.         l = r[4];
  710.         while (l>0)
  711.         { k = Physical(w,p,p+l);
  712.           if (!k.start)
  713.           { err=ERR(&BadMemory);
  714.             break;
  715.           }
  716.           err = swix(OS_GBPB,IN(R0|R1|R2|R3)|OUT(R2|R3),4,h,k.start,k.end-k.start,&q,&m);
  717.           if (err)
  718.             break;
  719.           if (q!=k.end || m)
  720.           { err = ERR(&Failed);
  721.             break;
  722.           }
  723.           p+=k.end-k.start;
  724.           l-=k.end-k.start;
  725.         }
  726.         if (!err)
  727.           err = swix(OS_Find,IN(R0|R1),0,h);
  728.         else
  729.           (void)swix(OS_Find,IN(R0|R1),0,h);
  730.       }
  731.     }
  732.     Virtual(w);
  733.     break;
  734.   
  735.    case OS_FSControl: 
  736.     Normal(w);
  737.     switch (r[0])
  738.     { default: Virtual(w); goto uk;
  739.       case 27:          /* Wipe objects */
  740.       { char name[256];
  741.         FromMem(w,r[1],name,sizeof(name));
  742.         err = swix(OS_FSControl,IN(R0|R1|R2|R3|R4|R5|R6|R7),r[0],name,r[2],r[3],r[4],r[5],r[6],r[7]);
  743.         break;
  744.       }
  745.     }
  746.     Virtual(w);
  747.     break;
  748.   
  749.   
  750.    case OS_CLI: 
  751.     { char buf[256];
  752.       Normal(w);
  753.       FromMem(w,r[0],buf,sizeof(buf));
  754.       err=swix(OS_CLI,IN(R0),&buf);
  755.       Virtual(w);
  756.     }
  757.     break;
  758.   
  759.   /* BASICTrans swis */
  760.   case BASICTrans_HELP:
  761.   case BASICTrans_Message:
  762.   case BASICTrans_Error:
  763.     V2Ext(w);
  764.     err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
  765.                            OUT(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
  766.          r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
  767.         &r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
  768.     Ext2V(w);
  769.     break;
  770.   
  771.    default: 
  772.     if (swinum>=0x100 && swinum<0x200)
  773.     { outc(w,(char)swinum);
  774.       break;
  775.     }
  776.   uk:
  777.     Normal(w);
  778.     swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
  779.     printf("UKSwi %s PC=%08x ",s,r[15]);
  780.     for (i=0;i<=8;i++)
  781.       printf("R%d=%08x ",i,r[i]);
  782.     printf("Allow(Yn)?\n");
  783.     Virtual(w);
  784.   lp:
  785.     switch (getc(w))
  786.     { case -1:
  787.         w->EscapeCondition = 0;
  788.         /* FALL THROUGH */
  789.       default:
  790.         goto lp;
  791.       case 'n': case'N':
  792.         err = ERR(&NotAllowed);
  793.         break;
  794.       case 'y': case 'Y': case 13:
  795.         V2Ext(w);
  796.         err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
  797.                                OUT(PSW|R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
  798.              r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
  799.        &psw,&r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
  800.         r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  801.         Ext2V(w);
  802.         break;
  803.     }
  804.     break;
  805.   
  806.   }
  807. #if 0
  808.     Normal(w);
  809.     for (i=0;i<=15;i++)
  810.       printf("R%d=%08x ",i,r[i]);
  811.     if (err)
  812.       printf("**** ERROR **** %d %s",err->num,err->msg);
  813.     printf("\n");
  814.     if (r[15]&0x0c000003)
  815.     { printf("***Bad PC***\n");
  816.       RealDoOff(w);
  817.     }
  818.     Virtual(w);
  819. #endif
  820.   if (!err)
  821.     return w;
  822.   if (instr&XOS_Bit) /* X form */
  823.   { r[0]=(int)err;
  824.     r[15]|=V_bit;
  825.     return w;
  826.   }
  827.   if (-1==w->Error)
  828.   { Normal(w);
  829.     printf("***Error:%s",err->msg);
  830.     RealDoOff(w);
  831.   }
  832.   WriteRange(w,w->ErrorBuf,w->ErrorBuf+264);
  833.   ((int*)w->ErrorBuf)[0] = r[15];
  834.   ((int*)w->ErrorBuf)[1] = err->num;
  835.   strcpy( (char *)&((int*)w->ErrorBuf)[2], err->msg );
  836.   r[0] = w->ErrorR0;
  837.   r[15] = w->Error & ~3;
  838.   return w;
  839. }
  840.  
  841.  int CVUpCall( int r0, int r1, int r2, WKSP *w) 
  842. { /* Called with sp a 1K chunk out of svcstack */
  843.   switch(r0)
  844.   { case 256:
  845.       r0 = 0; /* Not quite sure what on earth is going on here, but better stop it! */
  846.       break;
  847.     default:
  848.       break;
  849.   }
  850.     return r0;
  851. }
  852.  
  853.  
  854. /* ******************** Ext mode handlers */
  855.  int CExtWriteC(int c, WKSP *w) 
  856. { /* called with stack a 1K bit out of svcstack */
  857.   w->outbuf[w->outcount++]=c;
  858.   if (w->outcount>=OUTMAX-2)
  859.   { Ext2Norm(w);
  860.     printflush(w);
  861.     FindPages(w);
  862.     Norm2Ext(w);
  863.   }
  864.   return 0x80000000;     /* VC CC */
  865. }
  866.  
  867.  int CExtUpCall(int r0,int r1,int r2,WKSP *w) 
  868. { /* Called with sp a 1K chunk out of svcstack */
  869.   switch(r0)
  870.   { case 256:
  871.       r0 = 0;
  872.       break;
  873.     default:
  874.       break;
  875.   }
  876.   return r0;
  877. }
  878.  
  879.  int CExtError(WKSP *w) 
  880. { /* Called in user, ext mode */
  881.   printf("ExtError PC=%08x errnum %d errmess %s****\n",w->errPC,w->errnum,w->errmess);
  882.   Ext2V(w);
  883.   return (int)&w->errnum;
  884. }
  885.  
  886.  void CExtExit(WKSP *w) 
  887. { /* Called in user, ext mode */
  888.   Ext2V(w);
  889. }
  890.  
  891.  
  892. /* ******************** Normal mode handlers */
  893.  void __main(private *p,char *cmd) 
  894. { /* This is called in user mode, with its stack at the top of the WimpSlot */
  895.   wimp_eventdata b;
  896.   struct Error *e;
  897.   char *buf[64];
  898.   int version,ourtask,outtask,txt,i;
  899.   WKSP *w;
  900.   strcpy(b.msg.data.chars+8,cmd);
  901.   swi(OS_ReadArgs,IN(R0|R1|R2|R3),
  902.         ",wimpslot/K,name/K,pagefile/K,ctrl/S,display/S,quit/S,task,txt", cmd, buf, sizeof(buf));
  903.   if (!buf[0])
  904.     return;
  905.   swi(Wimp_Initialise,IN(R0|R1|R2)|OUT(R0|R1),200,0x4b534154,
  906.                 buf[2]?buf[2]:"Virtual",&version,&ourtask);
  907.   if (!buf[7] || !buf[8])
  908.   { memcpy(b.msg.data.chars,"virtual ",8);
  909.     b.msg.hdr.action = 0x808c5; /* TaskWindow_NewTask; */
  910.     b.msg.hdr.your_ref = 0;
  911.     b.msg.hdr.size = (21+(strlen(b.msg.data.chars)|3));
  912.     swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,0);
  913.     swi(OS_Exit,0);
  914.   }
  915.   outtask = xtoi(buf[7]);
  916.   txt = xtoi(buf[8]);
  917.  
  918.   b.msg.hdr.action = /*TaskWindow_Ego*/ 0x808c2;
  919.   b.msg.hdr.your_ref = 0;
  920.   b.msg.data.words[0]=txt;
  921.   b.msg.hdr.size = 24;
  922.   swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,outtask);
  923.  
  924.   w = alloc(sizeof(WKSP));
  925.   p->w = w;
  926.   p->uses++;
  927.   w->private = p;
  928.   w->outtask = outtask;
  929.   w->ourtask = ourtask;
  930.   w->outcount = 0;
  931.   w->incount = 0;
  932.   w->instart = 0;
  933.   w->EscapeCondition = 0;
  934.   w->EscapeChar = 27;
  935.   w->moreavailable = 0;
  936.   strcpy(w->pagefilename,buf[3]?buf[3]:"swap:pagefile0");
  937.   strcpy(w->command,buf[0]?buf[0]:"GOS");
  938.   w->ApplicationSpace=buf[1]?sizetoi(buf[1])+K32:M24;
  939.   if (w->ApplicationSpace>M24)
  940.     w->ApplicationSpace=M24;
  941.   w->UpCall = w->Error = w->Exit = w->Escape = w->UndefinedInstruction = w->PrefetchAbort = w->DataAbort = w->AddressException = -1;
  942.   w->DDECLSize = 0;
  943.   w->DDECL = 0;
  944.   i=0;
  945.   while (0!=(e=swix(OS_Find,IN(R0|R1)|OUT(R0),0x80,w->pagefilename,&w->pagefile)) && i<10)
  946.     w->pagefilename[strlen(w->pagefilename)-1]++,i++;
  947.   if (e)
  948.   { swi(Wimp_ReportError,IN(R0|R1|R2),e,2,"Virtual");
  949.     swi(OS_Exit,0);
  950.   }
  951.   svcmode();
  952.   swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
  953. #if 0
  954.   printf("cmd=%s\n",w->command);
  955.   printf("wimpslot=%08x\n",w->ApplcationSpace);
  956.   printf("name=%s\n",buf[2]);
  957.   printf("pagefile=%s\n",w->pagefilename);
  958.   printf("ctrl=%08x\n",(int)buf[4]);
  959.   printf("display=%08x\n",(int)buf[5]);
  960.   printf("quit=%08x\n",(int)buf[6]);
  961.   printf("task=%08x\n",outtask);
  962.   printf("txt=%08x\n",txt);
  963. #endif
  964.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),6,&NormError,w,&w->errPC,
  965.                         &w->OldError,&w->OldErrorR0,&w->OldErrorBuf);
  966.   swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),16,&NormUpCall,w,&w->OldUpCall,&w->OldUpCallR12);
  967.   swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),11,&NormExit,w,&w->OldExit,&w->OldExitR12);
  968.  
  969.   Initourmem(w);
  970.   SetWimpMemMap(w);
  971.   SetVirtualSlot(w,w->ApplicationSpace-K32);
  972.   w->MemoryLimit = w->ApplicationSpace;
  973. #if 0
  974.   printf("Going virtual\n");
  975. #endif
  976.   Virtual(w);
  977.   usermode();
  978.   worksemaphore = 0;    /* Enable interupts */
  979. #ifdef DEBUG
  980.   swi(OS_Write0,IN(R0),"This is virtual: OS_CLI ");
  981.   swi(OS_Write0,IN(R0),w->command);
  982.   swi(OS_NewLine,0);
  983. #endif
  984.   swi(OS_CLI,IN(R0),w->command);
  985.   swi(OS_Exit,0);
  986. }
  987.  
  988.  void RealDoOff(WKSP *w) 
  989. {
  990.   private *priv=w->private;
  991.   wimp_eventdata b;
  992. #ifdef DEBUG
  993.   printf("RealDoOff\n");
  994. #endif
  995.   swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
  996.   printflush(w);
  997.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),6,w->OldError,w->OldErrorR0,w->OldErrorBuf);
  998.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,w->OldExit,w->OldExitR12);
  999.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,w->OldUpCall,w->OldUpCallR12);
  1000.   Finishourmem(w);
  1001.   usermode();
  1002.   b.msg.hdr.action = /*TaskWindow_Morio*/ 0x808c3;
  1003.   b.msg.hdr.your_ref = 0;
  1004.   b.msg.hdr.size = 20;
  1005.   swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,w->outtask);
  1006.  
  1007.   swi(Wimp_CloseDown, 0);
  1008.   swix(OS_Find,IN(R0|R1),0,w->pagefile);
  1009.   swix(OS_File,IN(R0|R1),6,w->pagefilename);
  1010.   free((char *)w->stacktop-STACKSIZE);
  1011.   free(w->DDECL);
  1012.   free(w);
  1013.   priv->uses--;
  1014.   priv->w = 0;
  1015.   swi(OS_Exit,0);
  1016. }
  1017.  
  1018.  int CNormError( WKSP *w )
  1019. { printf("NormError: PC=%08x errnum %d errmess %s\n",w->errPC,w->errnum,w->errmess);
  1020.   swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
  1021.   swi(Wimp_ReportError,IN(R0|R1|R2),&w->errnum,2,"Virtual");
  1022.   swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
  1023.   RealDoOff(w);
  1024.   return 0;
  1025. }
  1026.  
  1027.  void CNormExit(WKSP *w)
  1028. { printf("NormExit\n");
  1029.   RealDoOff(w);
  1030. }
  1031.  
  1032.  int CNormWriteC(int c, WKSP *w) 
  1033. { /* called with stack a 1K bit out of svcstack */
  1034.   w->outbuf[w->outcount++]=c;
  1035.   if (w->outcount>=OUTMAX-2)
  1036.   { printflush(w);
  1037.     FindPages(w);
  1038.   }
  1039.   return 0x80000000;     /* VC CC */
  1040. }
  1041.  
  1042.  int CNormUpCall(int r0,int r1,int r2,WKSP *w) 
  1043. { /* Called with sp a 1K chunk out of svcstack */
  1044.   switch(r0)
  1045.   { case 256:
  1046.       { char *cmd, *tptr;
  1047.         w->UpCall = w->Error = w->Exit = w->Escape = w->UndefinedInstruction = w->PrefetchAbort = w->DataAbort = w->AddressException = -1;
  1048.         SetWimpMemMap(w);
  1049.         SetVirtualSlot(w,w->ApplicationSpace-K32);
  1050.         Virtual(w);
  1051.         swi(OS_GetEnv,OUT(R0|R2),&cmd,&tptr);
  1052.         strcpy(w->command,cmd);
  1053.         memcpy(w->starttime,tptr,5);
  1054.         worksemaphore = 0;    /* Enable interupts */
  1055.         break;
  1056.       }
  1057.     default:
  1058.       break;
  1059.   }
  1060.   return r0;
  1061. }
  1062.  
  1063.  
  1064.