How did the 1802 call and return instructions work?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
3
down vote

favorite












The RCA 1802 processor was used in a number of systems such as the ELF and COMX-35, and also apparently in the US space program (with its hardened variant).



From memory, it had a rather unusual set of instructions for doing function calls and returns. Can anyone detail how this actually worked in practice?










share|improve this question

























    up vote
    3
    down vote

    favorite












    The RCA 1802 processor was used in a number of systems such as the ELF and COMX-35, and also apparently in the US space program (with its hardened variant).



    From memory, it had a rather unusual set of instructions for doing function calls and returns. Can anyone detail how this actually worked in practice?










    share|improve this question























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      The RCA 1802 processor was used in a number of systems such as the ELF and COMX-35, and also apparently in the US space program (with its hardened variant).



      From memory, it had a rather unusual set of instructions for doing function calls and returns. Can anyone detail how this actually worked in practice?










      share|improve this question













      The RCA 1802 processor was used in a number of systems such as the ELF and COMX-35, and also apparently in the US space program (with its hardened variant).



      From memory, it had a rather unusual set of instructions for doing function calls and returns. Can anyone detail how this actually worked in practice?







      rca-1802






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 3 hours ago









      paxdiablo

      286213




      286213




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          2
          down vote













          The 1802 used a method known as SCRT, the standard call and return technique. The chip was actually endowed with a full complement of sixteen 16-bit general-purpose registers(a), but no dedicated stack pointer or program counter. The SCRT was one method for doing calls using this limitation.



          You could actually use any register as the program counter with the SEP Rn instruction (where n was a value 0..F indicating which of the registers was to be used). This basically said to start using that register for the program counter, leaving whatever register was previously being used with its last contents (one byte beyond the SEP instruction that switched the program counter over).



          So, by using some of those sixteen registers in a dedicated manner, you could easily "emulate" the more conventional instructions found on other processors.



          Note that the details below are from rather distant memories, they may not be exact (in terms of what registers were used for what, for example), but they should give you the basic idea.




          There was a "usual" program counter (R3), and the R4 and R5 registers were set respectively to the addresses of the SCRT call and return functions. R2 was used as a stack pointer.



          In order to call another function, you therefore encoded a SEP R4 followed by the address that you wanted to call. This immediately started using R4 as the program counter, leaving R3 pointing at the memory containing the address that you were calling.



          The SCRT call code running at R4 would:



          • store the return address (R3, to be adjusted on return to skip over the address) onto the stack (controlled by R2);

          • load the address (pointed at by R3) into R3; then finally

          • execute SEP R3 to continue execution at that new address.

          It would, of course, have to ensure R4 was set back to the start of the SCRT call function and, from memory, this was done by placing the sep r3 instruction immediately before the call or return function and then jumping to that as the final step of that function. This would auto-magically leave R4 (or R5) set to the correct value for next time.




          Similarly, a SEP R5 in your code (the SCRT return) would start running the return function which would:



          • pull the return address off the stack at R2, into R3, and adjust it to skip over the address.

          • do SEP R3 (using the same trickery mentioned above) to return to the original code.


          So, in terms of implementation, the set-up was something like:



          ScrtCallDone:
          sep r3
          ScrtCall:
          ; code for doing reg/mem manipulations for call
          br ScrtCallDone

          ScrtRetDone:
          sep r3
          ScrtRet:
          ; code for doing reg/mem manipulations for ret
          br ScrtRetDone

          macro call %address:
          sep r4
          dw address
          endmacro

          macro ret:
          sep r5
          endmacro


          Then, in terms of what you would see in your code, it would be as simple as:



           call subfunc
          ; do other stuff then return

          subfunc:
          ; do sub-function stuff
          ret



          (a) This rather massive (at the time) register bank was actually one of the big selling features of the chip, despite the fact you immediately lost a large chunk of them (SCRT, DMA and interrupts, from memory). Truly the triumph of marketing over reality :-)






          share|improve this answer






















          • Ha! That's a beautiful hack. I designed a processor earlier this year that has its PC in a general purpose register and copied the last PC into another register whenever that register is modified, but if I'd thought of doing it this way it would have saved the need to update the register file twice in a single cycle! Although a call+return on my system is two instructions shorter...
            – Jules
            13 mins ago











          Your Answer







          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "648"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          noCode: true, onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f7968%2fhow-did-the-1802-call-and-return-instructions-work%23new-answer', 'question_page');

          );

          Post as a guest






























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          2
          down vote













          The 1802 used a method known as SCRT, the standard call and return technique. The chip was actually endowed with a full complement of sixteen 16-bit general-purpose registers(a), but no dedicated stack pointer or program counter. The SCRT was one method for doing calls using this limitation.



          You could actually use any register as the program counter with the SEP Rn instruction (where n was a value 0..F indicating which of the registers was to be used). This basically said to start using that register for the program counter, leaving whatever register was previously being used with its last contents (one byte beyond the SEP instruction that switched the program counter over).



          So, by using some of those sixteen registers in a dedicated manner, you could easily "emulate" the more conventional instructions found on other processors.



          Note that the details below are from rather distant memories, they may not be exact (in terms of what registers were used for what, for example), but they should give you the basic idea.




          There was a "usual" program counter (R3), and the R4 and R5 registers were set respectively to the addresses of the SCRT call and return functions. R2 was used as a stack pointer.



          In order to call another function, you therefore encoded a SEP R4 followed by the address that you wanted to call. This immediately started using R4 as the program counter, leaving R3 pointing at the memory containing the address that you were calling.



          The SCRT call code running at R4 would:



          • store the return address (R3, to be adjusted on return to skip over the address) onto the stack (controlled by R2);

          • load the address (pointed at by R3) into R3; then finally

          • execute SEP R3 to continue execution at that new address.

          It would, of course, have to ensure R4 was set back to the start of the SCRT call function and, from memory, this was done by placing the sep r3 instruction immediately before the call or return function and then jumping to that as the final step of that function. This would auto-magically leave R4 (or R5) set to the correct value for next time.




          Similarly, a SEP R5 in your code (the SCRT return) would start running the return function which would:



          • pull the return address off the stack at R2, into R3, and adjust it to skip over the address.

          • do SEP R3 (using the same trickery mentioned above) to return to the original code.


          So, in terms of implementation, the set-up was something like:



          ScrtCallDone:
          sep r3
          ScrtCall:
          ; code for doing reg/mem manipulations for call
          br ScrtCallDone

          ScrtRetDone:
          sep r3
          ScrtRet:
          ; code for doing reg/mem manipulations for ret
          br ScrtRetDone

          macro call %address:
          sep r4
          dw address
          endmacro

          macro ret:
          sep r5
          endmacro


          Then, in terms of what you would see in your code, it would be as simple as:



           call subfunc
          ; do other stuff then return

          subfunc:
          ; do sub-function stuff
          ret



          (a) This rather massive (at the time) register bank was actually one of the big selling features of the chip, despite the fact you immediately lost a large chunk of them (SCRT, DMA and interrupts, from memory). Truly the triumph of marketing over reality :-)






          share|improve this answer






















          • Ha! That's a beautiful hack. I designed a processor earlier this year that has its PC in a general purpose register and copied the last PC into another register whenever that register is modified, but if I'd thought of doing it this way it would have saved the need to update the register file twice in a single cycle! Although a call+return on my system is two instructions shorter...
            – Jules
            13 mins ago















          up vote
          2
          down vote













          The 1802 used a method known as SCRT, the standard call and return technique. The chip was actually endowed with a full complement of sixteen 16-bit general-purpose registers(a), but no dedicated stack pointer or program counter. The SCRT was one method for doing calls using this limitation.



          You could actually use any register as the program counter with the SEP Rn instruction (where n was a value 0..F indicating which of the registers was to be used). This basically said to start using that register for the program counter, leaving whatever register was previously being used with its last contents (one byte beyond the SEP instruction that switched the program counter over).



          So, by using some of those sixteen registers in a dedicated manner, you could easily "emulate" the more conventional instructions found on other processors.



          Note that the details below are from rather distant memories, they may not be exact (in terms of what registers were used for what, for example), but they should give you the basic idea.




          There was a "usual" program counter (R3), and the R4 and R5 registers were set respectively to the addresses of the SCRT call and return functions. R2 was used as a stack pointer.



          In order to call another function, you therefore encoded a SEP R4 followed by the address that you wanted to call. This immediately started using R4 as the program counter, leaving R3 pointing at the memory containing the address that you were calling.



          The SCRT call code running at R4 would:



          • store the return address (R3, to be adjusted on return to skip over the address) onto the stack (controlled by R2);

          • load the address (pointed at by R3) into R3; then finally

          • execute SEP R3 to continue execution at that new address.

          It would, of course, have to ensure R4 was set back to the start of the SCRT call function and, from memory, this was done by placing the sep r3 instruction immediately before the call or return function and then jumping to that as the final step of that function. This would auto-magically leave R4 (or R5) set to the correct value for next time.




          Similarly, a SEP R5 in your code (the SCRT return) would start running the return function which would:



          • pull the return address off the stack at R2, into R3, and adjust it to skip over the address.

          • do SEP R3 (using the same trickery mentioned above) to return to the original code.


          So, in terms of implementation, the set-up was something like:



          ScrtCallDone:
          sep r3
          ScrtCall:
          ; code for doing reg/mem manipulations for call
          br ScrtCallDone

          ScrtRetDone:
          sep r3
          ScrtRet:
          ; code for doing reg/mem manipulations for ret
          br ScrtRetDone

          macro call %address:
          sep r4
          dw address
          endmacro

          macro ret:
          sep r5
          endmacro


          Then, in terms of what you would see in your code, it would be as simple as:



           call subfunc
          ; do other stuff then return

          subfunc:
          ; do sub-function stuff
          ret



          (a) This rather massive (at the time) register bank was actually one of the big selling features of the chip, despite the fact you immediately lost a large chunk of them (SCRT, DMA and interrupts, from memory). Truly the triumph of marketing over reality :-)






          share|improve this answer






















          • Ha! That's a beautiful hack. I designed a processor earlier this year that has its PC in a general purpose register and copied the last PC into another register whenever that register is modified, but if I'd thought of doing it this way it would have saved the need to update the register file twice in a single cycle! Although a call+return on my system is two instructions shorter...
            – Jules
            13 mins ago













          up vote
          2
          down vote










          up vote
          2
          down vote









          The 1802 used a method known as SCRT, the standard call and return technique. The chip was actually endowed with a full complement of sixteen 16-bit general-purpose registers(a), but no dedicated stack pointer or program counter. The SCRT was one method for doing calls using this limitation.



          You could actually use any register as the program counter with the SEP Rn instruction (where n was a value 0..F indicating which of the registers was to be used). This basically said to start using that register for the program counter, leaving whatever register was previously being used with its last contents (one byte beyond the SEP instruction that switched the program counter over).



          So, by using some of those sixteen registers in a dedicated manner, you could easily "emulate" the more conventional instructions found on other processors.



          Note that the details below are from rather distant memories, they may not be exact (in terms of what registers were used for what, for example), but they should give you the basic idea.




          There was a "usual" program counter (R3), and the R4 and R5 registers were set respectively to the addresses of the SCRT call and return functions. R2 was used as a stack pointer.



          In order to call another function, you therefore encoded a SEP R4 followed by the address that you wanted to call. This immediately started using R4 as the program counter, leaving R3 pointing at the memory containing the address that you were calling.



          The SCRT call code running at R4 would:



          • store the return address (R3, to be adjusted on return to skip over the address) onto the stack (controlled by R2);

          • load the address (pointed at by R3) into R3; then finally

          • execute SEP R3 to continue execution at that new address.

          It would, of course, have to ensure R4 was set back to the start of the SCRT call function and, from memory, this was done by placing the sep r3 instruction immediately before the call or return function and then jumping to that as the final step of that function. This would auto-magically leave R4 (or R5) set to the correct value for next time.




          Similarly, a SEP R5 in your code (the SCRT return) would start running the return function which would:



          • pull the return address off the stack at R2, into R3, and adjust it to skip over the address.

          • do SEP R3 (using the same trickery mentioned above) to return to the original code.


          So, in terms of implementation, the set-up was something like:



          ScrtCallDone:
          sep r3
          ScrtCall:
          ; code for doing reg/mem manipulations for call
          br ScrtCallDone

          ScrtRetDone:
          sep r3
          ScrtRet:
          ; code for doing reg/mem manipulations for ret
          br ScrtRetDone

          macro call %address:
          sep r4
          dw address
          endmacro

          macro ret:
          sep r5
          endmacro


          Then, in terms of what you would see in your code, it would be as simple as:



           call subfunc
          ; do other stuff then return

          subfunc:
          ; do sub-function stuff
          ret



          (a) This rather massive (at the time) register bank was actually one of the big selling features of the chip, despite the fact you immediately lost a large chunk of them (SCRT, DMA and interrupts, from memory). Truly the triumph of marketing over reality :-)






          share|improve this answer














          The 1802 used a method known as SCRT, the standard call and return technique. The chip was actually endowed with a full complement of sixteen 16-bit general-purpose registers(a), but no dedicated stack pointer or program counter. The SCRT was one method for doing calls using this limitation.



          You could actually use any register as the program counter with the SEP Rn instruction (where n was a value 0..F indicating which of the registers was to be used). This basically said to start using that register for the program counter, leaving whatever register was previously being used with its last contents (one byte beyond the SEP instruction that switched the program counter over).



          So, by using some of those sixteen registers in a dedicated manner, you could easily "emulate" the more conventional instructions found on other processors.



          Note that the details below are from rather distant memories, they may not be exact (in terms of what registers were used for what, for example), but they should give you the basic idea.




          There was a "usual" program counter (R3), and the R4 and R5 registers were set respectively to the addresses of the SCRT call and return functions. R2 was used as a stack pointer.



          In order to call another function, you therefore encoded a SEP R4 followed by the address that you wanted to call. This immediately started using R4 as the program counter, leaving R3 pointing at the memory containing the address that you were calling.



          The SCRT call code running at R4 would:



          • store the return address (R3, to be adjusted on return to skip over the address) onto the stack (controlled by R2);

          • load the address (pointed at by R3) into R3; then finally

          • execute SEP R3 to continue execution at that new address.

          It would, of course, have to ensure R4 was set back to the start of the SCRT call function and, from memory, this was done by placing the sep r3 instruction immediately before the call or return function and then jumping to that as the final step of that function. This would auto-magically leave R4 (or R5) set to the correct value for next time.




          Similarly, a SEP R5 in your code (the SCRT return) would start running the return function which would:



          • pull the return address off the stack at R2, into R3, and adjust it to skip over the address.

          • do SEP R3 (using the same trickery mentioned above) to return to the original code.


          So, in terms of implementation, the set-up was something like:



          ScrtCallDone:
          sep r3
          ScrtCall:
          ; code for doing reg/mem manipulations for call
          br ScrtCallDone

          ScrtRetDone:
          sep r3
          ScrtRet:
          ; code for doing reg/mem manipulations for ret
          br ScrtRetDone

          macro call %address:
          sep r4
          dw address
          endmacro

          macro ret:
          sep r5
          endmacro


          Then, in terms of what you would see in your code, it would be as simple as:



           call subfunc
          ; do other stuff then return

          subfunc:
          ; do sub-function stuff
          ret



          (a) This rather massive (at the time) register bank was actually one of the big selling features of the chip, despite the fact you immediately lost a large chunk of them (SCRT, DMA and interrupts, from memory). Truly the triumph of marketing over reality :-)







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 2 hours ago

























          answered 2 hours ago









          paxdiablo

          286213




          286213











          • Ha! That's a beautiful hack. I designed a processor earlier this year that has its PC in a general purpose register and copied the last PC into another register whenever that register is modified, but if I'd thought of doing it this way it would have saved the need to update the register file twice in a single cycle! Although a call+return on my system is two instructions shorter...
            – Jules
            13 mins ago

















          • Ha! That's a beautiful hack. I designed a processor earlier this year that has its PC in a general purpose register and copied the last PC into another register whenever that register is modified, but if I'd thought of doing it this way it would have saved the need to update the register file twice in a single cycle! Although a call+return on my system is two instructions shorter...
            – Jules
            13 mins ago
















          Ha! That's a beautiful hack. I designed a processor earlier this year that has its PC in a general purpose register and copied the last PC into another register whenever that register is modified, but if I'd thought of doing it this way it would have saved the need to update the register file twice in a single cycle! Although a call+return on my system is two instructions shorter...
          – Jules
          13 mins ago





          Ha! That's a beautiful hack. I designed a processor earlier this year that has its PC in a general purpose register and copied the last PC into another register whenever that register is modified, but if I'd thought of doing it this way it would have saved the need to update the register file twice in a single cycle! Although a call+return on my system is two instructions shorter...
          – Jules
          13 mins ago


















           

          draft saved


          draft discarded















































           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f7968%2fhow-did-the-1802-call-and-return-instructions-work%23new-answer', 'question_page');

          );

          Post as a guest













































































          Comments

          Popular posts from this blog

          What does second last employer means? [closed]

          Installing NextGIS Connect into QGIS 3?

          One-line joke