1 //  Primitives to manipulate registers and addresses.
  2 //  Last modified on 06/06/74 at 18:22:13 by R F Mabee.
  3 //  Revised for 6180 and installed with Version 3.4 of the compiler, R F Mabee.
  4 //  First installed with Version 2.7 by R F Mabee.
  5 
  6 //  Copyright (c) 1974 by Massachusetts Institute of Technology and Honeywell Information Systems, Inc.
  7 
  8 //  General permission is granted to copy and use this program, but not to sell it, provided that the above
  9 //  copyright statement is given.  Contact Information Processing Services, MIT, for further information.
 10 //  Please contact R F Mabee at MIT for information on this program and versions for other machines.
 11 
 12 get "bcpl_cg_head"
 13 get "bcpl_opcodes"
 14 
 15 //  LoadRegister moves a CG operand into an arithmetic register.
 16 
 17 let LoadRegister (t, r) = valof
 18      $(   let q = FindInRegister (t, r)
 19           if q ne 0 resultis Preserve (q)
 20           if r = Ar | r = Qr then if FindInRegister (t, Qr + Ar - r) ne 0 do
 21                $(   SwapAandQ ()
 22                     resultis Preserve (r)
 23                $)
 24           if IsNumber (t) resultis LoadNumber (EvalNumber (t!0, t!1), r, t!2)
 25           r := GetRegister (r)
 26           Makeaddressable (t)
 27           Outop (r = EAQr -> Fld, FormOpcode (Lda, r))
 28           IndicatorsSetBy := r
 29           resultis Preserve (r)
 30      $)
 31 and LoadNumber (n, r, c) = valof
 32      $(   r := GetRegister (r)
 33           let Op = Lda
 34           test r = EAQr
 35           then Op := Fld
 36           or if n < 0 then unless n = (1 lshift 35) do Op, n := Lca, - n        //  Can't complement most negative number.
 37           Literal (n, c)
 38           Outop (FormOpcode (Op, r))
 39           IndicatorsSetBy := r
 40           resultis Preserve (r)
 41      $)
 42 and SwapAandQ () be
 43      $(   Outop4 (Llr, 36, 0, "exchange A and Q")
 44           IndicatorsSetBy := 0
 45           let p, q = RegisterTemps!Ar, RegisterTemps!Qr
 46           RegisterTemps!Ar, RegisterTemps!Qr := q, p
 47           if p ne 0 do p!2 := Qr
 48           if q ne 0 do q!2 := Ar
 49      $)
 50 and LoadPointer (t, r) = valof
 51      $(   let q = FindInRegister (t, r)
 52           if q ne 0 resultis Preserve (q)
 53           r := GetRegister (r)
 54           test IsAddress (t)
 55           then $(   SetupAddr (t)
 56                     Outop (FormOpcode (Eapap, r))
 57                $)
 58           or   $(   Makeaddressable (t)
 59                     Outop (FormOpcode (Lprpap, r))
 60                $)
 61           resultis Preserve (r)
 62      $)
 63 and LoadIndex (t, r) = valof
 64      $(   let q = FindInRegister (t, r)
 65           if q = 0 & r = AnyXr do q := FindInRegister (t, AorQr)      //  A and Q can be used as index registers.
 66           if q ne 0 resultis Preserve (q)
 67           r := GetRegister (r)
 68           test IsAddress (t)
 69           then $(   SetupAddr (t)
 70                     Outop (FormOpcode (Eax0, r))
 71                $)
 72           or   $(   Makeaddressable (t)
 73                     Outop (FormOpcode (Lxl0, r))
 74                $)
 75           IndicatorsSetBy := r
 76           resultis Preserve (r)
 77      $)
 78 and LoadAppropriateRegister (t, r) = valof
 79      $(   if r = 0 do
 80                $(   r := FindInRegister (t, AorQr)
 81                     if r = 0 do r := FindInRegister (t, AnyPr)
 82                     if r = 0 do r := FindInRegister (t, EAQr)
 83                     if r ne 0 resultis Preserve (r)
 84                     r := IsAddress (t) -> AnyPr, AorQr
 85                $)
 86           if r = AorQr | Satisfactory (r, AorQr) | r = EAQr resultis LoadRegister (t, r)
 87           if r = AnyPr | Satisfactory (r, AnyPr) resultis LoadPointer (t, r)
 88           CGreport (UnexpectedCase, r, "LoadAppropriateRegister")
 89           resultis Ar
 90      $)
 91 
 92 and Makeaddressable (t) be
 93      $(   test IsNumber (t)
 94           then Literal (EvalNumber (t!0, t!1), t!2)
 95           or test IsStored (t)
 96           then SetATP (t)
 97           or   $(   let u = list LV_GLOBAL, 0, 0            //  Temporary cell.
 98                     Store (t, u)
 99                     Address, Tag, Param := 0, Sp, 0
100                $)
101           unless t!2 = 0 do Comment := t!2
102      $)
103 and SetupAddr (t) be
104      $(   test IsAddress (t)
105           then SetATP (t)
106           or   $(   let r = LoadPointer (t, AnyPr)
107                     Address, Tag, Param := 0, FormTag (r), 0
108                $)
109           unless t!2 = 0 do Comment := t!2
110      $)
111 and SetATP (t) be
112      $(   Address, Tag, Param := 0, 0, 0
113           switchon t!0 into
114                $(   case GLOBAL_S: case LV_GLOBAL:
115                               Address, Tag := t!1, Sp
116                               endcase
117                     case TEMP_S:
118                               let h = LookupTemp (t!1)
119                               if h ne 0 then if h!1 = VECAP_S | h!1 = LVECAP_S do
120                                    $(   CombineAddress (lv h!2, lv h!5, h!8)
121                                         endcase
122                                    $)
123                     case LOCAL_S: case LV_LOCAL:
124                     case LV_TEMP:
125                               Address, Tag := t!1 + SaveSpaceSize, StackRefTag
126                               endcase
127                     case LV_ARG_OUT:
128                               Address, Tag, Param := t!1 + SaveSpaceSize, StackRefTag, LabMaxSSP
129                               endcase
130                     case STATIC_S: case LV_STATIC:
131                               Address, Tag := t!1 + 8, Lp
132                               endcase
133                     case EXTERNAL_S:
134                               Tag, Param := Lp | Star, Compexternal (t!1)
135                               endcase
136                     case LABEL_S: case RTDEF_S:
137                               Param := t!1
138                               endcase
139                     case STRINGCONST_S:
140                               Compstring (t!1)
141                               endcase
142                     case TABLE_S:
143                               Comptable (t!1)
144                               endcase
145                     default:  CGreport (UnexpectedCase, t!0, "SetATP")
146                $)
147           CheckAddr ()
148      $)
149 and CompareToZero (t) be
150      $(   let r = FindInRegister (t, AorQr)
151           test r ne 0
152           then unless r = IndicatorsSetBy do
153                $(   Outop3 (FormOpcode (Cmpa, r), 0, Dl)
154                     IndicatorsSetBy := r
155                $)
156           or   $(   Makeaddressable (t)
157                     Outop (Szn)
158                     IndicatorsSetBy := 0
159                $)
160      $)
161 
162 and StoreRegister (r, To) be
163      $(   let Op = valof switchon r into
164                $(   case Ar: case Qr:
165                     default:
166                               resultis Sta
167                     case Apr: case Abr: case Bpr: case Bbr: case Lbr:
168                               resultis Sprpap
169                     case EAQr:
170                               resultis Fstr
171                $)
172           SetupAddr (To)
173           test Machine = 645 & Op = Sprpap
174           then $(   let A, T, P = Address, Tag, Param
175                     Outop (FormOpcode (Sprpap, r + 1))
176                     Outop3 (Eax0, 0, FormTag (r))
177                     Address, Tag, Param := A, T, P
178                     Outop (Sxl0)
179                $)
180           or Outop (FormOpcode (Op, r))
181           RegisterUsage!r := 0                    //  Indicate register not needed for anything.
182      $)
183 and Store (From, To) be
184           test IsZero (From)
185           then $(   SetupAddr (To)
186                     Outop (Stz)
187                $)
188           or   $(   let r = LoadAppropriateRegister (From, 0)
189                     StoreRegister (r, To)
190                $)
191 
192 and Preserve (r) = valof
193      $(   UsageCounter := UsageCounter + 1
194           RegisterUsage!r := UsageCounter
195           resultis r
196      $)
197 and GetRegister (r) = valof
198      $(   switchon r into
199                $(   default:  CGreport (UnexpectedCase, r, "GetRegister")
200                               r := Ar
201 
202                     case Ar: case Qr:
203                               MakeAvailable (EAQr)                    //  EAQr overlaps both Ar and Qr.
204                               endcase
205 
206                     case EAQr:
207                               MakeAvailable (Ar)
208                               MakeAvailable (Qr)
209                               endcase
210 
211                     case Xr2: case Xr3: case Xr4: case Xr5: case Xr6:
212                     case Apr: case Abr: case Bpr: case Bbr: case Lbr:
213                               endcase
214 
215                     case AorQr:
216                               r := RegisterUsage!Ar < RegisterUsage!Qr -> Ar, Qr
217                               MakeAvailable (EAQr)
218                               endcase
219 
220                     case AnyPr:
221                               r := RegisterUsage!Bpr < RegisterUsage!Apr -> Bpr, Apr
222                               if Machine = 6180 do
223                                    $(   let T = table Abr, Bbr, Lbr
224                                         for i = 0 to 2 if RegisterUsage!(T!i) < RegisterUsage!r do r := T!i
225                                    $)
226                               endcase
227 
228                     case AnyXr:
229                               r := Xr2
230                               let T = table Xr3, Xr4, Xr5, Xr6
231                               for i = 0 to 3 if RegisterUsage!(T!i) < RegisterUsage!r do r := T!i
232                               endcase
233                $)
234           MakeAvailable (r)
235           resultis r
236      $)
237 and Satisfactory (r, q) = valof
238      $(   switchon q into
239                $(   case AnyXr:
240                               if r = Xr2 | r = Xr3 | r = Xr4 | r = Xr5 | r = Xr6 resultis true
241                               resultis false
242                     case AorQr:
243                               if r = Ar | r = Qr resultis true
244                               resultis false
245                     case AnyPr:
246                               if r = Apr | r = Abr | r = Bpr | r = Bbr | r = Lbr resultis true
247                               resultis false
248                     default:  resultis r = q
249                $)
250      $)
251 and MakeAvailable (r) be
252      $(   let h = RegisterTemps!r
253           if h = 0 return
254           let To = list LV_TEMP, h!0, "temporary"
255           StoreRegister (r, To)
256           RegisterTemps!r, RegisterUsage!r := 0, 0
257           h!0 := -1
258      $)
259 
260 and Literal (n, c) be
261      $(   Address, Tag, Param, Comment := n & $8777777, Dl, 0, c
262           if Address = n return
263           test Address = 0
264           then Address, Tag := n rshift 18, Du
265           or AddLiteral (lv n, 1, c, 0)
266      $)