<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Nov 18, 2015 at 6:44 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">Hi Ryan,<div><br></div><div>    I&#39;m currently reviewing Tim&#39;s new CPIC code to make it work on X64.  I see the MIPSEL code is very heavyweight, e.g.</div><div><br></div><div><div><span style="white-space:pre-wrap">        </span> lui at, tagHigh</div><div><span style="white-space:pre-wrap">        </span> ori at, at, tagLow</div><div><span style="white-space:pre-wrap">        </span> subu t0, s5, at (Cmp)</div><div><span style="white-space:pre-wrap">        </span> slt ... (Cmp)</div><div><span style="white-space:pre-wrap">        </span> slt ... (Cmp)</div><div><span style="white-space:pre-wrap">        </span> sltu ... (Cmp)</div><div><span style="white-space:pre-wrap">        </span> sltu ... (Cmp)</div><div><span style="white-space:pre-wrap">        </span> lui s4, objRefHigh</div><div><span style="white-space:pre-wrap">        </span> ori s4, s4, objRefLow</div><div><span style="white-space:pre-wrap">        </span> bne t0, zr, +12</div><div><span style="white-space:pre-wrap">        </span> nop (delay slot)</div><div><span style="white-space:pre-wrap">        </span> j target</div><div><span style="white-space:pre-wrap">        </span> nop (delay slot)</div><div><span style="white-space:pre-wrap">        </span> .... &lt;-- followingAddress</div></div><div><br></div><div>The code sequence needs to</div><div>    load the 32-bit SendNumArgs register with a constant (a method up or 0)</div><div>    compare the 32-bit TempReg register against a 32 bit constant and if equal, jump to a target within 16Mb of the sequence.</div><div><br></div><div>So what&#39;s the ideal MIPS code for that sequence?  We don&#39;t need those 4 Cmp adjuncts following the initial &quot;subu t0, s5, at (Cmp&quot; do we? </div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>Right now CPICs perform the compare before the load of SendNumArgs, but that&#39;s just my attempt at making the x86 code that fraction faster.  I&#39;m happy to discard that and reverse the order to benefit MIPS; I doubt it&#39;ll make any differenced to x86 and if it did, the code could be rewritten to use one order for MIPS and one order for x86.</div></div></blockquote><div><br></div><div>Those 5 instructions for compare are the implementation of a CmpRR that doesn&#39;t know which result is actually needed. The short version, if we swap the loads so we can collapse the comparison, would be</div><div><br></div><div>lui s4, objRefHigh</div><div>ori s4, s4, objRefLow</div><div>lui x, tagHigh</div><div>ori x, x, tagLow</div><div>bne x, s5, +12<br></div><div>nop (delay slot)</div><div>j target</div><div>nop (delay slot)</div><div><br></div><div>The two branches are still necessary because conditional branches can only reach +/- 131kB, which is too small for the method zone. </div><div><br></div><div>If we&#39;re feeling really architecture specific we can even use those delay slots</div><div><br></div><div><div>ori x, x, tagLow</div><div>lui s4, objRefHigh</div><div>bne x, s5, +12</div><div>lui x, next case&#39;s tagHigh (delay slot)<br></div><div>j target</div><div>ori s4, s4, objRefLow (delay slot)<br></div></div><div><br></div><div>although I wouldn&#39;t want to try to express this in RTL.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="gmail_extra"><div class="gmail_quote">On Tue, Nov 17, 2015 at 10:04 PM,  <span dir="ltr">&lt;<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br>
Ryan Macnak uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-rmacnak.1524.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/VMMaker/VMMaker.oscog-rmacnak.1524.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-rmacnak.1524<br>
Author: rmacnak<br>
Time: 17 November 2015, 10:03:52.949 pm<br>
UUID: d298c397-7a0b-4973-b1e1-39c9b08053c9<br>
Ancestors: VMMaker.oscog-eem.1523<br>
<br>
Get MIPSEL up to the first CPIC extension.<br>
<br>
Add separate RTL opcodes for Add/Sub/Mul with overflow check.<br>
Fix relative jump offsets.<br>
Fix MoveMwrR with large offsets.<br>
Fix confusion of call as jump in initial CPIC setup.<br>
<br>
=============== Diff against VMMaker.oscog-eem.1523 ===============<br>
<br>
Item was added:<br>
+ ----- Method: CogARMCompiler&gt;&gt;hasConditionRegister (in category &#39;testing&#39;) -----<br>
+ hasConditionRegister<br>
+       &quot;Answer if the receiver supports, e.g., JumpOverflow after a regular AddRR&quot;<br>
+       &lt;inline: true&gt;<br>
+       ^true!<br>
<br>
Item was added:<br>
+ ----- Method: CogAbstractInstruction&gt;&gt;hasConditionRegister (in category &#39;testing&#39;) -----<br>
+ hasConditionRegister<br>
+       &quot;Answer if the receiver supports, e.g., JumpOverflow after a regular AddRR&quot;<br>
+       &lt;inline: true&gt;<br>
+       ^self subclassResponsibility!<br>
<br>
Item was added:<br>
+ ----- Method: CogIA32Compiler&gt;&gt;hasConditionRegister (in category &#39;testing&#39;) -----<br>
+ hasConditionRegister<br>
+       &quot;Answer if the receiver supports, e.g., JumpOverflow after a regular AddRR&quot;<br>
+       &lt;inline: true&gt;<br>
+       ^true!<br>
<br>
Item was changed:<br>
  CogAbstractInstruction subclass: #CogMIPSELCompiler<br>
        instanceVariableNames: &#39;&#39;<br>
+       classVariableNames: &#39;Cmp CmpSGT CmpSLT CmpUGT CmpULT ConcreteVarBaseReg Overflow OverflowTemp1 OverflowTemp2 TargetReg&#39;<br>
-       classVariableNames: &#39;Cmp CmpSGT CmpSLT CmpUGT CmpULT ConcreteVarBaseReg TargetReg&#39;<br>
        poolDictionaries: &#39;MIPSConstants&#39;<br>
        category: &#39;VMMaker-JIT&#39;!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler class&gt;&gt;initialize (in category &#39;as yet unclassified&#39;) -----<br>
  initialize<br>
        &quot;CogMIPSELCompiler initialize&quot;<br>
<br>
        super initialize.<br>
<br>
        ConcreteVarBaseReg := S6.<br>
<br>
        &quot;Simulating a condition register.&quot;<br>
        Cmp := T0.<br>
        CmpSLT := T1.<br>
        CmpSGT := T2.<br>
        CmpULT := T3.<br>
        CmpUGT := T4.<br>
+       Overflow := T0.<br>
+       OverflowTemp1 := T1.<br>
+       OverflowTemp2 := T2.<br>
<br>
        &quot;OABI position independent code expects T9 to have its entry point on entry?&quot;<br>
        self flag: #OABI.<br>
        TargetReg := T9. !<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;computeMaximumSize (in category &#39;generate machine code&#39;) -----<br>
  computeMaximumSize<br>
        &quot;Each MIPS instruction has 4 bytes. Many abstract opcodes need more than one<br>
         instruction. Instructions that refer to constants and/or literals depend on literals<br>
         being stored in-line or out-of-line.<br>
<br>
         N.B.  The ^N forms are to get around the bytecode compiler&#39;s long branch<br>
         limits which are exceeded when each case jumps around the otherwise.&quot;<br>
<br>
        opcode<br>
                caseOf: {<br>
                &quot;Noops &amp; Pseudo Ops&quot;<br>
                [Label]                                 -&gt; [^0].<br>
                [Literal]                                       -&gt; [^4].<br>
                [AlignmentNops]         -&gt; [^(operands at: 0) - 4].<br>
                [Fill16]                                        -&gt; [^4].<br>
                [Fill32]                                        -&gt; [^4].<br>
                [FillFromWord]                  -&gt; [^4].<br>
                [Nop]                                   -&gt; [^4].<br>
                &quot;Control&quot;<br>
                [Call]                                  -&gt; [^self literalLoadInstructionBytes + 8].<br>
                [CallFull]                              -&gt; [^self literalLoadInstructionBytes + 8].<br>
                [JumpR]                                 -&gt; [^8].<br>
                [Jump]                                  -&gt; [^8].<br>
                [JumpFull]                              -&gt; [^self literalLoadInstructionBytes + 8].<br>
                [JumpLong]                              -&gt; [^self literalLoadInstructionBytes + 8].<br>
                [JumpZero]                              -&gt; [^8].<br>
                [JumpNonZero]                   -&gt; [^8].<br>
                [JumpNegative]                  -&gt; [^8].<br>
                [JumpNonNegative]               -&gt; [^8].<br>
                [JumpOverflow]                  -&gt; [^8].<br>
                [JumpNoOverflow]                -&gt; [^8].<br>
                [JumpCarry]                     -&gt; [^8].<br>
                [JumpNoCarry]                   -&gt; [^8].<br>
                [JumpLess]                              -&gt; [^8].<br>
                [JumpGreaterOrEqual]    -&gt; [^8].<br>
                [JumpGreater]                   -&gt; [^8].<br>
                [JumpLessOrEqual]               -&gt; [^8].<br>
                [JumpBelow]                     -&gt; [^8].<br>
                [JumpAboveOrEqual]      -&gt; [^8].<br>
                [JumpAbove]                     -&gt; [^8].<br>
                [JumpBelowOrEqual]      -&gt; [^8].<br>
                [JumpLongZero]          -&gt; [^self literalLoadInstructionBytes + 8].<br>
                [JumpLongNonZero]       -&gt; [^self literalLoadInstructionBytes + 8].<br>
                [JumpFPEqual]                   -&gt; [^8].<br>
                [JumpFPNotEqual]                -&gt; [^8].<br>
                [JumpFPLess]                    -&gt; [^8].<br>
                [JumpFPGreaterOrEqual]-&gt; [^8].<br>
                [JumpFPGreater]         -&gt; [^8].<br>
                [JumpFPLessOrEqual]     -&gt; [^8].<br>
                [JumpFPOrdered]         -&gt; [^8].<br>
                [JumpFPUnordered]               -&gt; [^8].<br>
                [RetN]                                  -&gt; [^8].<br>
                [Stop]                                  -&gt; [^4].<br>
<br>
                &quot;Arithmetic&quot;<br>
                [AddCqR]                                -&gt; [^12].<br>
                [AndCqR]                                -&gt; [^16].<br>
                [AndCqRR]                               -&gt; [^12].<br>
                [CmpCqR]                                -&gt; [^28].<br>
                [OrCqR]                                 -&gt; [^12].<br>
                [SubCqR]                                -&gt; [^12].<br>
                [TstCqR]                                -&gt; [^12].<br>
                [XorCqR]                                -&gt; [^12].<br>
                [AddCwR]                                -&gt; [^12].<br>
                [AndCwR]                                -&gt; [^12].<br>
                [CmpCwR]                                -&gt; [^28].<br>
                [OrCwR]                         -&gt; [^12].<br>
                [SubCwR]                                -&gt; [^12].<br>
                [XorCwR]                                -&gt; [^12].<br>
                [AddRR]                                 -&gt; [^4].<br>
                [AndRR]                                 -&gt; [^4].<br>
                [CmpRR]                         -&gt; [^20].<br>
                [OrRR]                                  -&gt; [^4].<br>
                [XorRR]                                 -&gt; [^4].<br>
                [SubRR]                                 -&gt; [^4].<br>
                [NegateR]                               -&gt; [^4].<br>
+               [LoadEffectiveAddressMwrR] -&gt; [^12].<br>
-               [LoadEffectiveAddressMwrR]<br>
-                                                                       -&gt; [^self rotateable8bitImmediate: (operands at: 0)<br>
-                                                                                       ifTrue: [:r :i| 4]<br>
-                                                                                       ifFalse: [self literalLoadInstructionBytes + 4]].<br>
-<br>
                [LogicalShiftLeftCqR]           -&gt; [^4].<br>
                [LogicalShiftRightCqR]          -&gt; [^4].<br>
                [ArithmeticShiftRightCqR]       -&gt; [^4].<br>
                [LogicalShiftLeftRR]                    -&gt; [^4].<br>
                [LogicalShiftRightRR]           -&gt; [^4].<br>
                [ArithmeticShiftRightRR]                -&gt; [^4].<br>
                [AddRdRd]                                       -&gt; [^4].<br>
                [CmpRdRd]                                       -&gt; [^4].<br>
                [SubRdRd]                                       -&gt; [^4].<br>
                [MulRdRd]                                       -&gt; [^4].<br>
                [DivRdRd]                                       -&gt; [^4].<br>
                [SqrtRd]                                        -&gt; [^4].<br>
+               [SubCheckOverflowCqR]   -&gt; [^28].<br>
                &quot;Data Movement&quot;<br>
                [MoveCqR]                               -&gt; [^8 &quot;or 4&quot;].<br>
                [MoveCwR]                               -&gt; [^8].<br>
                [MoveRR]                                -&gt; [^4].<br>
                [MoveRdRd]                              -&gt; [^4].<br>
                [MoveAwR]                               -&gt; [^(self isAddressRelativeToVarBase: (operands at: 0))<br>
                                                                                                        ifTrue: [4]<br>
                                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveRAw]                               -&gt; [^(self isAddressRelativeToVarBase: (operands at: 1))<br>
                                                                                                        ifTrue: [4]<br>
                                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
+               [MoveAbR]                               -&gt; [^(self isAddressRelativeToVarBase: (operands at: 0))<br>
+                                                                                                       ifTrue: [4]<br>
+                                                                                                       ifFalse: [self literalLoadInstructionBytes + 4]].<br>
+               [MoveRAb]                               -&gt; [^(self isAddressRelativeToVarBase: (operands at: 1))<br>
+                                                                                                       ifTrue: [4]<br>
+                                                                                                       ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveRMwr]                      -&gt; [^16].<br>
                [MoveRdM64r]                    -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [MoveMbrR]                              -&gt; [^16].<br>
                [MoveRMbr]                              -&gt; [^16].<br>
                [MoveM16rR]                     -&gt; [^4].<br>
                [MoveM64rRd]                    -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [MoveMwrR]                      -&gt; [^16].<br>
                [MoveXbrRR]                     -&gt; [^0].<br>
                [MoveRXbrR]                     -&gt; [^0].<br>
                [MoveXwrRR]                     -&gt; [^12].<br>
                [MoveRXwrR]                     -&gt; [^12].<br>
                [PopR]                                  -&gt; [^8].<br>
                [PushR]                                 -&gt; [^8].<br>
                [PushCw]                                -&gt; [^16].<br>
                [PushCq]                                -&gt; [^16].<br>
+               [PrefetchAw]                    -&gt; [^12].<br>
-               [PrefetchAw]                    -&gt; [^(self isAddressRelativeToVarBase: (operands at: 0))<br>
-                                                                               ifTrue: [4]<br>
-                                                                               ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                &quot;Conversion&quot;<br>
                [ConvertRRd]                    -&gt; [^8].<br>
                }.<br>
        ^0 &quot;to keep C compiler quiet&quot;<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJump (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJump<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 8.<br>
        self flag: #BranchRange.<br>
        self machineCodeAt: 0 put: (self beqR: ZR R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: self nop. &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpNoOverflow (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizeJumpNoOverflow<br>
+       | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
+       self flag: #BranchRange.<br>
+       self machineCodeAt: 0 put: (self bgezR: Overflow offset: offset).<br>
+       self machineCodeAt: 4 put: self nop. &quot;Delay slot&quot;<br>
+       ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpNonZero (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpNonZero<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self flag: #BranchRange.<br>
        self machineCodeAt: 0 put: (self bneR: Cmp R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: self nop. &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpOverflow (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizeJumpOverflow<br>
+       | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
+       self flag: #BranchRange.<br>
+       self machineCodeAt: 0 put: (self bltzR: Overflow offset: offset).<br>
+       self machineCodeAt: 4 put: self nop. &quot;Delay slot&quot;<br>
+       ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpSignedGreaterEqual (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpSignedGreaterEqual<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self machineCodeAt: 0 put: (self bneR: CmpSLT R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: (self nop). &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpSignedGreaterThan (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpSignedGreaterThan<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self machineCodeAt: 0 put: (self bneR: CmpSGT R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: (self nop). &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpSignedLessEqual (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpSignedLessEqual<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self machineCodeAt: 0 put: (self beqR: CmpSGT R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: (self nop). &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpSignedLessThan (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpSignedLessThan<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self machineCodeAt: 0 put: (self bneR: CmpSLT R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: (self nop). &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpUnsignedGreaterEqual (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpUnsignedGreaterEqual<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self machineCodeAt: 0 put: (self bneR: CmpULT R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: (self nop). &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpUnsignedGreaterThan (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpUnsignedGreaterThan<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self machineCodeAt: 0 put: (self bneR: CmpUGT R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: (self nop). &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpUnsignedLessEqual (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpUnsignedLessEqual<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self machineCodeAt: 0 put: (self beqR: CmpUGT R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: (self nop). &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpUnsignedLessThan (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpUnsignedLessThan<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self machineCodeAt: 0 put: (self bneR: CmpULT R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: (self nop). &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeJumpZero (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeJumpZero<br>
        | offset |<br>
+       offset := self computeJumpTargetOffsetPlus: 4.<br>
-       offset := self computeJumpTargetOffsetPlus: 12.<br>
        self flag: #BranchRange.<br>
        self machineCodeAt: 0 put: (self beqR: Cmp R: ZR offset: offset).<br>
        self machineCodeAt: 4 put: self nop. &quot;Delay slot&quot;<br>
        ^machineCodeSize := 8!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizeLoadEffectiveAddressMwrR (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizeLoadEffectiveAddressMwrR<br>
+       &lt;var: #offset type: #sqInt&gt;<br>
+       | baseReg offset destReg |<br>
+       offset := operands at: 0.<br>
+       baseReg := self concreteRegister: (operands at: 1).<br>
+       destReg := self concreteRegister: (operands at: 2).<br>
+       (self isShortOffset: offset) ifTrue:<br>
+               [self machineCodeAt: 0 put: (self addiuR: destReg R: baseReg C: offset).<br>
+               ^machineCodeSize := 4].<br>
+<br>
+       self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: offset)).<br>
+       self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: offset)).<br>
+       self machineCodeAt: 8 put: (self adduR: destReg R: baseReg R: AT).<br>
+       ^machineCodeSize := 12.<br>
+ !<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizeMoveAbR (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizeMoveAbR<br>
+       | srcAddr destReg |<br>
+       srcAddr := operands at: 0.<br>
+       destReg := self concreteRegister: (operands at: 1).<br>
+<br>
+       (self isAddressRelativeToVarBase: srcAddr) ifTrue:<br>
+               [self machineCodeAt: 0 put: (self lwR: destReg base: ConcreteVarBaseReg offset: srcAddr - cogit varBaseAddress).<br>
+                ^machineCodeSize := 4].<br>
+<br>
+       self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: srcAddr)).<br>
+       self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: srcAddr)).<br>
+       self machineCodeAt: 8 put: (self lbuR: destReg base: AT offset: 0).<br>
+       ^machineCodeSize := 12!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeMoveMwrR (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeMoveMwrR<br>
        &lt;var: #offset type: #sqInt&gt;<br>
        | baseReg offset destReg |<br>
        offset := operands at: 0.<br>
        baseReg := self concreteRegister: (operands at: 1).<br>
        destReg := self concreteRegister: (operands at: 2).<br>
        (self isShortOffset: offset) ifTrue:<br>
                [self machineCodeAt: 0 put: (self lwR: destReg base: baseReg offset: offset).<br>
                ^machineCodeSize := 4].<br>
<br>
        self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: offset)).<br>
        self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: offset)).<br>
+       self machineCodeAt: 8 put: (self adduR: AT R: baseReg R: AT).<br>
+       self machineCodeAt: 12 put: (self lwR: destReg base: AT offset: 0).<br>
+       ^machineCodeSize := 16.<br>
-       self machineCodeAt: 8 put: (self adduR: AT R: baseReg R: ZR).<br>
-       self machineCodeAt: 0 put: (self lwR: destReg base: AT offset: 0).<br>
-       ^machineCodeSize := 4.<br>
  !<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizeMoveRAb (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizeMoveRAb<br>
+       | srcReg destAddr |<br>
+       srcReg := self concreteRegister: (operands at: 0).<br>
+       destAddr := operands at: 1.<br>
+<br>
+       (self isAddressRelativeToVarBase: destAddr) ifTrue:<br>
+               [self machineCodeAt: 0 put: (self swR: srcReg base: ConcreteVarBaseReg offset: destAddr - cogit varBaseAddress).<br>
+                ^machineCodeSize := 4].<br>
+<br>
+       self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: destAddr)).<br>
+       self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: destAddr)).<br>
+       self machineCodeAt: 8 put: (self sbR: srcReg base: AT offset: 0).<br>
+       ^machineCodeSize := 12!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;concretizeMoveXwrRR (in category &#39;generate machine code - concretize&#39;) -----<br>
  concretizeMoveXwrRR<br>
        | indexReg baseReg destReg |<br>
        indexReg := self concreteRegister: (operands at: 0).<br>
        baseReg := self concreteRegister: (operands at: 1).<br>
        destReg := self concreteRegister: (operands at: 2).<br>
        self machineCodeAt: 0 put: (self sllR: AT R: indexReg C: 2). &quot;index is in words&quot;<br>
        self machineCodeAt: 4 put: (self adduR: AT R: baseReg R: AT).<br>
+       self machineCodeAt: 8 put: (self lwR: destReg base: AT offset: 0).<br>
-       self machineCodeAt: 8 put: (self lwR: destReg base: baseReg offset: 0).<br>
        ^machineCodeSize := 12!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizePrefetchAw (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizePrefetchAw<br>
+       | address |<br>
+       address := operands at: 0.<br>
+       self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: address)).<br>
+       self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: address)).<br>
+       self machineCodeAt: 8 put: (self prefR: AT offset: 0 hint: HintLoad).<br>
+       ^machineCodeSize := 12!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizePushCq (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizePushCq<br>
+       ^self concretizePushCw!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizePushCw (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizePushCw<br>
+       | value |<br>
+       value := operands at: 0.<br>
+       self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: value)).<br>
+       self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: value)).<br>
+       self machineCodeAt: 8 put: (self addiuR: SP R: SP C: -4).<br>
+       self machineCodeAt: 12 put: (self swR: AT base: SP offset: 0).<br>
+       ^machineCodeSize := 16!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;concretizeSubCheckOverflowCqR (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizeSubCheckOverflowCqR<br>
+       | value reg |<br>
+       value := operands at: 0.<br>
+       reg := self concreteRegister: (operands at: 1).<br>
+       self machineCodeAt: 0 put: (self luiR: AT C: (self high16BitsOf: value)).<br>
+       self machineCodeAt: 4 put: (self oriR: AT R: AT C: (self low16BitsOf: value)).<br>
+<br>
+       &quot;Save original LHS&quot;<br>
+       self machineCodeAt: 8 put: (self adduR: OverflowTemp1 R: reg R: ZR).<br>
+<br>
+       &quot;The actual subtraction&quot;<br>
+       self machineCodeAt: 12 put: (self subuR: reg R: reg R: AT).<br>
+<br>
+       &quot;Set sign bit of OverflowTemp2 if sign of result differs from sign of RHS.&quot;<br>
+       self machineCodeAt: 16 put: (self xorR: OverflowTemp2 R: reg R: AT).<br>
+       &quot;Set sign bit of OverflowTemp1 if sign of result differs from sign of LHS.&quot;<br>
+       self machineCodeAt: 20 put: (self xorR: OverflowTemp1 R: reg R: OverflowTemp1).<br>
+       &quot;Set sign bit of Overflow if sign of result differs from both LHS and RHS, which indicates overflow.&quot;<br>
+       self machineCodeAt: 24 put: (self andR: Overflow R: OverflowTemp1 R: OverflowTemp2).<br>
+       ^machineCodeSize := 28!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;dispatchConcretize (in category &#39;generate machine code&#39;) -----<br>
  dispatchConcretize<br>
        &quot;Attempt to generate concrete machine code for the instruction at address.<br>
         This is the inner dispatch of concretizeAt: actualAddress which exists only<br>
         to get around the branch size limits in the SqueakV3 (blue book derived)<br>
         bytecode set.&quot;<br>
        &lt;returnTypeC: #void&gt;<br>
        opcode caseOf: {<br>
                &quot;Noops &amp; Pseudo Ops&quot;<br>
                [Label]                                 -&gt; [^self concretizeLabel].<br>
                [AlignmentNops]         -&gt; [^self concretizeAlignmentNops].<br>
                [Fill16]                                        -&gt; [^self concretizeFill16].<br>
                [Fill32]                                        -&gt; [^self concretizeFill32].<br>
                [FillFromWord]                  -&gt; [^self concretizeFillFromWord].<br>
                [Nop]                                   -&gt; [^self concretizeNop].<br>
                &quot;Control&quot;<br>
                [Call]                                          -&gt; [^self concretizeCall]. &quot;call code within code space&quot;<br>
                [CallFull]                                      -&gt; [^self concretizeCallFull]. &quot;call code anywhere in address space&quot;<br>
                [JumpR]                                         -&gt; [^self concretizeJumpR].<br>
                [JumpFull]                                      -&gt; [^self concretizeJumpFull].&quot;jump within address space&quot;<br>
                [JumpLong]                                      -&gt; [^self concretizeJumpLong].&quot;jumps witihn code space&quot;<br>
                [JumpLongZero]                  -&gt; [^self concretizeJumpLongZero].<br>
                [JumpLongNonZero]               -&gt; [^self concretizeJumpLongNonZero].<br>
                [Jump]                                          -&gt; [^self concretizeJump].<br>
                [JumpZero]                                      -&gt; [^self concretizeJumpZero].<br>
                [JumpNonZero]                           -&gt; [^self concretizeJumpNonZero].<br>
                [JumpNegative]                          -&gt; [^self concretizeUnimplemented].<br>
                [JumpNonNegative]                       -&gt; [^self concretizeUnimplemented].<br>
                [JumpOverflow]                          -&gt; [^self concretizeUnimplemented].<br>
+               [JumpNoOverflow]                        -&gt; [^self concretizeJumpNoOverflow].<br>
-               [JumpNoOverflow]                        -&gt; [^self concretizeUnimplemented].<br>
                [JumpCarry]                             -&gt; [^self concretizeUnimplemented].<br>
                [JumpNoCarry]                           -&gt; [^self concretizeUnimplemented].<br>
                [JumpLess]                                      -&gt; [^self concretizeJumpSignedLessThan].<br>
                [JumpGreaterOrEqual]            -&gt; [^self concretizeJumpSignedGreaterEqual].<br>
                [JumpGreater]                           -&gt; [^self concretizeJumpSignedGreaterThan].<br>
                [JumpLessOrEqual]                       -&gt; [^self concretizeJumpSignedLessEqual].<br>
                [JumpBelow]                             -&gt; [^self concretizeJumpUnsignedLessThan].<br>
                [JumpAboveOrEqual]              -&gt; [^self concretizeJumpUnsignedGreaterEqual].<br>
                [JumpAbove]                             -&gt; [^self concretizeJumpUnsignedGreaterThan].<br>
                [JumpBelowOrEqual]              -&gt; [^self concretizeJumpUnsignedLessEqual].<br>
                [JumpFPEqual]                           -&gt; [^self concretizeUnimplemented].<br>
                [JumpFPNotEqual]                        -&gt; [^self concretizeUnimplemented].<br>
                [JumpFPLess]                            -&gt; [^self concretizeUnimplemented].<br>
                [JumpFPGreaterOrEqual]  -&gt; [^self concretizeUnimplemented].<br>
                [JumpFPGreater]                 -&gt; [^self concretizeUnimplemented].<br>
                [JumpFPLessOrEqual]             -&gt; [^self concretizeUnimplemented].<br>
                [JumpFPOrdered]                 -&gt; [^self concretizeUnimplemented].<br>
                [JumpFPUnordered]                       -&gt; [^self concretizeUnimplemented].<br>
                [RetN]                                          -&gt; [^self concretizeRetN].<br>
                [Stop]                                          -&gt; [^self concretizeStop].<br>
                &quot;Arithmetic&quot;<br>
                [AddCqR]                                        -&gt; [^self concretizeAddCqR].<br>
                [AndCqR]                                        -&gt; [^self concretizeAndCqR].<br>
                [AndCqRR]                                       -&gt; [^self concretizeAndCqRR].<br>
                [CmpCqR]                                        -&gt; [^self concretizeCmpCqR].<br>
                [OrCqR]                                         -&gt; [^self concretizeOrCqR].<br>
                [SubCqR]                                        -&gt; [^self concretizeSubCqR].<br>
                [TstCqR]                                        -&gt; [^self concretizeTstCqR].<br>
                [XorCqR]                                        -&gt; [^self concretizeXorCqR].<br>
                [AddCwR]                                        -&gt; [^self concretizeAddCwR].<br>
                [AndCwR]                                        -&gt; [^self concretizeAndCwR].<br>
                [CmpCwR]                                        -&gt; [^self concretizeCmpCwR].<br>
                [OrCwR]                                 -&gt; [^self concretizeOrCwR].<br>
                [SubCwR]                                        -&gt; [^self concretizeSubCwR].<br>
                [XorCwR]                                        -&gt; [^self concretizeXorCwR].<br>
                [AddRR]                                         -&gt; [^self concretizeAddRR].<br>
                [AndRR]                                         -&gt; [^self concretizeAndRR].<br>
                [CmpRR]                                 -&gt; [^self concretizeCmpRR].<br>
                [OrRR]                                          -&gt; [^self concretizeOrRR].<br>
                [SubRR]                                         -&gt; [^self concretizeSubRR].<br>
                [XorRR]                                         -&gt; [^self concretizeUnimplemented].<br>
                [AddRdRd]                                       -&gt; [^self concretizeUnimplemented].<br>
                [CmpRdRd]                                       -&gt; [^self concretizeUnimplemented].<br>
                [DivRdRd]                                       -&gt; [^self concretizeUnimplemented].<br>
                [MulRdRd]                                       -&gt; [^self concretizeUnimplemented].<br>
                [SubRdRd]                                       -&gt; [^self concretizeUnimplemented].<br>
                [SqrtRd]                                        -&gt; [^self concretizeUnimplemented].<br>
                [NegateR]                                               -&gt; [^self concretizeNegateR].<br>
+               [LoadEffectiveAddressMwrR]      -&gt; [^self concretizeLoadEffectiveAddressMwrR].<br>
-               [LoadEffectiveAddressMwrR]      -&gt; [^self concretizeUnimplemented].<br>
                [ArithmeticShiftRightCqR]               -&gt; [^self concretizeArithmeticShiftRightCqR].<br>
                [LogicalShiftRightCqR]                  -&gt; [^self concretizeLogicalShiftRightCqR].<br>
                [LogicalShiftLeftCqR]                   -&gt; [^self concretizeLogicalShiftLeftCqR].<br>
                [ArithmeticShiftRightRR]                        -&gt; [^self concretizeArithmeticShiftRightRR].<br>
                [LogicalShiftLeftRR]                            -&gt; [^self concretizeLogicalShiftLeftRR].<br>
                [LogicalShiftRightRR]                   -&gt; [^self concretizeLogicalShiftRightRR].<br>
                &quot;Data Movement&quot;<br>
                [MoveCqR]                       -&gt; [^self concretizeMoveCqR].<br>
                [MoveCwR]                       -&gt; [^self concretizeMoveCwR].<br>
                [MoveRR]                        -&gt; [^self concretizeMoveRR].<br>
                [MoveAwR]                       -&gt; [^self concretizeMoveAwR].<br>
                [MoveRAw]                       -&gt; [^self concretizeMoveRAw].<br>
+               [MoveAbR]                       -&gt; [^self concretizeMoveAbR].<br>
+               [MoveRAb]                       -&gt; [^self concretizeMoveRAb].<br>
                [MoveMbrR]                      -&gt; [^self concretizeMoveMbrR].<br>
                [MoveRMbr]                      -&gt; [^self concretizeUnimplemented].<br>
                [MoveM16rR]             -&gt; [^self concretizeMoveM16rR].<br>
                [MoveM64rRd]            -&gt; [^self concretizeUnimplemented].<br>
                [MoveMwrR]              -&gt; [^self concretizeMoveMwrR].<br>
                [MoveXbrRR]             -&gt; [^self concretizeUnimplemented].<br>
                [MoveRXbrR]             -&gt; [^self concretizeUnimplemented].<br>
                [MoveXwrRR]             -&gt; [^self concretizeMoveXwrRR].<br>
                [MoveRXwrR]             -&gt; [^self concretizeMoveRXwrR].<br>
                [MoveRMwr]              -&gt; [^self concretizeMoveRMwr].<br>
                [MoveRdM64r]            -&gt; [^self concretizeUnimplemented].<br>
                [PopR]                          -&gt; [^self concretizePopR].<br>
                [PushR]                         -&gt; [^self concretizePushR].<br>
+               [PushCq]                        -&gt; [^self concretizePushCq].<br>
+               [PushCw]                        -&gt; [^self concretizePushCw].<br>
+               [PrefetchAw]            -&gt; [^self concretizePrefetchAw].<br>
+               [SubCheckOverflowCqR] -&gt; [^self concretizeSubCheckOverflowCqR].<br>
-               [PushCq]                        -&gt; [^self concretizeUnimplemented].<br>
-               [PushCw]                        -&gt; [^self concretizeUnimplemented].<br>
-               [PrefetchAw]            -&gt; [^self concretizeUnimplemented].<br>
                &quot;Conversion&quot;<br>
                [ConvertRRd]            -&gt; [^self concretizeUnimplemented]}!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;hasConditionRegister (in category &#39;testing&#39;) -----<br>
+ hasConditionRegister<br>
+       &quot;Answer if the receiver supports, e.g., JumpOverflow after a regular AddRR&quot;<br>
+       &lt;inline: true&gt;<br>
+       ^false!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;hasThreeAddressArithmetic (in category &#39;testing&#39;) -----<br>
  hasThreeAddressArithmetic<br>
+       &quot;Answer if the receiver supports three-address arithmetic instructions&quot;<br>
+       &lt;inline: true&gt;<br>
        ^true!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;inlineCacheTagAt: (in category &#39;inline cacheing&#39;) -----<br>
+ inlineCacheTagAt: callSiteReturnAddress<br>
+       &quot;Answer the inline cache tag for the return address of a send.&quot;<br>
+<br>
+       &quot;MoveCwR ClassReg selectorIndex/expectedClass<br>
+        Call: unlinked send stub/expectedTarget<br>
+        Push ReceiverResult &lt;-- callSiteReturnAddress&quot;<br>
+<br>
+       &quot;lui s3, selector/tagHigh<br>
+        ori s3, s3, selector/tagLow<br>
+        lui t9, stub/targetHigh<br>
+        ori t9, t9, stub/targetLow<br>
+        jalr t9<br>
+        nop (delay slot)<br>
+        ...  &lt;-- callSiteReturnAddress&quot;<br>
+<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 24) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 20) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 16) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 12) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 8) = SPECIAL.<br>
+       self assert: (self functionAtAddress: callSiteReturnAddress - 8) = JALR.<br>
+       self assert: (objectMemory longAt: callSiteReturnAddress - 4) = self nop.<br>
+<br>
+       ^self literalAtAddress: callSiteReturnAddress - 20!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;jumpShortByteSize (in category &#39;accessing&#39;) -----<br>
+ jumpShortByteSize<br>
+       ^8!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;literalAtAddress:put: (in category &#39;inline cacheing&#39;) -----<br>
  literalAtAddress: mcpc put: newLiteral<br>
+       | oldUpper newUpper oldLower newLower |<br>
+       self assert: (self opcodeAtAddress: mcpc - 4) = LUI.<br>
-       | instruction |<br>
        self assert: (self opcodeAtAddress: mcpc) = ORI.<br>
+<br>
+       oldUpper := objectMemory longAt: mcpc - 4.<br>
+       newUpper := (oldUpper bitAnd: 16rFFFF0000) bitOr: (self high16BitsOf: newLiteral).<br>
+       objectMemory longAt: mcpc - 4 put: newUpper.<br>
+<br>
+       oldLower := objectMemory longAt: mcpc.<br>
+       newLower := (oldLower bitAnd: 16rFFFF0000) bitOr: (self low16BitsOf: newLiteral).<br>
+       objectMemory longAt: mcpc put: newLower.<br>
+<br>
        self assert: (self opcodeAtAddress: mcpc - 4) = LUI.<br>
+       self assert: (self opcodeAtAddress: mcpc) = ORI.<br>
<br>
+       self assert: (self literalAtAddress: mcpc) = newLiteral.<br>
-       instruction := (objectMemory longAt: mcpc) bitAnd: 16rFFFF000.<br>
-       instruction := instruction bitOr: (self low16BitsOf: newLiteral).<br>
-       objectMemory longAt: mcpc put: instruction.<br>
-<br>
-       instruction := (objectMemory longAt: mcpc - 4) bitAnd: 16rFFFF000.<br>
-       instruction := instruction bitOr: (self high16BitsOf: newLiteral).<br>
-       objectMemory longAt: mcpc put: instruction.<br>
<br>
        ^newLiteral!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;loadPICLiteralByteSize (in category &#39;accessing&#39;) -----<br>
+ loadPICLiteralByteSize<br>
+       &quot;Answer the byte size of a MoveCwR opcode&#39;s corresponding machine code<br>
+        when the argument is a PIC.  This is for the self-reference at the end of a<br>
+        closed PIC.&quot;<br>
+       &lt;inline: true&gt;<br>
+       ^self loadLiteralByteSize!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;prefR:offset:hint: (in category &#39;encoding - memory&#39;) -----<br>
+ prefR: baseReg offset: offset hint: hint<br>
+       self flag: #todo. &quot;Should we generate a nop instead? gcc gives an error trying to assemble this for mips1 (1985), mips2 (1990) and mips3 (1992), but succeeds with mips4 (1994) and mips32 (1999).&quot;<br>
+       self assert: (hint == HintLoad or: [hint == HintStore]).<br>
+       ^self itype: PREF rs: baseReg rt: hint signedImmediate: offset!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;relocateMethodReferenceBeforeAddress:by: (in category &#39;inline cacheing&#39;) -----<br>
+ relocateMethodReferenceBeforeAddress: pc by: delta<br>
+       | oldValue newValue |<br>
+       cogit disassembleFrom: pc - 8 to: pc.<br>
+<br>
+       oldValue := self literalAtAddress: pc - 4.<br>
+       newValue := oldValue + delta.<br>
+       self literalAtAddress: pc - 4 put: newValue.<br>
+<br>
+       cogit disassembleFrom: pc - 8 to: pc.<br>
+       self assert: (self literalAtAddress: pc - 4) = newValue.<br>
+       !<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;rewriteCPICCaseAt:tag:objRef:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteCPICCaseAt: followingAddress tag: newTag objRef: newObjRef target: newTarget<br>
+       &quot;rewrite the three values involved in a CPIC case. Used by the create &amp; extend cpcic methods&quot;<br>
+<br>
+       &quot;lui at, tagHigh<br>
+        ori at, at, tagLow<br>
+        subu t0, s5, at (Cmp)<br>
+        slt ... (Cmp)<br>
+        slt ... (Cmp)<br>
+        sltu ... (Cmp)<br>
+        sltu ... (Cmp)<br>
+        lui s4, objRefHigh<br>
+        ori s4, s4, objRefLow<br>
+        bne t0, zr, +12<br>
+        nop (delay slot)<br>
+        j target<br>
+        nop (delay slot)<br>
+        .... &lt;-- followingAddress&quot;<br>
+<br>
+       cogit disassembleFrom: followingAddress - 52 to: followingAddress.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 52) = LUI.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 48) = ORI.<br>
+       self assert: (self functionAtAddress: followingAddress - 44) = SUBU.<br>
+       self assert: (self functionAtAddress: followingAddress - 40) = SLT.<br>
+       self assert: (self functionAtAddress: followingAddress - 36) = SLT.<br>
+       self assert: (self functionAtAddress: followingAddress - 32) = SLTU.<br>
+       self assert: (self functionAtAddress: followingAddress - 28) = SLTU.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 24) = LUI.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 20) = ORI.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 16) = BNE.<br>
+       self assert: (objectMemory longAt: followingAddress - 12) = self nop.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 8) = J.<br>
+       self assert: (objectMemory longAt: followingAddress - 4) = self nop.<br>
+<br>
+       self literalAtAddress: followingAddress - 48 put: newTag.<br>
+       self literalAtAddress: followingAddress - 20 put: newObjRef.<br>
+       self rewriteJTypeAtAddress: followingAddress - 8 target: newTarget.<br>
+<br>
+       cogit disassembleFrom: followingAddress - 52 to: followingAddress.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 52) = LUI.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 48) = ORI.<br>
+       self assert: (self functionAtAddress: followingAddress - 44) = SUBU.<br>
+       self assert: (self functionAtAddress: followingAddress - 40) = SLT.<br>
+       self assert: (self functionAtAddress: followingAddress - 36) = SLT.<br>
+       self assert: (self functionAtAddress: followingAddress - 32) = SLTU.<br>
+       self assert: (self functionAtAddress: followingAddress - 28) = SLTU.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 24) = LUI.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 20) = ORI.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 16) = BNE.<br>
+       self assert: (objectMemory longAt: followingAddress - 12) = self nop.<br>
+       self assert: (self opcodeAtAddress: followingAddress - 8) = J.<br>
+       self assert: (objectMemory longAt: followingAddress - 4) = self nop.<br>
+<br>
+       ^56!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;rewriteCPICJumpAt:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteCPICJumpAt: callSiteReturnAddress target: callTargetAddress<br>
+       &quot;Rewrite a jump instruction to call a different target.  This variant is used to reset the<br>
+       jumps in the prototype CPIC to suit each use,.<br>
+       Answer the extent of the code change which is used to compute the range of the icache to flush.&quot;<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+<br>
+       cogit disassembleFrom: callSiteReturnAddress - 16 to: callSiteReturnAddress + 16.<br>
+       self halt.!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;rewriteCallAt:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteCallAt: callSiteReturnAddress target: callTargetAddress<br>
+       &quot;Rewrite a call instruction to call a different target.  This variant is used to link PICs<br>
+        in ceSendMiss et al,.<br>
+       Answer the extent of the code change which is used to compute the range of the icache to flush.&quot;<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+<br>
+       &quot;lui t9, stub/targetHigh<br>
+        ori t9, t9, stub/targetLow<br>
+        jalr t9<br>
+        nop (delay slot)<br>
+        ...  &lt;-- callSiteReturnAddress&quot;<br>
+<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 16) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 12) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 8) = SPECIAL.<br>
+       self assert: (self functionAtAddress: callSiteReturnAddress - 8) = JALR.<br>
+       self assert: (objectMemory longAt: callSiteReturnAddress - 4) = self nop.<br>
+<br>
+       cogit disassembleFrom: callSiteReturnAddress - 16 to: callSiteReturnAddress.<br>
+<br>
+       self literalAtAddress: callSiteReturnAddress - 12 put: callTargetAddress.<br>
+<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 16) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 12) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 8) = SPECIAL.<br>
+       self assert: (self functionAtAddress: callSiteReturnAddress - 8) = JALR.<br>
+       self assert: (objectMemory longAt: callSiteReturnAddress - 4) = self nop.<br>
+<br>
+       cogit disassembleFrom: callSiteReturnAddress - 16 to: callSiteReturnAddress.<br>
+<br>
+       ^20!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;rewriteInlineCacheAt:tag:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteInlineCacheAt: callSiteReturnAddress tag: cacheTag target: callTargetAddress<br>
+       &quot;Rewrite an inline cache to call a different target for a new tag.  This variant is used<br>
+        to link unlinked sends in ceSend:to:numArgs: et al.  Answer the extent of the code<br>
+        change which is used to compute the range of the icache to flush.&quot;<br>
+<br>
+       &quot;MoveCwR ClassReg selectorIndex/expectedClass<br>
+        Call: unlinked send stub/expectedTarget<br>
+        Push ReceiverResult &lt;-- callSiteReturnAddress&quot;<br>
+<br>
+       &quot;lui s3, selector/tagHigh<br>
+        ori s3, s3, selector/tagLow<br>
+        lui t9, stub/targetHigh<br>
+        ori t9, t9, stub/targetLow<br>
+        jalr t9<br>
+        nop (delay slot)<br>
+        ...  &lt;-- callSiteReturnAddress&quot;<br>
+<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 24) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 20) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 16) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 12) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 8) = SPECIAL.<br>
+       self assert: (self functionAtAddress: callSiteReturnAddress - 8) = JALR.<br>
+       self assert: (objectMemory longAt: callSiteReturnAddress - 4) = self nop.<br>
+<br>
+       cogit disassembleFrom: callSiteReturnAddress - 24 to: callSiteReturnAddress.<br>
+<br>
+       self literalAtAddress: callSiteReturnAddress - 20 put: cacheTag.<br>
+       self literalAtAddress: callSiteReturnAddress - 12 put: callTargetAddress.<br>
+<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 24) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 20) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 16) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 12) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 8) = SPECIAL.<br>
+       self assert: (self functionAtAddress: callSiteReturnAddress - 8) = JALR.<br>
+       self assert: (objectMemory longAt: callSiteReturnAddress - 4) = self nop.<br>
+<br>
+       cogit disassembleFrom: callSiteReturnAddress - 24 to: callSiteReturnAddress.<br>
+<br>
+       ^28!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;rewriteJTypeAtAddress:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteJTypeAtAddress: mcpc target: newTarget<br>
+       | regionMask |<br>
+       regionMask := 16rF0000000.<br>
+       &quot;mcpc + 4: relative to delay slot not j&quot;<br>
+       self assert: (mcpc + 4 bitAnd: regionMask) = (newTarget bitAnd: regionMask).<br>
+       objectMemory longAt: mcpc put: (self jA: newTarget).!<br>
<br>
Item was added:<br>
+ ----- Method: CogMIPSELCompiler&gt;&gt;rewriteJumpLongAt:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteJumpLongAt: callSiteReturnAddress target: callTargetAddress<br>
+       &quot;Rewrite a jump instruction to call a different target.  This variant is used to reset the<br>
+       jumps in the prototype CPIC to suit each use,.<br>
+       Answer the extent of the code change which is used to compute the range of the icache to flush.&quot;<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+<br>
+       &quot;lui t9, stub/targetHigh<br>
+        ori t9, t9, stub/targetLow<br>
+        jr t9<br>
+        nop (delay slot)<br>
+        ...  &lt;-- callSiteReturnAddress&quot;<br>
+<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 16) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 12) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 8) = SPECIAL.<br>
+       self assert: (self functionAtAddress: callSiteReturnAddress - 8) = JR.<br>
+       self assert: (objectMemory longAt: callSiteReturnAddress - 4) = self nop.<br>
+<br>
+       cogit disassembleFrom: callSiteReturnAddress - 16 to: callSiteReturnAddress.<br>
+<br>
+       self literalAtAddress: callSiteReturnAddress - 12 put: callTargetAddress.<br>
+<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 16) = LUI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 12) = ORI.<br>
+       self assert: (self opcodeAtAddress: callSiteReturnAddress - 8) = SPECIAL.<br>
+       self assert: (self functionAtAddress: callSiteReturnAddress - 8) = JR.<br>
+       self assert: (objectMemory longAt: callSiteReturnAddress - 4) = self nop.<br>
+<br>
+       cogit disassembleFrom: callSiteReturnAddress - 16 to: callSiteReturnAddress.<br>
+<br>
+       ^20!<br>
<br>
Item was changed:<br>
  ----- Method: CogMIPSELCompiler&gt;&gt;rtype:rs:rt:rd:sa:funct: (in category &#39;encoding&#39;) -----<br>
  rtype: opcode rs: rs rt: rt rd: rd sa: sa funct: funct<br>
        self assert: (opcode between: 0 and: 63).<br>
        self assert: (rs between: 0 and: 31).<br>
        self assert: (rt between: 0 and: 31).<br>
        self assert: (rd between: 0 and: 31).<br>
+       self assert: (sa between: 0 and: 31).<br>
-       self assert: (sa between: 0 and: 15).<br>
        self assert: (funct between: 0 and: 63).<br>
        ^(((((opcode &lt;&lt; 26) bitOr: (rs &lt;&lt; 21)) bitOr: (rt &lt;&lt; 16)) bitOr: (rd &lt;&lt; 11)) bitOr: (sa &lt;&lt; 6)) bitOr: funct!<br>
<br>
Item was changed:<br>
  SharedPool subclass: #CogRTLOpcodes<br>
        instanceVariableNames: &#39;&#39;<br>
+       classVariableNames: &#39;AddCheckOverflowCqR AddCheckOverflowRR AddCqR AddCwR AddRR AddRdRd AlignmentNops AndCqR AndCqRR AndCwR AndRR Arg0Reg Arg1Reg ArithmeticShiftRightCqR ArithmeticShiftRightRR Call CallFull ClassReg CmpC32R CmpCqR CmpCwR CmpRR CmpRdRd ConvertRRd DPFPReg0 DPFPReg1 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6 DPFPReg7 DivRdRd FPReg Fill16 Fill32 Fill8 FillBytesFrom FillFromWord FirstJump FirstShortJump Jump JumpAbove JumpAboveOrEqual JumpBelow JumpBelowOrEqual JumpCarry JumpFPEqual JumpFPGreater JumpFPGreaterOrEqual JumpFPLess JumpFPLessOrEqual JumpFPNotEqual JumpFPOrdered JumpFPUnordered JumpFull JumpGreater JumpGreaterOrEqual JumpLess JumpLessOrEqual JumpLong JumpLongNonZero JumpLongZero JumpNegative JumpNoCarry JumpNoOverflow JumpNonNegative JumpNonZero JumpOverflow JumpR JumpZero Label LastJump LastRTLCode LinkReg Literal LoadEffectiveAddressMwrR LoadEffectiveAddressXowrR LogicalShiftLeftCqR LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightRR MoveAbR MoveAwR MoveC32R MoveC64R MoveCqR MoveCwR MoveM16rR MoveM32rR MoveM64rRd MoveMbrR MoveMwrR MoveRAb MoveRAw MoveRM16r MoveRM32r MoveRMbr MoveRMwr MoveRR MoveRX16rR MoveRX32rR MoveRXbrR MoveRXowr MoveRXwrR MoveRdM64r MoveRdRd MoveX16rRR MoveX32rRR MoveXbrRR MoveXowrR MoveXwrRR MulRdRd NegateR Nop OrCqR OrCwR OrRR PCReg PopR PrefetchAw PushCq PushCw PushR RISCTempReg ReceiverResultReg RetN SPReg Scratch0Reg Scratch1Reg Scratch2Reg Scratch3Reg Scratch4Reg Scratch5Reg Scratch6Reg Scratch7Reg SendNumArgsReg SqrtRd Stop SubCheckOverflowCqR SubCheckOverflowRR SubCqR SubCwR SubRR SubRdRd TempReg TstCqR VarBaseReg XorCqR XorCwR XorRR&#39;<br>
-       classVariableNames: &#39;AddCqR AddCwR AddRR AddRdRd AlignmentNops AndCqR AndCqRR AndCwR AndRR Arg0Reg Arg1Reg ArithmeticShiftRightCqR ArithmeticShiftRightRR Call CallFull ClassReg CmpC32R CmpCqR CmpCwR CmpRR CmpRdRd ConvertRRd DPFPReg0 DPFPReg1 DPFPReg2 DPFPReg3 DPFPReg4 DPFPReg5 DPFPReg6 DPFPReg7 DivRdRd FPReg Fill16 Fill32 Fill8 FillBytesFrom FillFromWord FirstJump FirstShortJump Jump JumpAbove JumpAboveOrEqual JumpBelow JumpBelowOrEqual JumpCarry JumpFPEqual JumpFPGreater JumpFPGreaterOrEqual JumpFPLess JumpFPLessOrEqual JumpFPNotEqual JumpFPOrdered JumpFPUnordered JumpFull JumpGreater JumpGreaterOrEqual JumpLess JumpLessOrEqual JumpLong JumpLongNonZero JumpLongZero JumpNegative JumpNoCarry JumpNoOverflow JumpNonNegative JumpNonZero JumpOverflow JumpR JumpZero Label LastJump LastRTLCode LinkReg Literal LoadEffectiveAddressMwrR LoadEffectiveAddressXowrR LogicalShiftLeftCqR LogicalShiftLeftRR LogicalShiftRightCqR LogicalShiftRightRR MoveAbR MoveAwR MoveC32R MoveC64R MoveCqR MoveCwR MoveM16rR MoveM32rR MoveM64rRd MoveMbrR MoveMwrR MoveRAb MoveRAw MoveRM16r MoveRM32r MoveRMbr MoveRMwr MoveRR MoveRX16rR MoveRX32rR MoveRXbrR MoveRXowr MoveRXwrR MoveRdM64r MoveRdRd MoveX16rRR MoveX32rRR MoveXbrRR MoveXowrR MoveXwrRR MulRdRd NegateR Nop OrCqR OrCwR OrRR PCReg PopR PrefetchAw PushCq PushCw PushR RISCTempReg ReceiverResultReg RetN SPReg Scratch0Reg Scratch1Reg Scratch2Reg Scratch3Reg Scratch4Reg Scratch5Reg Scratch6Reg Scratch7Reg SendNumArgsReg SqrtRd Stop SubCqR SubCwR SubRR SubRdRd TempReg TstCqR VarBaseReg XorCqR XorCwR XorRR&#39;<br>
        poolDictionaries: &#39;&#39;<br>
        category: &#39;VMMaker-JIT&#39;!<br>
<br>
  !CogRTLOpcodes commentStamp: &#39;&lt;historical&gt;&#39; prior: 0!<br>
  I am a pool for the Register-Transfer-Language to which Cog compiles.  I define unique integer values for all RTL opcodes and abstract registers.  See CogAbstractInstruction for instances of instructions with the opcodes that I define.!<br>
<br>
Item was changed:<br>
  ----- Method: CogRTLOpcodes class&gt;&gt;initialize (in category &#39;class initialization&#39;) -----<br>
  initialize<br>
        &quot;Abstract opcodes are a compound of a one word operation specifier and zero or more operand type specifiers.<br>
         e.g. MoveRR is the Move opcode with two register operand specifiers and defines a move register to<br>
         register instruction from operand 0 to operand 1.  The word and register size is assumed to be either 32-bits on<br>
         a 32-bit architecture or 64-bits on a 64-bit architecture.  The abstract machine is mostly a 2 address machine<br>
         with the odd three address instruction added to better exploit RISCs.<br>
                        (self initialize)<br>
        The operand specifiers are<br>
                R               - general purpose register<br>
                Rd              - double-precision floating-point register<br>
                Cq              - a `quick&#39; constant that can be encoded in the minimum space possible.<br>
                Cw              - a constant with word size where word is the default operand size for the Smalltalk VM, 32-bits<br>
                                  for a 32-bit VM, 64-bits for a 64-bit VM.  The generated constant must occupy the default number<br>
                                  of bits.  This allows e.g. a garbage collector to update the value without invalidating the code.<br>
                C32     - a constant with 32 bit size.  The generated constant must occupy 32 bits.<br>
                C64     - a constant with 64 bit size.  The generated constant must occupy 64 bits.<br>
                Aw              - memory word at an absolute address<br>
                Ab              - memory byte at an absolute address<br>
                Mwr     - memory word whose address is at a constant offset from an address in a register<br>
                Mbr             - memory byte whose address is at a constant offset from an address in a register (zero-extended on read)<br>
                M16r    - memory 16-bit halfword whose address is at a constant offset from an address in a register<br>
                M32r    - memory 32-bit halfword whose address is at a constant offset from an address in a register<br>
                M64r    - memory 64-bit doubleword whose address is at a constant offset from an address in a register<br>
                XbrR    - memory word whose address is r * byte size away from an address in a register<br>
                X16rR   - memory word whose address is r * (2 bytes size) away from an address in a register<br>
                X32rR   - memory word whose address is r * (4 bytes size) away from an address in a register<br>
                XwrR    - memory word whose address is r * word size away from an address in a register<br>
                XowrR   - memory word whose address is (r * word size) + o away from an address in a register (scaled indexed)<br>
<br>
        An alternative would be to decouple opcodes from operands, e.g.<br>
                Move := 1. Add := 2. Sub := 3...<br>
                RegisterOperand := 1. ConstantQuickOperand := 2. ConstantWordOperand := 3...<br>
        But not all combinations make sense and even fewer are used so we stick with the simple compound approach.<br>
<br>
        The assumption is that comparison and arithmetic instructions set condition codes and that move instructions<br>
        leave the condition codes unaffected.  In particular LoadEffectiveAddressMwrR does not set condition codes<br>
        although it can be used to do arithmetic.<br>
<br>
        Not all of the definitions in opcodeDefinitions below are implemented.  In particular we do not implement the<br>
        XowrR scaled index addressing mode since it requires 4 operands.<br>
<br>
        Note that there are no generic division instructions defined, but a processor may define some.<br>
<br>
        Branch/Call ranges.  Jump[Cond] can be generated as short as possible.  Call/Jump[Cond]Long must be generated<br>
        in the same number of bytes irrespective of displacement since their targets may be updated, but they need only<br>
        span 16Mb, the maximum size of the code zone.  This allows e.g. ARM to use single-word call and jump instructions<br>
        for most calls and jumps.  CallFull/JumpFull must also be generated in the same number of bytes irrespective of<br>
        displacement for the same reason, but they must be able to span the full (32-bit or 64-bit) address space because<br>
        they are used to call code in the C runtime, which may be distant from the code zone.  CallFull/JumpFull are allowed<br>
        to use the cResultRegister as a scratch if required (e.g. on x64 where there is no direct 64-bit call or jump).<br>
<br>
        Byte reads.  If the concrete compiler class answers true to byteReadsZeroExtend then byte reads must zero-extend<br>
        the byte read into the destination register.  If not, the other bits of the register should be left undisturbed and the<br>
        Cogit will add an instruction to zero the register as required.  Under no circumstances should byte reads sign-extend.<br>
<br>
        16-bit (and on 64-bits, 32-bit) reads.  These /are/ expected to always zero-extend.&quot;<br>
<br>
        | opcodeNames refs |<br>
        &quot;A small fixed set of abstract registers are defined and used in code generation<br>
         for Smalltalk code, and executes on stack pages in the stack zone.<br>
         These are mapped to processor-specific registers by concreteRegister:&quot;<br>
        FPReg := -1.    &quot;A frame pointer is used for Smalltalk frames.&quot;<br>
        SPReg := -2.<br>
        ReceiverResultReg := -3.                &quot;The receiver at point of send, and return value of a send&quot;<br>
        TempReg := -4.<br>
        ClassReg := -5.                                 &quot;The inline send cache class tag is in this register, loaded at the send site&quot;<br>
        SendNumArgsReg := -6.           &quot;Sends &gt; 2 args set the arg count in this reg&quot;<br>
        Arg0Reg := -7.                                  &quot;In the StackToRegisterMappingCogit 1 &amp; 2 arg sends marshall into these registers.&quot;<br>
        Arg1Reg := -8.<br>
<br>
        &quot;A small fixed set of abstract scratch registers for register-rich machines (ARM can use 1, x64 can use 6).&quot;<br>
        Scratch0Reg := -9.<br>
        Scratch1Reg := -10.<br>
        Scratch2Reg := -11.<br>
        Scratch3Reg := -12.<br>
        Scratch4Reg := -13.<br>
        Scratch5Reg := -14.<br>
        Scratch6Reg := -15.<br>
        Scratch7Reg := -16.<br>
<br>
        &quot;RISC-specific registers&quot;<br>
        LinkReg := -17.<br>
        RISCTempReg := -18.     &quot;Used to synthesize CISC instructions from multiple RISC instructions.&quot;<br>
        PCReg := -19.<br>
        VarBaseReg := -20.              &quot;If useful, points to base of interpreter variables.&quot;<br>
<br>
        &quot;Floating-point registers&quot;<br>
        DPFPReg0 := -21.<br>
        DPFPReg1 := -22.<br>
        DPFPReg2 := -23.<br>
        DPFPReg3 := -24.<br>
        DPFPReg4 := -25.<br>
        DPFPReg5 := -26.<br>
        DPFPReg6 := -27.<br>
        DPFPReg7 := -28.<br>
<br>
        opcodeNames := #(&quot;Noops &amp; Pseudo Ops&quot;<br>
                                                Label<br>
                                                Literal                 &quot;a word-sized literal&quot;<br>
                                                AlignmentNops<br>
                                                FillBytesFrom   &quot;output operand 0&#39;s worth of bytes from the address in operand 1&quot;<br>
                                                Fill8                           &quot;output a byte&#39;s worth of bytes with operand 0&quot;<br>
                                                Fill16                  &quot;output two byte&#39;s worth of bytes with operand 0&quot;<br>
                                                Fill32                  &quot;output four byte&#39;s worth of bytes with operand 0&quot;<br>
                                                FillFromWord    &quot;output BytesPerWord&#39;s worth of bytes with operand 0 + operand 1&quot;<br>
                                                Nop<br>
<br>
                                                &quot;Control&quot;<br>
                                                Call                                    &quot;call within the code zone&quot;<br>
                                                CallFull                                &quot;call anywhere within the full address space&quot;<br>
                                                RetN<br>
                                                JumpR                           &quot;Not a regular jump, i.e. not pc dependent.&quot;<br>
                                                Stop                            &quot;Halt the processor&quot;<br>
<br>
                                                &quot;N.B.  Jumps are contiguous.  Long and Full jumps are contigiuous within them.  See FirstJump et al below&quot;<br>
                                                JumpFull                        &quot;Jump anywhere within the address space&quot;<br>
                                                JumpLong                        &quot;Jump anywhere within the 16mb code zone.&quot;<br>
                                                JumpLongZero                    &quot;a.k.a. JumpLongEqual&quot;<br>
                                                JumpLongNonZero         &quot;a.k.a. JumpLongNotEqual&quot;<br>
                                                Jump                            &quot;short jumps; can be encoded in as few bytes as possible; will not be disturbed by GC or relocation.&quot;<br>
                                                JumpZero                                &quot;a.k.a. JumpEqual&quot;<br>
                                                JumpNonZero                     &quot;a.k.a. JumpNotEqual&quot;<br>
                                                JumpNegative<br>
                                                JumpNonNegative<br>
                                                JumpOverflow<br>
                                                JumpNoOverflow<br>
                                                JumpCarry<br>
                                                JumpNoCarry<br>
                                                JumpLess                        &quot;signed&quot;<br>
                                                JumpGreaterOrEqual<br>
                                                JumpGreater<br>
                                                JumpLessOrEqual<br>
                                                JumpBelow                       &quot;unsigned&quot;<br>
                                                JumpAboveOrEqual<br>
                                                JumpAbove<br>
                                                JumpBelowOrEqual<br>
<br>
                                                JumpFPEqual<br>
                                                JumpFPNotEqual<br>
                                                JumpFPLess<br>
                                                JumpFPLessOrEqual<br>
                                                JumpFPGreater<br>
                                                JumpFPGreaterOrEqual<br>
                                                JumpFPOrdered<br>
                                                JumpFPUnordered<br>
<br>
                                                &quot;Data Movement; destination is always last operand&quot;<br>
                                                MoveRR<br>
                                                MoveAwR<br>
                                                MoveRAw<br>
                                                MoveAbR<br>
                                                MoveRAb<br>
                                                MoveMwrR MoveRMwr MoveXwrRR MoveRXwrR MoveXowrR MoveRXowr<br>
                                                MoveM16rR MoveRM16r MoveX16rRR MoveRX16rR<br>
                                                MoveM32rR MoveRM32r MoveX32rRR MoveRX32rR<br>
                                                MoveMbrR MoveRMbr MoveXbrRR MoveRXbrR<br>
                                                MoveCqR MoveCwR MoveC32R MoveC64R<br>
                                                MoveRdRd MoveM64rRd MoveRdM64r<br>
                                                PopR PushR PushCq PushCw<br>
                                                PrefetchAw<br>
<br>
                                                &quot;Arithmetic; destination is always last operand except Cmp; CmpXR is SubRX with no update of result&quot;<br>
                                                LoadEffectiveAddressMwrR LoadEffectiveAddressXowrR &quot;Variants of add/multiply&quot;<br>
                                                NegateR &quot;2&#39;s complement negation&quot;<br>
                                                ArithmeticShiftRightCqR ArithmeticShiftRightRR<br>
                                                LogicalShiftRightCqR LogicalShiftRightRR<br>
                                                LogicalShiftLeftCqR LogicalShiftLeftRR<br>
<br>
                                                CmpRR AddRR SubRR AndRR OrRR XorRR<br>
                                                CmpCqR AddCqR SubCqR AndCqR OrCqR TstCqR XorCqR<br>
                                                CmpCwR CmpC32R AddCwR SubCwR AndCwR OrCwR XorCwR<br>
<br>
+                                               AddCheckOverflowCqR AddCheckOverflowRR SubCheckOverflowCqR SubCheckOverflowRR MulCheckOverflowRR<br>
+<br>
                                                AndCqRR<br>
<br>
                                                CmpRdRd AddRdRd SubRdRd MulRdRd DivRdRd SqrtRd<br>
<br>
                                                &quot;Conversion&quot;<br>
                                                ConvertRRd<br>
<br>
                                                LastRTLCode).<br>
<br>
        &quot;Magic auto declaration. Add to the classPool any new variables and nuke any obsolete ones, and assign values&quot;<br>
        &quot;Find the variables directly referenced by this method&quot;<br>
        refs := (thisContext method literals select: [:l| l isVariableBinding and: [classPool includesKey: l key]]) collect:<br>
                                [:ea| ea key].<br>
        &quot;Move to Undeclared any opcodes in classPool not in opcodes or this method.&quot;<br>
        (classPool keys reject: [:k| (opcodeNames includes: k) or: [refs includes: k]]) do:<br>
                [:k|<br>
                Undeclared declare: k from: classPool].<br>
        &quot;Declare as class variables and number elements of opcodeArray above&quot;<br>
        opcodeNames withIndexDo:<br>
                [:classVarName :value|<br>
                self classPool<br>
                        declare: classVarName from: Undeclared;<br>
                        at: classVarName put: value].<br>
<br>
        &quot;For CogAbstractInstruction&gt;&gt;isJump etc...&quot;<br>
        FirstJump := JumpFull.<br>
        LastJump := JumpFPUnordered.<br>
        FirstShortJump := Jump.<br>
<br>
        &quot;And now initialize the backends; they add their own opcodes and hence these must be reinitialized.&quot;<br>
        (Smalltalk classNamed: #CogAbstractInstruction) ifNotNil:<br>
                [:cogAbstractInstruction| cogAbstractInstruction allSubclasses do: [:sc| sc initialize]]!<br>
<br>
Item was added:<br>
+ ----- Method: CogX64Compiler&gt;&gt;hasConditionRegister (in category &#39;testing&#39;) -----<br>
+ hasConditionRegister<br>
+       &quot;Answer if the receiver supports, e.g., JumpOverflow after a regular AddRR&quot;<br>
+       &lt;inline: true&gt;<br>
+       ^true!<br>
<br>
Item was added:<br>
+ ----- Method: Cogit&gt;&gt;AddCheckOverflowCq:R: (in category &#39;abstract instructions&#39;) -----<br>
+ AddCheckOverflowCq: quickConstant R: reg<br>
+       &lt;inline: true&gt;<br>
+       &lt;returnTypeC: #&#39;AbstractInstruction *&#39;&gt;<br>
+       backEnd hasConditionRegister ifTrue:<br>
+               [^self AddCq: quickConstant R: reg].<br>
+       ^self gen: AddCheckOverflowCqR quickConstant: quickConstant operand: reg!<br>
<br>
Item was added:<br>
+ ----- Method: Cogit&gt;&gt;AddCheckOverflowR:R: (in category &#39;abstract instructions&#39;) -----<br>
+ AddCheckOverflowR: reg1 R: reg2<br>
+       &lt;inline: true&gt;<br>
+       &lt;returnTypeC: #&#39;AbstractInstruction *&#39;&gt;<br>
+       backEnd hasConditionRegister ifTrue:<br>
+               [^self AddR: reg1 R: reg2].<br>
+       ^self gen: AddCheckOverflowRR operand: reg1 operand: reg2!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;MoveR:R: (in category &#39;abstract instructions&#39;) -----<br>
  MoveR: reg1 R: reg2<br>
        &lt;inline: true&gt;<br>
        &lt;returnTypeC: #&#39;AbstractInstruction *&#39;&gt;<br>
        ^self gen: MoveRR operand: reg1 operand: reg2!<br>
<br>
Item was added:<br>
+ ----- Method: Cogit&gt;&gt;MulCheckOverflowR:R: (in category &#39;abstract instructions&#39;) -----<br>
+ MulCheckOverflowR: reg1 R: reg2<br>
+       &quot;Multiplication is a little weird on some processors.  Defer to the backEnd<br>
+        to allow it to generate any special code it may need to.&quot;<br>
+       &lt;returnTypeC: #&#39;AbstractInstruction *&#39;&gt;<br>
+       &lt;inline: false&gt;<br>
+       backEnd hasConditionRegister ifTrue:<br>
+               [^self MulR: reg1 R: reg2].<br>
+       backEnd genCheckOverflowMulR: reg1 R: reg2.<br>
+       ^self abstractInstructionAt: opcodeIndex - 1!<br>
<br>
Item was added:<br>
+ ----- Method: Cogit&gt;&gt;SubCheckOverflowCq:R: (in category &#39;abstract instructions&#39;) -----<br>
+ SubCheckOverflowCq: quickConstant R: reg<br>
+       &lt;inline: true&gt;<br>
+       &lt;returnTypeC: #&#39;AbstractInstruction *&#39;&gt;<br>
+       backEnd hasConditionRegister ifTrue:<br>
+               [^self SubCq: quickConstant R: reg].<br>
+       ^self gen: SubCheckOverflowCqR quickConstant: quickConstant operand: reg!<br>
<br>
Item was added:<br>
+ ----- Method: Cogit&gt;&gt;SubCheckOverflowR:R: (in category &#39;abstract instructions&#39;) -----<br>
+ SubCheckOverflowR: reg1 R: reg2<br>
+       &lt;inline: true&gt;<br>
+       &lt;returnTypeC: #&#39;AbstractInstruction *&#39;&gt;<br>
+       backEnd hasConditionRegister ifTrue:<br>
+               [^self SubR: reg1 R: reg2].<br>
+       ^self gen: SubCheckOverflowRR operand: reg1 operand: reg2!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;configureCPIC:Case0:Case1Method:tag:isMNUCase:numArgs:delta: (in category &#39;in-line cacheing&#39;) -----<br>
  configureCPIC: cPIC Case0: case0CogMethod Case1Method: case1Method tag: case1Tag isMNUCase: isMNUCase numArgs: numArgs delta: addrDelta<br>
        &quot;Configure a copy of the prototype CPIC for a two-case PIC for<br>
        case0CogMethod and<br>
        case1Method<br>
        case1Tag.<br>
         The tag for case0CogMethod is at the send site and so doesn&#39;t need to be generated.<br>
         case1Method may be any of<br>
                - a Cog method; jump to its unchecked entry-point<br>
                - a CompiledMethod; jump to the ceInterpretFromPIC trampoline<br>
                - nil; call ceMNUFromPIC<br>
        addDelta is the address change from the prototype to the new CPCI location, needed<br>
        because the loading of the CPIC lable at the end may use a literal instead of a pc relative&quot;<br>
        &lt;var: #cPIC type: #&#39;CogMethod *&#39;&gt;<br>
        &lt;var: #case0CogMethod type: #&#39;CogMethod *&#39;&gt;<br>
        | operand targetEntry caseEndAddress|<br>
        &lt;var: #targetEntry type: #&#39;void *&#39;&gt;<br>
        self assert: case1Method notNil.<br>
<br>
+       &quot;adjust the call at missOffset, the ceAbortXArgs&quot;<br>
+       backEnd rewriteCallAt: cPIC asInteger + missOffset target: (self picAbortTrampolineFor: numArgs).<br>
-       &quot;adjust the jump at missOffset, the ceAbortXArgs&quot;<br>
-       backEnd rewriteJumpLongAt: cPIC asInteger + missOffset target: (self picAbortTrampolineFor: numArgs).<br>
<br>
        self assert: (objectRepresentation inlineCacheTagIsYoung: case1Tag) not.<br>
        (isMNUCase not<br>
         and: [coInterpreter methodHasCogMethod: case1Method])<br>
                ifTrue:<br>
                        [operand := 0.<br>
                         targetEntry := ((coInterpreter cogMethodOf: case1Method) asInteger + cmNoCheckEntryOffset) asVoidPointer]<br>
                ifFalse: &quot;We do not scavenge PICs, hence we cannot cache the MNU method if it is in new space.&quot;<br>
                        [operand := (case1Method isNil or: [objectMemory isYoungObject: case1Method])<br>
                                                        ifTrue: [0]<br>
                                                        ifFalse: [case1Method].<br>
                         targetEntry := case1Method isNil ifTrue: [cPIC asInteger + (self sizeof: CogMethod)] ifFalse: [cPIC asInteger + self picInterpretAbortOffset]].<br>
<br>
        &quot;set the jump to the case0 method&quot;<br>
        backEnd rewriteJumpLongAt: cPIC asInteger + firstCPICCaseOffset target: case0CogMethod asInteger + cmNoCheckEntryOffset.<br>
<br>
        caseEndAddress := self addressOfEndOfCase: 2 inCPIC: cPIC.<br>
<br>
        &quot;update the cpic case - deferred to backend because messy&quot;<br>
        backEnd rewriteCPICCaseAt: caseEndAddress tag: case1Tag objRef: operand target: (isMNUCase ifTrue: [cPIC asInteger + (self sizeof: CogMethod)] ifFalse: [targetEntry]) asInteger.<br>
<br>
        &quot;update the loading of the PCIC label address&quot;<br>
        backEnd relocateMethodReferenceBeforeAddress: cPIC asInteger + cPICEndOfCodeOffset - backEnd jumpLongByteSize by: addrDelta.<br>
<br>
        &quot;write the final desperate jump to cePICMissXArgs&quot;<br>
        backEnd rewriteJumpLongAt: cPIC asInteger + cPICEndOfCodeOffset target: (self cPICMissTrampolineFor: numArgs).<br>
        ^0<br>
        &quot;self disassembleFrom: cPIC + (self sizeof: CogMethod) to: cPIC + closedPICSize - 1.&quot;!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit&gt;&gt;genPrimitiveAdd (in category &#39;primitive generators&#39;) -----<br>
  genPrimitiveAdd<br>
        &quot;Stack looks like<br>
                receiver (also in ResultReceiverReg)<br>
                arg<br>
                return address&quot;<br>
        | jumpNotSI jumpOvfl |<br>
        &lt;var: #jumpNotSI type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #jumpOvfl type: #&#39;AbstractInstruction *&#39;&gt;<br>
        self genLoadArgAtDepth: 0 into: TempReg.<br>
        self MoveR: TempReg R: ClassReg.<br>
        jumpNotSI := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.<br>
        objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ClassReg.<br>
        self MoveR: ReceiverResultReg R: TempReg.<br>
+       self AddCheckOverflowR: ClassReg R: TempReg.<br>
-       self AddR: ClassReg R: TempReg.<br>
        jumpOvfl := self JumpOverflow: 0.<br>
        self MoveR: TempReg R: ReceiverResultReg.<br>
        self RetN: (self primRetNOffsetFor: 1).<br>
        jumpOvfl jmpTarget: (jumpNotSI jmpTarget: self Label).<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit&gt;&gt;genPrimitiveMultiply (in category &#39;primitive generators&#39;) -----<br>
  genPrimitiveMultiply<br>
        | jumpNotSI jumpOvfl |<br>
        &lt;var: #jumpNotSI type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #jumpOvfl type: #&#39;AbstractInstruction *&#39;&gt;<br>
        self genLoadArgAtDepth: 0 into: TempReg.<br>
        self MoveR: TempReg R: ClassReg.<br>
        jumpNotSI := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.<br>
        objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: ClassReg.<br>
        self MoveR: ReceiverResultReg R: TempReg.<br>
        objectRepresentation genRemoveSmallIntegerTagsInScratchReg: TempReg.<br>
+       self MulCheckOverflowR: TempReg R: ClassReg.<br>
-       self MulR: TempReg R: ClassReg.<br>
        jumpOvfl := self JumpOverflow: 0.<br>
        objectRepresentation genSetSmallIntegerTagsIn: ClassReg.<br>
        self MoveR: ClassReg R: ReceiverResultReg.<br>
        self RetN: (self primRetNOffsetFor: 1).<br>
        jumpOvfl jmpTarget: (jumpNotSI jmpTarget: self Label).<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit&gt;&gt;genPrimitiveSubtract (in category &#39;primitive generators&#39;) -----<br>
  genPrimitiveSubtract<br>
        &quot;Stack looks like<br>
                receiver (also in ResultReceiverReg)<br>
                arg<br>
                return address&quot;<br>
        | jumpNotSI jumpOvfl |<br>
        &lt;var: #jumpNotSI type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #jumpOvfl type: #&#39;AbstractInstruction *&#39;&gt;<br>
        self genLoadArgAtDepth: 0 into: TempReg.<br>
        self MoveR: TempReg R: ClassReg.<br>
        jumpNotSI := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.<br>
        self MoveR: ReceiverResultReg R: TempReg.<br>
+       self SubCheckOverflowR: ClassReg R: TempReg.<br>
-       self SubR: ClassReg R: TempReg.<br>
        jumpOvfl := self JumpOverflow: 0.<br>
        objectRepresentation genAddSmallIntegerTagsTo: TempReg.<br>
        self MoveR: TempReg R: ReceiverResultReg.<br>
        self RetN: (self primRetNOffsetFor: 1).<br>
        jumpOvfl jmpTarget: (jumpNotSI jmpTarget: self Label).<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit&gt;&gt;genPrimitiveAdd (in category &#39;primitive generators&#39;) -----<br>
  genPrimitiveAdd<br>
        | jumpNotSI jumpOvfl |<br>
        &lt;var: #jumpNotSI type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #jumpOvfl type: #&#39;AbstractInstruction *&#39;&gt;<br>
        self MoveR: Arg0Reg R: ClassReg.<br>
        jumpNotSI := objectRepresentation genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.<br>
        objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ClassReg.<br>
+       self AddCheckOverflowR: ReceiverResultReg R: ClassReg.<br>
-       self AddR: ReceiverResultReg R: ClassReg.<br>
        jumpOvfl := self JumpOverflow: 0.<br>
        self MoveR: ClassReg R: ReceiverResultReg.<br>
        self RetN: 0.<br>
        jumpOvfl jmpTarget: (jumpNotSI jmpTarget: self Label).<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit&gt;&gt;genPrimitiveMultiply (in category &#39;primitive generators&#39;) -----<br>
  genPrimitiveMultiply<br>
        | jumpNotSI jumpOvfl |<br>
        &lt;var: #jumpNotSI type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #jumpOvfl type: #&#39;AbstractInstruction *&#39;&gt;<br>
        self MoveR: Arg0Reg R: ClassReg.<br>
        self MoveR: ReceiverResultReg R: Arg1Reg.<br>
        jumpNotSI := objectRepresentation genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg..<br>
        objectRepresentation genShiftAwaySmallIntegerTagsInScratchReg: ClassReg.<br>
        objectRepresentation genRemoveSmallIntegerTagsInScratchReg: Arg1Reg.<br>
+       self MulCheckOverflowR: Arg1Reg R: ClassReg.<br>
-       self MulR: Arg1Reg R: ClassReg.<br>
        jumpOvfl := self JumpOverflow: 0.<br>
        objectRepresentation genSetSmallIntegerTagsIn: ClassReg.<br>
        self MoveR: ClassReg R: ReceiverResultReg.<br>
        self RetN: 0.<br>
        jumpOvfl jmpTarget: (jumpNotSI jmpTarget: self Label).<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit&gt;&gt;genPrimitiveSubtract (in category &#39;primitive generators&#39;) -----<br>
  genPrimitiveSubtract<br>
        | jumpNotSI jumpOvfl |<br>
        &lt;var: #jumpNotSI type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #jumpOvfl type: #&#39;AbstractInstruction *&#39;&gt;<br>
        jumpNotSI := objectRepresentation genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.<br>
        self MoveR: ReceiverResultReg R: TempReg.<br>
+       self SubCheckOverflowR: Arg0Reg R: TempReg.<br>
-       self SubR: Arg0Reg R: TempReg.<br>
        jumpOvfl := self JumpOverflow: 0.<br>
        objectRepresentation genAddSmallIntegerTagsTo: TempReg.<br>
        self MoveR: TempReg R: ReceiverResultReg.<br>
        self RetN: 0.<br>
        jumpOvfl jmpTarget: (jumpNotSI jmpTarget: self Label).<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit&gt;&gt;genSpecialSelectorArithmetic (in category &#39;bytecode generators&#39;) -----<br>
  genSpecialSelectorArithmetic<br>
        | primDescriptor rcvrIsConst argIsConst rcvrIsInt argIsInt rcvrInt argInt result<br>
         jumpNotSmallInts jumpContinue annotateInst instToAnnotate index |<br>
        &lt;var: #primDescriptor type: #&#39;BytecodeDescriptor *&#39;&gt;<br>
        &lt;var: #jumpNotSmallInts type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #jumpContinue type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #instToAnnotate type: #&#39;AbstractInstruction *&#39;&gt;<br>
        primDescriptor := self generatorAt: byte0.<br>
        argIsInt := (argIsConst := self ssTop type = SSConstant)<br>
                                 and: [objectMemory isIntegerObject: (argInt := self ssTop constant)].<br>
        rcvrIsInt := (rcvrIsConst := (self ssValue: 1) type = SSConstant)<br>
                                 and: [objectMemory isIntegerObject: (rcvrInt := (self ssValue: 1) constant)].<br>
<br>
        (argIsInt and: [rcvrIsInt]) ifTrue:<br>
                [rcvrInt := objectMemory integerValueOf: rcvrInt.<br>
                 argInt := objectMemory integerValueOf: argInt.<br>
                 primDescriptor opcode caseOf: {<br>
                        [AddRR] -&gt; [result := rcvrInt + argInt].<br>
                        [SubRR] -&gt; [result := rcvrInt - argInt].<br>
                        [AndRR] -&gt; [result := rcvrInt bitAnd: argInt].<br>
                        [OrRR]  -&gt; [result := rcvrInt bitOr: argInt] }.<br>
                (objectMemory isIntegerValue: result) ifTrue:<br>
                        [&quot;Must enter any annotatedConstants into the map&quot;<br>
                         self annotateBytecodeIfAnnotated: (self ssValue: 1).<br>
                         self annotateBytecodeIfAnnotated: self ssTop.<br>
                         &quot;Must annotate the bytecode for correct pc mapping.&quot;<br>
                        ^self ssPop: 2; ssPushAnnotatedConstant: (objectMemory integerObjectOf: result)].<br>
                ^self genSpecialSelectorSend].<br>
<br>
        &quot;If there&#39;s any constant involved other than a SmallInteger don&#39;t attempt to inline.&quot;<br>
        ((rcvrIsConst and: [rcvrIsInt not])<br>
         or: [argIsConst and: [argIsInt not]]) ifTrue:<br>
                [^self genSpecialSelectorSend].<br>
<br>
        &quot;If we know nothing about the types then better not to inline as the inline cache and<br>
         primitive code is not terribly slow so wasting time on duplicating tag tests is pointless.&quot;<br>
        (argIsInt or: [rcvrIsInt]) ifFalse:<br>
                [^self genSpecialSelectorSend].<br>
<br>
        argIsInt<br>
                ifTrue:<br>
                        [self ssFlushTo: simStackPtr - 2.<br>
                         (self ssValue: 1) popToReg: ReceiverResultReg.<br>
                         annotateInst := self ssTop annotateUse.<br>
                         self ssPop: 2.<br>
                         self MoveR: ReceiverResultReg R: TempReg]<br>
                ifFalse:<br>
                        [self marshallSendArguments: 1.<br>
                         self MoveR: Arg0Reg R: TempReg.<br>
                         rcvrIsInt ifFalse:<br>
                                [objectRepresentation isSmallIntegerTagNonZero<br>
                                        ifTrue: [self AndR: ReceiverResultReg R: TempReg]<br>
                                        ifFalse: [self OrR: ReceiverResultReg R: TempReg]]].<br>
        jumpNotSmallInts := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.<br>
        primDescriptor opcode caseOf: {<br>
                [AddRR] -&gt; [argIsInt<br>
                                                ifTrue:<br>
+                                                       [instToAnnotate := self AddCheckOverflowCq: argInt - ConstZero R: ReceiverResultReg.<br>
-                                                       [instToAnnotate := self AddCq: argInt - ConstZero R: ReceiverResultReg.<br>
                                                         jumpContinue := self JumpNoOverflow: 0.<br>
                                                         &quot;overflow; must undo the damage before continuing&quot;<br>
                                                         self SubCq: argInt - ConstZero R: ReceiverResultReg]<br>
                                                ifFalse:<br>
                                                        [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: ReceiverResultReg.<br>
+                                                        self AddCheckOverflowR: Arg0Reg R: ReceiverResultReg.<br>
-                                                        self AddR: Arg0Reg R: ReceiverResultReg.<br>
                                                        jumpContinue := self JumpNoOverflow: 0.<br>
                                                        &quot;overflow; must undo the damage before continuing&quot;<br>
                                                         rcvrIsInt<br>
                                                                ifTrue: [self MoveCq: rcvrInt R: ReceiverResultReg]<br>
                                                                ifFalse:<br>
                                                                        [self SubR: Arg0Reg R: ReceiverResultReg.<br>
                                                                         objectRepresentation genSetSmallIntegerTagsIn: ReceiverResultReg]]].<br>
                [SubRR] -&gt; [argIsInt<br>
                                                ifTrue:<br>
+                                                       [instToAnnotate := self SubCheckOverflowCq: argInt - ConstZero R: ReceiverResultReg.<br>
-                                                       [instToAnnotate := self SubCq: argInt - ConstZero R: ReceiverResultReg.<br>
                                                         jumpContinue := self JumpNoOverflow: 0.<br>
                                                         &quot;overflow; must undo the damage before continuing&quot;<br>
                                                         self AddCq: argInt - ConstZero R: ReceiverResultReg]<br>
                                                ifFalse:<br>
                                                        [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: Arg0Reg.<br>
+                                                        self SubCheckOverflowR: Arg0Reg R: ReceiverResultReg.<br>
-                                                        self SubR: Arg0Reg R: ReceiverResultReg.<br>
                                                         jumpContinue := self JumpNoOverflow: 0.<br>
                                                         &quot;overflow; must undo the damage before continuing&quot;<br>
                                                         self AddR: Arg0Reg R: ReceiverResultReg.<br>
                                                         objectRepresentation genSetSmallIntegerTagsIn: Arg0Reg]].<br>
                [AndRR] -&gt; [argIsInt<br>
                                                ifTrue: [instToAnnotate := self AndCq: argInt R: ReceiverResultReg]<br>
                                                ifFalse: [self AndR: Arg0Reg R: ReceiverResultReg].<br>
                                        jumpContinue := self Jump: 0].<br>
                [OrRR]  -&gt; [argIsInt<br>
                                                ifTrue: [instToAnnotate := self OrCq: argInt R: ReceiverResultReg]<br>
                                                ifFalse: [self OrR: Arg0Reg R: ReceiverResultReg].<br>
                                        jumpContinue := self Jump: 0] }.<br>
        jumpNotSmallInts jmpTarget: self Label.<br>
        argIsInt ifTrue:<br>
                [annotateInst ifTrue: [self annotateBytecode: instToAnnotate].<br>
                 self MoveCq: argInt R: Arg0Reg].<br>
        index := byte0 - self firstSpecialSelectorBytecodeOffset.<br>
        self genMarshalledSend: index negated - 1 numArgs: 1 sendTable: ordinarySendTrampolines.<br>
        jumpContinue jmpTarget: self Label.<br>
        ^0!<br>
<br><span class=""><font color="#888888">
</font></span></blockquote></div><span class=""><font color="#888888"><br><br clear="all"><div><br></div>-- <br><div><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</font></span></div>
</blockquote></div><br></div></div>