diff --git a/programs/develop/oberon07/Compiler.kex b/programs/develop/oberon07/Compiler.kex index fa02e0eccc..6c3abc7677 100644 Binary files a/programs/develop/oberon07/Compiler.kex and b/programs/develop/oberon07/Compiler.kex differ diff --git a/programs/develop/oberon07/tools/RVM32I.ob07 b/programs/develop/oberon07/tools/RVM32I.ob07 deleted file mode 100644 index 1aa501c065..0000000000 --- a/programs/develop/oberon07/tools/RVM32I.ob07 +++ /dev/null @@ -1,575 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020, Anton Krotov - All rights reserved. -*) - -(* - RVM32I executor and disassembler - - for win32 only - - Usage: - RVM32I.exe -run [program parameters] - RVM32I.exe -dis -*) - -MODULE RVM32I; - -IMPORT SYSTEM, File, Args, Out, API, HOST, RTL; - - -CONST - - opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opABS = 5; - opXCHG = 6; opLDR8 = 7; opLDR16 = 8; opLDR32 = 9; opPUSH = 10; opPUSHC = 11; - opPOP = 12; opJGZ = 13; opJZ = 14; opJNZ = 15; opLLA = 16; opJGA = 17; - opJLA = 18; opJMP = 19; opCALL = 20; opCALLI = 21; - - opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32; - opSTR8 = 34; opSTR16 = 36; opSTR32 = 38; opINCL = 40; opEXCL = 42; - opIN = 44; opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54; - opLSL = 56; opROR = 58; opMIN = 60; opMAX = 62; opEQ = 64; opNE = 66; - opLT = 68; opLE = 70; opGT = 72; opGE = 74; opBT = 76; - - opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33; - opSTR8C = 35; opSTR16C = 37; opSTR32C = 39; opINCLC = 41; opEXCLC = 43; - opINC = 45; opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55; - opLSLC = 57; opRORC = 59; opMINC = 61; opMAXC = 63; opEQC = 65; opNEC = 67; - opLTC = 69; opLEC = 71; opGTC = 73; opGEC = 75; opBTC = 77; - - opLEA = 78; opLABEL = 79; opSYSCALL = 80; - - - ACC = 0; BP = 3; SP = 4; - - Types = 0; - Strings = 1; - Global = 2; - Heap = 3; - Stack = 4; - - -TYPE - - COMMAND = POINTER TO RECORD - - op, param1, param2: INTEGER; - next: COMMAND - - END; - - -VAR - - R: ARRAY 32 OF INTEGER; - - Sections: ARRAY 5 OF RECORD address: INTEGER; name: ARRAY 16 OF CHAR END; - - first, last: COMMAND; - - Labels: ARRAY 30000 OF COMMAND; - - F: INTEGER; buf: ARRAY 65536 OF BYTE; cnt: INTEGER; - - -PROCEDURE syscall (ptr: INTEGER); -VAR - fn, p1, p2, p3, p4, r: INTEGER; - - proc2: PROCEDURE (a, b: INTEGER): INTEGER; - proc3: PROCEDURE (a, b, c: INTEGER): INTEGER; - proc4: PROCEDURE (a, b, c, d: INTEGER): INTEGER; - -BEGIN - SYSTEM.GET(ptr, fn); - SYSTEM.GET(ptr + 4, p1); - SYSTEM.GET(ptr + 8, p2); - SYSTEM.GET(ptr + 12, p3); - SYSTEM.GET(ptr + 16, p4); - CASE fn OF - | 0: HOST.ExitProcess(p1) - | 1: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.GetCurrentDirectory)); - r := proc2(p1, p2) - | 2: SYSTEM.PUT(SYSTEM.ADR(proc3), SYSTEM.ADR(HOST.GetArg)); - r := proc3(p1 + 2, p2, p3) - | 3: SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileRead)); - SYSTEM.PUT(ptr, proc4(p1, p2, p3, p4)) - | 4: SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileWrite)); - SYSTEM.PUT(ptr, proc4(p1, p2, p3, p4)) - | 5: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileCreate)); - SYSTEM.PUT(ptr, proc2(p1, p2)) - | 6: HOST.FileClose(p1) - | 7: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileOpen)); - SYSTEM.PUT(ptr, proc2(p1, p2)) - | 8: HOST.OutChar(CHR(p1)) - | 9: SYSTEM.PUT(ptr, HOST.GetTickCount()) - |10: SYSTEM.PUT(ptr, HOST.UnixTime()) - |11: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.isRelative)); - SYSTEM.PUT(ptr, proc2(p1, p2)) - |12: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.chmod)); - r := proc2(p1, p2) - END -END syscall; - - -PROCEDURE exec; -VAR - cmd: COMMAND; - param1, param2: INTEGER; - temp: INTEGER; - -BEGIN - cmd := first; - WHILE cmd # NIL DO - param1 := cmd.param1; - param2 := cmd.param2; - CASE cmd.op OF - |opSTOP: cmd := last - |opRET: SYSTEM.MOVE(R[SP], SYSTEM.ADR(cmd), 4); INC(R[SP], 4) - |opENTER: DEC(R[SP], 4); SYSTEM.PUT32(R[SP], R[BP]); R[BP] := R[SP]; WHILE param1 > 0 DO DEC(R[SP], 4); SYSTEM.PUT32(R[SP], 0); DEC(param1) END - |opPOP: SYSTEM.GET32(R[SP], R[param1]); INC(R[SP], 4) - |opNEG: R[param1] := -R[param1] - |opNOT: R[param1] := ORD(-BITS(R[param1])) - |opABS: R[param1] := ABS(R[param1]) - |opXCHG: temp := R[param1]; R[param1] := R[param2]; R[param2] := temp - |opLDR8: SYSTEM.GET8(R[param2], R[param1]); R[param1] := R[param1] MOD 256; - |opLDR16: SYSTEM.GET16(R[param2], R[param1]); R[param1] := R[param1] MOD 65536; - |opLDR32: SYSTEM.GET32(R[param2], R[param1]) - |opPUSH: DEC(R[SP], 4); SYSTEM.PUT32(R[SP], R[param1]) - |opPUSHC: DEC(R[SP], 4); SYSTEM.PUT32(R[SP], param1) - |opJGZ: IF R[param1] > 0 THEN cmd := Labels[cmd.param2] END - |opJZ: IF R[param1] = 0 THEN cmd := Labels[cmd.param2] END - |opJNZ: IF R[param1] # 0 THEN cmd := Labels[cmd.param2] END - |opLLA: SYSTEM.MOVE(SYSTEM.ADR(Labels[cmd.param2]), SYSTEM.ADR(R[param1]), 4) - |opJGA: IF R[ACC] > param1 THEN cmd := Labels[cmd.param2] END - |opJLA: IF R[ACC] < param1 THEN cmd := Labels[cmd.param2] END - |opJMP: cmd := Labels[cmd.param1] - |opCALL: DEC(R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(cmd), R[SP], 4); cmd := Labels[cmd.param1] - |opCALLI: DEC(R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(cmd), R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(R[param1]), SYSTEM.ADR(cmd), 4) - |opMOV: R[param1] := R[param2] - |opMOVC: R[param1] := param2 - |opMUL: R[param1] := R[param1] * R[param2] - |opMULC: R[param1] := R[param1] * param2 - |opADD: INC(R[param1], R[param2]) - |opADDC: INC(R[param1], param2) - |opSUB: DEC(R[param1], R[param2]) - |opSUBC: DEC(R[param1], param2) - |opDIV: R[param1] := R[param1] DIV R[param2] - |opDIVC: R[param1] := R[param1] DIV param2 - |opMOD: R[param1] := R[param1] MOD R[param2] - |opMODC: R[param1] := R[param1] MOD param2 - |opSTR8: SYSTEM.PUT8(R[param1], R[param2]) - |opSTR8C: SYSTEM.PUT8(R[param1], param2) - |opSTR16: SYSTEM.PUT16(R[param1], R[param2]) - |opSTR16C: SYSTEM.PUT16(R[param1], param2) - |opSTR32: SYSTEM.PUT32(R[param1], R[param2]) - |opSTR32C: SYSTEM.PUT32(R[param1], param2) - |opINCL: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) + {R[param2]})) - |opINCLC: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) + {param2})) - |opEXCL: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) - {R[param2]})) - |opEXCLC: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) - {param2})) - |opIN: R[param1] := ORD(R[param1] IN BITS(R[param2])) - |opINC: R[param1] := ORD(R[param1] IN BITS(param2)) - |opAND: R[param1] := ORD(BITS(R[param1]) * BITS(R[param2])) - |opANDC: R[param1] := ORD(BITS(R[param1]) * BITS(param2)) - |opOR: R[param1] := ORD(BITS(R[param1]) + BITS(R[param2])) - |opORC: R[param1] := ORD(BITS(R[param1]) + BITS(param2)) - |opXOR: R[param1] := ORD(BITS(R[param1]) / BITS(R[param2])) - |opXORC: R[param1] := ORD(BITS(R[param1]) / BITS(param2)) - |opASR: R[param1] := ASR(R[param1], R[param2]) - |opASRC: R[param1] := ASR(R[param1], param2) - |opLSR: R[param1] := LSR(R[param1], R[param2]) - |opLSRC: R[param1] := LSR(R[param1], param2) - |opLSL: R[param1] := LSL(R[param1], R[param2]) - |opLSLC: R[param1] := LSL(R[param1], param2) - |opROR: R[param1] := ROR(R[param1], R[param2]) - |opRORC: R[param1] := ROR(R[param1], param2) - |opMIN: R[param1] := MIN(R[param1], R[param2]) - |opMINC: R[param1] := MIN(R[param1], param2) - |opMAX: R[param1] := MAX(R[param1], R[param2]) - |opMAXC: R[param1] := MAX(R[param1], param2) - |opEQ: R[param1] := ORD(R[param1] = R[param2]) - |opEQC: R[param1] := ORD(R[param1] = param2) - |opNE: R[param1] := ORD(R[param1] # R[param2]) - |opNEC: R[param1] := ORD(R[param1] # param2) - |opLT: R[param1] := ORD(R[param1] < R[param2]) - |opLTC: R[param1] := ORD(R[param1] < param2) - |opLE: R[param1] := ORD(R[param1] <= R[param2]) - |opLEC: R[param1] := ORD(R[param1] <= param2) - |opGT: R[param1] := ORD(R[param1] > R[param2]) - |opGTC: R[param1] := ORD(R[param1] > param2) - |opGE: R[param1] := ORD(R[param1] >= R[param2]) - |opGEC: R[param1] := ORD(R[param1] >= param2) - |opBT: R[param1] := ORD((R[param1] < R[param2]) & (R[param1] >= 0)) - |opBTC: R[param1] := ORD((R[param1] < param2) & (R[param1] >= 0)) - |opLEA: R[param1 MOD 256] := Sections[param1 DIV 256].address + param2 - |opLABEL: - |opSYSCALL: syscall(R[param1]) - END; - cmd := cmd.next - END -END exec; - - -PROCEDURE disasm (name: ARRAY OF CHAR; t_count, c_count, glob, heap: INTEGER); -VAR - cmd: COMMAND; - param1, param2, i, t, ptr: INTEGER; - b: BYTE; - - - PROCEDURE String (s: ARRAY OF CHAR); - VAR - n: INTEGER; - - BEGIN - n := LENGTH(s); - IF n > LEN(buf) - cnt THEN - ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt); - cnt := 0 - END; - SYSTEM.MOVE(SYSTEM.ADR(s[0]), SYSTEM.ADR(buf[0]) + cnt, n); - INC(cnt, n) - END String; - - - PROCEDURE Ln; - BEGIN - String(0DX + 0AX) - END Ln; - - - PROCEDURE hexdgt (n: INTEGER): CHAR; - BEGIN - IF n < 10 THEN - INC(n, ORD("0")) - ELSE - INC(n, ORD("A") - 10) - END - - RETURN CHR(n) - END hexdgt; - - - PROCEDURE Hex (x: INTEGER); - VAR - str: ARRAY 11 OF CHAR; - n: INTEGER; - - BEGIN - n := 10; - str[10] := 0X; - WHILE n > 2 DO - str[n - 1] := hexdgt(x MOD 16); - x := x DIV 16; - DEC(n) - END; - str[1] := "x"; - str[0] := "0"; - String(str) - END Hex; - - - PROCEDURE Byte (x: BYTE); - VAR - str: ARRAY 5 OF CHAR; - - BEGIN - str[4] := 0X; - str[3] := hexdgt(x MOD 16); - str[2] := hexdgt(x DIV 16); - str[1] := "x"; - str[0] := "0"; - String(str) - END Byte; - - - PROCEDURE Reg (n: INTEGER); - VAR - s: ARRAY 2 OF CHAR; - BEGIN - IF n = BP THEN - String("BP") - ELSIF n = SP THEN - String("SP") - ELSE - String("R"); - s[1] := 0X; - IF n >= 10 THEN - s[0] := CHR(n DIV 10 + ORD("0")); - String(s) - END; - s[0] := CHR(n MOD 10 + ORD("0")); - String(s) - END - END Reg; - - - PROCEDURE Reg2 (r1, r2: INTEGER); - BEGIN - Reg(r1); String(", "); Reg(r2) - END Reg2; - - - PROCEDURE RegC (r, c: INTEGER); - BEGIN - Reg(r); String(", "); Hex(c) - END RegC; - - - PROCEDURE RegL (r, label: INTEGER); - BEGIN - Reg(r); String(", L"); Hex(label) - END RegL; - - -BEGIN - Sections[Types].name := "TYPES"; - Sections[Strings].name := "STRINGS"; - Sections[Global].name := "GLOBAL"; - Sections[Heap].name := "HEAP"; - Sections[Stack].name := "STACK"; - - F := File.Create(name); - ASSERT(F > 0); - cnt := 0; - String("CODE:"); Ln; - cmd := first; - WHILE cmd # NIL DO - param1 := cmd.param1; - param2 := cmd.param2; - CASE cmd.op OF - |opSTOP: String("STOP") - |opRET: String("RET") - |opENTER: String("ENTER "); Hex(param1) - |opPOP: String("POP "); Reg(param1) - |opNEG: String("NEG "); Reg(param1) - |opNOT: String("NOT "); Reg(param1) - |opABS: String("ABS "); Reg(param1) - |opXCHG: String("XCHG "); Reg2(param1, param2) - |opLDR8: String("LDR8 "); Reg2(param1, param2) - |opLDR16: String("LDR16 "); Reg2(param1, param2) - |opLDR32: String("LDR32 "); Reg2(param1, param2) - |opPUSH: String("PUSH "); Reg(param1) - |opPUSHC: String("PUSH "); Hex(param1) - |opJGZ: String("JGZ "); RegL(param1, param2) - |opJZ: String("JZ "); RegL(param1, param2) - |opJNZ: String("JNZ "); RegL(param1, param2) - |opLLA: String("LLA "); RegL(param1, param2) - |opJGA: String("JGA "); Hex(param1); String(", L"); Hex(param2) - |opJLA: String("JLA "); Hex(param1); String(", L"); Hex(param2) - |opJMP: String("JMP L"); Hex(param1) - |opCALL: String("CALL L"); Hex(param1) - |opCALLI: String("CALL "); Reg(param1) - |opMOV: String("MOV "); Reg2(param1, param2) - |opMOVC: String("MOV "); RegC(param1, param2) - |opMUL: String("MUL "); Reg2(param1, param2) - |opMULC: String("MUL "); RegC(param1, param2) - |opADD: String("ADD "); Reg2(param1, param2) - |opADDC: String("ADD "); RegC(param1, param2) - |opSUB: String("SUB "); Reg2(param1, param2) - |opSUBC: String("SUB "); RegC(param1, param2) - |opDIV: String("DIV "); Reg2(param1, param2) - |opDIVC: String("DIV "); RegC(param1, param2) - |opMOD: String("MOD "); Reg2(param1, param2) - |opMODC: String("MOD "); RegC(param1, param2) - |opSTR8: String("STR8 "); Reg2(param1, param2) - |opSTR8C: String("STR8 "); RegC(param1, param2) - |opSTR16: String("STR16 "); Reg2(param1, param2) - |opSTR16C: String("STR16 "); RegC(param1, param2) - |opSTR32: String("STR32 "); Reg2(param1, param2) - |opSTR32C: String("STR32 "); RegC(param1, param2) - |opINCL: String("INCL "); Reg2(param1, param2) - |opINCLC: String("INCL "); RegC(param1, param2) - |opEXCL: String("EXCL "); Reg2(param1, param2) - |opEXCLC: String("EXCL "); RegC(param1, param2) - |opIN: String("IN "); Reg2(param1, param2) - |opINC: String("IN "); RegC(param1, param2) - |opAND: String("AND "); Reg2(param1, param2) - |opANDC: String("AND "); RegC(param1, param2) - |opOR: String("OR "); Reg2(param1, param2) - |opORC: String("OR "); RegC(param1, param2) - |opXOR: String("XOR "); Reg2(param1, param2) - |opXORC: String("XOR "); RegC(param1, param2) - |opASR: String("ASR "); Reg2(param1, param2) - |opASRC: String("ASR "); RegC(param1, param2) - |opLSR: String("LSR "); Reg2(param1, param2) - |opLSRC: String("LSR "); RegC(param1, param2) - |opLSL: String("LSL "); Reg2(param1, param2) - |opLSLC: String("LSL "); RegC(param1, param2) - |opROR: String("ROR "); Reg2(param1, param2) - |opRORC: String("ROR "); RegC(param1, param2) - |opMIN: String("MIN "); Reg2(param1, param2) - |opMINC: String("MIN "); RegC(param1, param2) - |opMAX: String("MAX "); Reg2(param1, param2) - |opMAXC: String("MAX "); RegC(param1, param2) - |opEQ: String("EQ "); Reg2(param1, param2) - |opEQC: String("EQ "); RegC(param1, param2) - |opNE: String("NE "); Reg2(param1, param2) - |opNEC: String("NE "); RegC(param1, param2) - |opLT: String("LT "); Reg2(param1, param2) - |opLTC: String("LT "); RegC(param1, param2) - |opLE: String("LE "); Reg2(param1, param2) - |opLEC: String("LE "); RegC(param1, param2) - |opGT: String("GT "); Reg2(param1, param2) - |opGTC: String("GT "); RegC(param1, param2) - |opGE: String("GE "); Reg2(param1, param2) - |opGEC: String("GE "); RegC(param1, param2) - |opBT: String("BT "); Reg2(param1, param2) - |opBTC: String("BT "); RegC(param1, param2) - |opLEA: String("LEA "); Reg(param1 MOD 256); String(", "); String(Sections[param1 DIV 256].name); String(" + "); Hex(param2) - |opLABEL: String("L"); Hex(param1); String(":") - |opSYSCALL: String("SYSCALL "); Reg(param1) - END; - Ln; - cmd := cmd.next - END; - - String("TYPES:"); - ptr := Sections[Types].address; - FOR i := 0 TO t_count - 1 DO - IF i MOD 4 = 0 THEN - Ln; String("WORD ") - ELSE - String(", ") - END; - SYSTEM.GET32(ptr, t); INC(ptr, 4); - Hex(t) - END; - Ln; - - String("STRINGS:"); - ptr := Sections[Strings].address; - FOR i := 0 TO c_count - 1 DO - IF i MOD 8 = 0 THEN - Ln; String("BYTE ") - ELSE - String(", ") - END; - SYSTEM.GET8(ptr, b); INC(ptr); - Byte(b) - END; - Ln; - - String("GLOBAL:"); Ln; - String("WORDS "); Hex(glob); Ln; - String("HEAP:"); Ln; - String("WORDS "); Hex(heap); Ln; - String("STACK:"); Ln; - String("WORDS 8"); Ln; - - ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt); - File.Close(F) -END disasm; - - -PROCEDURE GetCommand (adr: INTEGER): COMMAND; -VAR - op, param1, param2: INTEGER; - res: COMMAND; - -BEGIN - op := 0; param1 := 0; param2 := 0; - SYSTEM.GET32(adr, op); - SYSTEM.GET32(adr + 4, param1); - SYSTEM.GET32(adr + 8, param2); - NEW(res); - res.op := op; - res.param1 := param1; - res.param2 := param2; - res.next := NIL - - RETURN res -END GetCommand; - - -PROCEDURE main; -VAR - name, param: ARRAY 1024 OF CHAR; - cmd: COMMAND; - file, fsize, n: INTEGER; - - descr: ARRAY 12 OF INTEGER; - - offTypes, offStrings, GlobalSize, HeapStackSize, DescrSize: INTEGER; - -BEGIN - Out.Open; - Args.GetArg(1, name); - F := File.Open(name, File.OPEN_R); - IF F > 0 THEN - DescrSize := LEN(descr) * SYSTEM.SIZE(INTEGER); - fsize := File.Seek(F, 0, File.SEEK_END); - ASSERT(fsize > DescrSize); - file := API._NEW(fsize); - ASSERT(file # 0); - n := File.Seek(F, 0, File.SEEK_BEG); - ASSERT(fsize = File.Read(F, file, fsize)); - File.Close(F); - - SYSTEM.MOVE(file + fsize - DescrSize, SYSTEM.ADR(descr[0]), DescrSize); - offTypes := descr[0]; - ASSERT(offTypes < fsize - DescrSize); - ASSERT(offTypes > 0); - ASSERT(offTypes MOD 12 = 0); - offStrings := descr[1]; - ASSERT(offStrings < fsize - DescrSize); - ASSERT(offStrings > 0); - ASSERT(offStrings MOD 4 = 0); - ASSERT(offStrings > offTypes); - GlobalSize := descr[2]; - ASSERT(GlobalSize > 0); - HeapStackSize := descr[3]; - ASSERT(HeapStackSize > 0); - - Sections[Types].address := API._NEW(offStrings - offTypes); - ASSERT(Sections[Types].address # 0); - SYSTEM.MOVE(file + offTypes, Sections[Types].address, offStrings - offTypes); - - Sections[Strings].address := API._NEW(fsize - offStrings - DescrSize); - ASSERT(Sections[Strings].address # 0); - SYSTEM.MOVE(file + offStrings, Sections[Strings].address, fsize - offStrings - DescrSize); - - Sections[Global].address := API._NEW(GlobalSize * 4); - ASSERT(Sections[Global].address # 0); - - Sections[Heap].address := API._NEW(HeapStackSize * 4); - ASSERT(Sections[Heap].address # 0); - - Sections[Stack].address := Sections[Heap].address + HeapStackSize * 4 - 32; - - n := offTypes DIV 12; - first := GetCommand(file + offTypes - n * 12); - last := first; - DEC(n); - WHILE n > 0 DO - cmd := GetCommand(file + offTypes - n * 12); - IF cmd.op = opLABEL THEN - Labels[cmd.param1] := cmd - END; - last.next := cmd; - last := cmd; - DEC(n) - END; - file := API._DISPOSE(file); - Args.GetArg(2, param); - IF param = "-dis" THEN - Args.GetArg(3, name); - IF name # "" THEN - disasm(name, (offStrings - offTypes) DIV 4, fsize - offStrings - DescrSize, GlobalSize, HeapStackSize) - END - ELSIF param = "-run" THEN - exec - END - ELSE - Out.String("file not found"); Out.Ln - END -END main; - - -BEGIN - ASSERT(RTL.bit_depth = 32); - main -END RVM32I. \ No newline at end of file diff --git a/programs/develop/oberon07/tools/RVMxI.ob07 b/programs/develop/oberon07/tools/RVMxI.ob07 deleted file mode 100644 index af40b4481a..0000000000 --- a/programs/develop/oberon07/tools/RVMxI.ob07 +++ /dev/null @@ -1,668 +0,0 @@ -(* - BSD 2-Clause License - - Copyright (c) 2020-2021, Anton Krotov - All rights reserved. -*) - -(* - RVMxI executor and disassembler - - Usage: - RVMxI.exe -run [program parameters] - RVMxI.exe -dis -*) - -MODULE RVMxI; - -IMPORT SYSTEM, File, Args, Out, API, HOST; - - -CONST - - szWORD = HOST.bit_depth DIV 8; - - opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opNOP = 5; - opXCHG = 6; opLDB = 7; opLDH = 8; opLDW = 9; opPUSH = 10; opPUSHC = 11; - opPOP = 12; opLABEL = 13; opLEA = 14; opLLA = 15; - opLDD = 16; (* 17, 18 *) - opJMP = 19; opCALL = 20; opCALLI = 21; - - opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32; - opSTB = 34; opSTH = 36; opSTW = 38; opSTD = 40; (* 42, 44 *) - opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54; - opLSL = 56; opROR = 58; (* 60, 62 *) opCMP = 64; - - opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33; - opSTBC = 35; opSTHC = 37; opSTWC = 39; opSTDC = 41; (* 43, 45 *) - opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55; - opLSLC = 57; opRORC = 59; (* 61, 63 *) opCMPC = 65; - - opBIT = 66; opSYSCALL = 67; opJBT = 68; opADDRC = 69; - - opJEQ = 70; opJNE = 71; opJLT = 72; opJGE = 73; opJGT = 74; opJLE = 75; - opSEQ = 76; opSNE = 77; opSLT = 78; opSGE = 79; opSGT = 80; opSLE = 81; - - - nREG = 16; - ACC = 0; BP = 3; SP = 4; - - Types = 0; - Strings = 1; - Global = 2; - Heap = 3; - Stack = 4; - - -TYPE - - COMMAND = POINTER TO RECORD - - op, param1, param2: INTEGER; - next, prev: COMMAND - - END; - - LABELS = ARRAY 30000 OF COMMAND; - - SECTIONS = ARRAY 5 OF INTEGER; - - -VAR - - Sections: SECTIONS; - - first, last: COMMAND; - - Labels: LABELS; - - F: INTEGER; buf: ARRAY 65536 OF BYTE; cnt: INTEGER; - - -PROCEDURE syscall (ptr: INTEGER); -VAR - fn, r, n: INTEGER; - - proc2: PROCEDURE (a, b: INTEGER): INTEGER; - proc3: PROCEDURE (a, b, c: INTEGER): INTEGER; - proc4: PROCEDURE (a, b, c, d: INTEGER): INTEGER; - - r1, r2: REAL; - - - PROCEDURE GetInt (ptr, n: INTEGER): INTEGER; - BEGIN - SYSTEM.GET(ptr + SYSTEM.SIZE(INTEGER) * n, n) - RETURN n - END GetInt; - - - PROCEDURE GetReal (ptr, n: INTEGER): REAL; - VAR - r: REAL; - - BEGIN - SYSTEM.GET(ptr + SYSTEM.SIZE(INTEGER) * n, r) - RETURN r - END GetReal; - - -BEGIN - fn := GetInt(ptr, 0); - CASE fn OF - | 0: - HOST.ExitProcess(GetInt(ptr, 1)) - - | 1: - SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.GetCurrentDirectory)); - r := proc2(GetInt(ptr, 1), GetInt(ptr, 2)) - - | 2: - n := GetInt(ptr, 1); - SYSTEM.PUT(SYSTEM.ADR(proc3), SYSTEM.ADR(HOST.GetArg)); - r := proc3(n - ORD(n = 0) + 2, GetInt(ptr, 2), GetInt(ptr, 3)) - - | 3: - SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileRead)); - SYSTEM.PUT(ptr, proc4(GetInt(ptr, 1), GetInt(ptr, 2), GetInt(ptr, 3), GetInt(ptr, 4))) - - | 4: - SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileWrite)); - SYSTEM.PUT(ptr, proc4(GetInt(ptr, 1), GetInt(ptr, 2), GetInt(ptr, 3), GetInt(ptr, 4))) - - | 5: - SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileCreate)); - SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2))) - - | 6: - HOST.FileClose(GetInt(ptr, 1)) - - | 7: - SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileOpen)); - SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2))) - - | 8: - HOST.OutChar(CHR(GetInt(ptr, 1))) - - | 9: - SYSTEM.PUT(ptr, HOST.GetTickCount()) - - |10: - SYSTEM.PUT(ptr, HOST.UnixTime()) - - |11: - SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.isRelative)); - SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2))) - - |12: - SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.chmod)); - r := proc2(GetInt(ptr, 1), GetInt(ptr, 2)) - - |100..103: - r1 := GetReal(ptr, 1); - r2 := GetReal(ptr, 2); - CASE fn OF - |100: SYSTEM.PUT(ptr, r2 * r1) - |101: SYSTEM.PUT(ptr, r2 / r1) - |102: SYSTEM.PUT(ptr, r2 + r1) - |103: SYSTEM.PUT(ptr, r2 - r1) - END - - |104: - r1 := GetReal(ptr, 2); - r2 := GetReal(ptr, 3); - CASE GetInt(ptr, 1) OF - |0: SYSTEM.PUT(ptr, ORD(r2 = r1)) - |1: SYSTEM.PUT(ptr, ORD(r2 # r1)) - |2: SYSTEM.PUT(ptr, ORD(r2 < r1)) - |3: SYSTEM.PUT(ptr, ORD(r2 <= r1)) - |4: SYSTEM.PUT(ptr, ORD(r2 > r1)) - |5: SYSTEM.PUT(ptr, ORD(r2 >= r1)) - END - - |105: - SYSTEM.PUT(ptr, FLOOR(GetReal(ptr, 1))) - - |106: - SYSTEM.PUT(ptr, FLT(GetInt(ptr, 1))) - - END -END syscall; - - -PROCEDURE exec (VAR Labels: LABELS; first, last: COMMAND; Sections: SECTIONS); -VAR - cmd: COMMAND; - param1, param2, i: INTEGER; - R: ARRAY nREG OF INTEGER; - - fe, fl, fb: BOOLEAN; - -BEGIN - FOR i := 0 TO LEN(Labels) - 1 DO - cmd := Labels[i]; - IF cmd # NIL THEN - REPEAT - cmd := cmd.next - UNTIL cmd.op # opLABEL; - Labels[i] := cmd - END - END; - - cmd := first; - WHILE cmd # NIL DO - IF cmd.op = opLABEL THEN - cmd.prev.next := cmd.next; - cmd.next.prev := cmd.prev - END; - cmd := cmd.next - END; - - FOR i := 0 TO LEN(Labels) - 1 DO - IF Labels[i] # NIL THEN - Labels[i] := Labels[i].prev - END - END; - - cmd := first; - WHILE cmd # NIL DO - param1 := cmd.param1; - param2 := cmd.param2; - - CASE cmd.op OF - |opSTOP: cmd := last - |opRET: SYSTEM.GET(R[SP], cmd); INC(R[SP], szWORD) - |opENTER: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], R[BP]); R[BP] := R[SP]; - WHILE param1 > 0 DO DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], 0); DEC(param1) END - |opPOP: SYSTEM.GET(R[SP], R[param1]); INC(R[SP], szWORD) - |opPUSH: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], R[param1]) - |opPUSHC: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], param1) - |opCALL: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], cmd); cmd := Labels[param1] - |opCALLI: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], cmd); SYSTEM.GET(SYSTEM.ADR(R[param1]), cmd) - |opNEG: R[param1] := -R[param1] - |opNOT: R[param1] := ORD(-BITS(R[param1])) - |opNOP: - |opXCHG: i := R[param1]; R[param1] := R[param2]; R[param2] := i - |opLDB: i := param1 MOD 256; SYSTEM.GET8(R[param1 DIV 256] + param2, R[i]); R[i] := R[i] MOD 256 - |opLDH: i := param1 MOD 256; SYSTEM.GET16(R[param1 DIV 256] + param2, R[i]); R[i] := R[i] MOD 65536 - |opLDW: SYSTEM.GET32(R[param1 DIV 256] + param2, R[param1 MOD 256]); - $IF (CPU_X8664) - R[param1 MOD 256] := R[param1 MOD 256] MOD 100000000H - $END - |opLDD: SYSTEM.GET(R[param1 DIV 256] + param2, R[param1 MOD 256]) - |opLLA: SYSTEM.GET(SYSTEM.ADR(Labels[param2]), R[param1]) - |opJMP: cmd := Labels[param1] - |opMOV: R[param1] := R[param2] - |opMOVC: R[param1] := param2 - |opMUL: R[param1] := R[param1] * R[param2] - |opMULC: R[param1] := R[param1] * param2 - |opADD: INC(R[param1], R[param2]) - |opADDC: INC(R[param1], param2) - |opSUB: DEC(R[param1], R[param2]) - |opSUBC: DEC(R[param1], param2) - |opDIV: R[param1] := R[param1] DIV R[param2] - |opDIVC: R[param1] := R[param1] DIV param2 - |opMOD: R[param1] := R[param1] MOD R[param2] - |opMODC: R[param1] := R[param1] MOD param2 - |opSTB: SYSTEM.PUT8(R[param1 DIV 256] + param2, R[param1 MOD 256]) - |opSTH: SYSTEM.PUT16(R[param1 DIV 256] + param2, R[param1 MOD 256]) - |opSTW: SYSTEM.PUT32(R[param1 DIV 256] + param2, R[param1 MOD 256]) - |opSTD: SYSTEM.PUT(R[param1 DIV 256] + param2, R[param1 MOD 256]) - |opSTBC: SYSTEM.PUT8(R[param1], param2) - |opSTHC: SYSTEM.PUT16(R[param1], param2) - |opSTWC: SYSTEM.PUT32(R[param1], param2) - |opSTDC: SYSTEM.PUT(R[param1], param2) - |opAND: R[param1] := ORD(BITS(R[param1]) * BITS(R[param2])) - |opANDC: R[param1] := ORD(BITS(R[param1]) * BITS(param2)) - |opOR: R[param1] := ORD(BITS(R[param1]) + BITS(R[param2])) - |opORC: R[param1] := ORD(BITS(R[param1]) + BITS(param2)) - |opXOR: R[param1] := ORD(BITS(R[param1]) / BITS(R[param2])) - |opXORC: R[param1] := ORD(BITS(R[param1]) / BITS(param2)) - |opASR: R[param1] := ASR(R[param1], R[param2]) - |opASRC: R[param1] := ASR(R[param1], param2) - |opLSR: R[param1] := LSR(R[param1], R[param2]) - |opLSRC: R[param1] := LSR(R[param1], param2) - |opLSL: R[param1] := LSL(R[param1], R[param2]) - |opLSLC: R[param1] := LSL(R[param1], param2) - |opROR: R[param1] := ROR(R[param1], R[param2]) - |opRORC: R[param1] := ROR(R[param1], param2) - |opLEA: R[param1 MOD 256] := Sections[param1 DIV 256] + param2 - (*|opLABEL:*) - |opSYSCALL: syscall(R[param1]) - |opADDRC: R[param1 MOD 256] := R[param1 DIV 256] + param2 - |opCMP: fl := R[param1] < R[param2]; fe := R[param1] = R[param2]; fb := fl & (R[param1] >= 0) - |opCMPC: fl := R[param1] < param2; fe := R[param1] = param2; fb := fl & (R[param1] >= 0) - |opJEQ: IF fe THEN cmd := Labels[param1] END - |opJNE: IF ~fe THEN cmd := Labels[param1] END - |opJLT: IF fl THEN cmd := Labels[param1] END - |opJLE: IF fl OR fe THEN cmd := Labels[param1] END - |opJGT: IF ~fl & ~fe THEN cmd := Labels[param1] END - |opJGE: IF ~fl THEN cmd := Labels[param1] END - |opSEQ: R[param1] := ORD(fe) - |opSNE: R[param1] := ORD(~fe) - |opSLT: R[param1] := ORD(fl) - |opSLE: R[param1] := ORD(fl OR fe) - |opSGT: R[param1] := ORD(~fl & ~fe) - |opSGE: R[param1] := ORD(~fl) - |opJBT: IF fb THEN cmd := Labels[param1] END - |opBIT: R[param1] := ORD({R[param2]}) - END; - cmd := cmd.next - END -END exec; - - -PROCEDURE disasm (name: ARRAY OF CHAR; t_count, c_count, glob, heap: INTEGER); -VAR - cmd: COMMAND; - param1, param2, i, t, ptr: INTEGER; - b: BYTE; - Names: ARRAY 5, 16 OF CHAR; - - - PROCEDURE String (s: ARRAY OF CHAR); - VAR - n: INTEGER; - - BEGIN - n := LENGTH(s); - IF n > LEN(buf) - cnt THEN - ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt); - cnt := 0 - END; - SYSTEM.MOVE(SYSTEM.ADR(s[0]), SYSTEM.ADR(buf[0]) + cnt, n); - INC(cnt, n) - END String; - - - PROCEDURE Ln; - BEGIN - String(0DX + 0AX) - END Ln; - - - PROCEDURE hexdgt (n: INTEGER): CHAR; - BEGIN - IF n < 10 THEN - INC(n, ORD("0")) - ELSE - INC(n, ORD("A") - 10) - END - - RETURN CHR(n) - END hexdgt; - - - PROCEDURE Hex (x: INTEGER); - VAR - str: ARRAY 19 OF CHAR; - n: INTEGER; - - BEGIN - n := szWORD * 2 + 2; - str[n] := 0X; - WHILE n > 2 DO - str[n - 1] := hexdgt(x MOD 16); - x := x DIV 16; - DEC(n) - END; - str[1] := "x"; - str[0] := "0"; - String(str) - END Hex; - - - PROCEDURE Byte (x: BYTE); - VAR - str: ARRAY 5 OF CHAR; - - BEGIN - str[4] := 0X; - str[3] := hexdgt(x MOD 16); - str[2] := hexdgt(x DIV 16); - str[1] := "x"; - str[0] := "0"; - String(str) - END Byte; - - - PROCEDURE Reg (n: INTEGER); - VAR - s: ARRAY 2 OF CHAR; - BEGIN - IF n = BP THEN - String("BP") - ELSIF n = SP THEN - String("SP") - ELSE - String("R"); - s[1] := 0X; - IF n >= 10 THEN - s[0] := CHR(n DIV 10 + ORD("0")); - String(s) - END; - s[0] := CHR(n MOD 10 + ORD("0")); - String(s) - END - END Reg; - - - PROCEDURE Reg2 (r1, r2: INTEGER); - BEGIN - Reg(r1); String(", "); Reg(r2) - END Reg2; - - - PROCEDURE RegC (r, c: INTEGER); - BEGIN - Reg(r); String(", "); Hex(c) - END RegC; - - - PROCEDURE RegL (r, label: INTEGER); - BEGIN - Reg(r); String(", L"); Hex(label) - END RegL; - - -BEGIN - Names[Types] := "TYPES"; - Names[Strings] := "STRINGS"; - Names[Global] := "GLOBAL"; - Names[Heap] := "HEAP"; - Names[Stack] := "STACK"; - - F := File.Create(name); - ASSERT(F > 0); - cnt := 0; - String("CODE:"); Ln; - cmd := first; - WHILE cmd # NIL DO - param1 := cmd.param1; - param2 := cmd.param2; - CASE cmd.op OF - |opSTOP: String("STOP") - |opRET: String("RET") - |opENTER: String("ENTER "); Hex(param1) - |opPOP: String("POP "); Reg(param1) - |opNEG: String("NEG "); Reg(param1) - |opNOT: String("NOT "); Reg(param1) - |opNOP: String("NOP") - |opXCHG: String("XCHG "); Reg2(param1, param2) - |opLDB: String("LDB "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]") - |opLDH: String("LDH "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]") - |opLDW: String("LDW "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]") - |opLDD: String("LDD "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]") - |opPUSH: String("PUSH "); Reg(param1) - |opPUSHC: String("PUSH "); Hex(param1) - |opLLA: String("LLA "); RegL(param1, param2) - |opJMP: String("JMP L"); Hex(param1) - |opCALL: String("CALL L"); Hex(param1) - |opCALLI: String("CALL "); Reg(param1) - |opMOV: String("MOV "); Reg2(param1, param2) - |opMOVC: String("MOV "); RegC(param1, param2) - |opMUL: String("MUL "); Reg2(param1, param2) - |opMULC: String("MUL "); RegC(param1, param2) - |opADD: String("ADD "); Reg2(param1, param2) - |opADDC: String("ADD "); RegC(param1, param2) - |opSUB: String("SUB "); Reg2(param1, param2) - |opSUBC: String("SUB "); RegC(param1, param2) - |opDIV: String("DIV "); Reg2(param1, param2) - |opDIVC: String("DIV "); RegC(param1, param2) - |opMOD: String("MOD "); Reg2(param1, param2) - |opMODC: String("MOD "); RegC(param1, param2) - |opSTB: String("STB ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256) - |opSTH: String("STH ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256) - |opSTW: String("STW ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256) - |opSTD: String("STD ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256) - |opSTBC: String("STB ["); Reg(param1); String("], "); Hex(param2) - |opSTHC: String("STH ["); Reg(param1); String("], "); Hex(param2) - |opSTWC: String("STW ["); Reg(param1); String("], "); Hex(param2) - |opSTDC: String("STD ["); Reg(param1); String("], "); Hex(param2) - |opAND: String("AND "); Reg2(param1, param2) - |opANDC: String("AND "); RegC(param1, param2) - |opOR: String("OR "); Reg2(param1, param2) - |opORC: String("OR "); RegC(param1, param2) - |opXOR: String("XOR "); Reg2(param1, param2) - |opXORC: String("XOR "); RegC(param1, param2) - |opASR: String("ASR "); Reg2(param1, param2) - |opASRC: String("ASR "); RegC(param1, param2) - |opLSR: String("LSR "); Reg2(param1, param2) - |opLSRC: String("LSR "); RegC(param1, param2) - |opLSL: String("LSL "); Reg2(param1, param2) - |opLSLC: String("LSL "); RegC(param1, param2) - |opROR: String("ROR "); Reg2(param1, param2) - |opRORC: String("ROR "); RegC(param1, param2) - |opLEA: String("LEA "); Reg(param1 MOD 256); String(", "); String(Names[param1 DIV 256]); String(" + "); Hex(param2) - |opADDRC: String("ADD "); Reg(param1 MOD 256); String(", "); Reg(param1 DIV 256); String(", "); Hex(param2) - |opLABEL: String("L"); Hex(param1); String(":") - |opSYSCALL: String("SYSCALL "); Reg(param1) - |opCMP: String("CMP "); Reg2(param1, param2) - |opCMPC: String("CMP "); RegC(param1, param2) - |opJEQ: String("JEQ L"); Hex(param1) - |opJNE: String("JNE L"); Hex(param1) - |opJLT: String("JLT L"); Hex(param1) - |opJLE: String("JLE L"); Hex(param1) - |opJGT: String("JGT L"); Hex(param1) - |opJGE: String("JGE L"); Hex(param1) - |opSEQ: String("SEQ "); Reg(param1) - |opSNE: String("SNE "); Reg(param1) - |opSLT: String("SLT "); Reg(param1) - |opSLE: String("SLE "); Reg(param1) - |opSGT: String("SGT "); Reg(param1) - |opSGE: String("SGE "); Reg(param1) - |opJBT: String("JBT L"); Hex(param1) - |opBIT: String("BIT "); Reg2(param1, param2) - END; - Ln; - cmd := cmd.next - END; - - String("TYPES:"); - ptr := Sections[Types]; - FOR i := 0 TO t_count - 1 DO - IF i MOD 4 = 0 THEN - Ln; String("WORD ") - ELSE - String(", ") - END; - SYSTEM.GET(ptr, t); INC(ptr, szWORD); - Hex(t) - END; - Ln; - - String("STRINGS:"); - ptr := Sections[Strings]; - FOR i := 0 TO c_count - 1 DO - IF i MOD 8 = 0 THEN - Ln; String("BYTE ") - ELSE - String(", ") - END; - SYSTEM.GET8(ptr, b); INC(ptr); - Byte(b) - END; - Ln; - - String("GLOBAL:"); Ln; - String("WORDS "); Hex(glob); Ln; - String("HEAP:"); Ln; - String("WORDS "); Hex(heap); Ln; - String("STACK:"); Ln; - String("WORDS 8"); Ln; - - ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt); - File.Close(F) -END disasm; - - -PROCEDURE GetCommand (adr: INTEGER): COMMAND; -VAR - op, param1, param2: INTEGER; - res: COMMAND; - -BEGIN - op := 0; param1 := 0; param2 := 0; - SYSTEM.GET(adr, op); - SYSTEM.GET(adr + szWORD, param1); - SYSTEM.GET(adr + szWORD * 2, param2); - NEW(res); - res.op := op; - res.param1 := param1; - res.param2 := param2; - res.next := NIL - - RETURN res -END GetCommand; - - -PROCEDURE main; -VAR - name, param: ARRAY 1024 OF CHAR; - cmd: COMMAND; - file, fsize, n: INTEGER; - - descr: ARRAY 12 OF INTEGER; - - offTypes, offStrings, GlobalSize, HeapStackSize, DescrSize: INTEGER; - -BEGIN - Out.Open; - Args.GetArg(1, name); - F := File.Open(name, File.OPEN_R); - IF F > 0 THEN - DescrSize := LEN(descr) * SYSTEM.SIZE(INTEGER); - fsize := File.Seek(F, 0, File.SEEK_END); - ASSERT(fsize > DescrSize); - file := API._NEW(fsize); - ASSERT(file # 0); - n := File.Seek(F, 0, File.SEEK_BEG); - ASSERT(fsize = File.Read(F, file, fsize)); - File.Close(F); - - SYSTEM.MOVE(file + fsize - DescrSize, SYSTEM.ADR(descr[0]), DescrSize); - offTypes := descr[0]; - ASSERT(offTypes < fsize - DescrSize); - ASSERT(offTypes > 0); - ASSERT(offTypes MOD (3 * szWORD) = 0); - offStrings := descr[1]; - ASSERT(offStrings < fsize - DescrSize); - ASSERT(offStrings > 0); - ASSERT(offStrings MOD szWORD = 0); - ASSERT(offStrings > offTypes); - GlobalSize := descr[2]; - ASSERT(GlobalSize > 0); - HeapStackSize := descr[3]; - ASSERT(HeapStackSize > 0); - - Sections[Types] := API._NEW(offStrings - offTypes); - ASSERT(Sections[Types] # 0); - SYSTEM.MOVE(file + offTypes, Sections[Types], offStrings - offTypes); - - Sections[Strings] := API._NEW(fsize - offStrings - DescrSize); - ASSERT(Sections[Strings] # 0); - SYSTEM.MOVE(file + offStrings, Sections[Strings], fsize - offStrings - DescrSize); - - Sections[Global] := API._NEW(GlobalSize * szWORD); - ASSERT(Sections[Global] # 0); - - Sections[Heap] := API._NEW(HeapStackSize * szWORD); - ASSERT(Sections[Heap] # 0); - - Sections[Stack] := Sections[Heap] + HeapStackSize * szWORD - szWORD*8; - - n := offTypes DIV (3 * szWORD); - - first := GetCommand(file + offTypes - n * (3 * szWORD)); - first.prev := NIL; - last := first; - DEC(n); - WHILE n > 0 DO - cmd := GetCommand(file + offTypes - n * (3 * szWORD)); - IF cmd.op = opLABEL THEN - Labels[cmd.param1] := cmd - END; - last.next := cmd; - cmd.prev := last; - last := cmd; - DEC(n) - END; - file := API._DISPOSE(file); - Args.GetArg(2, param); - IF param = "-dis" THEN - Args.GetArg(3, name); - IF name # "" THEN - disasm(name, (offStrings - offTypes) DIV szWORD, fsize - offStrings - DescrSize, GlobalSize, HeapStackSize) - END - ELSIF param = "-run" THEN - exec(Labels, first, last, Sections) - END - ELSE - Out.String("file not found"); Out.Ln - END -END main; - - -BEGIN - main -END RVMxI. \ No newline at end of file diff --git a/programs/develop/oberon07/tools/RVMxI.txt b/programs/develop/oberon07/tools/RVMxI.txt deleted file mode 100644 index 945ef862be..0000000000 --- a/programs/develop/oberon07/tools/RVMxI.txt +++ /dev/null @@ -1,270 +0,0 @@ - - Экспериментальная 32/64-битная виртуальная машина RVMxI ---------------------------------------------------------------------------------------------------- - -Использование - - Скомпилировать исполнитель/дизассемблер в .\tools\RVMxI.ob07 - для Windows32/64 Console или Linux32/64: - - Compiler.exe .\tools\RVMxI.ob07 win32con -nochk a -out RVMxI.exe - Compiler.exe .\tools\RVMxI.ob07 win64con -nochk a -out RVMxI.exe - Compiler ./tools/RVMxI.ob07 linux32exe -nochk a -out RVMxI - Compiler ./tools/RVMxI.ob07 linux64exe -nochk a -out RVMxI - - Будет создан файл "RVMxI.exe" и/или "RVMxI". - - Компилировать программу в байт-код RVMxI: - - Compiler.exe program.ob07 rvm32i [-ram size] [-def host_linux] - Compiler.exe program.ob07 rvm64i [-ram size] [-def host_linux] - -ram size -- установить размер оперативной памяти для программы в килобайтах 32768..262144 - (32..256 Мбайт), по умолчанию 32768 (32 Мбайт) - -def host_linux -- если байт-код будет исполняться на Linux (по умолчанию -- Windows) - - Будет создан файл "program.bin". - - Выпонить программу: - - RVMxI.exe program.bin -run <параметры> - - Дизассемблировать программу: - - RVMxI.exe program.bin -dis program.txt - - Будет создан файл "program.txt". ---------------------------------------------------------------------------------------------------- - -Архитектура - - Регистры - - Не меньше пяти 32/64-битных регистров: - - R0, R1, R2 регистры общего назначения - BP(R3) указатель кадра стэка - SP(R4) указатель стэка (растет вниз) - - R5, R6... регистры общего назначения (опционально) - - Регистра связи нет (адрес возврата передается через стэк), - регистр-счетчик команд (PC) -- скрытый, регистр флагов -- скрытый. - - Нет вещественных регистров, операции с плавающей точкой (single (32-бит) или double (64-бит)) - эмулируются. - - Формат кадра стэка - - Стэк: - - меньше <- |лок. переменные|старый BP|адрес возврата|парам1|парам2|...|парамN| -> больше - - (* 32 бита *) - адрес(парам1) = BP + 8 - адрес(парам2) = BP + 12 - ... - - (* 64 бита *) - адрес(парам1) = BP + 16 - адрес(парам2) = BP + 24 - ... - - Параметры передаются через стэк справа налево (как cdecl), результат передается через R0, - вызывающая процедура очищает стэк (как cdecl). - ---------------------------------------------------------------------------------------------------- - -Формат "исполняемого" файла - - RECORD - - Text: ARRAY i OF RECORD opcode, param1, param2: INTEGER END; (* байт-код *) - Types: ARRAY t OF INTEGER; (* таблица типов-записей *) - Strings: ARRAY s OF BYTE; (* строковые литералы *) - offTypes: INTEGER; (* смещение таблицы типов-записей от начала файла (в байтах) *) - offStrings: INTEGER; (* смещение строковых литералов от начала файла (в байтах) *) - GlobalSize: INTEGER; (* размер глобальных переменных (в словах; слово = 4 байта) *) - HeapStackSize: INTEGER; (* размер области кучи/стэка (в словах; слово = 4 байта) *) - Reserved: ARRAY 8 OF INTEGER (* зарезервировано *) - - END - - Где: - - INTEGER = INT32/INT64 - i = offTypes DIV (3 * sizeof(INTEGER)); - t = (offStrings - offTypes) DIV sizeof(INTEGER) - s = FILE_SIZE - offStrings - 12 * sizeof(INTEGER) ---------------------------------------------------------------------------------------------------- - -Система команд - - мнемоника опкод парам1 парам2 действие - - STOP 0 0 0 остановить программу - RET 1 0 0 возврат из процедуры (pop PC) - ENTER imm 2 imm 0 push BP; BP := SP; WHILE imm > 0 DO push 0; DEC(imm) END - NEG Rn 3 n 0 Rn := -Rn - NOT Rn 4 n 0 Rn := ORD(-BITS(Rn)) - NOP 5 0 0 нет операции - XCHG Rn, Rm 6 n m temp := Rn; Rn := Rm; Rm := temp - LDB Rn, [Rm + imm] 7 m*256 + n imm Rn := UInt8Ptr(Rm + imm)^ - LDH Rn, [Rm + imm] 8 m*256 + n imm Rn := UInt16Ptr(Rm + imm)^ - LDW Rn, [Rm + imm] 9 m*256 + n imm Rn := UInt32Ptr(Rm + imm)^ -* PUSH Rn 10 n 0 DEC(SP, 4); UInt32Ptr(SP)^ := Rn -* PUSH imm 11 imm 0 DEC(SP, 4); UInt32Ptr(SP)^ := imm -* POP Rn 12 n 0 Rn := UInt32Ptr(SP)^; INC(SP, 4) -** PUSH Rn 10 n 0 DEC(SP, 8); UInt64Ptr(SP)^ := Rn -** PUSH imm 11 imm 0 DEC(SP, 8); UInt64Ptr(SP)^ := imm -** POP Rn 12 n 0 Rn := UInt64Ptr(SP)^; INC(SP, 8) - L#hex: 13 hex 0 метка: - LEA Rn, TYPES + imm 14 n + 000H imm Rn := imm + address(TYPES) - LEA Rn, STRINGS + imm 14 n + 100H imm Rn := imm + address(STRINGS) - LEA Rn, GLOBAL + imm 14 n + 200H imm Rn := imm + address(GLOBAL) - LEA Rn, HEAP + imm 14 n + 300H imm Rn := imm + address(HEAP) - LEA Rn, STACK + imm 14 n + 400H imm Rn := imm + address(STACK) - LLA Rn, L#hex 15 n hex Rn := address(L#hex) -** LDD Rn, [Rm + imm] 16 m*256 + n imm Rn := UInt64Ptr(Rm + imm)^ - - JMP L#hex 19 hex 0 goto L#hex - CALL L#hex 20 hex 0 push PC; goto L#hex - CALL Rn 21 n 0 push PC; goto Rn - MOV Rn, Rm 22 n m Rn := Rm - MOV Rn, imm 23 n imm Rn := imm - MUL Rn, Rm 24 n m Rn := Rn * Rm - MUL Rn, imm 25 n imm Rn := Rm * imm - ADD Rn, Rm 26 n m Rn := Rn + Rm - ADD Rn, imm 27 n imm Rn := Rn + imm - SUB Rn, Rm 28 n m Rn := Rn - Rm - SUB Rn, imm 29 n imm Rn := Rn - imm - DIV Rn, Rm 30 n m Rn := Rn DIV Rm - DIV Rn, imm 31 n imm Rn := Rn DIV imm - MOD Rn, Rm 32 n m Rn := Rn MOD Rm - MOD Rn, imm 33 n imm Rn := Rn MOD imm - STB [Rn + imm], Rm 34 n*256 + m imm UInt8Ptr(Rn + imm)^ := Rm MOD 256 - STB [Rn], imm 35 n imm UInt8Ptr(Rn)^ := imm MOD 256 - STH [Rn + imm], Rm 36 n*256 + m imm UInt16Ptr(Rn + imm)^ := Rm MOD 65536 - STH [Rn], imm 37 n imm UInt16Ptr(Rn)^ := imm MOD 65536 -* STW [Rn + imm], Rm 38 n*256 + m imm UInt32Ptr(Rn + imm)^ := Rm -* STW [Rn], imm 39 n imm UInt32Ptr(Rn)^ := imm -** STW [Rn + imm], Rm 38 n*256 + m imm UInt32Ptr(Rn + imm)^ := Rm MOD 100000000H -** STW [Rn], imm 39 n imm UInt32Ptr(Rn)^ := imm MOD 100000000H -** STD [Rn + imm], Rm 40 n*256 + m imm UInt64Ptr(Rn + imm)^ := Rm -** STD [Rn], imm 41 n imm UInt64Ptr(Rn)^ := imm - - AND Rn, Rm 46 n m Rn := ORD(BITS(Rn) * BITS(Rm)) - AND Rn, imm 47 n imm Rn := ORD(BITS(Rn) * BITS(imm)) - OR Rn, Rm 48 n m Rn := ORD(BITS(Rn) + BITS(Rm)) - OR Rn, imm 49 n imm Rn := ORD(BITS(Rn) + BITS(imm)) - XOR Rn, Rm 50 n m Rn := ORD(BITS(Rn) / BITS(Rm)) - XOR Rn, imm 51 n imm Rn := ORD(BITS(Rn) / BITS(imm)) - ASR Rn, Rm 52 n m Rn := ASR(Rn, Rm) - ASR Rn, imm 53 n imm Rn := ASR(Rn, imm) - LSR Rn, Rm 54 n m Rn := LSR(Rn, Rm) - LSR Rn, imm 55 n imm Rn := LSR(Rn, imm) - LSL Rn, Rm 56 n m Rn := LSL(Rn, Rm) - LSL Rn, imm 57 n imm Rn := LSL(Rn, imm) - ROR Rn, Rm 58 n m Rn := ROR(Rn, Rm) - ROR Rn, imm 59 n imm Rn := ROR(Rn, imm) - - CMP Rn, Rm 64 n m сравнить Rn и Rm - CMP Rn, imm 65 n imm сравнить Rn и imm - BIT Rn, Rm 66 n m Rn := ORD({Rm}) - SYSCALL Rn 67 n 0 системный вызов; Rn содержит адрес параметров - JBT L#hex 68 hex 0 перейти на метку L#hex, если "ниже" - ADD Rn, Rm, imm 69 m*256 + n imm Rn := Rm + imm - JEQ L#hex 70 hex 0 перейти на метку L#hex, если "равно" - JNE L#hex 71 hex 0 перейти на метку L#hex, если "не равно" - JLT L#hex 72 hex 0 перейти на метку L#hex, если "меньше" - JGE L#hex 73 hex 0 перейти на метку L#hex, если "не меньше" - JGT L#hex 74 hex 0 перейти на метку L#hex, если "больше" - JLE L#hex 75 hex 0 перейти на метку L#hex, если "не больше" - SEQ Rn 76 n 0 если "равно": Rn := 1, иначе Rn := 0 - SNE Rn 77 n 0 если "не равно": Rn := 1, иначе Rn := 0 - SLT Rn 78 n 0 если "меньше": Rn := 1, иначе Rn := 0 - SGE Rn 79 n 0 если "не меньше": Rn := 1, иначе Rn := 0 - SGT Rn 80 n 0 если "больше": Rn := 1, иначе Rn := 0 - SLE Rn 81 n 0 если "не больше": Rn := 1, иначе Rn := 0 - -Команда CMP сохраняет результат сравнения в скрытом регистре, этот результат используется -в командах перехода по условию (JEQ, JNE, JLT, JGE, JGT, JLE, JBT) а также в командах -установки регистра по условию (SEQ, SNE, SLT, SGE, SGT, SLE). - -* Команда для 32-битной виртуальной машины -** Команда для 64-битной виртуальной машины - ---------------------------------------------------------------------------------------------------- - -Общая структура программы - - CODE: (* машинный код *) - LEA SP, STACK + 0x00000000 (* точка входа; инициализация регистра SP *) - ... - STOP (* конец программы *) - - TYPES: (* таблица типов-записей *) - WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000 - WORD 0x00000002, 0x00000002, 0x00000002, 0x00000002 - WORD 0x00000000, 0x00000006, 0x00000000, 0x00000000 - WORD 0x00000002, 0x00000000, 0x0000000D, 0x0000000E - WORD 0x0000000C, 0x0000000E, 0x0000000C, 0x00000000 - WORD 0x00000000, 0x0000000C, 0x0000000C, 0x00000016 - WORD 0x00000000, 0x0000000C, 0x0000000C, 0x0000000C - WORD 0x00000000, 0x00000000, 0x0000000C, 0x0000000C - WORD 0x0000000C, 0x0000000C, 0x0000000C, 0x0000000C - WORD 0x0000000C, 0x0000000C, 0x00000000, 0x00000000 - WORD 0x0000000C, 0x0000000C, 0x0000000C, 0x00000000 - WORD 0x00000000, 0x0000000C, 0x0000002D, 0x0000002D - WORD 0x0000002D, 0x00000030, 0x00000030, 0x00000030 - WORD 0x00000030, 0x0000002D, 0x00000000, 0x00000000 - WORD 0x0000000A, 0x00000000, 0x00000002, 0x00000000 - WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000 - WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000 - WORD 0x00000000, 0x0000000C, 0x0000000C, 0x00000000 - WORD 0x00000000, 0x0000000C, 0x00000049, 0x00000049 - WORD 0x00000049, 0x0000004C, 0x0000004C, 0x0000004C - WORD 0x00000049, 0x0000000C, 0x00000000, 0x0000000C - WORD 0x00000053, 0x00000053, 0x00000053, 0x00000053 - WORD 0x0000000C, 0x00000000, 0x00000000, 0x00000000 - WORD 0x00000006, 0x0000000C - - STRINGS: (* строковые литералы *) - BYTE 0x46, 0x50, 0x55, 0x00, 0x54, 0x72, 0x61, 0x70 - BYTE 0x00, 0x0D, 0x0A, 0x00, 0x61, 0x73, 0x73, 0x65 - BYTE 0x72, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x61 - BYTE 0x69, 0x6C, 0x75, 0x72, 0x65, 0x00, 0x4E, 0x49 - BYTE 0x4C, 0x20, 0x64, 0x65, 0x72, 0x65, 0x66, 0x65 - BYTE 0x72, 0x65, 0x6E, 0x63, 0x65, 0x00, 0x62, 0x61 - BYTE 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x6F - BYTE 0x72, 0x00, 0x4E, 0x49, 0x4C, 0x20, 0x70, 0x72 - BYTE 0x6F, 0x63, 0x65, 0x64, 0x75, 0x72, 0x65, 0x20 - BYTE 0x63, 0x61, 0x6C, 0x6C, 0x00, 0x74, 0x79, 0x70 - BYTE 0x65, 0x20, 0x67, 0x75, 0x61, 0x72, 0x64, 0x20 - BYTE 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x69, 0x6E - BYTE 0x64, 0x65, 0x78, 0x20, 0x6F, 0x75, 0x74, 0x20 - BYTE 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65 - BYTE 0x00, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64 - BYTE 0x20, 0x43, 0x41, 0x53, 0x45, 0x00, 0x61, 0x72 - BYTE 0x72, 0x61, 0x79, 0x20, 0x61, 0x73, 0x73, 0x69 - BYTE 0x67, 0x6E, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x65 - BYTE 0x72, 0x72, 0x6F, 0x72, 0x00, 0x43, 0x48, 0x52 - BYTE 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F, 0x66, 0x20 - BYTE 0x72, 0x61, 0x6E, 0x67, 0x65, 0x00, 0x57, 0x43 - BYTE 0x48, 0x52, 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F - BYTE 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x00 - BYTE 0x42, 0x59, 0x54, 0x45, 0x20, 0x6F, 0x75, 0x74 - BYTE 0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67 - BYTE 0x65, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20 - BYTE 0x28, 0x00, 0x29, 0x3A, 0x20, 0x00, 0x6D, 0x6F - BYTE 0x64, 0x75, 0x6C, 0x65, 0x3A, 0x20, 0x00, 0x6C - BYTE 0x69, 0x6E, 0x65, 0x3A, 0x20, 0x00, 0x52, 0x54 - BYTE 0x4C, 0x00, 0x54, 0x65, 0x73, 0x74, 0x00, 0x00 - - GLOBAL: - WORDS 0x00000004 (* размер глобальных переменных в словах (слово = 4 или 8 байт) *) - - HEAP: - WORDS 0x007FFFBF (* размер области кучи/стэка в словах (слово = 4 или 8 байт) *) - STACK: - WORDS 8 (* зарезервировано *) ----------------------------------------------------------------------------------------------------