This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[R]ILC in ABI specification

Quoting SPRAB89 publication, section 3.2

"In addition, the ILC and RILC are callee-save registers."

This would mean that any subroutine that uses SPLOOP would have to save ILC prior overriding it and restore saved value prior return. However, if I disassemble compiler-generated code that uses SPLOOPs I can't see that compiler would preserve ILC [or RILC], all MVC instructions addressing ILC have it as destination, not a single one as source. Who gets it wrong, specification or compiler?

  • The compiler will never software pipeline a loop which contains a call, so it can safely assume that there are no nested SPLOOPs.

    However, interrupt handler functions do need to save and restore SPLOOP.  See this related article.

    So, ILC and RILC aren't handled exactly the same as other callee-saved registers, and this should be clarified in the specification.  I've submitted SDSCM00042746 to get this updated.

  • Archaeologist said:
    The compiler will never software pipeline a loop which contains a call, so it can safely assume that there are no nested SPLOOPs.

    I don't think it's possible to make a call from within SPLOOP, so the only possible usage scenario for ILC being callee-saved would be to load ILC, call function and then fire SPLOOP..

    Archaeologist said:
    So, ILC and RILC aren't handled exactly the same as other callee-saved registers, and this should be clarified in the specification.  I've submitted SDSCM00042746 to get this updated.

    I'd argue that they should not be thought of as "not exactly as other callee-saved registers", but as "caller-saved" or "volatile" and specified as such. On tightly related matter Section 7.3 from SPRI187S needs to be fixed accordingly.
    On related matter of potentially confusing documentation. Consider following quote from just mentioned SPRU187S, Section 7.5.1
    "You must preserve registers A10 to A15, B3, and B10 to B15, and you may need to preserve A3."
    I don't have to preserve B3 or A3. I have use for them, but I don't have to preserve. Well, next bullet says that only A10-15 and B10-15 that needs to be restored, but "must be preserved" can be interpreted as "make sure they have same value upon return."
  • ILC and RILC are certainly not caller-saved.  In non-interrupt-handling code, the compiler does not generate direct references to them, so it would never set ILC and then call a function.  SPRAB89 is trying to say that you need to handle these registers in interrupt handling functions, and I agree this could be made more clear.

    I'll add your comments to defect report SDSCM00042746.

  • If [R]ILC are not caller-saved, then say A0 is not caller-saved either. One can argue about terminology, but what you are saying is that caller can not rely on [R]ILC being preserved, just like say A0, don't you? And therefore they fall to same category. As far as interrupt handling goes all registers have to preserved, ILC, as well as say A0, don't they? So that caller-/callee-saved nomenclature does not apply there. It's appropriate to remind interrupt handler programmers that they have additional responsibility on C64+ to preserve the registers in question, but it's hardly appropriate to confuse them by classifying them callee-saved in inter-procedure calling convention section.

    Anyway, the question appears to be answered and I, being non-interrupt handler assembler programmer, don't have to preserve  [R]ILC in my subroutine.

    Thank you very much.

  • I've found another potential victim for misinterpretation of SPRAB89, AMR register (and by extension GFPGFR and GPLY[AB] ones). My original objection was that [R]ILC should not be classified as "callee-saved", but as "caller-saved". TI's objection to my objection was that [R]ILC are not "caller-saved", because interrupt service routine has to preserve them. But let's have a look at AMR (and by extension Galois control registers). Following TI's logic for telling apart "callee-" and "caller-saved" registers AMR would fall to "callee-saved" category, because interrupt handler would have to not only save its value, but even explicitly zero it upon entry. Failure to do so would have as devastating effect as failure to preserve [R]ILC, specifically in interrupt handler that is. But is it "callee-saved"? It's not named explicitly, specification only says "all other registers are caller-saved" and "at function call boundaries it must be 0", latter naturally assured by caller. Once again, "callee-/caller-saved" classification does not apply to interrupt handlers, nor should specification describe any particular compiler...