0,0 → 1,1780 |
(* |
BSD 2-Clause License |
|
Copyright (c) 2019-2021, Anton Krotov |
All rights reserved. |
*) |
|
MODULE MSP430; |
|
IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX, |
UTILS, C := CONSOLE, PROG, RTL := MSP430RTL; |
|
|
CONST |
|
chkSTK* = 6; |
|
minRAM* = 128; maxRAM* = 2048; |
minROM* = 2048; maxROM* = 24576; |
|
StkReserve = RTL.StkReserve; |
|
IntVectorSize* = RTL.IntVectorSize; |
|
PC = 0; SP = 1; SR = 2; CG = 3; |
|
R4 = 4; R5 = 5; R6 = 6; R7 = 7; |
|
HP = RTL.HP; |
|
ACC = R4; |
|
opRRC = 1000H; opSWPB = 1080H; opRRA = 1100H; opSXT = 1180H; |
opPUSH = 1200H; opCALL = 1280H; opRETI = 1300H; |
|
opMOV = 04000H; opADD = 05000H; opADDC = 06000H; opSUBC = 07000H; |
opSUB = 08000H; opCMP = 09000H; opDADD = 0A000H; opBIT = 0B000H; |
opBIC = 0C000H; opBIS = 0D000H; opXOR = 0E000H; opAND = 0F000H; |
|
opJNE = 2000H; opJEQ = 2400H; opJNC = 2800H; opJC = 2C00H; |
opJN = 3000H; opJGE = 3400H; opJL = 3800H; opJMP = 3C00H; |
|
sREG = 0; sIDX = 16; sINDIR = 32; sINCR = 48; BW = 64; dIDX = 128; |
|
NOWORD = 10000H; |
|
RCODE = 0; RDATA = 1; RBSS = 2; |
|
je = 0; jne = je + 1; |
jge = 2; jl = jge + 1; |
jle = 4; jg = jle + 1; |
jb = 6; |
|
|
TYPE |
|
ANYCODE = POINTER TO RECORD (LISTS.ITEM) |
|
offset: INTEGER |
|
END; |
|
WORD = POINTER TO RECORD (ANYCODE) |
|
val: INTEGER |
|
END; |
|
LABEL = POINTER TO RECORD (ANYCODE) |
|
num: INTEGER |
|
END; |
|
JMP = POINTER TO RECORD (ANYCODE) |
|
cc, label: INTEGER; |
short: BOOLEAN |
|
END; |
|
CALL = POINTER TO RECORD (ANYCODE) |
|
label: INTEGER |
|
END; |
|
COMMAND = IL.COMMAND; |
|
RELOC = POINTER TO RECORD (LISTS.ITEM) |
|
section: INTEGER; |
WordPtr: WORD |
|
END; |
|
|
VAR |
|
R: REG.REGS; |
|
CodeList: LISTS.LIST; |
RelList: LISTS.LIST; |
|
mem: ARRAY 65536 OF BYTE; |
|
Labels: CHL.INTLIST; |
|
IV: ARRAY RTL.LenIV OF INTEGER; |
|
IdxWords: RECORD src, dst: INTEGER END; |
|
StkCnt, MaxStkCnt: INTEGER; |
|
|
PROCEDURE CheckProcDataSize* (VarSize, RamSize: INTEGER): BOOLEAN; |
RETURN (VarSize + 1) * 2 + StkReserve + RTL.VarSize < RamSize |
END CheckProcDataSize; |
|
|
PROCEDURE EmitLabel (L: INTEGER); |
VAR |
label: LABEL; |
|
BEGIN |
NEW(label); |
label.num := L; |
LISTS.push(CodeList, label) |
END EmitLabel; |
|
|
PROCEDURE EmitWord (val: INTEGER); |
VAR |
word: WORD; |
|
BEGIN |
IF val < 0 THEN |
ASSERT(val >= -32768); |
val := val MOD 65536 |
ELSE |
ASSERT(val <= 65535) |
END; |
NEW(word); |
word.val := val; |
LISTS.push(CodeList, word) |
END EmitWord; |
|
|
PROCEDURE EmitJmp (cc, label: INTEGER); |
VAR |
jmp: JMP; |
|
BEGIN |
NEW(jmp); |
jmp.cc := cc; |
jmp.label := label; |
jmp.short := FALSE; |
LISTS.push(CodeList, jmp) |
END EmitJmp; |
|
|
PROCEDURE EmitCall (label: INTEGER); |
VAR |
call: CALL; |
|
BEGIN |
NEW(call); |
call.label := label; |
LISTS.push(CodeList, call) |
END EmitCall; |
|
|
PROCEDURE IncStk; |
BEGIN |
INC(StkCnt); |
MaxStkCnt := MAX(StkCnt, MaxStkCnt) |
END IncStk; |
|
|
PROCEDURE bw (b: BOOLEAN): INTEGER; |
RETURN BW * ORD(b) |
END bw; |
|
|
PROCEDURE src_x (x, Rn: INTEGER): INTEGER; |
VAR |
res: INTEGER; |
|
BEGIN |
IF (x = 0) & ~(Rn IN {PC, SR, CG}) THEN |
res := Rn * 256 + sINDIR |
ELSE |
IdxWords.src := x; |
res := Rn * 256 + sIDX |
END |
|
RETURN res |
END src_x; |
|
|
PROCEDURE dst_x (x, Rn: INTEGER): INTEGER; |
BEGIN |
IdxWords.dst := x |
RETURN Rn + dIDX |
END dst_x; |
|
|
PROCEDURE indir (Rn: INTEGER): INTEGER; |
RETURN Rn * 256 + sINDIR |
END indir; |
|
|
PROCEDURE incr (Rn: INTEGER): INTEGER; |
RETURN Rn * 256 + sINCR |
END incr; |
|
|
PROCEDURE imm (x: INTEGER): INTEGER; |
VAR |
res: INTEGER; |
|
BEGIN |
CASE x OF |
| 0: res := CG * 256 |
| 1: res := CG * 256 + sIDX |
| 2: res := indir(CG) |
| 4: res := indir(SR) |
| 8: res := incr(SR) |
|-1: res := incr(CG) |
ELSE |
res := incr(PC); |
IdxWords.src := x |
END |
|
RETURN res |
END imm; |
|
|
PROCEDURE Op2 (op, src, dst: INTEGER); |
BEGIN |
ASSERT(BITS(op) - {6, 12..15} = {}); |
ASSERT(BITS(src) - {4, 5, 8..11} = {}); |
ASSERT(BITS(dst) - {0..3, 7} = {}); |
|
EmitWord(op + src + dst); |
|
IF IdxWords.src # NOWORD THEN |
EmitWord(IdxWords.src); |
IdxWords.src := NOWORD |
END; |
|
IF IdxWords.dst # NOWORD THEN |
EmitWord(IdxWords.dst); |
IdxWords.dst := NOWORD |
END |
END Op2; |
|
|
PROCEDURE Op1 (op, reg, As: INTEGER); |
BEGIN |
EmitWord(op + reg + As) |
END Op1; |
|
|
PROCEDURE MovRR (src, dst: INTEGER); |
BEGIN |
Op2(opMOV, src * 256, dst) |
END MovRR; |
|
|
PROCEDURE PushImm (imm: INTEGER); |
BEGIN |
imm := UTILS.Long(imm); |
CASE imm OF |
| 0: Op1(opPUSH, CG, sREG) |
| 1: Op1(opPUSH, CG, sIDX) |
| 2: Op1(opPUSH, CG, sINDIR) |
|-1: Op1(opPUSH, CG, sINCR) |
ELSE |
Op1(opPUSH, PC, sINCR); |
EmitWord(imm) |
END; |
IncStk |
END PushImm; |
|
|
PROCEDURE PutWord (word: INTEGER; VAR adr: INTEGER); |
BEGIN |
ASSERT(~ODD(adr)); |
ASSERT((0 <= word) & (word <= 65535)); |
mem[adr] := word MOD 256; |
mem[adr + 1] := word DIV 256; |
INC(adr, 2) |
END PutWord; |
|
|
PROCEDURE NewLabel (): INTEGER; |
BEGIN |
CHL.PushInt(Labels, 0) |
RETURN IL.NewLabel() |
END NewLabel; |
|
|
PROCEDURE LabelOffs (n: INTEGER): INTEGER; |
RETURN CHL.GetInt(Labels, n) |
END LabelOffs; |
|
|
PROCEDURE Fixup (CodeAdr, IntVectorSize: INTEGER): INTEGER; |
VAR |
cmd: ANYCODE; |
adr: INTEGER; |
offset: INTEGER; |
diff: INTEGER; |
cc: INTEGER; |
shorted: BOOLEAN; |
|
BEGIN |
REPEAT |
shorted := FALSE; |
offset := CodeAdr DIV 2; |
|
cmd := CodeList.first(ANYCODE); |
WHILE cmd # NIL DO |
cmd.offset := offset; |
CASE cmd OF |
|LABEL: CHL.SetInt(Labels, cmd.num, offset) |
|JMP: INC(offset); |
IF ~cmd.short THEN |
INC(offset); |
IF cmd.cc # opJMP THEN |
INC(offset) |
END |
END |
|
|CALL: INC(offset, 2) |
|WORD: INC(offset) |
END; |
cmd := cmd.next(ANYCODE) |
END; |
|
cmd := CodeList.first(ANYCODE); |
WHILE cmd # NIL DO |
IF (cmd IS JMP) & ~cmd(JMP).short THEN |
diff := LabelOffs(cmd(JMP).label) - cmd.offset - 1; |
IF ABS(diff) <= 512 THEN |
cmd(JMP).short := TRUE; |
shorted := TRUE |
END |
END; |
cmd := cmd.next(ANYCODE) |
END |
|
UNTIL ~shorted; |
|
IF offset * 2 > 10000H - IntVectorSize THEN |
ERRORS.Error(203) |
END; |
|
adr := CodeAdr; |
cmd := CodeList.first(ANYCODE); |
WHILE cmd # NIL DO |
CASE cmd OF |
|LABEL: |
|
|JMP: IF ~cmd.short THEN |
CASE cmd.cc OF |
|opJNE: cc := opJEQ |
|opJEQ: cc := opJNE |
|opJNC: cc := opJC |
|opJC: cc := opJNC |
|opJGE: cc := opJL |
|opJL: cc := opJGE |
|opJMP: cc := opJMP |
END; |
|
IF cc # opJMP THEN |
PutWord(cc + 2, adr) (* jcc L *) |
END; |
|
PutWord(4030H, adr); (* MOV @PC+, PC *) |
PutWord(LabelOffs(cmd.label) * 2, adr) |
(* L: *) |
ELSE |
diff := LabelOffs(cmd.label) - cmd.offset - 1; |
ASSERT((-512 <= diff) & (diff <= 511)); |
PutWord(cmd.cc + diff MOD 1024, adr) |
END |
|
|CALL: PutWord(12B0H, adr); (* CALL @PC+ *) |
PutWord(LabelOffs(cmd.label) * 2, adr) |
|
|WORD: PutWord(cmd.val, adr) |
|
END; |
cmd := cmd.next(ANYCODE) |
END |
|
RETURN adr - CodeAdr |
END Fixup; |
|
|
PROCEDURE Push (reg: INTEGER); |
BEGIN |
Op1(opPUSH, reg, sREG); |
IncStk |
END Push; |
|
|
PROCEDURE Pop (reg: INTEGER); |
BEGIN |
Op2(opMOV, incr(SP), reg); |
DEC(StkCnt) |
END Pop; |
|
|
PROCEDURE Test (reg: INTEGER); |
BEGIN |
Op2(opCMP, imm(0), reg) |
END Test; |
|
|
PROCEDURE Clear (reg: INTEGER); |
BEGIN |
Op2(opMOV, imm(0), reg) |
END Clear; |
|
|
PROCEDURE mov (dst, src: INTEGER); |
BEGIN |
MovRR(src, dst) |
END mov; |
|
|
PROCEDURE xchg (reg1, reg2: INTEGER); |
BEGIN |
Push(reg1); |
mov(reg1, reg2); |
Pop(reg2) |
END xchg; |
|
|
PROCEDURE Reloc (section: INTEGER); |
VAR |
reloc: RELOC; |
|
BEGIN |
NEW(reloc); |
reloc.section := section; |
reloc.WordPtr := CodeList.last(WORD); |
LISTS.push(RelList, reloc) |
END Reloc; |
|
|
PROCEDURE CallRTL (proc, params: INTEGER); |
BEGIN |
IncStk; |
DEC(StkCnt); |
EmitCall(RTL.rtl[proc].label); |
RTL.Used(proc); |
IF params > 0 THEN |
Op2(opADD, imm(params * 2), SP); |
DEC(StkCnt, params) |
END |
END CallRTL; |
|
|
PROCEDURE UnOp (VAR reg: INTEGER); |
BEGIN |
REG.UnOp(R, reg) |
END UnOp; |
|
|
PROCEDURE BinOp (VAR reg1, reg2: INTEGER); |
BEGIN |
REG.BinOp(R, reg1, reg2) |
END BinOp; |
|
|
PROCEDURE GetRegA; |
BEGIN |
ASSERT(REG.GetReg(R, ACC)) |
END GetRegA; |
|
|
PROCEDURE drop; |
BEGIN |
REG.Drop(R) |
END drop; |
|
|
PROCEDURE GetAnyReg (): INTEGER; |
RETURN REG.GetAnyReg(R) |
END GetAnyReg; |
|
|
PROCEDURE PushAll (NumberOfParameters: INTEGER); |
BEGIN |
REG.PushAll(R); |
DEC(R.pushed, NumberOfParameters) |
END PushAll; |
|
|
PROCEDURE PushAll_1; |
BEGIN |
REG.PushAll_1(R) |
END PushAll_1; |
|
|
PROCEDURE cond (op: INTEGER): INTEGER; |
VAR |
res: INTEGER; |
|
BEGIN |
CASE op OF |
|IL.opGT, IL.opGTC: res := jg |
|IL.opGE, IL.opGEC: res := jge |
|IL.opLT, IL.opLTC: res := jl |
|IL.opLE, IL.opLEC: res := jle |
|IL.opEQ, IL.opEQC: res := je |
|IL.opNE, IL.opNEC: res := jne |
END |
|
RETURN res |
END cond; |
|
|
PROCEDURE jcc (cc, label: INTEGER); |
VAR |
L: INTEGER; |
|
BEGIN |
CASE cc OF |
|jne: |
EmitJmp(opJNE, label) |
|je: |
EmitJmp(opJEQ, label) |
|jge: |
EmitJmp(opJGE, label) |
|jl: |
EmitJmp(opJL, label) |
|jle: |
EmitJmp(opJL, label); |
EmitJmp(opJEQ, label) |
|jg: |
L := NewLabel(); |
EmitJmp(opJEQ, L); |
EmitJmp(opJGE, label); |
EmitLabel(L) |
|jb: |
EmitJmp(opJNC, label) |
END |
END jcc; |
|
|
PROCEDURE setcc (cc, reg: INTEGER); |
VAR |
L: INTEGER; |
|
BEGIN |
L := NewLabel(); |
Op2(opMOV, imm(1), reg); |
jcc(cc, L); |
Clear(reg); |
EmitLabel(L) |
END setcc; |
|
|
PROCEDURE Shift2 (op, reg, n: INTEGER); |
VAR |
reg2: INTEGER; |
|
BEGIN |
IF n >= 8 THEN |
CASE op OF |
|IL.opASR2: Op1(opSWPB, reg, sREG); Op1(opSXT, reg, sREG) |
|IL.opROR2: Op1(opSWPB, reg, sREG) |
|IL.opLSL2: Op1(opSWPB, reg, sREG); Op2(opBIC, imm(255), reg) |
|IL.opLSR2: Op2(opBIC, imm(255), reg); Op1(opSWPB, reg, sREG) |
END; |
DEC(n, 8) |
END; |
|
IF (op = IL.opROR2) & (n > 0) THEN |
reg2 := GetAnyReg(); |
MovRR(reg, reg2) |
ELSE |
reg2 := -1 |
END; |
|
WHILE n > 0 DO |
CASE op OF |
|IL.opASR2: Op1(opRRA, reg, sREG) |
|IL.opROR2: Op1(opRRC, reg2, sREG); Op1(opRRC, reg, sREG) |
|IL.opLSL2: Op2(opADD, reg * 256, reg) |
|IL.opLSR2: Op2(opBIC, imm(1), SR); Op1(opRRC, reg, sREG) |
END; |
DEC(n) |
END; |
|
IF reg2 # -1 THEN |
drop |
END |
|
END Shift2; |
|
|
PROCEDURE Neg (reg: INTEGER); |
BEGIN |
Op2(opXOR, imm(-1), reg); |
Op2(opADD, imm(1), reg) |
END Neg; |
|
|
PROCEDURE LocalOffset (offset: INTEGER): INTEGER; |
RETURN (offset + StkCnt - ORD(offset > 0)) * 2 |
END LocalOffset; |
|
|
PROCEDURE LocalDst (offset: INTEGER): INTEGER; |
RETURN dst_x(LocalOffset(offset), SP) |
END LocalDst; |
|
|
PROCEDURE LocalSrc (offset: INTEGER): INTEGER; |
RETURN src_x(LocalOffset(offset), SP) |
END LocalSrc; |
|
|
PROCEDURE translate (chk_stk: BOOLEAN); |
VAR |
cmd, next: COMMAND; |
|
opcode, param1, param2, L, a, n, c1, c2: INTEGER; |
|
reg1, reg2: INTEGER; |
|
cc: INTEGER; |
|
word: WORD; |
|
BEGIN |
cmd := IL.codes.commands.first(COMMAND); |
|
WHILE cmd # NIL DO |
|
param1 := cmd.param1; |
param2 := cmd.param2; |
|
opcode := cmd.opcode; |
|
CASE opcode OF |
|IL.opJMP: |
EmitJmp(opJMP, param1) |
|
|IL.opCALL: |
IncStk; |
DEC(StkCnt); |
EmitCall(param1) |
|
|IL.opCALLP: |
IncStk; |
DEC(StkCnt); |
UnOp(reg1); |
Op1(opCALL, reg1, sREG); |
drop; |
ASSERT(R.top = -1) |
|
|IL.opPRECALL: |
PushAll(0) |
|
|IL.opLABEL: |
EmitLabel(param1) |
|
|IL.opSADR_PARAM: |
Op1(opPUSH, PC, sINCR); |
IncStk; |
EmitWord(param2); |
Reloc(RDATA) |
|
|IL.opERR: |
CallRTL(RTL._error, 2) |
|
|IL.opPUSHC: |
PushImm(param2) |
|
|IL.opONERR: |
DEC(StkCnt); |
EmitWord(0C232H); (* BIC #8, SR; DINT *) |
EmitWord(4303H); (* MOV R3, R3; NOP *) |
PushImm(param2); |
EmitJmp(opJMP, param1) |
|
|IL.opLEAVEC: |
Pop(PC) |
|
|IL.opENTER: |
ASSERT(R.top = -1); |
EmitLabel(param1); |
n := param2 MOD 65536; |
param2 := param2 DIV 65536; |
StkCnt := 0; |
IF chk_stk THEN |
L := NewLabel(); |
Op2(opMOV, SP * 256, R4); |
Op2(opSUB, HP * 256, R4); |
Op2(opCMP, imm(StkReserve), R4); |
word := CodeList.last(WORD); |
jcc(jge, L); |
DEC(StkCnt); |
EmitWord(0C232H); (* BIC #8, SR; DINT *) |
EmitWord(4303H); (* MOV R3, R3; NOP *) |
PushImm(n); |
EmitJmp(opJMP, cmd.param3); |
EmitLabel(L) |
END; |
|
IF param2 > 8 THEN |
Op2(opMOV, imm(param2), R4); |
L := NewLabel(); |
EmitLabel(L); |
Push(CG); |
Op2(opSUB, imm(1), R4); |
jcc(jne, L) |
ELSE |
FOR n := 1 TO param2 DO |
Push(CG) |
END |
END; |
StkCnt := param2; |
MaxStkCnt := StkCnt |
|
|IL.opLEAVE, IL.opLEAVER: |
ASSERT(param2 = 0); |
IF opcode = IL.opLEAVER THEN |
UnOp(reg1); |
IF reg1 # ACC THEN |
mov(ACC, reg1) |
END; |
drop |
END; |
ASSERT(R.top = -1); |
ASSERT(StkCnt = param1); |
IF chk_stk THEN |
INC(word.val, MaxStkCnt * 2) |
END; |
IF param1 > 0 THEN |
Op2(opADD, imm(param1 * 2), SP) |
END; |
Pop(PC) |
|
|IL.opRES: |
ASSERT(R.top = -1); |
GetRegA |
|
|IL.opCLEANUP: |
IF param2 # 0 THEN |
Op2(opADD, imm(param2 * 2), SP); |
DEC(StkCnt, param2) |
END |
|
|IL.opCONST: |
next := cmd.next(COMMAND); |
IF next.opcode = IL.opCONST THEN |
c1 := param2; |
c2 := next.param2; |
next := next.next(COMMAND); |
IF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN |
Op2(opMOV + bw(next.opcode = IL.opSAVE8), imm(c1), dst_x(c2, SR)); |
cmd := next |
ELSE |
Op2(opMOV, imm(param2), GetAnyReg()) |
END |
ELSIF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN |
UnOp(reg1); |
Op2(opMOV + bw(next.opcode = IL.opSAVE8), reg1 * 256, dst_x(param2, SR)); |
drop; |
cmd := next |
ELSE |
Op2(opMOV, imm(param2), GetAnyReg()) |
END |
|
|IL.opSADR: |
Op2(opMOV, incr(PC), GetAnyReg()); |
EmitWord(param2); |
Reloc(RDATA) |
|
|IL.opGADR: |
Op2(opMOV, incr(PC), GetAnyReg()); |
EmitWord(param2); |
Reloc(RBSS) |
|
|IL.opLADR: |
reg1 := GetAnyReg(); |
n := LocalOffset(param2); |
Op2(opMOV, SP * 256, reg1); |
IF n # 0 THEN |
Op2(opADD, imm(n), reg1) |
END |
|
|IL.opLLOAD8: |
Op2(opMOV + BW, LocalSrc(param2), GetAnyReg()) |
|
|IL.opLLOAD16, IL.opVADR: |
Op2(opMOV, LocalSrc(param2), GetAnyReg()) |
|
|IL.opGLOAD8: |
Op2(opMOV + BW, src_x(param2, SR), GetAnyReg()); |
Reloc(RBSS) |
|
|IL.opGLOAD16: |
Op2(opMOV, src_x(param2, SR), GetAnyReg()); |
Reloc(RBSS) |
|
|IL.opLOAD8: |
UnOp(reg1); |
Op2(opMOV + BW, indir(reg1), reg1) |
|
|IL.opLOAD16: |
UnOp(reg1); |
Op2(opMOV, indir(reg1), reg1) |
|
|IL.opVLOAD8: |
reg1 := GetAnyReg(); |
Op2(opMOV, LocalSrc(param2), reg1); |
Op2(opMOV + BW, indir(reg1), reg1) |
|
|IL.opVLOAD16: |
reg1 := GetAnyReg(); |
Op2(opMOV, LocalSrc(param2), reg1); |
Op2(opMOV, indir(reg1), reg1) |
|
|IL.opSAVE, IL.opSAVE16: |
BinOp(reg2, reg1); |
Op2(opMOV, reg2 * 256, dst_x(0, reg1)); |
drop; |
drop |
|
|IL.opSAVE8: |
BinOp(reg2, reg1); |
Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1)); |
drop; |
drop |
|
|IL.opSAVE8C: |
UnOp(reg1); |
Op2(opMOV + BW, imm(param2), dst_x(0, reg1)); |
drop |
|
|IL.opSAVE16C, IL.opSAVEC: |
UnOp(reg1); |
Op2(opMOV, imm(param2), dst_x(0, reg1)); |
drop |
|
|IL.opUMINUS: |
UnOp(reg1); |
Neg(reg1) |
|
|IL.opADD: |
BinOp(reg1, reg2); |
Op2(opADD, reg2 * 256, reg1); |
drop |
|
|IL.opADDC: |
IF param2 # 0 THEN |
UnOp(reg1); |
Op2(opADD, imm(param2), reg1) |
END |
|
|IL.opSUB: |
BinOp(reg1, reg2); |
Op2(opSUB, reg2 * 256, reg1); |
drop |
|
|IL.opSUBR, IL.opSUBL: |
UnOp(reg1); |
IF param2 # 0 THEN |
Op2(opSUB, imm(param2), reg1) |
END; |
IF opcode = IL.opSUBL THEN |
Neg(reg1) |
END |
|
|IL.opLADR_SAVEC: |
Op2(opMOV, imm(param2), LocalDst(param1)) |
|
|IL.opLADR_SAVE: |
UnOp(reg1); |
Op2(opMOV, reg1 * 256, LocalDst(param2)); |
drop |
|
|IL.opGADR_SAVEC: |
Op2(opMOV, imm(param2), dst_x(param1, SR)); |
Reloc(RBSS) |
|
|IL.opCONST_PARAM: |
PushImm(param2) |
|
|IL.opPARAM: |
IF param2 = 1 THEN |
UnOp(reg1); |
Push(reg1); |
drop |
ELSE |
ASSERT(R.top + 1 <= param2); |
PushAll(param2) |
END |
|
|IL.opEQ..IL.opGE, |
IL.opEQC..IL.opGEC: |
|
IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN |
BinOp(reg1, reg2); |
Op2(opCMP, reg2 * 256, reg1); |
drop |
ELSE |
UnOp(reg1); |
Op2(opCMP, imm(param2), reg1) |
END; |
|
drop; |
cc := cond(opcode); |
next := cmd.next(COMMAND); |
|
IF next.opcode = IL.opJNZ THEN |
jcc(cc, next.param1); |
cmd := next |
ELSIF next.opcode = IL.opJZ THEN |
jcc(ORD(BITS(cc) / {0}), next.param1); |
cmd := next |
ELSE |
setcc(cc, GetAnyReg()) |
END |
|
|IL.opNOP, IL.opAND, IL.opOR: |
|
|IL.opCODE: |
EmitWord(param2) |
|
|IL.opDROP: |
UnOp(reg1); |
drop |
|
|IL.opJNZ1: |
UnOp(reg1); |
Test(reg1); |
jcc(jne, param1) |
|
|IL.opJG: |
UnOp(reg1); |
Test(reg1); |
jcc(jg, param1) |
|
|IL.opJNZ: |
UnOp(reg1); |
Test(reg1); |
jcc(jne, param1); |
drop |
|
|IL.opJZ: |
UnOp(reg1); |
Test(reg1); |
jcc(je, param1); |
drop |
|
|IL.opNOT: |
UnOp(reg1); |
Test(reg1); |
setcc(je, reg1) |
|
|IL.opORD: |
UnOp(reg1); |
Test(reg1); |
setcc(jne, reg1) |
|
|IL.opGET: |
BinOp(reg1, reg2); |
drop; |
drop; |
Op2(opMOV + bw(param2 = 1), indir(reg1), dst_x(0, reg2)) |
|
|IL.opGETC: |
UnOp(reg2); |
drop; |
Op2(opMOV + bw(param2 = 1), src_x(param1, SR), dst_x(0, reg2)) |
|
|IL.opCHKBYTE: |
BinOp(reg1, reg2); |
Op2(opCMP, imm(256), reg1); |
jcc(jb, param1) |
|
|IL.opCHKIDX: |
UnOp(reg1); |
Op2(opCMP, imm(param2), reg1); |
jcc(jb, param1) |
|
|IL.opCHKIDX2: |
BinOp(reg1, reg2); |
IF param2 # -1 THEN |
Op2(opCMP, reg1 * 256, reg2); |
jcc(jb, param1) |
END; |
INCL(R.regs, reg1); |
DEC(R.top); |
R.stk[R.top] := reg2 |
|
|IL.opINCC, IL.opINCCB: |
UnOp(reg1); |
Op2(opADD + bw(opcode = IL.opINCCB), imm(param2), dst_x(0, reg1)); |
drop |
|
|IL.opDECCB: |
UnOp(reg1); |
Op2(opSUB + BW, imm(param2), dst_x(0, reg1)); |
drop |
|
|IL.opINC, IL.opINCB: |
BinOp(reg1, reg2); |
Op2(opADD + bw(opcode = IL.opINCB), reg1 * 256, dst_x(0, reg2)); |
drop; |
drop |
|
|IL.opDEC, IL.opDECB: |
BinOp(reg1, reg2); |
Op2(opSUB + bw(opcode = IL.opDECB), reg1 * 256, dst_x(0, reg2)); |
drop; |
drop |
|
|IL.opLADR_INCC, IL.opLADR_INCCB: |
Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), LocalDst(param1)) |
|
|IL.opLADR_DECCB: |
Op2(opSUB + BW, imm(param2), LocalDst(param1)) |
|
|IL.opLADR_INC, IL.opLADR_INCB: |
UnOp(reg1); |
Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, LocalDst(param2)); |
drop |
|
|IL.opLADR_DEC, IL.opLADR_DECB: |
UnOp(reg1); |
Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, LocalDst(param2)); |
drop |
|
|IL.opPUSHT: |
UnOp(reg1); |
Op2(opMOV, src_x(-2, reg1), GetAnyReg()) |
|
|IL.opISREC: |
PushAll(2); |
PushImm(param2); |
CallRTL(RTL._guardrec, 3); |
GetRegA |
|
|IL.opIS: |
PushAll(1); |
PushImm(param2); |
CallRTL(RTL._is, 2); |
GetRegA |
|
|IL.opTYPEGR: |
PushAll(1); |
PushImm(param2); |
CallRTL(RTL._guardrec, 2); |
GetRegA |
|
|IL.opTYPEGP: |
UnOp(reg1); |
PushAll(0); |
Push(reg1); |
PushImm(param2); |
CallRTL(RTL._guard, 2); |
GetRegA |
|
|IL.opTYPEGD: |
UnOp(reg1); |
PushAll(0); |
Op1(opPUSH, reg1, sIDX); |
IncStk; |
EmitWord(-2); |
PushImm(param2); |
CallRTL(RTL._guardrec, 2); |
GetRegA |
|
|IL.opMULS: |
BinOp(reg1, reg2); |
Op2(opAND, reg2 * 256, reg1); |
drop |
|
|IL.opMULSC: |
UnOp(reg1); |
Op2(opAND, imm(param2), reg1) |
|
|IL.opDIVS: |
BinOp(reg1, reg2); |
Op2(opXOR, reg2 * 256, reg1); |
drop |
|
|IL.opDIVSC: |
UnOp(reg1); |
Op2(opXOR, imm(param2), reg1) |
|
|IL.opADDS: |
BinOp(reg1, reg2); |
Op2(opBIS, reg2 * 256, reg1); |
drop |
|
|IL.opSUBS: |
BinOp(reg1, reg2); |
Op2(opBIC, reg2 * 256, reg1); |
drop |
|
|IL.opADDSC: |
UnOp(reg1); |
Op2(opBIS, imm(param2), reg1) |
|
|IL.opSUBSL: |
UnOp(reg1); |
Op2(opXOR, imm(-1), reg1); |
Op2(opAND, imm(param2), reg1) |
|
|IL.opSUBSR: |
UnOp(reg1); |
Op2(opBIC, imm(param2), reg1) |
|
|IL.opUMINS: |
UnOp(reg1); |
Op2(opXOR, imm(-1), reg1) |
|
|IL.opLENGTH: |
PushAll(2); |
CallRTL(RTL._length, 2); |
GetRegA |
|
|IL.opMAX,IL.opMIN: |
BinOp(reg1, reg2); |
Op2(opCMP, reg2 * 256, reg1); |
IF opcode = IL.opMIN THEN |
cc := opJL + 1 |
ELSE |
cc := opJGE + 1 |
END; |
EmitWord(cc); (* jge/jl L *) |
MovRR(reg2, reg1); |
(* L: *) |
drop |
|
|IL.opMAXC, IL.opMINC: |
UnOp(reg1); |
Op2(opCMP, imm(param2), reg1); |
L := NewLabel(); |
IF opcode = IL.opMINC THEN |
cc := jl |
ELSE |
cc := jge |
END; |
jcc(cc, L); |
Op2(opMOV, imm(param2), reg1); |
EmitLabel(L) |
|
|IL.opSWITCH: |
UnOp(reg1); |
IF param2 = 0 THEN |
reg2 := ACC |
ELSE |
reg2 := R5 |
END; |
IF reg1 # reg2 THEN |
ASSERT(REG.GetReg(R, reg2)); |
ASSERT(REG.Exchange(R, reg1, reg2)); |
drop |
END; |
drop |
|
|IL.opENDSW: |
|
|IL.opCASEL: |
Op2(opCMP, imm(param1), ACC); |
jcc(jl, param2) |
|
|IL.opCASER: |
Op2(opCMP, imm(param1), ACC); |
jcc(jg, param2) |
|
|IL.opCASELR: |
Op2(opCMP, imm(param1), ACC); |
IF param2 = cmd.param3 THEN |
jcc(jne, param2) |
ELSE |
jcc(jl, param2); |
jcc(jg, cmd.param3) |
END |
|
|IL.opSBOOL: |
BinOp(reg2, reg1); |
Test(reg2); |
setcc(jne, reg2); |
Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1)); |
drop; |
drop |
|
|IL.opSBOOLC: |
UnOp(reg1); |
Op2(opMOV + BW, imm(param2), dst_x(0, reg1)); |
drop |
|
|IL.opEQS .. IL.opGES: |
PushAll(4); |
PushImm((opcode - IL.opEQS) * 12); |
CallRTL(RTL._strcmp, 5); |
GetRegA |
|
|IL.opLEN: |
UnOp(reg1); |
drop; |
EXCL(R.regs, reg1); |
|
WHILE param2 > 0 DO |
UnOp(reg2); |
drop; |
DEC(param2) |
END; |
|
INCL(R.regs, reg1); |
ASSERT(REG.GetReg(R, reg1)) |
|
|IL.opLSL, IL.opASR, IL.opROR, IL.opLSR: |
PushAll(2); |
CASE opcode OF |
|IL.opLSL: CallRTL(RTL._lsl, 2) |
|IL.opASR: CallRTL(RTL._asr, 2) |
|IL.opROR: CallRTL(RTL._ror, 2) |
|IL.opLSR: CallRTL(RTL._lsr, 2) |
END; |
GetRegA |
|
|IL.opLSL1, IL.opASR1, IL.opROR1, IL.opLSR1: |
UnOp(reg1); |
PushAll_1; |
PushImm(param2); |
Push(reg1); |
drop; |
CASE opcode OF |
|IL.opLSL1: CallRTL(RTL._lsl, 2) |
|IL.opASR1: CallRTL(RTL._asr, 2) |
|IL.opROR1: CallRTL(RTL._ror, 2) |
|IL.opLSR1: CallRTL(RTL._lsr, 2) |
END; |
GetRegA |
|
|IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2: |
param2 := param2 MOD 16; |
IF param2 # 0 THEN |
UnOp(reg1); |
Shift2(opcode, reg1, param2) |
END |
|
|IL.opMUL: |
PushAll(2); |
CallRTL(RTL._mul, 2); |
GetRegA |
|
|IL.opMULC: |
UnOp(reg1); |
|
a := param2; |
IF a > 1 THEN |
n := UTILS.Log2(a) |
ELSIF a < -1 THEN |
n := UTILS.Log2(-a) |
ELSE |
n := -1 |
END; |
|
IF a = 1 THEN |
|
ELSIF a = -1 THEN |
Neg(reg1) |
ELSIF a = 0 THEN |
Clear(reg1) |
ELSE |
IF n > 0 THEN |
IF a < 0 THEN |
Neg(reg1) |
END; |
Shift2(IL.opLSL2, reg1, n) |
ELSE |
PushAll(1); |
PushImm(a); |
CallRTL(RTL._mul, 2); |
GetRegA |
END |
END |
|
|IL.opDIV: |
PushAll(2); |
CallRTL(RTL._divmod, 2); |
GetRegA |
|
|IL.opDIVR: |
ASSERT(param2 > 0); |
|
IF param2 > 1 THEN |
n := UTILS.Log2(param2); |
IF n > 0 THEN |
UnOp(reg1); |
Shift2(IL.opASR2, reg1, n) |
ELSE |
PushAll(1); |
PushImm(param2); |
CallRTL(RTL._divmod, 2); |
GetRegA |
END |
END |
|
|IL.opDIVL: |
UnOp(reg1); |
PushAll_1; |
PushImm(param2); |
Push(reg1); |
drop; |
CallRTL(RTL._divmod, 2); |
GetRegA |
|
|IL.opMOD: |
PushAll(2); |
CallRTL(RTL._divmod, 2); |
ASSERT(REG.GetReg(R, R5)) |
|
|IL.opMODR: |
ASSERT(param2 > 0); |
|
IF param2 = 1 THEN |
UnOp(reg1); |
Clear(reg1) |
ELSE |
IF UTILS.Log2(param2) > 0 THEN |
UnOp(reg1); |
Op2(opAND, imm(param2 - 1), reg1) |
ELSE |
PushAll(1); |
PushImm(param2); |
CallRTL(RTL._divmod, 2); |
ASSERT(REG.GetReg(R, R5)) |
END |
END |
|
|IL.opMODL: |
UnOp(reg1); |
PushAll_1; |
PushImm(param2); |
Push(reg1); |
drop; |
CallRTL(RTL._divmod, 2); |
ASSERT(REG.GetReg(R, R5)) |
|
|IL.opCOPYS: |
ASSERT(R.top = 3); |
Push(R.stk[2]); |
Push(R.stk[0]); |
Op2(opCMP, R.stk[1] * 256, R.stk[3]); |
EmitWord(3801H); (* JL L1 *) |
MovRR(R.stk[1], R.stk[3]); |
(* L1: *) |
Push(R.stk[3]); |
drop; |
drop; |
drop; |
drop; |
CallRTL(RTL._move, 3) |
|
|IL.opCOPY: |
PushAll(2); |
PushImm(param2); |
CallRTL(RTL._move, 3) |
|
|IL.opMOVE: |
PushAll(3); |
CallRTL(RTL._move, 3) |
|
|IL.opCOPYA: |
PushAll(4); |
PushImm(param2); |
CallRTL(RTL._arrcpy, 5); |
GetRegA |
|
|IL.opROT: |
PushAll(0); |
MovRR(SP, ACC); |
Push(ACC); |
PushImm(param2); |
CallRTL(RTL._rot, 2) |
|
|IL.opSAVES: |
UnOp(reg1); |
PushAll_1; |
Op1(opPUSH, PC, sINCR); |
IncStk; |
EmitWord(param2); |
Reloc(RDATA); |
Push(reg1); |
drop; |
PushImm(param1); |
CallRTL(RTL._move, 3) |
|
|IL.opCASET: |
Push(R5); |
Push(R5); |
PushImm(param2); |
CallRTL(RTL._guardrec, 2); |
Pop(R5); |
Test(ACC); |
jcc(jne, param1) |
|
|IL.opCHR: |
UnOp(reg1); |
Op2(opAND, imm(255), reg1) |
|
|IL.opABS: |
UnOp(reg1); |
Test(reg1); |
L := NewLabel(); |
jcc(jge, L); |
Neg(reg1); |
EmitLabel(L) |
|
|IL.opEQB, IL.opNEB: |
BinOp(reg1, reg2); |
drop; |
|
Test(reg1); |
L := NewLabel(); |
jcc(je, L); |
Op2(opMOV, imm(1), reg1); |
EmitLabel(L); |
|
Test(reg2); |
L := NewLabel(); |
jcc(je, L); |
Op2(opMOV, imm(1), reg2); |
EmitLabel(L); |
|
Op2(opCMP, reg2 * 256, reg1); |
IF opcode = IL.opEQB THEN |
setcc(je, reg1) |
ELSE |
setcc(jne, reg1) |
END |
|
|IL.opSAVEP: |
UnOp(reg1); |
Op2(opMOV, incr(PC), reg1 + dIDX); |
EmitWord(param2); |
Reloc(RCODE); |
EmitWord(0); |
drop |
|
|IL.opPUSHP: |
Op2(opMOV, incr(PC), GetAnyReg()); |
EmitWord(param2); |
Reloc(RCODE) |
|
|IL.opEQP, IL.opNEP: |
UnOp(reg1); |
Op2(opCMP, incr(PC), reg1); |
EmitWord(param1); |
Reloc(RCODE); |
drop; |
reg1 := GetAnyReg(); |
|
IF opcode = IL.opEQP THEN |
setcc(je, reg1) |
ELSIF opcode = IL.opNEP THEN |
setcc(jne, reg1) |
END |
|
|IL.opVADR_PARAM: |
reg1 := GetAnyReg(); |
Op2(opMOV, LocalSrc(param2), reg1); |
Push(reg1); |
drop |
|
|IL.opNEW: |
PushAll(1); |
n := param2 + 2; |
ASSERT(UTILS.Align(n, 2)); |
PushImm(n); |
PushImm(param1); |
CallRTL(RTL._new, 3) |
|
|IL.opRSET: |
PushAll(2); |
CallRTL(RTL._set, 2); |
GetRegA |
|
|IL.opRSETR: |
PushAll(1); |
PushImm(param2); |
CallRTL(RTL._set, 2); |
GetRegA |
|
|IL.opRSETL: |
UnOp(reg1); |
PushAll_1; |
PushImm(param2); |
Push(reg1); |
drop; |
CallRTL(RTL._set, 2); |
GetRegA |
|
|IL.opRSET1: |
PushAll(1); |
CallRTL(RTL._set1, 1); |
GetRegA |
|
|IL.opINCLC: |
UnOp(reg1); |
Op2(opBIS, imm(ORD({param2})), dst_x(0, reg1)); |
drop |
|
|IL.opEXCLC: |
UnOp(reg1); |
Op2(opBIC, imm(ORD({param2})), dst_x(0, reg1)); |
drop |
|
|IL.opIN: |
PushAll(2); |
CallRTL(RTL._in, 2); |
GetRegA |
|
|IL.opINR: |
PushAll(1); |
PushImm(param2); |
CallRTL(RTL._in, 2); |
GetRegA |
|
|IL.opINL: |
PushAll(1); |
PushImm(param2); |
CallRTL(RTL._in2, 2); |
GetRegA |
|
|IL.opINCL: |
PushAll(2); |
CallRTL(RTL._incl, 2) |
|
|IL.opEXCL: |
PushAll(2); |
CallRTL(RTL._excl, 2) |
|
|IL.opLADR_INCL, IL.opLADR_EXCL: |
PushAll(1); |
MovRR(SP, ACC); |
n := LocalOffset(param2); |
IF n # 0 THEN |
Op2(opADD, imm(n), ACC) |
END; |
Push(ACC); |
IF opcode = IL.opLADR_INCL THEN |
CallRTL(RTL._incl, 2) |
ELSIF opcode = IL.opLADR_EXCL THEN |
CallRTL(RTL._excl, 2) |
END |
|
|IL.opLADR_INCLC: |
Op2(opBIS, imm(ORD({param2})), LocalDst(param1)) |
|
|IL.opLADR_EXCLC: |
Op2(opBIC, imm(ORD({param2})), LocalDst(param1)) |
|
END; |
|
cmd := cmd.next(COMMAND) |
END; |
|
ASSERT(R.pushed = 0); |
ASSERT(R.top = -1) |
END translate; |
|
|
PROCEDURE prolog; |
VAR |
i: INTEGER; |
|
BEGIN |
RTL.Init(EmitLabel, EmitWord, EmitCall); |
FOR i := 0 TO LEN(RTL.rtl) - 1 DO |
RTL.Set(i, NewLabel()) |
END; |
|
IV[LEN(IV) - 1] := NewLabel(); |
EmitLabel(IV[LEN(IV) - 1]); |
Op2(opMOV, incr(PC), SP); |
EmitWord(0); |
Op2(opMOV, incr(PC), HP); |
EmitWord(0); |
Op2(opMOV, imm(5A80H), dst_x(0120H, SR)); (* stop WDT *) |
Op2(opMOV, imm(RTL.empty_proc), dst_x(0, SP)); |
Op2(opMOV, imm(RTL.empty_proc), dst_x(2, SP)); |
END prolog; |
|
|
PROCEDURE epilog; |
VAR |
L1, i, n: INTEGER; |
|
BEGIN |
Op2(opBIS, imm(10H), SR); (* CPUOFF *) |
|
L1 := NewLabel(); |
FOR i := 0 TO LEN(IV) - 2 DO |
IV[i] := NewLabel(); |
EmitLabel(IV[i]); |
PushImm(i); |
IF i # LEN(IV) - 2 THEN |
EmitJmp(opJMP, L1) |
END |
END; |
|
EmitLabel(L1); |
|
n := 0; |
FOR i := 0 TO 15 DO |
IF i IN R.regs THEN |
Push(i); |
INC(n) |
END |
END; |
|
MovRR(SP, R4); |
Op2(opADD, imm(n * 2), R4); |
|
Push(R4); |
Op1(opPUSH, R4, sINDIR); |
Op1(opCALL, SR, sIDX); EmitWord(-RTL.VarSize); Reloc(RBSS); (* call int *) |
Op2(opADD, imm(4), SP); |
|
FOR i := 15 TO 0 BY -1 DO |
IF i IN R.regs THEN |
Pop(i) |
END |
END; |
|
Op2(opADD, imm(2), SP); |
Op1(opRETI, 0, 0); |
|
RTL.Gen |
END epilog; |
|
|
PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS); |
VAR |
i, adr, heap, stack, TextSize, TypesSize, bits, n, val: INTEGER; |
|
Code, Data, Bss: RECORD address, size: INTEGER END; |
|
ram, rom: INTEGER; |
|
reloc: RELOC; |
|
BEGIN |
IdxWords.src := NOWORD; |
IdxWords.dst := NOWORD; |
|
ram := options.ram; |
rom := options.rom; |
|
IF ODD(ram) THEN DEC(ram) END; |
IF ODD(rom) THEN DEC(rom) END; |
|
ram := MIN(MAX(ram, minRAM), maxRAM); |
rom := MIN(MAX(rom, minROM), maxROM); |
|
IF IL.codes.bss > ram - StkReserve - RTL.VarSize THEN |
ERRORS.Error(204) |
END; |
|
Labels := CHL.CreateIntList(); |
FOR i := 1 TO IL.codes.lcount DO |
CHL.PushInt(Labels, 0) |
END; |
|
CodeList := LISTS.create(NIL); |
RelList := LISTS.create(NIL); |
REG.Init(R, Push, Pop, mov, xchg, {R4, R5, R6, R7}); |
|
prolog; |
translate(chkSTK IN options.checking); |
epilog; |
|
TypesSize := CHL.Length(IL.codes.types) * 2; |
Data.size := CHL.Length(IL.codes.data); |
IF ODD(Data.size) THEN |
CHL.PushByte(IL.codes.data, 0); |
INC(Data.size) |
END; |
Code.size := Fixup(0, IntVectorSize + TypesSize + Data.size); |
Code.address := 10000H - (IntVectorSize + TypesSize + Data.size + Code.size); |
IF Code.address < 10000H - rom THEN |
ERRORS.Error(203) |
END; |
Code.size := Fixup(Code.address, IntVectorSize + TypesSize + Data.size); |
Data.address := Code.address + Code.size; |
TextSize := Code.size + Data.size; |
|
IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN |
ERRORS.Error(203) |
END; |
|
stack := RTL.ram + ram; |
Bss.size := IL.codes.bss + IL.codes.bss MOD 2; |
DEC(stack, Bss.size); |
Bss.address := stack; |
DEC(stack, RTL.VarSize); |
heap := RTL.ram; |
ASSERT(stack - heap >= StkReserve); |
adr := Code.address + 2; |
PutWord(stack, adr); |
adr := Code.address + 6; |
PutWord(heap, adr); |
|
reloc := RelList.first(RELOC); |
WHILE reloc # NIL DO |
adr := reloc.WordPtr.offset * 2; |
val := reloc.WordPtr.val; |
CASE reloc.section OF |
|RCODE: PutWord(LabelOffs(val) * 2, adr) |
|RDATA: PutWord(val + Data.address, adr) |
|RBSS: PutWord((val + Bss.address) MOD 65536, adr) |
END; |
reloc := reloc.next(RELOC) |
END; |
|
adr := Data.address; |
|
FOR i := 0 TO Data.size - 1 DO |
mem[adr] := CHL.GetByte(IL.codes.data, i); |
INC(adr) |
END; |
|
FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO |
PutWord(CHL.GetInt(IL.codes.types, i), adr) |
END; |
|
FOR i := 0 TO 15 DO |
PutWord((33 - i) * i, adr); |
END; |
|
FOR n := 0 TO 15 DO |
bits := ORD({0 .. n}); |
FOR i := 0 TO 15 - n DO |
PutWord(bits, adr); |
bits := LSL(bits, 1) |
END |
END; |
|
PutWord(4130H, adr); (* RET *) |
PutWord(stack, adr); |
PutWord(0001H, adr); (* bsl signature (adr 0FFBEH) *) |
|
FOR i := 0 TO LEN(IV) - 1 DO |
PutWord(LabelOffs(IV[i]) * 2, adr) |
END; |
|
INC(TextSize, IntVectorSize + TypesSize + Code.address MOD 16); |
INC(Bss.size, StkReserve + RTL.VarSize); |
|
WR.Create(outname); |
HEX.Data(mem, Code.address - Code.address MOD 16, TextSize); |
HEX.End; |
WR.Close; |
|
C.Dashes; |
C.String(" rom: "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String(" ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)"); |
C.Ln; |
C.String(" ram: "); C.Int(Bss.size); C.String(" of "); C.Int(ram); C.String(" ("); C.Int(Bss.size * 100 DIV ram); C.StringLn("%)") |
END CodeGen; |
|
|
END MSP430. |