proc.dart 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. part of trisc;
  2. class internal{
  3. static final haltMe = new tryte(-13);
  4. static final nop = new tryte.zero();
  5. }
  6. enum CPUresult{
  7. ok,
  8. stop,
  9. skip
  10. }
  11. abstract class CPU{
  12. bool get debug;
  13. set debug(bool);
  14. void reset();
  15. CPUresult next();
  16. }
  17. class ProcFactory{
  18. static CPU newCPU(RAM mem, {int27 pc: null}){
  19. if(pc==null)
  20. pc = new int27.zero();
  21. halt.on(condition: mem != null);
  22. return new _cpu(mem, pc);
  23. }
  24. }
  25. typedef CPUresult IRhandler(Operation op);
  26. class _cpu extends CPU{
  27. Registers reg;
  28. RAM mem;
  29. int27 ir;
  30. int27 pc;
  31. int step = 0;
  32. bool _debug = false;
  33. int27 start = new int27.zero();
  34. @override
  35. bool get debug => _debug;
  36. @override
  37. set debug(bool x){
  38. this._debug = x;
  39. }
  40. IRhandler handler(){
  41. var rh = reg.handler();
  42. var jump = (int27 to, bool link){
  43. if(link)
  44. reg[short(reg.length-1)] = pc * long(3); /* регистры запоминают адрес в трайтах */
  45. pc = to; /* сдвиг в словах */
  46. };
  47. var calc = (BranchOperation op, int27 adr){
  48. if(op.cond.jump.True){
  49. jump(adr, op.cond.link);
  50. }else if(op.cond.jump.Null){
  51. var nz = op.cond.nz;
  52. var eq = op.cond.eq;
  53. if(nz == TRUE && eq == NULL){
  54. if(reg.nz == TRUE) jump(adr, op.cond.link); /* > */
  55. }else if(nz == NULL && eq == NULL){
  56. if(reg.nz == NULL) jump(adr, op.cond.link); /* = */
  57. }else if(nz == FALSE && eq == NULL){
  58. if(reg.nz == FALSE) jump(adr, op.cond.link); /* < */
  59. }else if(nz == TRUE && eq == TRUE){
  60. if(reg.nz != FALSE) jump(adr, op.cond.link); /* >= */
  61. }else if(nz == NULL && eq == FALSE){
  62. if(reg.nz != NULL) jump(adr, op.cond.link); /* # */
  63. }else if(nz == FALSE && eq == FALSE){
  64. if(reg.nz != TRUE) jump(adr, op.cond.link); /* <= */
  65. }else halt.on(code: 215, msg: "$nz $eq");
  66. }
  67. };
  68. var def = (Operation op){
  69. if(op is Reg){
  70. return rh(op);
  71. }else if(op is BranchReg){
  72. calc(op, reg[op.c] ~/ long(3));
  73. return CPUresult.ok;
  74. }else if(op is BranchConst){
  75. calc(op, pc + op.offset);
  76. return CPUresult.ok;
  77. }else if (op is GetWord){
  78. reg[op.a] = new Mapper(mem)[(reg[op.b] + op.offset).toInt() ~/ 3];
  79. reg.updateNZ(op.a);
  80. return CPUresult.ok;
  81. }else if (op is SetWord){
  82. new Mapper(mem)[(reg[op.b] + op.offset).toInt() ~/ 3] = reg[op.a];
  83. return CPUresult.ok;
  84. }else if(op is GetTryte){
  85. reg[op.a] = long(mem[(reg[op.b] + op.offset).toInt()]);
  86. reg.updateNZ(op.a);
  87. return CPUresult.ok;
  88. }else if(op is SetTryte){
  89. mem[(reg[op.b] + op.offset).toInt()] = short(reg[op.a]);
  90. return CPUresult.ok;
  91. }else halt.on(msg: op.runtimeType);
  92. };
  93. return def;
  94. }
  95. CPUresult parse(int27 ir, IRhandler h){
  96. tryte format = short(ir >> 24);
  97. if(format == internal.nop){
  98. return CPUresult.skip;
  99. }else if(format == internal.haltMe){
  100. halt.on(condition: !debug, code: 146);
  101. return CPUresult.stop;
  102. }else{
  103. var ret = h(Op.parse(ir));
  104. halt.on(condition: ret!=null);
  105. return ret;
  106. }
  107. }
  108. @override
  109. void reset(){
  110. ir = new int27.zero();
  111. reg = new Registers();
  112. pc = start;
  113. }
  114. @override
  115. CPUresult next(){
  116. step++;
  117. ir = new Mapper(mem)[pc.toInt()];
  118. fmt.fine("step $step: [$pc]");
  119. pc += new int27.one();
  120. if(pc.toInt() == new Mapper(mem).length)
  121. pc = new int27.zero();
  122. fmt.fine(new Trits(ir));
  123. CPUresult ret = parse(ir, handler());
  124. fmt.fine(reg);
  125. fmt.fine("");
  126. return ret;
  127. }
  128. _cpu(this.mem, this.start){
  129. reset();
  130. }
  131. }