MODULE PCLIR;
IMPORT
Machine, KernelLog,
PCM, PCBT;
CONST
Statistics = FALSE;
Debug= FALSE;
TYPE
Opcode* = SHORTINT;
Register* = LONGINT;
Size* = SHORTINT;
CONST
NoSize* = 0;
Int8* = 1; Int16* = 2; Int32* = 3; Int64* = 4; Float32* = 5; Float64* = 6;
IntSize* = {Int8..Int64}; FloatSize* = {Float32 .. Float64};
none* = -1; FP* = -2; SP* = -3; Absolute* = -4;
HwReg* = -16;
TYPE
InstructionAttribute* = OBJECT END InstructionAttribute;
Instruction* = RECORD
op*: Opcode;
src1*, src2*, src3*: Register;
val*: LONGINT;
adr-: PCM.Attribute;
barrier-: LONGINT;
suppress*: BOOLEAN;
dstCount*: SHORTINT;
dstSize-: Size;
dstSigned-: BOOLEAN;
info*: InstructionAttribute;
END;
CONST
form00* = 0;
form0C* = 1;
form01* = 2;
form10* = 3;
form1C* = 4;
form11* = 5;
form1M* = 6;
formM1* = 7;
form02* = 8;
form12* = 9;
form02C* = 10;
form03* = 11;
formXX* = 12;
form1X* = {form1C, form1M, form10, form11, form12};
barrier* = 0;
commutative* = 1;
load* = 0; loadc* = 1; store* = 2; in* = 3; out* = 4; nop* = 5;
saveregs* = 6; loadregs* = 7; label* = 8; je* = 9; jne* = 10;
jlt* = 11; jle* = 12; jgt* = 13; jge* = 14; jb* = 15; jbe* = 16;
ja* = 17; jae* = 18; jf* = 19; jnf* = 20; jmp* = 21; call* = 22;
syscall* = 23; enter* = 24; exit* = 25; trap* = 26; tae* = 27;
tne* = 28; sete* = 29; setne* = 30; setlt* = 31; setle* = 32;
setgt* = 33; setge* = 34; setb* = 35; setbe* = 36; seta* = 37;
setae* = 38; setf* = 39; setnf* = 40; result* = 41; result2* = 42;
pop* = 43; ret* = 44; ret2* = 45; push* = 46; callreg* = 47;
kill* = 48; loadsp* = 49; convs* = 50; convu* = 51; copy* = 52;
not* = 53; neg* = 54; abs* = 55; mul* = 56; div* = 57; mod* = 58;
sub* = 59; add* = 60; and* = 61; or* = 62; xor* = 63; bts* = 64;
btc* = 65; ash* = 66; bsh* = 67; rot* = 68; phi* = 69; move* = 70;
inline* = 71; case* = 72; casel* = 73; casee* = 74; loadfp* = 75;
moveDown* = 76; finallylabel* = 77; saveregsaligned* = 78;
NofOpcodes* = saveregsaligned+1;
PieceLen = 128;
TYPE
InstructionSetDescription* = ARRAY NofOpcodes OF RECORD
format-: SHORTINT;
flags-: SET;
name-: ARRAY 9 OF CHAR;
emit-: EmitProc;
END;
Piece* = OBJECT
VAR
instr*: ARRAY PieceLen OF Instruction;
len: LONGINT;
next, prev: Piece;
PROCEDURE & Init*;
BEGIN len := 0; next := NIL; prev := NIL;
IF Statistics THEN Machine.AtomicInc(aPieceCount) END
END Init;
END Piece;
CodeAttributes* = POINTER TO RECORD END;
Code* = OBJECT (PCM.Attribute)
VAR
pc-: LONGINT;
first, last: Piece;
barrier-: LONGINT;
info-: CodeAttributes;
name*: ARRAY 32 OF CHAR;
PROCEDURE NewInstruction;
BEGIN
IF last.len = PieceLen THEN
NEW(last.next);
last.next.prev := last; last := last.next
END;
INC(last.len); INC(pc)
END NewInstruction;
PROCEDURE GetPiece*(VAR src: LONGINT; VAR p: Piece);
BEGIN
p := first;
WHILE src >= PieceLen DO
p := p.next; DEC(src, PieceLen)
END;
END GetPiece;
PROCEDURE Traverse*(proc: TraverseProc; reversed: BOOLEAN; context: ANY);
VAR p: Piece; pos, pc0: LONGINT;
BEGIN
IF reversed THEN
p := last; pc0 := pc;
WHILE p # NIL DO
pos := p.len;
WHILE pos > 0 DO
DEC(pos); DEC(pc0);
proc(SELF, p.instr[pos], pc0, context)
END;
p := p.prev
END
ELSE
p := first; pc0 := 0;
WHILE p # NIL DO
pos := 0;
WHILE pos < p.len DO
proc(SELF, p.instr[pos], pc0, context);
INC(pos); INC(pc0)
END;
p := p.next
END
END
END Traverse;
PROCEDURE & Init*;
BEGIN
IF Statistics THEN Machine.AtomicInc(aCodeCount) END;
NEW(first); last := first; barrier := 0
END Init;
END Code;
EmitProc* = PROCEDURE (code: Code; VAR instr: Instruction; pc: LONGINT);
TraverseProc* = PROCEDURE (code: Code; VAR instr: Instruction; pc: LONGINT; context: ANY);
AsmFixup* = POINTER TO RECORD
offset*: LONGINT;
adr*: PCM.Attribute;
next*: AsmFixup
END;
AsmBlock* = POINTER TO RECORD
len*: LONGINT;
code*: ARRAY 256 OF CHAR;
next*: AsmBlock
END;
AsmInline* = OBJECT (PCM.Attribute)
VAR
code*: AsmBlock;
fixup*: AsmFixup;
END AsmInline;
CodeArray* = POINTER TO ARRAY OF CHAR;
InitHandler* = PROCEDURE(): BOOLEAN;
DoneHandler* = PROCEDURE(VAR res: LONGINT);
GetCodeHandler* = PROCEDURE(VAR code: CodeArray; VAR codelength, hdrlength, addressFactor: LONGINT);
CodeGenerator* = RECORD
MaxCodeSize*: LONGINT;
SysCallMap*: POINTER TO ARRAY OF CHAR;
Init*: InitHandler;
Done*: DoneHandler;
Optimize*: PROCEDURE (code: Code);
GetCode*: GetCodeHandler;
DumpCode*: TraverseProc;
ParamAlign*: LONGINT;
END;
VAR
InstructionSet*: InstructionSetDescription;
InstructionInit*: PROCEDURE (VAR instr: Instruction);
CG*: CodeGenerator;
Address*, Set*, SizeType*: Size;
RegName: ARRAY 8 OF CHAR;
aTotalInstructions, aSuppressedInstructions,
aCodeCount, aPieceCount: LONGINT;
aInstrCount, aSupprInstrCount: ARRAY NofOpcodes OF LONGINT;
PROCEDURE InitInstr(VAR instr: Instruction; op: Opcode; size: Size; signed: BOOLEAN; val: LONGINT;
src1, src2, src3: Register; adr: PCM.Attribute; barrier: LONGINT);
BEGIN
instr.op := op; instr.val := val; instr.src1 := src1;
instr.src2 := src2; instr.src3 := src3;
instr.adr := adr;
instr.dstSize := size; instr.dstCount := 0; instr.dstSigned := signed;
instr.suppress := FALSE;
instr.barrier := barrier;
END InitInstr;
PROCEDURE Use(code: Code; reg: Register);
VAR p: Piece;
BEGIN
IF reg >= 0 THEN
code.GetPiece(reg, p); INC(p.instr[reg].dstCount)
END
END Use;
PROCEDURE SizeOf*(code: Code; reg: Register): Size;
VAR p: Piece;
BEGIN
IF reg >= 0 THEN
code.GetPiece(reg, p); RETURN (p.instr[reg].dstSize)
ELSIF (reg = FP) OR (reg = SP) THEN
RETURN Address
END;
RETURN NoSize
END SizeOf;
PROCEDURE Signed*(code: Code; reg: Register): BOOLEAN;
VAR p: Piece;
BEGIN
IF reg >= 0 THEN
code.GetPiece(reg, p); RETURN (p.instr[reg].dstSigned)
END;
RETURN FALSE
END Signed;
PROCEDURE NofBytes*(size: Size): SHORTINT;
BEGIN
CASE size OF
| Int8: RETURN 1
| Int16: RETURN 2
| Int32, Float32: RETURN 4
| Int64, Float64: RETURN 8
END
END NofBytes;
PROCEDURE NewInstr(code: Code; op: Opcode; size: Size; signed: BOOLEAN; val: LONGINT; s1, s2, s3: Register; adr: PCM.Attribute);
VAR p: Piece;
BEGIN
code.NewInstruction;
p := code.last;
InitInstr(p.instr[p.len-1], op, size, signed, val, s1, s2, s3, adr, code.barrier);
IF barrier IN InstructionSet[op].flags THEN code.barrier := code.pc END;
IF InstructionInit # NIL THEN InstructionInit(p.instr[p.len-1]) END
END NewInstr;
PROCEDURE EmitStoreAbsolute*(code: Code; offset: LONGINT; addr: PCM.Attribute; source: Register);
BEGIN
NewInstr(code, store, NoSize, FALSE, offset, Absolute, source, none, addr);
END EmitStoreAbsolute;
PROCEDURE EmitStoreRelative*(code: Code; offset: LONGINT; base, source: Register);
BEGIN
NewInstr(code, store, NoSize, FALSE, offset, base, source, none, NIL);
Use(code, source);
Use(code, base);
END EmitStoreRelative;
PROCEDURE EmitStoreReg*(code: Code; dst, source: Register);
BEGIN
ASSERT(dst <= HwReg);
NewInstr(code, store, NoSize, FALSE, none, dst, source, none, NIL);
Use(code, source);
END EmitStoreReg;
PROCEDURE EmitLoadAbsolute*(code: Code; size: Size; signed: BOOLEAN; VAR dest: Register; offs: LONGINT; addr: PCM.Attribute);
BEGIN
dest := code.pc;
NewInstr(code, load, size, signed, offs, Absolute, none, none, addr);
END EmitLoadAbsolute;
PROCEDURE EmitLoadRelative*(code: Code; size: Size; signed: BOOLEAN; VAR dest: Register; offset: LONGINT; base: Register);
BEGIN
dest := code.pc;
NewInstr(code, load, size, signed, offset, base, none, none, NIL);
Use(code, base);
END EmitLoadRelative;
PROCEDURE EmitLoadConst*(code: Code; VAR dest: Register; size: Size; signed: BOOLEAN; value: LONGINT);
BEGIN
ASSERT((Int8<=size) & (size<=Int64), 200);
dest := code.pc;
NewInstr(code, loadc, size, signed, value, none, none, none, NIL);
END EmitLoadConst;
PROCEDURE EmitLoadAddr*(code: Code; VAR dest: Register; offset: LONGINT; addr: PCM.Attribute);
BEGIN
dest := code.pc;
NewInstr(code, loadc, Address, FALSE, offset, none, none, none, addr);
END EmitLoadAddr;
PROCEDURE Emit0C*(code: Code; op: Opcode; val: LONGINT);
BEGIN
ASSERT(InstructionSet[op].format = form0C, 200);
NewInstr(code, op, NoSize, FALSE, val, none, none, none, NIL);
END Emit0C;
PROCEDURE EmitCall*(code: Code; proc: PCM.Attribute);
BEGIN
NewInstr(code, call, NoSize, FALSE, none, none, none, none, proc);
END EmitCall;
PROCEDURE EmitEnter*(code: Code; callconv: LONGINT; attr: PCM.Attribute);
BEGIN
NewInstr(code, enter, NoSize, FALSE, callconv, none, none, none, attr);
END EmitEnter;
PROCEDURE EmitFinallyLabel*(code: Code; attr: PCM.Attribute);
BEGIN
NewInstr(code, finallylabel, NoSize, FALSE, 0, none, none, none, attr);
END EmitFinallyLabel;
PROCEDURE EmitExit*(code: Code; callconv, parSize: LONGINT; attr: PCM.Attribute );
BEGIN
NewInstr(code, exit, NoSize, FALSE, callconv, parSize, none, none, attr );
END EmitExit;
PROCEDURE Emit00*(code: Code; op: Opcode);
BEGIN
ASSERT(InstructionSet[op].format = form00, 200);
NewInstr(code, op, NoSize, FALSE, none, none, none, none, NIL);
END Emit00;
PROCEDURE Emit01*(code: Code; op: Opcode; src: Register);
BEGIN
ASSERT(InstructionSet[op].format = form01, 200);
ASSERT((op # loadsp) OR (SizeOf(code, src) = Address), 201);
NewInstr(code, op, NoSize, FALSE, none, src, none, none, NIL);
Use(code, src)
END Emit01;
PROCEDURE Emit10*(code: Code; op: Opcode; VAR dest: Register; size: Size; signed: BOOLEAN);
BEGIN
ASSERT(InstructionSet[op].format = form10, 200);
dest := code.pc;
NewInstr(code, op, size, signed, none, none, none, none, NIL)
END Emit10;
PROCEDURE EmitConv*(code: Code; op: Opcode; VAR dest: Register; size: Size; signed: BOOLEAN; src: Register);
VAR s: Size; sign: BOOLEAN;
BEGIN
s := SizeOf(code, src);
sign := Signed(code, src);
ASSERT((size # s) OR (signed # sign) OR (op = in), 210);
ASSERT((op = convs) OR (op = convu) OR (op = copy) OR (op = in), 211);
dest := code.pc;
NewInstr(code, op, size, signed, none, src, none, none, NIL);
Use(code, src)
END EmitConv;
PROCEDURE Emit11*(code: Code; op: Opcode; VAR dest: Register; src1: Register);
VAR size: Size; signed: BOOLEAN;
BEGIN
ASSERT(InstructionSet[op].format = form11, 200);
dest := code.pc;
size := SizeOf(code, src1); signed := Signed(code, src1);
NewInstr(code, op, size, signed, none, src1, none, none, NIL);
Use(code, src1)
END Emit11;
PROCEDURE Emit02*(code: Code; op: Opcode; src1, src2: Register);
BEGIN
ASSERT(InstructionSet[op].format = form02, 200);
ASSERT((SizeOf(code, src1) = SizeOf(code, src2)) OR (op = out), 201);
NewInstr(code, op, NoSize, FALSE, none, src1, src2, none, NIL);
Use(code, src1); Use(code, src2)
END Emit02;
PROCEDURE Emit02C*(code: Code; op: Opcode; src1, src2: Register; val: LONGINT);
VAR size1, size2: Size;
BEGIN
size1 := SizeOf(code, src1);
size2 := SizeOf(code, src2);
ASSERT(InstructionSet[op].format = form02C, 200);
ASSERT(size1 = size2, 201);
NewInstr(code, op, NoSize, FALSE, val, src1, src2, none, NIL);
Use(code, src1); Use(code, src2)
END Emit02C;
PROCEDURE Emit03*(code: Code; op: Opcode; src1, src2, src3: Register);
BEGIN
ASSERT(InstructionSet[op].format = form03, 200);
ASSERT(Address = SizeOf(code, src1), 201);
ASSERT(Address = SizeOf(code, src2), 202);
NewInstr(code, op, NoSize, FALSE, none, src1, src2, src3, NIL);
Use(code, src1); Use(code, src2); Use(code, src3)
END Emit03;
PROCEDURE Emit12*(code: Code; op: Opcode; VAR dest: Register; src1, src2: Register);
VAR size, size2: Size; signed(*, signed2*): BOOLEAN;
BEGIN
ASSERT(InstructionSet[op].format = form12, 200);
ASSERT(op # phi, 201);
dest := code.pc;
size := SizeOf(code, src1); signed := Signed(code, src1);
size2 := SizeOf(code, src2);
ASSERT((((op >= ash) & (op <= rot)) & (Int8 = size2)) OR (size = size2) , 202);
NewInstr(code, op, size, signed, none, src1, src2, none, NIL);
Use(code, src1); Use(code, src2)
END Emit12;
PROCEDURE Emit12Sized*(code: Code; op: Opcode; VAR dest: Register; size: Size; src1, src2: Register);
VAR size1, size2: Size;
BEGIN
ASSERT(InstructionSet[op].format = form12, 200);
dest := code.pc;
size1 := SizeOf(code, src1);
size2 := SizeOf(code, src2);
ASSERT((((op >= ash) & (op <= rot)) & (Int8 = size2)) OR (size1 = size2), 202);
NewInstr(code, op, size, FALSE, none, src1, src2, none, NIL);
Use(code, src1); Use(code, src2)
END Emit12Sized;
PROCEDURE EmitInline*(code: Code; adr: PCM.Attribute);
BEGIN
NewInstr(code, inline, NoSize, FALSE, none, none, none, none, adr)
END EmitInline;
PROCEDURE EmitCase*(code: Code; VAR dst: Register; src: Register);
BEGIN
ASSERT(Int32 = SizeOf(code, src), 200);
dst := code.pc;
NewInstr(code, case, NoSize, FALSE, none, src, MAX(LONGINT), MIN(LONGINT), NIL);
Use(code, src);
END EmitCase;
PROCEDURE EmitCaseLine*(code: Code; base: Register; val: LONGINT);
VAR p: Piece;
BEGIN
NewInstr(code, casel, NoSize, FALSE, val, base, none, none, NIL);
code.GetPiece(base, p);
IF p.instr[base].src2 > val THEN p.instr[base].src2 := val END;
IF p.instr[base].src3 < val THEN p.instr[base].src3 := val END
END EmitCaseLine;
PROCEDURE EmitCaseElse*(code: Code; base: Register);
BEGIN
NewInstr(code, casee, NoSize, FALSE, none, base, none, none, NIL)
END EmitCaseElse;
PROCEDURE EmitPhi*(code: Code; VAR dest: Register; src1, src2: Register);
VAR size: Size; signed: BOOLEAN;
BEGIN
dest := code.pc;
size := SizeOf(code, src1); signed := Signed(code, src1);
ASSERT((src2 = none) OR (size = SizeOf(code, src2)) );
NewInstr(code, phi, size, signed, none, src1, src2, none, NIL)
END EmitPhi;
PROCEDURE PatchPhi*(code: Code; dest: Register; src2: Register);
VAR p: Piece;
BEGIN
code.GetPiece(dest, p); p.instr[dest].src2 := src2;
ASSERT((SizeOf(code, p.instr[dest].src1) = SizeOf(code, src2)) )
END PatchPhi;
PROCEDURE FixList*(code: Code; VAR pos: LONGINT; val: LONGINT);
VAR p: Piece; next: LONGINT;
BEGIN
WHILE pos # none DO
code.GetPiece(pos, p);
next := p.instr[pos].val; p.instr[pos].val := val;
pos := next
END
END FixList;
PROCEDURE MergeList*(code: Code; l1, l2: LONGINT): LONGINT;
VAR top: LONGINT; p: Piece;
BEGIN
IF l1 = none THEN RETURN l2
ELSIF l2 = none THEN RETURN l1
ELSE
top := l1;
code.GetPiece(l1, p);
WHILE p.instr[l1].val # none DO
l1 := p.instr[l1].val;
code.GetPiece(l1, p)
END;
p.instr[l1].val := l2;
RETURN top
END
END MergeList;
PROCEDURE SwapSources*(VAR instr: Instruction);
VAR t: Register;
BEGIN
ASSERT(InstructionSet[instr.op].format IN {form02, form12, form02C});
t := instr.src1; instr.src1 := instr.src2; instr.src2 := t
END SwapSources;
PROCEDURE DumpCode*(code: Code; VAR instr: Instruction; pc: LONGINT; context: ANY);
VAR op: Opcode; format: SHORTINT;
PROCEDURE Reg(r: LONGINT);
BEGIN
IF r = FP THEN
PCM.LogWStr("FP")
ELSIF r = SP THEN
PCM.LogWStr("SP")
ELSIF r <= HwReg THEN
PCM.LogWStr("HW");
PCM.LogWNum(HwReg-r)
ELSE
IF Signed(code, r) THEN PCM.LogW("S") END;
PCM.LogW(RegName[SizeOf(code, r)]);
PCM.LogWNum(r)
END
END Reg;
PROCEDURE Indirect(offs, base: LONGINT);
BEGIN
IF base <= HwReg THEN
Reg(base)
ELSIF base = Absolute THEN
PCM.LogW("@"); PCM.LogWNum(offs)
ELSE
PCM.LogWNum(offs); PCM.LogW("[");
Reg(base); PCM.LogW("]")
END
END Indirect;
PROCEDURE CaseOpd(src: Register; min, max: LONGINT);
BEGIN
Reg(src); PCM.LogWStr(" {"); PCM.LogWNum(min);
PCM.LogWStr(", "); PCM.LogWNum(max); PCM.LogW("}")
END CaseOpd;
PROCEDURE CaseLineOpd(base, val: LONGINT);
BEGIN
PCM.LogWNum(val); PCM.LogWStr(" {");
PCM.LogWNum(base); PCM.LogWStr("}")
END CaseLineOpd;
PROCEDURE CaseElseOpd(base: LONGINT);
BEGIN PCM.LogWStr(" {"); PCM.LogWNum(base); PCM.LogWStr("}")
END CaseElseOpd;
BEGIN
op := instr.op; format := InstructionSet[op].format;
PCM.LogWNum(pc); PCM.LogW(9X);
IF (format IN form1X) OR (op = load) THEN
PCM.LogWNum(instr.dstCount);
ELSE
PCM.LogWStr(" ")
END;
PCM.LogW(9X);
PCM.LogWStr(InstructionSet[op].name); PCM.LogW(9X);
CASE format OF
| form00:
| form0C:
PCM.LogWNum(instr.val);
IF instr.adr # NIL THEN PCM.LogWStr(" + @") END
| form01:
Reg(instr.src1)
| form10:
Reg(pc)
| form1C:
Reg(pc); PCM.LogWStr(", "); PCM.LogWNum(instr.val)
| form1M:
Reg(pc); PCM.LogWStr(", "); Indirect(instr.val, instr.src1)
| form11:
Reg(pc); PCM.LogWStr(", "); Reg(instr.src1)
| formM1:
Indirect(instr.val, instr.src1); PCM.LogWStr(", "); Reg(instr.src2)
| form02:
Reg(instr.src1); PCM.LogWStr(", "); Reg(instr.src2)
| form12:
Reg(pc); PCM.LogWStr(", "); Reg(instr.src1);
PCM.LogWStr(", "); Reg(instr.src2)
| form02C:
Reg(instr.src1); PCM.LogWStr(", "); Reg(instr.src2);
PCM.LogWStr(", "); PCM.LogWNum(instr.val)
| form03:
Reg(instr.src1); PCM.LogWStr(", "); Reg(instr.src2);
PCM.LogWStr(", "); Reg(instr.src3)
| formXX:
CASE op OF
| enter, exit:
| inline:
| case:
CaseOpd(instr.src1, instr.src2, instr.src3)
| casel:
CaseLineOpd(instr.src1, instr.val)
| casee:
CaseElseOpd(instr.src1)
END
END;
PCM.LogWLn;
END DumpCode;
PROCEDURE Emit*(code: Code);
VAR p: Piece; pos, pc0: LONGINT; trapped: BOOLEAN; c,piece: LONGINT;
PROCEDURE EmitInstruction(VAR instr: Instruction);
BEGIN
IF Statistics THEN
INC(aTotalInstructions);
INC(aInstrCount[instr.op]);
IF instr.suppress THEN
INC(aSuppressedInstructions);
INC(aSupprInstrCount[instr.op])
END
END;
IF ~instr.suppress THEN InstructionSet[instr.op].emit(code, instr, pc0) END
END EmitInstruction;
BEGIN
IF Debug THEN trapped := TRUE; c := 0; END;
p := code.first; pc0 := 0;
WHILE p # NIL DO
pos := 0;
WHILE pos < p.len DO
EmitInstruction(p.instr[pos]);
IF Debug THEN
KernelLog.Int(pos,0); KernelLog.String(" : "); KernelLog.String(InstructionSet[p.instr[pos].op].name);
KernelLog.Int(p.instr[pos].dstCount,10);
KernelLog.Ln;
INC(c);
END;
INC(pos); INC(pc0)
END;
p := p.next
END
;IF Debug THEN trapped := FALSE; END;
FINALLY
IF Debug THEN
IF trapped THEN
KernelLog.String("Compiler trapped while emiting code, here is the code segment"); KernelLog.Ln;
p := code.first; pc0 := 0; piece:= 0;
WHILE p # NIL DO
KernelLog.String("Piece: "); KernelLog.Int(piece,0); KernelLog.Ln; INC(piece);
pos := 0;
WHILE pos < p.len DO
KernelLog.Int(pos,0); KernelLog.String(" : "); KernelLog.String(InstructionSet[p.instr[pos].op].name);
KernelLog.Int(p.instr[pos].dstCount,10);
IF c =0 THEN KernelLog.String("(TRAP)"); END;
DEC(c);
KernelLog.Ln;
INC(pos); INC(pc0)
END;
p := p.next
END;
HALT(100);
END;
END;
END Emit;
PROCEDURE SetMethods*(op: Opcode; p: EmitProc);
BEGIN InstructionSet[op].emit := p
END SetMethods;
PROCEDURE CGInit(): BOOLEAN;
BEGIN RETURN FALSE
END CGInit;
PROCEDURE CGDone(VAR res: LONGINT);
BEGIN res := -1
END CGDone;
PROCEDURE CGGetCode(VAR code: CodeArray; VAR codelen, hdrlen, addressFactor: LONGINT);
BEGIN code := NIL; codelen := 0; hdrlen := 0; addressFactor := 1
END CGGetCode;
PROCEDURE CGDumpCode(code: Code; VAR instr: Instruction; pc: LONGINT; context: ANY);
END CGDumpCode;
PROCEDURE InitDefaultSyscalls*;
BEGIN
CG.SysCallMap[PCBT.casetable] := 0FFX;
CG.SysCallMap[PCBT.procaddr] := 0FEX;
CG.SysCallMap[PCBT.newrec] := 0FDX;
CG.SysCallMap[PCBT.newsys] := 0FCX;
CG.SysCallMap[PCBT.newarr] := 0FBX;
CG.SysCallMap[PCBT.start] := CHR(250);
CG.SysCallMap[PCBT.passivate] := CHR(249);
CG.SysCallMap[PCBT.lock] := CHR(247);
CG.SysCallMap[PCBT.unlock] := CHR(246);
CG.SysCallMap[PCBT.interfacelookup] := CHR(245);
CG.SysCallMap[PCBT.registerinterface] := CHR(244);
CG.SysCallMap[PCBT.getprocedure] := CHR(243);
END InitDefaultSyscalls;
PROCEDURE ShowStatistics*;
VAR i: LONGINT;
BEGIN
FOR i := 0 TO NofOpcodes-1 DO
KernelLog.String(InstructionSet[i].name);
KernelLog.Char(9X);
KernelLog.Int(aInstrCount[i], 8);
KernelLog.Int(aSupprInstrCount[i], 8);
KernelLog.Ln
END
END ShowStatistics;
PROCEDURE InitModule;
PROCEDURE NewInstr(op: Opcode; format: SHORTINT; name: ARRAY OF CHAR);
VAR i: LONGINT;
BEGIN
InstructionSet[op].format := format;
COPY(name, InstructionSet[op].name);
i := 0;
WHILE name[i] # 0X DO
InstructionSet[op].name[i] := name[i]; INC(i)
END;
WHILE i < 7 DO
InstructionSet[op].name[i] := 20X; INC(i)
END;
InstructionSet[op].name[7] := 0X;
END NewInstr;
BEGIN
NewInstr(load, form1M, "load");
NewInstr(loadc, form1C, "loadc");
NewInstr(store, formM1, "store");
NewInstr(in, form11, "in ");
NewInstr(out, form02, "out ");
NewInstr(nop, form00, "nop");
NewInstr(saveregs, form00, "saveregs");
NewInstr(loadregs, form00, "loadregs");
NewInstr(label, form0C, "label");
NewInstr(finallylabel, form0C, "finlabel");
NewInstr(je, form02C, "je");
NewInstr(jne, form02C, "jne");
NewInstr(jlt, form02C, "jlt");
NewInstr(jle, form02C, "jle");
NewInstr(jgt, form02C, "jgt");
NewInstr(jge, form02C, "jge");
NewInstr(jb, form02C, "jb");
NewInstr(jbe, form02C, "jbe");
NewInstr(ja, form02C, "ja");
NewInstr(jae, form02C, "jae");
NewInstr(jf, form02C, "jf");
NewInstr(jnf, form02C, "jnf");
NewInstr(jmp, form0C, "jmp");
NewInstr(call, form0C, "call");
NewInstr(syscall, form0C, "syscall");
NewInstr(enter, formXX, "enter");
NewInstr(exit, formXX, "exit");
NewInstr(trap, form0C, "trap");
NewInstr(tae, form02C, "tae");
NewInstr(tne, form02C, "tne");
NewInstr(sete, form12, "sete");
NewInstr(setne, form12, "setne");
NewInstr(setlt, form12, "setlt");
NewInstr(setle, form12, "setle");
NewInstr(setgt, form12, "setgt");
NewInstr(setge, form12, "setge");
NewInstr(setb, form12, "setb");
NewInstr(setbe, form12, "setbe");
NewInstr(seta, form12, "seta");
NewInstr(setae, form12, "setae");
NewInstr(setf, form12, "setf");
NewInstr(setnf, form12, "setnf");
NewInstr(result, form10, "result");
NewInstr(result2, form10, "result2");
NewInstr(pop, form10, "pop");
NewInstr(ret, form01, "ret");
NewInstr(ret2, form01, "ret2");
NewInstr(push, form01, "push");
NewInstr(callreg, form01, "callreg");
NewInstr(kill, form01, "kill");
NewInstr(loadsp, form01, "loadsp");
NewInstr(loadfp, form01, "loadfp");
NewInstr(convs, form11, "convs");
NewInstr(convu, form11, "convu");
NewInstr(copy, form11, "copy");
NewInstr(not, form11, "not");
NewInstr(neg, form11, "neg");
NewInstr(abs, form11, "abs");
NewInstr(mul, form12, "mul");
NewInstr(div, form12, "div");
NewInstr(mod, form12, "mod");
NewInstr(sub, form12, "sub");
NewInstr(add, form12, "add");
NewInstr(and, form12, "and");
NewInstr(or, form12, "or");
NewInstr(xor, form12, "xor");
NewInstr(bts, form12, "bts");
NewInstr(btc, form12, "btc");
NewInstr(ash, form12, "ash");
NewInstr(bsh, form12, "bsh");
NewInstr(rot, form12, "rot");
NewInstr(phi, form12, "phi");
NewInstr(move, form03, "move");
NewInstr(moveDown, form03, "moveDown");
NewInstr(inline, formXX, "inline");
NewInstr(case, formXX, "case");
NewInstr(casel, formXX, "casel");
NewInstr(casee, formXX, "casee");
InstructionSet[call].flags := {barrier};
InstructionSet[callreg].flags := {barrier};
InstructionSet[syscall].flags := {barrier};
InstructionSet[mul].flags := {commutative};
InstructionSet[add].flags := {commutative};
InstructionSet[and].flags := {commutative};
InstructionSet[or].flags := {commutative};
InstructionSet[xor].flags := {commutative};
InstructionSet[je].flags := {commutative};
InstructionSet[jne].flags := {commutative};
RegName[Int8] := "B";
RegName[Int16] := "W";
RegName[Int32] := "D";
RegName[Int64] := "Q";
RegName[Float32] := "F";
RegName[Float64] := "G";
InstructionInit := NIL;
CG.Init := CGInit;
CG.Done := CGDone;
CG.GetCode := CGGetCode;
CG.DumpCode := CGDumpCode;
IF Statistics THEN PCM.LogWLn; PCM.LogWStr("PCLIR.Statistics on") END
END InitModule;
BEGIN
Address := Int32;
Set := Int32;
InitModule
END PCLIR.
(*
20.09.03 prk "/Dcode" compiler option added
06.04.03 prk LIR code trace output adapted to new output model
20.02.02 be refinement in the code generator plugin
02.04.02 prk statistics
20.02.02 be refinement in the code generator plugin
06.08.01 prk Instruction: dst record removed, fields declared directly in instruction
29.05.01 be syscall structures moved to backend (PCLIR & code generators)
14.05.01 prk PCLIR.lea removed
11.05.01 prk correct handling of operation with hw-regs; PCLIR.loadsp instruction; PCC stack ops fixed
07.05.01 prk Installable code generators moved to PCLIR; debug function added
07.05.01 be register sign information added in the back-end
26.04.01 prk separation of RECORD and OBJECT in the parser
26.04.01 prk PCLIR.lea partly removed
28.03.01 prk Cleanup interface
15.03.01 prk calldel removed
15.03.01 prk ret2, result2 added
22.02.01 prk delegates
23.02.01 prk TraverseProc: context added
*)