Compiler source code listed below are analog of TinyContext for MS-DOS
and may be compiled with it. To do this all I/O functions from open() to halt() must be replaced
with it's MS-DOS analogs, Text array size must be increased from 2048 charactes
to 16384 characters (IMPORTANT!) and source code must be compiled to get cross compiler.
This cross compiler may be used to get PDP-11 compiler. For testing simhv/pdp11 emulator are used
(PDP-11/05 with 48Kb memory). Compiler binary and compiled program must be placed on punched tapes,
output code also on punched tape (in emulator environment tapes are files).
Source code:
char Text [ 2048];
word pText;
word nText;
word nLine;
word Code [ 8192];
word nCode;
word hFile;
char Heap [ 2048];
word nHeap;
word Name [ 256];
word Cls [ 256];
word Sub [ 256];
word Type [ 256];
word Size [ 256];
word Ofs [ 256];
word nName;
word nData;
word Stk [ 128];
word pStk;
char Buff [ 128];
word mul (word A, word B) is
word M:=0;
while B >0 do
word T :=A;
word I :=1;
while B-I>=I do
T:=T+T;
I:=I+I;
end
M:=M+T;
B:=B-I;
end
return M;
end
word div (word A, word B) is
word D:=0;
while A>=B do
word T :=B;
word I :=1;
while A-T>=T do
T:=T+T;
I:=I+I;
end
A:=A-T;
D:=D+I;
end
return D;
end
word mod (word A, word B) is
return A-mul(div(A,B),B);
end
word open() is
return 0;
end
word create() is
return 0;
end
word getc() is
inline 0x15C1, 0xFF68; // 012701 177550 // mov #TRS, R1
inline 0x0A89; // 005211 // inc (R1)
inline 0x35C9, 0x8080; // 032711 100200 // bit #100200, (R1)
inline 0x8104; // 100404 // bmi
inline 0x03FC; // 001774 // beq
inline 0x9C40, 0x0002; // 116100 000002 // movb 2(R1), R0
inline 0x0102; // 000402 // br
inline 0x15C0, 0xFF00; // 012700 177400 // mov #ERR, R0
end
word read() is
word P:=0;
word W:=getc();
while W!=0xFF00 do
Text[P]:=char(W);
P :=P+1;
if P>=2048 then
return P;
end
W:=getc();
end
return P;
end
char punch(word B) is
word B1:=B;
inline 0x15C1, 0xFF6C; // 012701 177554 // mov #TPS, R1
inline 0x9031, 0x0002; // 110061 000002 // movb R0, 2(R1)
inline 0x15C0, 0x0000; // 012700 000000 // mov #0, R0
inline 0x35C9, 0x8080; // 032711 100200 // bit #100200, (R1)
inline 0x8102; // 100402 // bmi
inline 0x03FC; // 001774 // beq
inline 0x0102; // 000402 // br
inline 0x15C0, 0x0001; // 012700 000001 // mov #1, R0
end
word write() is
word pCode:=0;
while pCode=nText then
pText :=0;
nText :=read();
if pText>=nText then
return char(0);
end
end
return Text[pText];
end
char Read() is
char Ch:=Look();
if Ch =char(10) then
nLine :=nLine+1;
end
pText :=pText+1;
putc (Ch);
return Ch;
end
word isalnum() is
if 'A'<=Look() then
if Look()<='Z' then
return 0;
end
end
if 'a'<=Look() then
if Look()<='z' then
return 0;
end
end
if '0'<=Look() then
if Look()<='9' then
return 0;
end
end
return 1;
end
word Digraph(char C1, char C2) is
if Buff[0]=C1 then
if Look()=C2 then
Buff[1]:=Read();
Buff[2]:=char(0);
end
end
end
char Scan() is
word pBuff:=0;
while pBuff =0 do
word sFlag:=0;
while sFlag =0 do
if Look()!=char( 9) then
if Look()!=char(10) then
if Look()!=char(13) then
if Look()!=char(32) then
sFlag:=1;
end
end
end
end
if sFlag=0 then
Read();
end
end
while isalnum()=0 do
Buff[pBuff]:= Read();
pBuff :=pBuff+1;
end
if pBuff=0 then
Buff[pBuff]:= Read();
pBuff :=pBuff+1;
end
Buff[pBuff] :=char(0);
Digraph('<', '=');
Digraph('!', '=');
Digraph('>', '=');
Digraph(':', '=');
if Buff[0]='/' then
if Look()='/' then
while Look()!=char(10) do
if Read()=char(0) then
Stop();
end
end
pBuff:=0;
end
end
end
end
word Comp(word pHeap) is
word pBuff:=0;
while Buff[pBuff]=Heap[pHeap] do
if Buff[pBuff]=char(0) then
return 0;
end
pHeap:=pHeap+1;
pBuff:=pBuff+1;
end
return 1;
end
word Find(word fFlag) is
word pName:=0;
while pName< nName do
if Comp(Name[pName])=0 then
return pName;
end
pName:=pName+1;
end
if fFlag=0 then
Stop();
end
return pName;
end
word Emi2(word W) is
Code[nCode]:=W;
nCode:=nCode+1;
end
word Emi3(word P, word W) is
//TODO
Code[P] :=W;
end
word Assign(word I) is
if Size[I]>1 then
Emi2(0x1581); // 012601 // mov (SP)+, R1
if Size[Type[I]]=1 then
Emi2(0x9031); // 110061 // movb R0, Adr(R1)
end
if Size[Type[I]]=2 then
Emi2(0x1031); // 010061 // mov R0, Adr(R1)
end
end
if Size[I]=1 then
if Size[Type[I]]=1 then
Emi2(0x901F); // 110037 // movb R0, @#Adr
end
if Size[Type[I]]=2 then
Emi2(0x101F); // 010037 // mov R0, @#Adr
end
end
Emi2(Ofs[I]);
end
word Expr() is
word eFlag:=0;
//if eFlag =0 then
if '0'<=Buff[0] then
if Buff[0]<='9' then
Emi2(0x15C0); // 012700 // mov #Val, R0
Emi2(val());
eFlag:=1;
end
end
if Buff[0]=''' then
//TODO 128..255
Emi2(0x15C0); // 012700 // mov #Val, R0
Emi2(word(Read()));
Read();
eFlag:=1;
end
if Buff[0]='(' then
Scan();
Expr();
eFlag:=1;
end
//end
if eFlag =0 then
word I:=Find(0);
if Cls[I]=1 then
Push(I);
Scan(); // (
Scan();
Expr();
I:=Pop();
end
if Cls[I]=2 then
if Size[I]>1 then
Push(I);
Scan(); // [
Scan();
Expr();
I:=Pop();
if Size[Type[I]]=1 then
Emi2(0x9C00); // 116000 // movb Adr(R0), R0
end
if Size[Type[I]]=2 then
Emi2(0x0CC0); // 006300 // asl R0
Emi2(0x1C00); // 016000 // mov Adr(R0), R0
end
end
if Size[I]=1 then
if Size[Type[I]]=1 then
Emi2(0x97C0); // 113700 // movb @#Adr, R0
end
if Size[Type[I]]=2 then
Emi2(0x17C0); // 013700 // mov @#Adr, R0
end
end
Emi2(Ofs[I]);
end
if Cls[I]=3 then
Scan(); // (
Push(I);
Sub[nName]:= 0;
word J:=I+1;
while Sub[J]=1 do
Push(J);
Scan();
Expr();
J:=Pop();
Assign(J);
J:=J+1;
end
I:=Pop();
if J=I+1 then
Scan(); // )
end
word W:=(0xFFFF-(((nCode+nCode)+4)-Ofs[I]))+1;
Emi2(0x09F7); // 004767 // jsr Ofs
Emi2(W);
end
end
Scan();
word I:=0;
if Buff[0]='+' then
I:=1;
end
if Buff[0]='-' then
I:=2;
end
if I!=0 then
Emi2(0x1026); // 010046 // mov R0, -(SP)
Push(I);
Scan();
Expr();
I:=Pop();
if I=1 then
Emi2(0x1581); // 012601 // mov (SP)+, R1
Emi2(0x6040); // 060100 // add R0, R1
end
if I=2 then
Emi2(0x1001); // 010001 // mov R0, R1
Emi2(0x1580); // 012600 // mov (SP)+, R0
Emi2(0xE040); // 160100 // sub R0, R1
end
end
end
word Cond() is
Scan();
Expr();
//TODO
word jCode:=0;
if Buff[0]='<' then
jCode:=0x8700; // 1034XX // blo Ofs
if Buff[1]='=' then
jCode:=0x8300; // 1014XX // blos Ofs
end
end
if Buff[0]='=' then
jCode:=0x0300; // 0014XX // beq Ofs
end
if Buff[0]='!' then
jCode:=0x0200; // 0010XX // bne Ofs
end
if Buff[0]='>' then
jCode:=0x8200; // 1010XX // bhi Ofs
if Buff[1]='=' then
jCode:=0x8600; // 1030XX // bhis Ofs
end
end
if jCode=0 then
Stop();
end
Emi2(0x1026); // 010046 // mov R0, -(SP)
Scan();
Expr();
Emi2(0x1581); // 012601 // mov (SP)+, R1
Emi2(0xE001); // 160001 // sub R1, R0
Emi2(jCode+2); // bxx 2
end
word Obj (word T) is
if Cls[T]!=1 then
Stop();
end
Name[nName]:=nHeap;
Type[nName]:= T;
Scan();
if Find(1)1 then
Scan(); // [
Scan();
Expr();
if Size[Type[I]]=2 then
Emi2(0x0CC0); // 006300 // asl R0
end
Emi2(0x1026); // 010046 // mov R0, -(SP)
end
Scan(); // :=
Scan();
Expr();
Assign(I);
end
if Cls[I]=3 then
Expr();
end
rFlag:=1; // 14.05.2006
end
Scan();
end
word Func(word Rts) is
Scan();
Ctrl();
while Comp(60)!=0 do // !end
Ctrl();
end
if rFlag!=0 then // 14.05.2006 // if rFlag=0 then
//Emi2(0x0087); // 000207 // rts
Emi2(Rts);
end
end
begin
Init();
hFile:=open();
pText:=0;
nText:=0;
nLine:=1;
Emi2(0x0077); // 000167 // jmp ?
nCode:=nCode+1;
Scan();
while Comp(31)!=0 do // !begin
Obj (Find(0));
char Ch:=Buff[0];
if Ch ='(' then
Cls [nName]:= 3;
Sub [nName]:= 0;
Ofs [nName]:=nCode+nCode;
nName :=nName+1;
Push(nName);
Scan();
if Buff[0]!=')' then
Obj (Find(0));
while Var(1)=',' do
Scan();
Obj (Find(0));
end
end
Scan(); // is
Func(0x0087);
Hide();
end
if Ch!='(' then
Var(0);
end
Scan();
end
Emi3 (1, (nCode+nCode)-4);
Func (0x0000);
close();
hFile:=create();
write();
close();
end
word open() is
inline 0xB4, 0x3D; // mov AH, 3DH
inline 0xB0, 0x00; // mov AL, 00H
inline 0xBA, 0x4A, 0xC1; // mov DX, @@Data+Ofs(Heap[64])
inline 0xCD, 0x21; // int 21H
end
word create() is
inline 0xB4, 0x3C; // mov AH, 03CH
inline 0xB9, 0x00, 0x00; // mov CX, 00H
inline 0xBA, 0x50, 0xC1; // mov DX, @@Data+Ofs(Heap[70])
inline 0xCD, 0x21; // int 21H
end
word read() is
inline 0xB4, 0x3F; // mov AH, 3FH
inline 0x8B, 0x1E, 0x08, 0xC1; // mov BX, word [@@DATA+Ofs(hFile)]
inline 0xB9, 0x00, 0x40; // mov CX, 16384
inline 0xBA, 0x00, 0x41; // mov DX, @@DATA+Ofs(Text)
inline 0xCD, 0x21; // int 21H
end
word write() is
inline 0xB4, 0x40; // mov AH, 40H
inline 0x8B, 0x1E, 0x08, 0xC1; // mov BX, word [@@DATA+Ofs(hFile)]
inline 0x8B, 0x0E, 0x06, 0xC1; // mov CX, word [@@DATA+Ofs(nCode)]
inline 0x03, 0xC9; // add CX, CX
inline 0xBA, 0x06, 0x81; // mov DX, @@DATA+Ofs(Code)
inline 0xCD, 0x21; // int 21H
end
word close() is
inline 0xB4, 0x3E; // mov AH, 3EH
inline 0x8B, 0x1E, 0x08, 0xC1; // mov BX, word [@@DATA+Ofs(hFile)]
inline 0xCD, 0x21; // int 21H
end
char putc(char C) is
char C1:=C;
inline 0x92; // xchg DX, AX
inline 0xB4, 0x02; // mov AH, 2
inline 0xCD, 0x21; // int 21H
end
word halt() is
inline 0xB8, 0x00, 0x4C; // mov AX, 4C00H
inline 0xCD, 0x21; // int 21H
end
To load compiler into memory small loader program listed below are used.
It may be entered on PDP-11 blinkenlight console (to enter in emulator
memory deposit commands are used, commands may be stored in pdp11.ini file):
Then "insert punched tape" with compiler binary and load it into memory
starting from address 000400 (0x100):
attach PTR C.COM
go 137742
Then "insert punched tape" with compiled program, blank tape in puncher,
set stack pointer (before loader, or if the loader is no longer needed,
you can set 137776 address) and run the compiler: