Path: utzoo!attcan!uunet!husc6!mailrus!ames!ncar!ico!rcd From: rcd@ico.ISC.COM (Dick Dunn) Newsgroups: comp.arch Subject: Re: Self-modifying code Summary: call to variable address, call on stack, self-mod code (again) Keywords: 6600 Message-ID: <7362@ico.ISC.COM> Date: 19 Jul 88 05:34:10 GMT References: <5254@june.cs.washington.edu> <76700032@p.cs.uiuc.edu> <361@scolex> <835@l.cc.purdue.edu> Organization: Interactive Systems Corp, Boulder, CO Lines: 39 First, a clarification: Self-modifying code was *not* necessary on the 6600 CPU. The call instruction generated a return instruction. However, it *was* "necessary" to use self-modifying code in the peripheral (I/O) processors, because there were certain operations on channels which required an immediate operand (the channel number)--the only reasonable way to select a channel at execution time was to modify the instruction. (A jump table of instructions with constant channel numbers would have worked, but would have been far too slow.) Back to the subroutine call in the CPU, which worked by planting a return instruction at the target, then jumping one word beyond. Herman Rubin asked: "And how would you call a function which is an argument?"... > The RJ would set up the return address, but how about the address in the call? > It is not that unusual to have subroutines or functions as arguments of called > subroutines, or computed by the program in some other way. Of course--even in FORTRAN this is common, and the 6600 was a FORTRAN machine if ever there was one. The answer is simple: You emulate the RJ instruction. You form the return instruction (actually this can be done at compile time to save execution) and plop it into memory just as the RJ would have done; then you jump to the target routine. The jump address is formed from a register plus a constant, so it can be a variable or computed address with no problem. This approach roughly doubles the time to call a routine; the return is unaffected. [It is one of life's enduring mysteries why the "RJ" (subroutine call) instruction allowed only a constant operand, while the "JP" (unconditional branch) allowed register plus constant! There was room in the RJ instruction format for a register.] It's interesting to look at what it costs to do subroutine calls with return addresses on a stack (instead of plunked into memory) so that you can have recursive calls. It's only about 1.5* the time for the native call/return to constant address, and it's about a break-even for call/ return to variable address. (It's slightly faster on the 6400, slower on the 6600.) -- Dick Dunn UUCP: {ncar,nbires}!ico!rcd (303)449-2870 ...Are you making this up as you go along?