uint Glulxe::ReadMemory(uint addr) { if (addr == 0xffffffff) { stackptr -= 4; return Stk4(stackptr); } else { return Mem4(addr); } }
uint Glulxe::ReadStructField(uint addr, uint fieldnum) { if (addr == 0xffffffff) { stackptr -= 4; return Stk4(stackptr); } else { return Mem4(addr + (fieldnum * 4)); } }
static glui32 write_stackstate(dest_t *dest, int portable) { glui32 res; glui32 lx; glui32 lastframe; /* If we're storing for the purpose of undo, we don't need to do any byte-swapping, because the result will only be used by this session. */ if (!portable) { res = write_buffer(dest, stack, stackptr); if (res) return res; return 0; } /* Write a portable stack image. To do this, we have to write stack frames in order, bottom to top. Remember that the last word of every stack frame is a pointer to the beginning of that stack frame. (This includes the last frame, because the save opcode pushes on a call stub before it calls perform_save().) */ lastframe = (glui32)(-1); while (1) { glui32 frameend, frm, frm2, frm3; unsigned char loctype, loccount; glui32 numlocals, frlen, locpos; /* Find the next stack frame (after the one in lastframe). Sadly, this requires searching the stack from the top down. We have to do this for *every* frame, which takes N^2 time overall. But save routines usually aren't nested very deep. If it becomes a practical problem, we can build a stack-frame array, which requires dynamic allocation. */ for (frm = stackptr, frameend = stackptr; frm != 0 && (frm2 = Stk4(frm-4)) != lastframe; frameend = frm, frm = frm2) { }; /* Write out the frame. */ frm2 = frm; frlen = Stk4(frm2); frm2 += 4; res = write_long(dest, frlen); if (res) return res; locpos = Stk4(frm2); frm2 += 4; res = write_long(dest, locpos); if (res) return res; frm3 = frm2; numlocals = 0; while (1) { loctype = Stk1(frm2); frm2 += 1; loccount = Stk1(frm2); frm2 += 1; res = write_byte(dest, loctype); if (res) return res; res = write_byte(dest, loccount); if (res) return res; if (loctype == 0 && loccount == 0) break; numlocals++; } if ((numlocals & 1) == 0) { res = write_byte(dest, 0); if (res) return res; res = write_byte(dest, 0); if (res) return res; frm2 += 2; } if (frm2 != frm+locpos) fatal_error("Inconsistent stack frame during save."); /* Write out the locals. */ for (lx=0; lx<numlocals; lx++) { loctype = Stk1(frm3); frm3 += 1; loccount = Stk1(frm3); frm3 += 1; if (loctype == 0 && loccount == 0) break; /* Put in up to 0, 1, or 3 bytes of padding, depending on loctype. */ while (frm2 & (loctype-1)) { res = write_byte(dest, 0); if (res) return res; frm2 += 1; } /* Put in this set of locals. */ switch (loctype) { case 1: do { res = write_byte(dest, Stk1(frm2)); if (res) return res; frm2 += 1; loccount--; } while (loccount); break; case 2: do { res = write_short(dest, Stk2(frm2)); if (res) return res; frm2 += 2; loccount--; } while (loccount); break; case 4: do { res = write_long(dest, Stk4(frm2)); if (res) return res; frm2 += 4; loccount--; } while (loccount); break; } } if (frm2 != frm+frlen) fatal_error("Inconsistent stack frame during save."); while (frm2 < frameend) { res = write_long(dest, Stk4(frm2)); if (res) return res; frm2 += 4; } /* Go on to the next frame. */ if (frameend == stackptr) break; /* All done. */ lastframe = frm; } return 0; }