home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-09-07 | 35.6 KB | 1,386 lines |
- /*
- * control.c
- * Part of the !Virtual distribution
- * (c) bdb/nas/fo, 1992-3
- */
-
- /* includes */
- #include "swis.h"
- #include "swiv.h"
- #include "wimp.h"
-
- #include "virtual.h"
- #include "lib.h"
- #include "pager.h"
- #include "output.h"
- #include "asm.h"
- #include "poll.h"
-
- #include "xswis.h" /* Some RO3 swis */
-
- /* constants */
- /*#define DEBUG*/
-
- #define N_bit 0x80000000
- #define Z_bit 0x40000000
- #define C_bit 0x20000000
- #define V_bit 0x10000000
- #define PSW_bits 0xF0000000
-
- static int * const swivec=(int*)8;
- static int wimp_version;
-
- /* errors */
- #define ERR(x) ((struct Error *)(x))
- static char BadMemory[] = { "XXXXNo memory at this address" };
- static char Failed[] = { "XXXXMisc Virtual swi failed" };
- static char NotAllowed[] = { "XXXXThis swi not allowed under virtual" };
-
- /* module wrapping */
- struct Error *Cinit(private **p) /* */
- { /* called with C stack a 1K bit out of svcstack. */
- struct Error *err;
- if (!*p)
- *p=alloc(sizeof(private));
- (*p)->uses = 0;
- (*p)->w = 0;
- worksemaphore = 1;
- err = swix(OS_CallEvery,IN(R0|R1|R2),15,&OurCallEvery,*p);
- if (err)
- free(*p),*p=0;
- return err;
- }
-
- struct Error *Cfinish(private **p)
- { /* called with C stack a 1K bit out of svcstack. */
- /* should check (*p)->uses */
- return swix(OS_RemoveTickerEvent,IN(R0|R1),&OurCallEvery,*p);
- }
-
- struct Error *CDoPhysical(int task, int addr, int len, int k[3],private *priv)
- { /* called with C stack a 1K bit out of svcstack. */
- WKSP *w=priv->w;
- RANGE r;
- if (w->ourtask!=task)
- return 0;
- r = Locate(w,addr,addr+len);
- k[0]=r.start; k[1]=r.end; k[2]=w->pagefile;
- return 0;
- }
-
-
- /* ******************** mode changers */
- void ClaimVVecs(WKSP *w)
- { int oldswi;
- workptr=w;
- swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),2,&VPrefetchAbort,&w->OldPrefetchAbort);
- swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),3,&VDataAbort,&w->OldDataAbort);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),7,&VCallBack,w,&w->regs,
- &w->OldCallBack,&w->OldCallBackR12,&w->OldCallBackRegs);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&VError,&w->errnum,&w->errPC);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&VUpCall,w);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&VExit,w);
- oldswi=*swivec;
- if (oldswi>>24==0xEA)
- ; /* B */
- oldswi=8+(int)swivec+(oldswi<<8>>6);
- w->OldSWIV=oldswi;
- workOldSWIV=oldswi;
- *swivec=(int)&VSWIV-8-(int)swivec>>2|0xEA000000;
- }
-
- void ReleaseVVecs(WKSP *w)
- {
- *swivec=w->OldSWIV-8-(int)swivec>>2|0xEA000000;
- swi(OS_ChangeEnvironment,IN(R0|R1),2,w->OldPrefetchAbort);
- swi(OS_ChangeEnvironment,IN(R0|R1),3,w->OldDataAbort);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),7,w->OldCallBack,w->OldCallBackR12,w->OldCallBackRegs);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
- }
-
- void ClaimExtVecs( WKSP *w )
- { swi(OS_Claim,IN(R0|R1|R2),3,&ExtWriteC,w);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&ExtError,w,&w->errPC);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&ExtUpCall,w);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&ExtExit,w);
- }
-
- void ReleaseExtVecs( WKSP *w )
- { swi(OS_Release,IN(R0|R1|R2),3,&ExtWriteC,w);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
- }
-
- void Virtual(WKSP *w)
- {
- virtualmem(w);
- ClaimVVecs(w);
- }
-
- void Normal(WKSP *w)
- {
- ReleaseVVecs(w);
- normalmem(w);
- }
-
- void V2Ext( WKSP *w )
- {
- ReleaseVVecs(w);
- ClaimExtVecs(w);
- }
-
- void Ext2V( WKSP *w )
- {
- ReleaseExtVecs(w);
- ClaimVVecs(w);
- }
-
- void Ext2Norm( WKSP *w)
- {
- ReleaseExtVecs(w);
- normalmem(w);
- }
-
- void Norm2Ext( WKSP *w)
- {
- virtualmem(w);
- ClaimExtVecs(w);
- }
-
-
- /* ******************** Virtual mode handlers */
- WKSP *CVWantAddr(WKSP *w, int start, int len)
- {
- if (len<0)
- start += len, len= -len;
- if (w->regs[15]&3)
- { Normal(w);
- printf("***** CWantAddr called from non-user mode. Disaster! *****\n");
- RealDoOff(w);
- }
- if (!WriteRange(w,start,start+len))
- { Normal(w);
- printf("***** CWantAddr can't get desired area: %08x+%08x****\n",start,len);
- RealDoOff(w);
- }
- return w;
- }
-
- void doeschand(WKSP *w,int n)
- { w->EscapeCondition = n;
- if (w->Escape != -1) {
- int result, * ruser = w->regs;
- if (w->EscapeR12 != -1)
- WriteRange(w, w->EscapeR12, w->EscapeR12+512);
- ReadRange(w, w->Escape, w->Escape+8);
- result = CallEscapeHandler(w->Escape, w->EscapeR12, (w->EscapeCondition == 2) ? 0x40 : 0);
- if (result == 1) {
- int j, * rcallback = (int *) w->CallBackBuf;
- /* call back flag is set */
- WriteRange(w, w->CallBackR12, w->CallBackR12 + 512);
- WriteRange(w, w->CallBackBuf, w->CallBackBuf + 16 * 4);
- ReadRange(w, w->CallBack, w->CallBack + 8);
- for (j = 0; j < 16; j++)
- rcallback[j] = ruser[j]; /* save user registers into callback buffer */
- ruser[12] = w->CallBackR12;
- ruser[15] = w->CallBack;
- }
- }
- }
-
- WKSP *CVCallBack(WKSP *w)
- { Normal(w);
- Poll(w);
- Virtual(w);
- if (1==w->EscapeCondition)
- doeschand(w,2);
- worksemaphore=1; /* Ready to reenable when we exit */
- return w;
- }
-
- WKSP *CVSWIV(WKSP *w,int instr)
- {
- int *r=w->regs;
- char s[256];
- struct Error *err=0;
- int psw,i;
- int swinum=instr&~(XOS_Bit|0xFF000000);
- r[15]&=~V_bit;
- #if 0
- Normal(w);
- swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
- printf("Swi %s PC=%08x ",s,r[15]);
- for (i=0;i<=14;i++)
- printf("R%d=%08x ",i,r[i]);
- printf("...");
- Virtual(w);
- #endif
- switch(swinum) {
- /* input/output */
-
- /*
- * OS SWIs
- */
-
- case OS_WriteC:
- outc(w,r[0]);
- break;
-
- case OS_Write0:
- { char *p;
- ReadRange(w,r[0],r[0]+1);
- for (p=(char *)r[0];*p;p++)
- { ReadPtr(w,(int)p);
- outc(w,*p);
- }
- r[0]=(int)++p;
- }
- break;
-
- case OS_WriteS:
- { char *p=(char *)(r[15]&~0xfc000003);
- char *q=p;
- for (;*p;p++)
- { ReadPtr(w,(int)p);
- outc(w,*p);
- }
- r[15]+=(((p+1)-q)|3)+1;
- }
- break;
-
- case OS_WriteN:
- { int n;
- for ( n=0; n<r[1]; n++ )
- { ReadPtr(w,r[0]+n);
- outc(w,((char *)r[0])[n]);
- }
- }
- break;
-
- case OS_NewLine:
- outc(w,'\r'); outc(w,'\n');
- break;
-
- case OS_ReadC:
- r[0]=getc(w);
- if (-1==r[0])
- { r[0] = 27;
- r[15]|=C_bit;
- }
- else
- r[15]&=~C_bit;
- if (1==w->EscapeCondition)
- doeschand(w,2);
- break;
-
- case OS_ReadLine:
- { char buf[256];
- int n=0,c;
- r[15]&=~C_bit;
- for (;;)
- { c=getc(w);
- switch (c)
- {
- case 13: case 10:
- buf[n]=13;
- break;
-
- case 27: case -1:
- r[15]|=C_bit;
- break;
-
- case 127: case 8:
- if (n>0)
- { outc(w,127); n--; }
- else
- outc(w,7);
- continue;
-
- case 21:
- while (n>0)
- { outc(w,127); n--; }
- continue;
-
- default:
- if (r[2]<=c && c<=r[3])
- { if (n<r[1]-1 && n<255)
- { buf[n++]=c;
- outc(w,c);
- }
- else
- outc(w,7);
- }
- else
- outc(w,7);
- continue;
-
- }
- outc(w,'\r'); outc(w,'\n');
- break;
- }
- WriteRange(w,r[0],r[0]+n+1);
- memcpy((void *)r[0],buf,n+1);
- r[1]=n;
- }
- if (1==w->EscapeCondition)
- doeschand(w,2);
- break;
-
- case OS_Byte:
- switch (r[0])
- { default: goto uk;
- case 0: /* display os version */
- Normal(w);
- err = swix(OS_Byte,IN(R0|R1)|OUT(R1),0,r[1],&r[1]);
- Virtual(w);
- break;
- case 2: /* switch input streams */
- #ifdef DEBUG
- Normal(w);
- printf("(FX 2,%d)",r[1]);
- Virtual(w);
- #endif
- break;
- case 3: /* switch output streams */
- #ifdef DEBUG
- Normal(w);
- printf("(FX 3,%d)",r[1]);
- Virtual(w);
- #endif
- break;
- case 15: /* clear input or all buffers */
- break;
- case 21: /* clear specific buffer */
- break;
- case 124: /* clear esc cond immed */
- w->EscapeCondition = 0;
- break;
- case 125: /* cause esc cond */
- doeschand(w,2);
- break;
- case 126: /* acknowledge escape cond */
- r[1]=w->EscapeCondition?0xff:0;
- if (w->EscapeCondition)
- doeschand(w,0);
- break;
- case 129: /* read keyboard for information */
- if (r[2] != 0xFF)
- {
- r[1]=lowgetc(w);
- if (r[1] == -1) r[2] = 0xFF;
- else r[2] = 0;
- } else goto uk;
- break;
- case 160:
- case 161:
- err = swix(OS_Byte,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
- break;
- case 0xDA: /* Read/write bytes in VDU queue */
- r[1]=0;
- break;
- case 0xDC: /* Read/write escape character */
- { int old = w->EscapeChar;
- w->EscapeChar = (w->EscapeChar&r[2])^r[1];
- r[1] = old;
- break;
- }
- case 0xE5: /* Read/write escape char enable */
- { int old = w->EscapeCharEnable;
- w->EscapeCharEnable = (w->EscapeCharEnable&r[2])^r[1];
- r[1] = old;
- break;
- }
- }
- break;
-
- case OS_Plot:
- Normal(w);
- err = swix(OS_Plot,IN(R0|R1|R2),r[0],r[1],r[2]);
- Virtual(w);
- break;
-
- case OS_SerialOp:
- err = ERR(&NotAllowed);
- break;
-
- case OS_Word:
- switch (r[0])
- { default: goto uk;
- case 1: case 2: case 3: case 4: case 14:
- WriteRange(w, r[1],r[1]+256);
- err = swix(OS_Word,IN(R0|R1),r[0],r[1]);
- break;
- }
- break;
-
- case OS_ReadUnsigned:
- ReadRange(w,r[1],r[1]+256);
- err = swix(OS_ReadUnsigned,IN(R0|R1|R2)|OUT(R1|R2),r[0],r[1],r[2],&r[1],&r[2]);
- break;
-
- case OS_EnterOS:
- #ifdef DEBUG
- Normal(w);
- printf("***OS_EnterOS (ignored) from %08x ****\n",r[15]);
- Virtual(w);
- #endif
- if (w->ingos) {
- r[15] = r[15] | 0x03;
- }
- break;
-
- case OS_IntOff:
- #ifdef DEBUG
- Normal(w);
- printf("***OS_IntOff (ignored) from %08x ****\n",r[15]);
- Virtual(w);
- #endif
- break;
-
- case OS_IntOn:
- #ifdef DEBUG
- Normal(w);
- printf("***OS_IntOn (ignored) from %08x ****\n",r[15]);
- Virtual(w);
- #endif
- break;
-
- case OS_Exit:
- #ifdef DEBUG
- Normal(w);
- printf("***OS_Exit from %08x ****\n",r[15]);
- Virtual(w);
- #endif
- if (-1==w->Exit)
- {
- if (w->started_ingos) {
- usermode();
- strcpy(w->command, "gos");
- swi(OS_CLI,IN(R0),w->command);
- }
- else {
- Normal(w);
- printflush(w);
- RealDoOff(w);
- }
- }
-
- /*
- * The return value Sys$ReturnCode has to be set here
- * Normally OS_Exit does this, but is never called here.
- */
- if (r[1] == 0x58454241) { /* ABEX */
- int val = r[2];
- Normal(w);
- err = swix(OS_SetVarVal, IN(R0|R1|R2|R3|R4),"Sys$ReturnCode", &val, 4, 0, 1);
- Virtual(w);
- }
- r[15] = w->Exit;
- r[12] = w->ExitR12;
- break;
-
- case OS_GenerateError:
- { char buf[264];
- Normal(w);
- FromMem(w,r[0],buf,sizeof(buf));
- printf("***GenerateError: PC=%08x %d %s\n",r[15],((int *)buf)[0],buf+4);
- Virtual(w);
- }
- getc(w);
- err = (void *)r[0];
- break;
-
- case OS_ChangeEnvironment:
- switch (r[0])
- { int t;
- #define ifswap(x,y) ((x)?((t)=(x),(x)=(y),(y)=(t)):((x)=(y)))
- default: goto uk;
- case 0: ifswap(r[1],w->MemoryLimit); break;
- case 1: ifswap(r[1],w->UndefinedInstruction); break;
- case 2: ifswap(r[1],w->PrefetchAbort); break;
- case 3: ifswap(r[1],w->DataAbort); break;
- case 4: ifswap(r[1],w->AddressException); break;
- case 5: ifswap(r[1],w->OtherExceptions); break;
- case 6: ifswap(r[1],w->Error); ifswap(r[2],w->ErrorR0); ifswap(r[3],w->ErrorBuf); break;
- case 7: ifswap(r[1],w->CallBack); ifswap(r[2],w->CallBackR12); ifswap(r[3],w->CallBackBuf); break;
- case 8: ifswap(r[1],w->BreakPoint); ifswap(r[2],w->BreakPointR12); ifswap(r[3],w->BreakPointBuf); break;
- case 9: ifswap(r[1],w->Escape); ifswap(r[2],w->EscapeR12); break;
- case 10: ifswap(r[1],w->Event); ifswap(r[2],w->EventR12); break;
- case 11: ifswap(r[1],w->Exit); ifswap(r[2],w->ExitR12); break;
- case 12: ifswap(r[1],w->UnusedSWI); ifswap(r[2],w->UnusedSWIR12); break;
- case 13: ifswap(r[1],w->ExceptionRegs); break;
- case 14: ifswap(r[1],w->ApplicationSpace); break;
- case 15: ifswap(r[1],w->CurrentlyActiveObject); break;
- case 16: ifswap(r[1],w->UpCall); ifswap(r[2],w->UpCallR12); break;
- }
- break;
-
- case OS_SetEnv:
- { int t;
- ifswap(r[0],w->Exit);
- ifswap(r[1],w->MemoryLimit);
- ifswap(r[2],w->ApplicationSpace);
- ifswap(r[4],w->UndefinedInstruction);
- ifswap(r[5],w->PrefetchAbort);
- ifswap(r[6],w->DataAbort);
- ifswap(r[7],w->AddressException);
- }
- break;
-
- case OS_Control: {
- int t;
- ifswap(r[0],w->Error); ifswap(r[1],w->ErrorBuf);
- ifswap(r[2],w->Escape);
- ifswap(r[3],w->Event);
- }
- break;
-
- case OS_ReadVduVariables: {
- int i = 0, value;
- Normal(w);
- while (FromMem(w, r[0] + i, &value, 4), value != -1) i += 4;
- Virtual(w);
- ReadRange(w, r[0], r[0] + i);
- WriteRange(w, r[1], r[1] + i);
- err = swix(OS_ReadVduVariables, IN(R0|R1), r[0], r[1]);
- }
- break;
-
- case OS_GetEnv:
- r[0]=(int)&w->command[0];
- r[1]=w->MemoryLimit;
- r[2]=(int)&w->starttime[0];
- break;
-
- case OS_ReadVarVal:
- ReadRange(w,r[0],r[0]+256);
- if (r[2]>=0)
- WriteRange(w,r[1],r[1]+r[2]);
- 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]);
- break;
-
- case OS_SetVarVal:
- ReadRange(w, r[0], r[0] + 256);
- if (r[2] > 0)
- ReadRange(w, r[1], r[1] + r[2]);
- if (r[3] > 0)
- ReadRange(w, r[3], r[3] + 256);
- err = swix(OS_SetVarVal,IN(R0|R1|R2|R3|R4)|OUT(R3|R4),r[0],r[1],r[2],r[3],r[4],&r[3],&r[4]);
- break;
-
- case OS_Module:
- switch (r[0])
- { default: goto uk;
- case 6:
- Normal(w);
- err = swix(OS_Module,IN(R0|R3)|OUT(R2),r[0],r[3],&r[2]);
- Virtual(w);
- break;
- case 7:
- Normal(w);
- err = swix(OS_Module,IN(R0|R2),r[0],r[2]);
- Virtual(w);
- break;
- case 18:
- ReadRange(w,r[1],r[1]+256);
- err = swix(OS_Module,IN(R0|R1)|OUT(R1|R2|R3|R4|R5),
- r[0],r[1],&r[1],&r[2],&r[3],&r[4],&r[5]);
- break;
- }
- break;
-
- case OS_ConvertHex8:
- WriteRange(w,r[1],r[1]+r[2]);
- err = swix(OS_ConvertHex8,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
- break;
-
- case OS_CLI:
- { char buf[256];
- Normal(w);
- FromMem(w,r[0],buf,sizeof(buf));
- if ((buf[0]|0x20)=='g' && (buf[1]|0x20)=='o' && (buf[2]|0x20)=='s' && buf[3]<=' ')
- w->ingos = 1;
- /*
- * Before loading a new programme into memory the old and new pages
- * should be on the same addresses.
- */
- FixMemoryPages(w);
- {
- int i = 0;
- while ((w->command[i] = buf[i]) >= ' ') i++;
- w->command[i] = 0;
- }
- err=swix(OS_CLI,IN(R0),buf);
- Virtual(w);
- }
- break;
-
- case OS_Mouse:
- Normal(w);
- err = swix(OS_Mouse,OUT(R0|R1|R2|R3),&r[0],&r[1],&r[2],&r[3]);
- Virtual(w);
- break;
-
- case OS_ReadMonotonicTime:
- Normal(w);
- err = swix(OS_ReadMonotonicTime,OUT(R0),&r[0]);
- Virtual(w);
- break;
-
- case OS_SWINumberFromString:
- { char buf[256];
- Normal(w);
- FromMem(w,r[1],buf,sizeof(buf));
- err=swix(OS_SWINumberFromString,IN(R1)|OUT(R0),&buf,&r[0]);
- Virtual(w);
- }
- break;
-
- /* Filesystem SWIs */
- case OS_Find:
- if (!r[0])
- { Normal(w);
- err = swix(OS_Find,IN(R0|R1)|OUT(PSW),r[0],r[1],&psw);
- Virtual(w);
- }
- else
- { char name[256];
- char path[256];
- Normal(w);
- FromMem(w,r[1],name,sizeof(name));
- if ((r[0]&3)==1 || (r[0]&3)==2)
- FromMem(w,r[2],path,sizeof(path));
- err = swix(OS_Find,IN(R0|R1|R2)|OUT(PSW|R0),r[0],name,path,&psw,&r[0]);
- Virtual(w);
- }
- break;
-
- case OS_BGet: case OS_BPut: case OS_Args:
- Normal(w);
- 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]);
- r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
- Virtual(w);
- break;
-
- case OS_GBPB:
- Normal(w);
- if (1<=r[0] && r[0]<=4)
- { /* read/write variety */
- while (r[3]>0)
- { RANGE k = Physical(w,r[2],r[2]+r[3]);
- int p = k.start;
- int l = k.end-k.start;
- int q,m;
- 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]);
- r[2]+=q-p;
- r[3]-=l-m;
- if (err || m)
- break;
- } }
- else if (5<=r[0] && r[0]<=8)
- { char buf[2048];
- FromMem(w,r[2],buf,sizeof(buf));
- 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]);
- ToMem(w,buf,r[2],sizeof(buf));
- }
- else if (9<=r[0] && r[0]<=12)
- { char dirname[256];
- char wild[256];
- RANGE k;
- FromMem(w,r[1],&dirname,sizeof(dirname));
- if (r[6])
- FromMem(w,r[6],&wild,sizeof(wild));
- k = Physical(w,r[2],r[2]+r[5]);
- err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(PSW|R3|R4),
- r[0],dirname,k.start,r[3],r[4],k.end-k.start,r[6]?wild:0,
- &psw,&r[3],&r[4]);
- }
- else
- { Virtual(w);
- goto uk;
- }
- r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
- Virtual(w);
- break;
-
- case OS_File:
- Normal(w);
- switch(r[0])
- { default: Virtual(w); goto uk;
- case 0: case 10: /* save a block of memory */
- {
- char name[256];
- int s[16];
- int h;
- FromMem(w,r[1],name,sizeof(name));
- err = swix(OS_Find,IN(R0|R1)|OUT(R0),0x8F,name,&h);
- if (err) break;
- /* write code from OS_GBPB handler above */
- s[0]=2; s[1]=h; s[2]=r[4]; s[3]=r[5]-r[4];
- while (s[3]>0)
- { RANGE k = Physical(w,s[2],s[2]+s[3]);
- int p = k.start;
- int l = k.end-k.start;
- int q,m;
- err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R2|R3|R4),s[0],s[1],p,l,s[4],&psw,&q,&m,&s[4]);
- s[2]+=q-p;
- s[3]-=l-m;
- if (err || m)
- break;
- }
- err = swix(OS_Find,IN(R0|R1),0,h);
- if (err) break;
- if (r[0] == 0)
- {
- err = swix(OS_File,IN(R0|R1|R2),2,name,r[2]);
- if (err) break;
- err = swix(OS_File,IN(R0|R1|R3),3,name,r[3]);
- } else
- {
- err = swix(OS_File,IN(R0|R1|R2),18,name,r[2]);
- }
- break;
- }
- case 5: case 13: case 15: case 17: /* read cat info */
- case 20: case 21: case 22: case 23:
- { int h;
- char path[256];
- char name[256];
- FromMem(w,r[1],name,sizeof(name));
- if (r[0]==13 || r[0]==15 || r[0]==21 || r[0]==22)
- FromMem(w,r[4],path,sizeof(path));
- err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5|R6),r[0],name,path,
- &r[0],&r[2],&r[3],&r[4],&r[5],&h);
- if (20<=r[0] && r[0]<=23)
- r[6]=h;
- break;
- }
- case 1: case 2: case 3: case 4: case 9: case 18: /* Write cat info */
- case 6: /* Delete */
- case 7: case 11: /* Create */
- case 8: /* Create directory */
- { char name[256];
- FromMem(w,r[1],name,sizeof(name));
- 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],
- &r[0],&r[2],&r[3],&r[4],&r[5]);
- break;
- }
- case 12: case 14: case 16: case 255: /* load */
- { int h;
- char path[256];
- char name[256];
- RANGE k;
- int l,m,q;
- int p=(r[3]&0xFF)?-1:r[2];
- int t = r[0]==255?0:r[0]==12?1:r[0]==14?2:r[0]==16?3:0;
- FromMem(w,r[1],name,sizeof(name));
- if (t==1 || t==2)
- FromMem(w,r[4],path,sizeof(path));
- err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5),"\x05\x0D\x0F\x11"[t],name,path,
- &r[0],&r[2],&r[3],&r[4],&r[5]);
- if (err)
- break;
- err = swix(OS_Find,IN(R0|R1|R2)|OUT(R0),0x4C+t,name,path,&h);
- if (err)
- break;
- if (p==-1)
- p = r[2];
- l = r[4];
- while (l>0)
- { k = Physical(w,p,p+l);
- if (!k.start)
- { err=ERR(&BadMemory);
- break;
- }
- err = swix(OS_GBPB,IN(R0|R1|R2|R3)|OUT(R2|R3),4,h,k.start,k.end-k.start,&q,&m);
- if (err)
- break;
- if (q!=k.end || m)
- { err = ERR(&Failed);
- break;
- }
- p+=k.end-k.start;
- l-=k.end-k.start;
- }
- if (!err)
- err = swix(OS_Find,IN(R0|R1),0,h);
- else
- (void)swix(OS_Find,IN(R0|R1),0,h);
- }
- }
- Virtual(w);
- break;
-
- case OS_FSControl:
- Normal(w);
- switch (r[0])
- { default: Virtual(w); goto uk;
- case 27: /* Wipe objects */
- { char name[256];
- FromMem(w,r[1],name,sizeof(name));
- 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]);
- break;
- }
- }
- Virtual(w);
- break;
-
- /*
- * RISCOS extension module SWIs
- */
-
- #ifndef SharedCLibrary_LibInitAPCS_R
- #define SharedCLibrary_LibInitAPCS_R 0x80681
- #endif
- case SharedCLibrary_LibInitAPCS_R:
- ReadRange(w,r[0],r[0]+256);
- WriteRange(w,r[1],r[1]+32768);
- err = swix(SharedCLibrary_LibInitAPCS_R,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(R0|R1|R2|R6),
- r[0],r[1],r[2],r[3],r[4],r[5],r[6],&r[0],&r[1],&r[2],&r[6]);
- break;
-
- case DDEUtils_Prefix:
- Normal(w);
- if (r[0] > 0) ReadRange(w,r[0],r[0]+256);
- err = swix(DDEUtils_Prefix, IN(R0), r[0]);
- Virtual(w);
- break;
-
- case DDEUtils_SetCLSize:
- Normal(w);
- free(w->DDECL);
- w->DDECLSize = r[0];
- w->DDECL = alloc(r[0]);
- Virtual(w);
- break;
-
- case DDEUtils_SetCL:
- Normal(w);
- FromMem(w,r[0],w->DDECL,w->DDECLSize);
- Virtual(w);
- break;
-
- case DDEUtils_GetCLSize:
- r[0] = w->DDECLSize;
- break;
-
- case DDEUtils_GetCL:
- Normal(w);
- ToMem(w,w->DDECL,r[0],w->DDECLSize);
- w->DDECLSize = 0;
- Virtual(w);
- break;
-
- case DDEUtils_ThrowbackStart:
- Normal(w);
- err = swix(DDEUtils_ThrowbackStart,0);
- Virtual(w);
- break;
-
- case DDEUtils_ThrowbackSend:
- { char file[256];
- char msg[256];
- Normal(w);
- FromMem(w,r[2],&file,sizeof(file));
- if (r[0])
- FromMem(w,r[5],&msg,sizeof(msg));
- err = swix(DDEUtils_ThrowbackSend,IN(R0|R2|R3|R4|R5),r[0],file,r[3],r[4],msg);
- Virtual(w);
- break;
- }
-
- case DDEUtils_ThrowbackEnd:
- Normal(w);
- err = swix(DDEUtils_ThrowbackEnd,0);
- Virtual(w);
- break;
-
- case MessageTrans_Lookup:
- case MessageTrans_ErrorLookup:
- ReadRange(w,r[1],r[1]+256);
- if (r[2])
- WriteRange(w,r[2],r[2]+r[3]);
- err = swix(swinum,IN(R0|R1|R2|R3|R4|R5|R6|R7)|OUT(R0|R2|R3),
- r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],&r[0],&r[2],&r[3]);
- break;
-
- case Wimp_ReadSysInfo:
- err = swix(Wimp_ReadSysInfo,IN(R0)|OUT(R0),r[0],&r[0]);
- break;
-
- case Wimp_SendMessage:
- ReadRange(w,r[1],r[1]+256);
- err = swix(Wimp_SendMessage,IN(R0|R1|R2)|OUT(R2),r[0],r[1],r[2],&r[2]);
- break;
-
- case FPEmulator_Version:
- err = swix(FPEmulator_Version,OUT(R0),&r[0]);
- break;
-
- case Territory_ReadCurrentTimeZone:
- err = swix(Territory_ReadCurrentTimeZone,OUT(R0|R1),&r[0],&r[1]);
- break;
-
- case Territory_ReadTimeZones:
- err = swix(Territory_ReadTimeZones,IN(R0)|OUT(R0|R1|R2|R3),r[0],&r[0],&r[1],&r[2],&r[3]);
- break;
-
- case Territory_ConvertTimeToOrdinals:
- ReadRange(w,r[1],r[1]+5);
- WriteRange(w,r[2],r[2]+32);
- err = swix(Territory_ConvertTimeToOrdinals,IN(R0|R1|R2),r[0],r[1],r[2]);
- break;
-
- case Wimp_SlotSize:
- /*
- * When this SWI is allowed, the wimpslot will be expanded to the
- * maximum value, or sometimes to a wrong value.
- * In the first case there is no space left for Edit's taskwindow,
- * so Virtual will stop.
- * I think a programme running under Virtual must not change its
- * 'Wimp_Slot'. The user can make any changes to the WimpSlot by
- * dragging a bar in the Tasks window.
- *
- * When a task wants to enlarge the wimpslot, ie make the 'DiskSlot'
- * bigger, will this be allowed.
- *
- * So this code is not compiled
- *
- swi(Wimp_SlotSize,IN(R0|R1),OUT(R1|R2),-1,r[1],&r[1],&r[2]);
- if (r[0]!=-1)
- { w->ApplicationSpace = r[0];
- w->MemoryLimit = r[0];
- }
- r[0]=w->ApplicationSpace;
- break;
- *
- * So here's my new code
- */
- if (r[0] != -1) {
- if (r[0] > w->ApplicationSpace - K32) { /* task asks for wimpslot extension */
- int i, OldAppSpace = w->ApplicationSpace;
- w->ApplicationSpace = ADDR(PLACE(r[0] + K32 + K32));
- if (w->ApplicationSpace > M24)
- w->ApplicationSpace = M24;
- w->MemoryLimit = w->ApplicationSpace;
- for (i = PLACE(OldAppSpace); i < PLACE(w->ApplicationSpace); i++) {
- w->ourmem[i] = TAGLOC(ZERO, 0);
- }
- }
- }
- r[0] = w->ApplicationSpace - K32;
- break;
-
- /* BASICTrans swis */
- case BASICTrans_HELP:
- case BASICTrans_Message:
- case BASICTrans_Error:
- V2Ext(w);
- err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
- OUT(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
- r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
- &r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
- Ext2V(w);
- break;
-
- case TaskWindow_TaskInfo:
- Normal(w);
- if (r[0] == 0)
- r[0] = 1;
- else
- err = swix(TaskWindow_TaskInfo,IN(R0)|OUT(R0),r[0],&r[0]);
- Virtual(w);
- break;
-
- case Virtual_TaskInfo:
- Normal(w);
- if (r[0] == 0)
- r[0] = 1;
- else
- err = swix(Virtual_TaskInfo,IN(R0)|OUT(R0),r[0],&r[0]);
- Virtual(w);
- break;
-
- case VM_TaskInfo:
- err = ERR(&NotAllowed);
- break;
-
- /*
- * Default (unrecognized SWIs) handling
- */
-
- default:
- if (swinum>=0x100 && swinum<0x200)
- { outc(w,(char)swinum);
- break;
- }
-
- uk:
- Normal(w);
- swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
- printf("UKSwi %s PC=%08x ",s,r[15]);
- for (i=0;i<=8;i++)
- printf("R%d=%08x ",i,r[i]);
- printf("Allow(Yn)?\n");
- Virtual(w);
- lp:
- switch (getc(w))
- { case -1:
- w->EscapeCondition = 0;
- /* FALL THROUGH */
- default:
- goto lp;
- case 'n': case'N':
- err = ERR(&NotAllowed);
- break;
- case 'y': case 'Y': case 13:
- V2Ext(w);
- err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
- OUT(PSW|R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
- r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
- &psw,&r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
- r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
- Ext2V(w);
- break;
- }
- break;
-
- }
- if (!err)
- return w;
- if (instr&XOS_Bit) /* X form */
- { r[0]=(int)err;
- r[15]|=V_bit;
- return w;
- }
- if (-1==w->Error)
- { Normal(w);
- printf("***Error:%s",err->msg);
- RealDoOff(w);
- }
- WriteRange(w,w->ErrorBuf,w->ErrorBuf+264);
- ((int*)w->ErrorBuf)[0] = r[15];
- ((int*)w->ErrorBuf)[1] = err->num;
- strcpy( (char *)&((int*)w->ErrorBuf)[2], err->msg );
- r[0] = w->ErrorR0;
- r[15] = w->Error & ~3;
- return w;
- }
-
- int CVUpCall( int r0, int r1, int r2, WKSP *w)
- { /* Called with sp a 1K chunk out of svcstack */
- switch(r0)
- { case 256:
- r0 = 0; /* Not quite sure what on earth is going on here, but better stop it! */
- break;
- default:
- break;
- }
- return r0;
- }
-
-
- /* ******************** Ext mode handlers */
- int CExtWriteC(int c, WKSP *w)
- { /* called with stack a 1K bit out of svcstack */
- w->outbuf[w->outcount++]=c;
- if (w->outcount>=OUTMAX-2)
- { Ext2Norm(w);
- printflush(w);
- FindPages(w);
- Norm2Ext(w);
- }
- return 0x80000000; /* VC CC */
- }
-
- int CExtUpCall(int r0,int r1,int r2,WKSP *w)
- { /* Called with sp a 1K chunk out of svcstack */
- switch(r0)
- { case 256:
- r0 = 0;
- break;
- default:
- break;
- }
- return r0;
- }
-
- int CExtError(WKSP *w)
- { /* Called in user, ext mode */
- printf("ExtError PC=%08x errnum %d errmess %s****\n",w->errPC,w->errnum,w->errmess);
- Ext2V(w);
- return (int)&w->errnum;
- }
-
- void CExtExit(WKSP *w)
- { /* Called in user, ext mode */
- Ext2V(w);
- }
-
-
- /* ******************** Normal mode handlers */
- void __main(private *p,char *cmd)
- { /* This is called in user mode, with its stack at the top of the WimpSlot */
- wimp_eventdata b;
- struct Error *e;
- char *buf[512];
- int ourtask,outtask,txt,i;
- WKSP *w;
-
- #ifdef DEBUG
- printf("%s\n", cmd);
- #endif
-
- swi(OS_ReadArgs,IN(R0|R1|R2|R3),
- ",wimpslot/K,name/K,pagefile/K,ctrl/S,display/S,quit/S,task,txt,discslot/K,nice/K", cmd, buf, sizeof(buf));
-
- #ifdef DEBUG
- printf("os_readargs passed\n");
- #endif
-
- if (buf[0] == 0) {
- strcpy(b.msg.data.chars+8, "gos ");
- strcpy(b.msg.data.chars+12, cmd);
- }
- else
- strcpy(b.msg.data.chars+8,cmd);
-
- swi(Wimp_Initialise,IN(R0|R1|R2)|OUT(R0|R1),200,0x4b534154,
- buf[2]?buf[2]:"Virtual",&wimp_version,&ourtask);
- if (!buf[7] || !buf[8])
- { memcpy(b.msg.data.chars,"virtual ",8);
- b.msg.hdr.action = 0x808c5; /* TaskWindow_NewTask; */
- b.msg.hdr.your_ref = 0;
- b.msg.hdr.size = (21+(strlen(b.msg.data.chars)|3));
- swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,0);
- swi(OS_Exit,0);
- }
- outtask = xtoi(buf[7]);
- txt = xtoi(buf[8]);
-
- b.msg.hdr.action = /*TaskWindow_Ego*/ 0x808c2;
- b.msg.hdr.your_ref = 0;
- b.msg.data.words[0]=txt;
- b.msg.hdr.size = 24;
- swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,outtask);
-
- w = alloc(sizeof(WKSP));
- p->w = w;
- p->uses++;
- w->private = p;
- w->outtask = outtask;
- w->ourtask = ourtask;
- w->outcount = 0;
- w->incount = 0;
- w->instart = 0;
- w->EscapeCondition = 0;
- w->EscapeChar = 27;
- w->EscapeCharEnable = 0;
- w->ingos = 0;
- w->started_ingos = 0;
- w->moreavailable = 0;
-
- /* check for DDE extended command line */
- e = swix(DDEUtils_GetCLSize, OUT(R0), &i);
- if ((!e) && (i != 0))
- {
- w->DDECL = alloc(i);
- w->DDECLSize = i;
- swix(DDEUtils_GetCL, IN(R0), w->DDECL);
- } else
- {
- w->DDECL = 0;
- w->DDECLSize = 0;
- }
-
- if (buf[10] == 0)
- {
- w->nice_run = 15; /* default */
- w->nice_delay = 0;
- } else
- {
- int level =sizetoi(buf[10]);
- w->nice_delay = 0;
- switch (level)
- {
- case 0: w->nice_run = 100;break;
- case 1: w->nice_run = 75; break;
- case 2: w->nice_run = 45; break;
- case 3: w->nice_run = 25; break;
- case 4: w->nice_run = 15; break;
- case 5: w->nice_run = 13;
- w->nice_delay = 10;
- break;
- case 6: w->nice_run = 11;
- w->nice_delay = 25;
- break;
- case 7: w->nice_run = 8;
- w->nice_delay = 50;
- break;
- case 8: w->nice_run = 7;
- w->nice_delay = 80;
- break;
- case 9: w->nice_run = 5;
- w->nice_delay = 100;
- break;
- default: w->nice_run = 100; break;
- }
- }
-
- e = swix(OS_RemoveTickerEvent,IN(R0|R1),&OurCallEvery,p);
- e = swix(OS_CallEvery,IN(R0|R1|R2),w->nice_run,&OurCallEvery,p);
-
- strcpy(w->pagefilename,buf[3]?buf[3]:"<Swap$Path>pagefile0");
- strcpy(w->command,buf[0]?buf[0]:"GOS");
-
- w->ApplicationSpace=buf[9]?sizetoi(buf[9])+K32:M24;
- if (w->ApplicationSpace>M24)
- w->ApplicationSpace=M24;
-
- if (buf[1] != 0)
- {
- int slotsize = sizetoi(buf[1]);
- if (slotsize<K32) slotsize = K32;
- swi(Wimp_SlotSize, IN(R0|R1), slotsize, -1);
- }
-
- w->UpCall = w->Error = w->Exit = w->Escape = w->UndefinedInstruction = w->PrefetchAbort = w->DataAbort = w->AddressException = -1;
- i=0;
- while (0!=(e=swix(OS_Find,IN(R0|R1)|OUT(R0),0x80,w->pagefilename,&w->pagefile)) && i<10)
- w->pagefilename[strlen(w->pagefilename)-1]++,i++;
- if (e)
- { swi(Wimp_ReportError,IN(R0|R1|R2),e,2,"Virtual");
- swi(OS_Exit,0);
- }
- svcmode();
- swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
- #ifdef DEBUG
- printf("cmd=%s\n",w->command);
- printf("wimpslot=%08x\n",w->ApplicationSpace);
- printf("name=%s\n",buf[2]);
- printf("pagefile=%s\n",w->pagefilename);
- printf("ctrl=%08x\n",(int)buf[4]);
- printf("display=%08x\n",(int)buf[5]);
- printf("quit=%08x\n",(int)buf[6]);
- printf("task=%08x\n",outtask);
- printf("txt=%08x\n",txt);
- printf("nice=%d\n",w->nice_run);
- #endif
- swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),6,&NormError,w,&w->errPC,
- &w->OldError,&w->OldErrorR0,&w->OldErrorBuf);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),16,&NormUpCall,w,&w->OldUpCall,&w->OldUpCallR12);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),11,&NormExit,w,&w->OldExit,&w->OldExitR12);
-
- Initourmem(w);
- SetWimpMemMap(w);
- SetVirtualSlot(w,w->ApplicationSpace-K32);
- w->MemoryLimit = w->ApplicationSpace;
- #ifdef DEBUG
- printf("Going virtual\n");
- #endif
- Virtual(w);
- usermode();
- worksemaphore = 0; /* Enable interupts */
- #ifdef DEBUG
- swi(OS_Write0,IN(R0),"This is virtual: OS_CLI ");
- swi(OS_Write0,IN(R0),w->command);
- swi(OS_NewLine,0);
- #endif
-
- if ((w->command[0]|0x20)=='g' && (w->command[1]|0x20)=='o' && (w->command[2]|0x20)=='s' && w->command[3]<=' ')
- w->started_ingos = 1;
- else
- w->started_ingos = 0;
-
- if (buf[6] == 0) w->started_ingos = 1;
-
- swi(OS_CLI,IN(R0),w->command);
- swi(OS_Exit,0);
- }
-
- void RealDoOff(WKSP *w)
- {
- private *priv=w->private;
- wimp_eventdata b;
- #ifdef DEBUG
- printf("RealDoOff\n");
- #endif
- swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
- printflush(w);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),6,w->OldError,w->OldErrorR0,w->OldErrorBuf);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,w->OldExit,w->OldExitR12);
- swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,w->OldUpCall,w->OldUpCallR12);
- Finishourmem(w);
- usermode();
- b.msg.hdr.action = /*TaskWindow_Morio*/ 0x808c3;
- b.msg.hdr.your_ref = 0;
- b.msg.hdr.size = 20;
- swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,w->outtask);
- swi(Wimp_CloseDown, 0);
- swix(OS_Find,IN(R0|R1),0,w->pagefile);
- swix(OS_File,IN(R0|R1),6,w->pagefilename);
- free((char *)w->stacktop-STACKSIZE);
- free(w->DDECL);
- free(w);
- priv->uses--;
- priv->w = 0;
- swi(OS_Exit,0);
- }
-
- int CNormError( WKSP *w )
- { printf("NormError: PC=%08x errnum %d errmess %s\n",w->errPC,w->errnum,w->errmess);
- swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
- swi(Wimp_ReportError,IN(R0|R1|R2),&w->errnum,2,"Virtual");
- swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
- RealDoOff(w);
- return 0;
- }
-
- void CNormExit(WKSP *w)
- {
- #ifdef DEBUG
- printf("NormExit\n");
- #endif
- RealDoOff(w);
- }
-
- int CNormWriteC(int c, WKSP *w)
- { /* called with stack a 1K bit out of svcstack */
- w->outbuf[w->outcount++]=c;
- if (w->outcount>=OUTMAX-2)
- { printflush(w);
- FindPages(w);
- }
- return 0x80000000; /* VC CC */
- }
-
- int CNormUpCall(int r0,int r1,int r2,WKSP *w)
- { /* Called with sp a 1K chunk out of svcstack */
- switch(r0)
- { case 256:
- { char *cmd, *tptr;
- Virtual(w);
- swi(OS_GetEnv,OUT(R0|R2),&cmd,&tptr);
- if ((w->command[0]|0x20)=='g' && (w->command[1]|0x20)=='o' && (w->command[2]|0x20)=='s' && w->command[3]<=' ')
- w->ingos = 1;
- else
- w->ingos = 0;
-
- /*
- * Only execute this under RO3
- */
- if (wimp_version >= 300) strcpy(w->command,cmd);
-
- memcpy(w->starttime,tptr,5);
- worksemaphore = 0; /* Enable interrupts */
- break;
- }
- default:
- break;
- }
- return r0;
- }
-