123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- part of trisc;
- class internal{
- static final haltMe = new tryte(-13);
- static final nop = new tryte.zero();
- }
- enum CPUresult{
- ok,
- stop,
- skip
- }
- abstract class CPU{
- bool get debug;
- set debug(bool);
- void reset();
- CPUresult next();
- }
- class ProcFactory{
- static CPU newCPU(RAM mem, {int27 pc: null}){
- if(pc==null)
- pc = new int27.zero();
- halt.on(condition: mem != null);
- return new _cpu(mem, pc);
- }
- }
- typedef CPUresult IRhandler(Operation op);
- class _cpu extends CPU{
- Registers reg;
- RAM mem;
- int27 ir;
- int27 pc;
- int step = 0;
- bool _debug = false;
- int27 start = new int27.zero();
- @override
- bool get debug => _debug;
- @override
- set debug(bool x){
- this._debug = x;
- }
- IRhandler handler(){
- var rh = reg.handler();
- var jump = (int27 to, bool link){
- if(link)
- reg[short(reg.length-1)] = pc * long(3); /* регистры запоминают адрес в трайтах */
- pc = to; /* сдвиг в словах */
- };
- var calc = (BranchOperation op, int27 adr){
- if(op.cond.jump.True){
- jump(adr, op.cond.link);
- }else if(op.cond.jump.Null){
- var nz = op.cond.nz;
- var eq = op.cond.eq;
- if(nz == TRUE && eq == NULL){
- if(reg.nz == TRUE) jump(adr, op.cond.link); /* > */
- }else if(nz == NULL && eq == NULL){
- if(reg.nz == NULL) jump(adr, op.cond.link); /* = */
- }else if(nz == FALSE && eq == NULL){
- if(reg.nz == FALSE) jump(adr, op.cond.link); /* < */
- }else if(nz == TRUE && eq == TRUE){
- if(reg.nz != FALSE) jump(adr, op.cond.link); /* >= */
- }else if(nz == NULL && eq == FALSE){
- if(reg.nz != NULL) jump(adr, op.cond.link); /* # */
- }else if(nz == FALSE && eq == FALSE){
- if(reg.nz != TRUE) jump(adr, op.cond.link); /* <= */
- }else halt.on(code: 215, msg: "$nz $eq");
- }
- };
- var def = (Operation op){
- if(op is Reg){
- return rh(op);
- }else if(op is BranchReg){
- calc(op, reg[op.c] ~/ long(3));
- return CPUresult.ok;
- }else if(op is BranchConst){
- calc(op, pc + op.offset);
- return CPUresult.ok;
- }else if (op is GetWord){
- reg[op.a] = new Mapper(mem)[(reg[op.b] + op.offset).toInt() ~/ 3];
- reg.updateNZ(op.a);
- return CPUresult.ok;
- }else if (op is SetWord){
- new Mapper(mem)[(reg[op.b] + op.offset).toInt() ~/ 3] = reg[op.a];
- return CPUresult.ok;
- }else if(op is GetTryte){
- reg[op.a] = long(mem[(reg[op.b] + op.offset).toInt()]);
- reg.updateNZ(op.a);
- return CPUresult.ok;
- }else if(op is SetTryte){
- mem[(reg[op.b] + op.offset).toInt()] = short(reg[op.a]);
- return CPUresult.ok;
- }else halt.on(msg: op.runtimeType);
- };
- return def;
- }
- CPUresult parse(int27 ir, IRhandler h){
- tryte format = short(ir >> 24);
- if(format == internal.nop){
- return CPUresult.skip;
- }else if(format == internal.haltMe){
- halt.on(condition: !debug, code: 146);
- return CPUresult.stop;
- }else{
- var ret = h(Op.parse(ir));
- halt.on(condition: ret!=null);
- return ret;
- }
- }
- @override
- void reset(){
- ir = new int27.zero();
- reg = new Registers();
- pc = start;
- }
- @override
- CPUresult next(){
- step++;
- ir = new Mapper(mem)[pc.toInt()];
- fmt.fine("step $step: [$pc]");
- pc += new int27.one();
- if(pc.toInt() == new Mapper(mem).length)
- pc = new int27.zero();
- fmt.fine(new Trits(ir));
- CPUresult ret = parse(ir, handler());
- fmt.fine(reg);
- fmt.fine("");
- return ret;
- }
- _cpu(this.mem, this.start){
- reset();
- }
- }
|