import "io" manifest { iv_none = 0, iv_memory = 1, iv_pagefault = 2, iv_unimpop = 3, iv_halt = 4, iv_divzero = 5, iv_unwrop = 6, iv_timer = 7, iv_privop = 8, iv_keybd = 9, iv_badcall = 10, iv_pagepriv = 11, iv_debug = 12, iv_intrfault = 13 } let ivec = table 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 let set_handler(int, fn) be if int >= 0 /\ int <= 13 then ivec ! int := fn let int_enable() be assembly { LOAD R1, [] SETSR R1, $INTVEC LOAD R1, 0 SETFL R1, $IP } let int_disable() be assembly { LOAD R1, 1 SETFL R1, $IP } let otherhandler(intcode, address, info) be { out("interrupt %d (%x, %d)\n", intcode, address, info); ireturn } let twotimes(x) be { let sptr, prev; if x = 0 then resultis 0; prev := twotimes(x-1); resultis prev+2 } let getpage(x) be { static { nextfreepage = 0, lastfreepage = 0 } test numbargs() > 0 then { let firstfreeword = ! 0x101; let lastexistingword = (! 0x100) - 1; nextfreepage := (firstfreeword + 2047) >> 11; lastfreepage := lastexistingword >> 11; out("first free page = %d = 0x%x\n", nextfreepage, nextfreepage); out("last free page = %d = 0x%x\n", lastfreepage, lastfreepage); } else { let p = nextfreepage; if p > lastfreepage then resultis -1; nextfreepage +:= 1; resultis p << 11 } } let printmemmap(pdpn) be { let pdaddr = pdpn << 11; out("pp %d:\n", pdpn); // pp = physical page for ptn = 0 to 1023 do if pdaddr ! ptn <> 0 then { let ptppn = (pdaddr ! ptn) >> 11; let ptaddr = ptppn << 11; out(" %d: pp %d for VAs 0x%x to 0x%x:\n", ptn, ptppn, ptn << 22, ((ptn+1) << 22)-1); for pn = 0 to 2047 do if ptaddr ! pn bitand 1 then { let pppn = (ptaddr ! pn) >> 11; let baseva = (ptn << 22) + (pn << 11); out(" %d: pp %d for VAs 0x%x to 0x%x:\n", pn, pppn, baseva, baseva+2047); } } } let start() be { let pdir, ptabusr, ptabusrstk, ptabsysstk; let sysstkpage; let lastusedpage = ((! 0x101) - 1) >> 11; let a, b; getpage("setup!"); pdir := getpage(); ptabusr := getpage(); ptabusrstk := getpage(); ptabsysstk := getpage(); sysstkpage := getpage(); set_handler(iv_pagefault, otherhandler); int_enable(); for i = 0 to 2047 do { pdir ! i := 0; ptabusr ! i := 0; ptabsysstk ! i := 0; ptabusrstk ! i := 0 } pdir ! 0 := ptabusr bitor 1; pdir ! 511 := ptabusrstk bitor 1; pdir ! 767 := ptabsysstk bitor 1; for pn = 0 to lastusedpage do ptabusr ! pn := (pn << 11) bitor 1; ptabusrstk ! 2047 := 0x7FFFF801; ptabsysstk ! 2047 := sysstkpage bitor 1; printmemmap(pdir >> 11); outs("Dangerous place\n"); assembly { store sp, r2 store fp, r3 load sp, 0xFFFF loadh sp, 0xBFFF load r1, [] setsr r1, $pdbr getsr r1, $flags sbit r1, $vm cbit r1, $sys flagsj r1, pc load sp, r2 load fp, r3 } outs("still alive\n"); a := 50; b := twotimes(a); out("twotimes(%d) = %d\n", a, b) }