Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

alpha.md (36095B)


      1 %{
      2 #define INTTMP ((0xff<<1)|(1<<22)|(1<<25)|(1<<27))
      3 #define INTVAR (0x3f<<9)
      4 #define FLTTMP ((0x3f<<10)|(0x1ff<<22))
      5 #define FLTVAR (0xff<<2)
      6 
      7 #define INTRET 0x00000001
      8 #define FLTRET 0x00000003
      9 
     10 #define readsreg(p) \
     11         (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
     12 #define setsrc(d) ((d) && (d)->x.regnode && \
     13         (d)->x.regnode->set == src->x.regnode->set && \
     14         (d)->x.regnode->mask&src->x.regnode->mask)
     15 
     16 #define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
     17 
     18 #include "c.h"
     19 #define NODEPTR_TYPE Node
     20 #define OP_LABEL(p) ((p)->op)
     21 #define LEFT_CHILD(p) ((p)->kids[0])
     22 #define RIGHT_CHILD(p) ((p)->kids[1])
     23 #define STATE_LABEL(p) ((p)->x.state)
     24 static void address(Symbol, Symbol, long);
     25 static void blkfetch(int, int, int, int);
     26 static void blkloop(int, int, int, int, int, int[]);
     27 static void blkstore(int, int, int, int);
     28 static void defaddress(Symbol);
     29 static void defconst(int, int, Value);
     30 static void defstring(int, char *);
     31 static void defsymbol(Symbol);
     32 static void doarg(Node);
     33 static void emit2(Node);
     34 static void export(Symbol);
     35 static void clobber(Node);
     36 static void function(Symbol, Symbol [], Symbol [], int);
     37 static void global(Symbol);
     38 static void import(Symbol);
     39 static void local(Symbol);
     40 static void progbeg(int, char **);
     41 static void progend(void);
     42 static void segment(int);
     43 static void space(int);
     44 static void target(Node);
     45 static Symbol ireg[32], freg[32];
     46 static Symbol iregw, fregw;
     47 
     48 static int tmpregs[] = {4, 2, 3};
     49 static Symbol blkreg;
     50 
     51 static int cseg;
     52 
     53 static char *currentfile;
     54 
     55 %}
     56 %start stmt
     57 %term CNSTF4=4113
     58 %term CNSTF8=8209
     59 %term CNSTF16=16401
     60 %term CNSTI1=1045
     61 %term CNSTI2=2069
     62 %term CNSTI4=4117
     63 %term CNSTI8=8213
     64 %term CNSTP4=4119
     65 %term CNSTP8=8215
     66 %term CNSTU1=1046
     67 %term CNSTU2=2070
     68 %term CNSTU4=4118
     69 %term CNSTU8=8214
     70  
     71 %term ARGB=41
     72 %term ARGF4=4129
     73 %term ARGF8=8225
     74 %term ARGF16=16417
     75 %term ARGI4=4133
     76 %term ARGI8=8229
     77 %term ARGP4=4135
     78 %term ARGP8=8231
     79 %term ARGU4=4134
     80 %term ARGU8=8230
     81 
     82 %term ASGNB=57
     83 %term ASGNF4=4145
     84 %term ASGNF8=8241
     85 %term ASGNF16=16433
     86 %term ASGNI1=1077
     87 %term ASGNI2=2101
     88 %term ASGNI4=4149
     89 %term ASGNI8=8245
     90 %term ASGNP4=4151
     91 %term ASGNP8=8247
     92 %term ASGNU1=1078
     93 %term ASGNU2=2102
     94 %term ASGNU4=4150
     95 %term ASGNU8=8246
     96 
     97 %term INDIRB=73
     98 %term INDIRF4=4161
     99 %term INDIRF8=8257
    100 %term INDIRF16=16449
    101 %term INDIRI1=1093
    102 %term INDIRI2=2117
    103 %term INDIRI4=4165
    104 %term INDIRI8=8261
    105 %term INDIRP4=4167
    106 %term INDIRP8=8263
    107 %term INDIRU1=1094
    108 %term INDIRU2=2118
    109 %term INDIRU4=4166
    110 %term INDIRU8=8262
    111 
    112 %term CVFF4=4209
    113 %term CVFF8=8305
    114 %term CVFF16=16497
    115 %term CVFI4=4213
    116 %term CVFI8=8309
    117 
    118 %term CVIF4=4225
    119 %term CVIF8=8321
    120 %term CVIF16=16513
    121 %term CVII1=1157
    122 %term CVII2=2181
    123 %term CVII4=4229
    124 %term CVII8=8325
    125 %term CVIU1=1158
    126 %term CVIU2=2182
    127 %term CVIU4=4230
    128 %term CVIU8=8326
    129 
    130 %term CVPP4=4247
    131 %term CVPP8=8343
    132 %term CVPP16=16535
    133 %term CVPU4=4246
    134 %term CVPU8=8342
    135 
    136 %term CVUI1=1205
    137 %term CVUI2=2229
    138 %term CVUI4=4277
    139 %term CVUI8=8373
    140 %term CVUP4=4279
    141 %term CVUP8=8375
    142 %term CVUP16=16567
    143 %term CVUU1=1206
    144 %term CVUU2=2230
    145 %term CVUU4=4278
    146 %term CVUU8=8374
    147 
    148 %term NEGF4=4289
    149 %term NEGF8=8385
    150 %term NEGF16=16577
    151 %term NEGI4=4293
    152 %term NEGI8=8389
    153 
    154 %term CALLB=217
    155 %term CALLF4=4305
    156 %term CALLF8=8401
    157 %term CALLF16=16593
    158 %term CALLI4=4309
    159 %term CALLI8=8405
    160 %term CALLP4=4311
    161 %term CALLP8=8407
    162 %term CALLU4=4310
    163 %term CALLU8=8406
    164 %term CALLV=216
    165 
    166 %term RETF4=4337
    167 %term RETF8=8433
    168 %term RETF16=16625
    169 %term RETI4=4341
    170 %term RETI8=8437
    171 %term RETP4=4343
    172 %term RETP8=8439
    173 %term RETU4=4342
    174 %term RETU8=8438
    175 %term RETV=248
    176 
    177 %term ADDRGP4=4359
    178 %term ADDRGP8=8455
    179 
    180 %term ADDRFP4=4375
    181 %term ADDRFP8=8471
    182 
    183 %term ADDRLP4=4391
    184 %term ADDRLP8=8487
    185 
    186 %term ADDF4=4401
    187 %term ADDF8=8497
    188 %term ADDF16=16689
    189 %term ADDI4=4405
    190 %term ADDI8=8501
    191 %term ADDP4=4407
    192 %term ADDP8=8503
    193 %term ADDU4=4406
    194 %term ADDU8=8502
    195 
    196 %term SUBF4=4417
    197 %term SUBF8=8513
    198 %term SUBF16=16705
    199 %term SUBI4=4421
    200 %term SUBI8=8517
    201 %term SUBP4=4423
    202 %term SUBP8=8519
    203 %term SUBU4=4422
    204 %term SUBU8=8518
    205 
    206 %term LSHI4=4437
    207 %term LSHI8=8533
    208 %term LSHU4=4438
    209 %term LSHU8=8534
    210 
    211 %term MODI4=4453
    212 %term MODI8=8549
    213 %term MODU4=4454
    214 %term MODU8=8550
    215 
    216 %term RSHI4=4469
    217 %term RSHI8=8565
    218 %term RSHU4=4470
    219 %term RSHU8=8566
    220 
    221 %term BANDI4=4485
    222 %term BANDI8=8581
    223 %term BANDU4=4486
    224 %term BANDU8=8582
    225 
    226 %term BCOMI4=4501
    227 %term BCOMI8=8597
    228 %term BCOMU4=4502
    229 %term BCOMU8=8598
    230 
    231 %term BORI4=4517
    232 %term BORI8=8613
    233 %term BORU4=4518
    234 %term BORU8=8614
    235 
    236 %term BXORI4=4533
    237 %term BXORI8=8629
    238 %term BXORU4=4534
    239 %term BXORU8=8630
    240 
    241 %term DIVF4=4545
    242 %term DIVF8=8641
    243 %term DIVF16=16833
    244 %term DIVI4=4549
    245 %term DIVI8=8645
    246 %term DIVU4=4550
    247 %term DIVU8=8646
    248 
    249 %term MULF4=4561
    250 %term MULF8=8657
    251 %term MULF16=16849
    252 %term MULI4=4565
    253 %term MULI8=8661
    254 %term MULU4=4566
    255 %term MULU8=8662
    256 
    257 %term EQF4=4577
    258 %term EQF8=8673
    259 %term EQF16=16865
    260 %term EQI4=4581
    261 %term EQI8=8677
    262 %term EQU4=4582
    263 %term EQU8=8678
    264 
    265 %term GEF4=4593
    266 %term GEF8=8689
    267 %term GEI4=4597
    268 %term GEI8=8693
    269 %term GEI16=16885
    270 %term GEU4=4598
    271 %term GEU8=8694
    272 
    273 %term GTF4=4609
    274 %term GTF8=8705
    275 %term GTF16=16897
    276 %term GTI4=4613
    277 %term GTI8=8709
    278 %term GTU4=4614
    279 %term GTU8=8710
    280 
    281 %term LEF4=4625
    282 %term LEF8=8721
    283 %term LEF16=16913
    284 %term LEI4=4629
    285 %term LEI8=8725
    286 %term LEU4=4630
    287 %term LEU8=8726
    288 
    289 %term LTF4=4641
    290 %term LTF8=8737
    291 %term LTF16=16929
    292 %term LTI4=4645
    293 %term LTI8=8741
    294 %term LTU4=4646
    295 %term LTU8=8742
    296 
    297 %term NEF4=4657
    298 %term NEF8=8753
    299 %term NEF16=16945
    300 %term NEI4=4661
    301 %term NEI8=8757
    302 %term NEU4=4662
    303 %term NEU8=8758
    304 
    305 %term JUMPV=584
    306 
    307 %term LABELV=600
    308 
    309 %term LOADB=233
    310 %term LOADF4=4321
    311 %term LOADF8=8417
    312 %term LOADF16=16609
    313 %term LOADI1=1253
    314 %term LOADI2=2277
    315 %term LOADI4=4325
    316 %term LOADI8=8421
    317 %term LOADP4=4327
    318 %term LOADP8=8423
    319 %term LOADU1=1254
    320 %term LOADU2=2278
    321 %term LOADU4=4326
    322 %term LOADU8=8422
    323 
    324 %term VREGP=711
    325 %%
    326 reg:  INDIRI1(VREGP)     "# read register\n"
    327 reg:  INDIRU1(VREGP)     "# read register\n"
    328 
    329 reg:  INDIRI2(VREGP)     "# read register\n"
    330 reg:  INDIRU2(VREGP)     "# read register\n"
    331 
    332 reg:  INDIRF4(VREGP)     "# read register\n"
    333 reg:  INDIRI4(VREGP)     "# read register\n"
    334 reg:  INDIRP4(VREGP)     "# read register\n"
    335 reg:  INDIRU4(VREGP)     "# read register\n"
    336 
    337 reg:  INDIRF8(VREGP)     "# read register\n"
    338 reg:  INDIRI8(VREGP)     "# read register\n"
    339 reg:  INDIRP8(VREGP)     "# read register\n"
    340 reg:  INDIRU8(VREGP)     "# read register\n"
    341 
    342 stmt: ASGNI1(VREGP,reg)  "# write register\n"
    343 stmt: ASGNU1(VREGP,reg)  "# write register\n"
    344 
    345 stmt: ASGNI2(VREGP,reg)  "# write register\n"
    346 stmt: ASGNU2(VREGP,reg)  "# write register\n"
    347 
    348 stmt: ASGNF4(VREGP,reg)  "# write register\n"
    349 stmt: ASGNI4(VREGP,reg)  "# write register\n"
    350 stmt: ASGNP4(VREGP,reg)  "# write register\n"
    351 stmt: ASGNU4(VREGP,reg)  "# write register\n"
    352 
    353 stmt: ASGNF8(VREGP,reg)  "# write register\n"
    354 stmt: ASGNI8(VREGP,reg)  "# write register\n"
    355 stmt: ASGNP8(VREGP,reg)  "# write register\n"
    356 stmt: ASGNU8(VREGP,reg)  "# write register\n"
    357 con: CNSTI1  "%a"
    358 con: CNSTU1  "%a"
    359 
    360 con: CNSTI2  "%a"
    361 con: CNSTU2  "%a"
    362 
    363 con: CNSTI4  "%a"
    364 con: CNSTU4  "%a"
    365 con: CNSTP4  "%a"
    366 
    367 con: CNSTI8  "%a"
    368 con: CNSTU8  "%a"
    369 con: CNSTP8  "%a"
    370 stmt: reg  ""
    371 acon: con     "%0"
    372 acon: ADDRGP8  "%a"
    373 
    374 addr: ADDI4(reg,acon)  "%1($%0)"
    375 addr: ADDI8(reg,acon)  "%1($%0)"
    376 addr: ADDU8(reg,acon)  "%1($%0)"
    377 addr: ADDP8(reg,acon)  "%1($%0)"
    378 
    379 addr: acon  "%0"
    380 addr: reg   "($%0)"
    381 
    382 addr: ADDRFP8  "%a+%F($sp)"
    383 addr: ADDRLP8  "%a+%F($sp)"
    384 
    385 reg: addr  "lda $%c,%0\n"  1
    386 
    387 reg: CNSTI1  "# reg\n"  range(a, 0, 0)
    388 reg: CNSTI2  "# reg\n"  range(a, 0, 0)
    389 reg: CNSTI4  "# reg\n"  range(a, 0, 0)
    390 reg: CNSTI8  "# reg\n"  range(a, 0, 0)
    391 reg: CNSTU1  "# reg\n"  range(a, 0, 0)
    392 reg: CNSTU2  "# reg\n"  range(a, 0, 0)
    393 reg: CNSTU4  "# reg\n"  range(a, 0, 0)
    394 reg: CNSTU8  "# reg\n"  range(a, 0, 0)
    395 reg: CNSTP8  "# reg\n"  range(a, 0, 0)
    396 
    397 stmt: ASGNI1(addr,reg)  "stb $%1,%0\n"  1
    398 stmt: ASGNU1(addr,reg)  "stb $%1,%0\n"  1
    399 stmt: ASGNI2(addr,reg)  "stw $%1,%0\n"  1
    400 stmt: ASGNU2(addr,reg)  "stw $%1,%0\n"  1
    401 
    402 stmt: ASGNI4(addr,reg)  "stl $%1,%0\n"  1
    403 stmt: ASGNU4(addr,reg)  "stl $%1,%0\n"  1
    404 stmt: ASGNI8(addr,reg)  "stq $%1,%0\n"  1
    405 stmt: ASGNU8(addr,reg)  "stq $%1,%0\n"  1
    406 stmt: ASGNP8(addr,reg)  "stq $%1,%0\n"  1
    407 
    408 reg:  INDIRI1(reg)   "ldb $%c,($%0)\n"  1
    409 reg:  INDIRI2(reg)   "ldw $%c,($%0)\n"  1
    410 reg:  INDIRI4(addr)  "ldl $%c,%0\n"  1
    411 reg:  INDIRI8(addr)  "ldq $%c,%0\n"  1
    412 reg:  INDIRP8(addr)  "ldq $%c,%0\n"  1
    413 reg:  INDIRU1(reg)   "ldbu $%c,($%0)\n"  1
    414 reg:  INDIRU2(reg)   "ldwu $%c,($%0)\n"  1
    415 reg:  INDIRU4(addr)  "ldl $%c,%0\nzap $%c,240,$%c\n"  2
    416 reg:  INDIRU8(addr)  "ldq $%c,%0\n"  1
    417 
    418 reg:  CVII4(INDIRI1(reg))   "ldb $%c,($%0)\n"  1
    419 reg:  CVII8(INDIRI1(reg))   "ldb $%c,($%0)\n"  1
    420 reg:  CVII4(INDIRI2(reg))   "ldw $%c,($%0)\n"  1
    421 reg:  CVII8(INDIRI2(reg))   "ldw $%c,($%0)\n"  1
    422 reg:  CVII8(INDIRI4(addr))  "ldl $%c,%0\n"  1
    423 
    424 reg:  CVUU4(INDIRU1(reg))   "ldbu $%c,($%0)\n"  1
    425 reg:  CVUU8(INDIRU1(reg))   "ldbu $%c,($%0)\n"  1
    426 reg:  CVUU4(INDIRU2(reg))   "ldwu $%c,($%0)\n"  1
    427 reg:  CVUU8(INDIRU2(reg))   "ldwu $%c,($%0)\n"  1
    428 reg:  CVUU8(INDIRU4(addr))  "ldl $%c,%0\nzap $%c,240,$%c\n"  2
    429 
    430 reg:  CVUI4(INDIRU1(reg))   "ldbu $%c,($%0)\n"  1
    431 reg:  CVUI8(INDIRU1(reg))   "ldbu $%c,($%0)\n"  1
    432 reg:  CVUI4(INDIRU2(reg))   "ldwu $%c,($%0)\n"  1
    433 reg:  CVUI8(INDIRU2(reg))   "ldwu $%c,($%0)\n"  1
    434 reg:  CVUI8(INDIRU4(addr))  "ldl $%c,%0\nzap $%c,240,$%c\n"  2
    435 
    436 reg:  CVIU8(reg)  "mov $%0,$%c\n"  move(a)
    437 
    438 reg:  INDIRF4(addr)     "lds $f%c,%0\n"  1
    439 reg:  INDIRF8(addr)     "ldt $f%c,%0\n"  1
    440 stmt: ASGNF4(addr,reg)  "sts $f%1,%0\n"  1
    441 stmt: ASGNF8(addr,reg)  "stt $f%1,%0\n"  1
    442 
    443 reg: MULI4(reg,rc)  "mull $%0,%1,$%c\n"   1
    444 reg: MULI8(reg,rc)  "mulq $%0,%1,$%c\n"   1
    445 reg: MULU4(reg,rc)  "mull $%0,%1,$%c\nzap $%c,240,$%c\n"  2
    446 reg: MULU8(reg,rc)  "mulq $%0,%1,$%c\n"   1
    447 
    448 reg: DIVI4(reg,rc)  "divl $%0,%1,$%c\n"   1
    449 reg: DIVI8(reg,rc)  "divq $%0,%1,$%c\n"   1
    450 reg: DIVU4(reg,rc)  "divlu $%0,%1,$%c\n"  1
    451 reg: DIVU8(reg,rc)  "divqu $%0,%1,$%c\n"  1
    452 reg: MODI4(reg,rc)  "reml $%0,%1,$%c\n"   1
    453 reg: MODI8(reg,rc)  "remq $%0,%1,$%c\n"   1
    454 reg: MODU4(reg,rc)  "remlu $%0,%1,$%c\n"  1
    455 reg: MODU8(reg,rc)  "remqu $%0,%1,$%c\n"  1
    456 
    457 rc:  con            "%0"
    458 rc:  reg            "$%0"
    459 
    460 reg: ADDI4(reg,rc)   "addl $%0,%1,$%c\n"  1
    461 reg: ADDI8(reg,rc)   "addq $%0,%1,$%c\n"  1
    462 reg: ADDP8(reg,rc)   "addq $%0,%1,$%c\n"  1
    463 reg: ADDU4(reg,rc)   "addl $%0,%1,$%c\nzap $%c,240,$%c\n"  2
    464 reg: ADDU8(reg,rc)   "addq $%0,%1,$%c\n"  1
    465 reg: SUBI4(reg,rc)   "subl $%0,%1,$%c\n"  1
    466 reg: SUBI8(reg,rc)   "subq $%0,%1,$%c\n"  1
    467 reg: SUBP8(reg,rc)   "subq $%0,%1,$%c\n"  1
    468 reg: SUBU4(reg,rc)   "subl $%0,%1,$%c\nzap $%c,240,$%c\n"  2
    469 reg: SUBU8(reg,rc)   "subq $%0,%1,$%c\n"  1
    470 
    471 reg: BANDI4(reg,rc)  "and $%0,%1,$%c\naddl $%c,0,$%c\n"   2
    472 reg: BANDI8(reg,rc)  "and $%0,%1,$%c\n"   1
    473 reg: BANDU4(reg,rc)  "and $%0,%1,$%c\n"   1
    474 reg: BANDU8(reg,rc)  "and $%0,%1,$%c\n"   1
    475 reg: BORI4(reg,rc)   "or $%0,%1,$%c\naddl $%c,0,$%c\n"   2
    476 reg: BORI8(reg,rc)   "or $%0,%1,$%c\n"    1
    477 reg: BORU4(reg,rc)   "or $%0,%1,$%c\n"    1
    478 reg: BORU8(reg,rc)   "or $%0,%1,$%c\n"    1
    479 reg: BXORI4(reg,rc)  "xor $%0,%1,$%c\naddl $%c,0,$%c\n"   2
    480 reg: BXORI8(reg,rc)  "xor $%0,%1,$%c\n"   1
    481 reg: BXORU4(reg,rc)  "xor $%0,%1,$%c\n"   1
    482 reg: BXORU8(reg,rc)  "xor $%0,%1,$%c\n"   1
    483 
    484 rc6: CNSTI4         "%a"  range(a,0,63)
    485 rc6: CNSTI8         "%a"  range(a,0,63)
    486 rc6: reg            "$%0"
    487 
    488 reg: LSHI4(reg,rc6)  "sll $%0,%1,$%c\naddl $%c,0,$%c\n"   2
    489 reg: LSHI8(reg,rc6)  "sll $%0,%1,$%c\n"  1
    490 reg: LSHU4(reg,rc6)  "sll $%0,%1,$%c\nzap $%c,240,$%c\n"  2
    491 reg: LSHU8(reg,rc6)  "sll $%0,%1,$%c\n"  1
    492 reg: RSHI4(reg,rc6)  "sra $%0,%1,$%c\naddl $%c,0,$%c\n"   2
    493 reg: RSHI8(reg,rc6)  "sra $%0,%1,$%c\n"  1
    494 reg: RSHU4(reg,rc6)  "srl $%0,%1,$%c\n"  1
    495 reg: RSHU8(reg,rc6)  "srl $%0,%1,$%c\n"  1
    496 
    497 reg: BCOMI4(reg)  "not $%0,$%c\naddl $%c,0,$%c\n"   2
    498 reg: BCOMU4(reg)  "not $%0,$%c\nzap $%c,240,$%c\n"  2
    499 reg: BCOMI8(reg)  "not $%0,$%c\n"   1
    500 reg: BCOMU8(reg)  "not $%0,$%c\n"   1
    501 reg: NEGI4(reg)   "negl $%0,$%c\n"  1
    502 reg: NEGI8(reg)   "negq $%0,$%c\n"  1
    503 reg: LOADI1(reg)  "mov $%0,$%c\n"  move(a)
    504 reg: LOADI2(reg)  "mov $%0,$%c\n"  move(a)
    505 reg: LOADI4(reg)  "mov $%0,$%c\n"  move(a)
    506 reg: LOADI8(reg)  "mov $%0,$%c\n"  move(a)
    507 reg: LOADP8(reg)  "mov $%0,$%c\n"  move(a)
    508 reg: LOADU1(reg)  "mov $%0,$%c\n"  move(a)
    509 reg: LOADU2(reg)  "mov $%0,$%c\n"  move(a)
    510 reg: LOADU4(reg)  "mov $%0,$%c\n"  move(a)
    511 reg: LOADU8(reg)  "mov $%0,$%c\n"  move(a)
    512 
    513 reg: ADDF4(reg,reg)  "adds $f%0,$f%1,$f%c\n"  1
    514 reg: ADDF8(reg,reg)  "addt $f%0,$f%1,$f%c\n"  1
    515 reg: DIVF4(reg,reg)  "divs $f%0,$f%1,$f%c\n"  1
    516 reg: DIVF8(reg,reg)  "divt $f%0,$f%1,$f%c\n"  1
    517 reg: MULF4(reg,reg)  "muls $f%0,$f%1,$f%c\n"  1
    518 reg: MULF8(reg,reg)  "mult $f%0,$f%1,$f%c\n"  1
    519 reg: SUBF4(reg,reg)  "subs $f%0,$f%1,$f%c\n"  1
    520 reg: SUBF8(reg,reg)  "subt $f%0,$f%1,$f%c\n"  1
    521 reg: LOADF4(reg)     "fmov $f%0,$f%c\n"       move(a)
    522 reg: LOADF8(reg)     "fmov $f%0,$f%c\n"       move(a)
    523 reg: NEGF4(reg)      "negs $f%0,$f%c\n"       1
    524 reg: NEGF8(reg)      "negt $f%0,$f%c\n"       1
    525 reg: CVII4(reg)  "sll $%0,8*(8-%a),$%c\nsra $%c,8*(8-%a),$%c\n"  2
    526 reg: CVII8(reg)  "sll $%0,8*(8-%a),$%c\nsra $%c,8*(8-%a),$%c\n"  2
    527 reg: CVUI4(reg)  "and $%0,(1<<(8*%a))-1,$%c\n"  1
    528 reg: CVUI8(reg)  "and $%0,(1<<(8*%a))-1,$%c\n"  1
    529 reg: CVUU4(reg)  "and $%0,(1<<(8*%a))-1,$%c\n"  1
    530 reg: CVUU8(reg)  "and $%0,(1<<(8*%a))-1,$%c\n"  1
    531 
    532 reg: CVUP8(reg)  "and $%0,(1<<(8*%a))-1,$%c\n"  1
    533 
    534 reg: CVFF4(reg)  "cvtts $f%0,$f%c\n"  1
    535 reg: CVFF8(reg)  "cvtst $f%0,$f%c\n"  1
    536 
    537 reg: CVIF4(reg)  "stq $%0,-56+%F($sp)\nldt $%f%c,-56+%F($sp)\ncvtqs $f%c,$f%c\n"  3
    538 reg: CVIF8(reg)  "stq $%0,-56+%F($sp)\nldt $%f%c,-56+%F($sp)\ncvtqt $f%c,$f%c\n"  3
    539 reg: CVIF4(INDIRI4(addr))  "lds $f%c,%0\ncvtlq $f%c,$f%c\ncvtqs $f%c,$f%c\n"  3
    540 reg: CVIF4(INDIRI8(addr))  "ldt $f%c,%0\ncvtqs $f%c,$f%c\n"  2
    541 reg: CVIF8(INDIRI4(addr))  "lds $f%c,%0\ncvtlq $f%c,$f%c\ncvtqt $f%c,$f%c\n"  3
    542 reg: CVIF8(INDIRI8(addr))  "ldt $f%c,%0\ncvtqt $f%c,$f%c\n"  2
    543 
    544 reg: CVFI4(reg)  "cvttqc $f%0,$f1\ncvtql $f1,$f1\nsts $f1,-56+%F($sp)\nldl $%c,-56+%F($sp)\n"  4
    545 reg: CVFI8(reg)  "cvttqc $f%0,$f1\nstt $f1,-56+%F($sp)\nldq $%c,-56+%F($sp)\n"  3
    546 
    547 stmt: LABELV  "%a:\n"
    548 
    549 stmt: JUMPV(acon)  "br %0\n"   1
    550 stmt: JUMPV(reg)   "jmp ($%0)\n"  1
    551 
    552 stmt: EQI4(reg,rc6)  "cmpeq $%0,%1,$23\nbne $23,%a\n"   2
    553 stmt: EQU4(reg,rc6)  "cmpeq $%0,%1,$23\nbne $23,%a\n"   2
    554 stmt: EQI8(reg,rc6)  "cmpeq $%0,%1,$23\nbne $23,%a\n"   2
    555 stmt: EQU8(reg,rc6)  "cmpeq $%0,%1,$23\nbne $23,%a\n"   2
    556 stmt: NEI4(reg,rc6)  "cmpeq $%0,%1,$23\nbeq $23,%a\n"   2
    557 stmt: NEU4(reg,rc6)  "cmpeq $%0,%1,$23\nbeq $23,%a\n"   2
    558 stmt: NEI8(reg,rc6)  "cmpeq $%0,%1,$23\nbeq $23,%a\n"   2
    559 stmt: NEU8(reg,rc6)  "cmpeq $%0,%1,$23\nbeq $23,%a\n"   2
    560 stmt: GEI4(reg,rc6)  "cmplt $%0,%1,$23\nbeq $23,%a\n"   2
    561 stmt: GEI8(reg,rc6)  "cmplt $%0,%1,$23\nbeq $23,%a\n"   2
    562 stmt: GEU4(reg,rc6)  "cmpult $%0,%1,$23\nbeq $23,%a\n"  1
    563 stmt: GEU8(reg,rc6)  "cmpult $%0,%1,$23\nbeq $23,%a\n"  1
    564 stmt: GTI4(reg,rc6)  "cmple $%0,%1,$23\nbeq $23,%a\n"   2
    565 stmt: GTI8(reg,rc6)  "cmple $%0,%1,$23\nbeq $23,%a\n"   2
    566 stmt: GTU4(reg,rc6)  "cmpule $%0,%1,$23\nbeq $23,%a\n"  1
    567 stmt: GTU8(reg,rc6)  "cmpule $%0,%1,$23\nbeq $23,%a\n"  1
    568 stmt: LEI4(reg,rc6)  "cmple $%0,%1,$23\nbne $23,%a\n"   2
    569 stmt: LEI8(reg,rc6)  "cmple $%0,%1,$23\nbne $23,%a\n"   2
    570 stmt: LEU4(reg,rc6)  "cmpule $%0,%1,$23\nbne $23,%a\n"  2
    571 stmt: LEU8(reg,rc6)  "cmpule $%0,%1,$23\nbne $23,%a\n"  2
    572 stmt: LTI4(reg,rc6)  "cmplt $%0,%1,$23\nbne $23,%a\n"   2
    573 stmt: LTI8(reg,rc6)  "cmplt $%0,%1,$23\nbne $23,%a\n"   2
    574 stmt: LTU4(reg,rc6)  "cmpult $%0,%1,$23\nbne $23,%a\n"  2
    575 stmt: LTU8(reg,rc6)  "cmpult $%0,%1,$23\nbne $23,%a\n"  2
    576 
    577 stmt: EQF4(reg,reg)  "cmpteq $f%0,$f%1,$f1\nfbne $f1,%a\n"  2
    578 stmt: EQF8(reg,reg)  "cmpteq $f%0,$f%1,$f1\nfbne $f1,%a\n"  2
    579 stmt: LEF4(reg,reg)  "cmptle $f%0,$f%1,$f1\nfbne $f1,%a\n"  2
    580 stmt: LEF8(reg,reg)  "cmptle $f%0,$f%1,$f1\nfbne $f1,%a\n"  2
    581 stmt: LTF4(reg,reg)  "cmptlt $f%0,$f%1,$f1\nfbne $f1,%a\n"  2
    582 stmt: LTF8(reg,reg)  "cmptlt $f%0,$f%1,$f1\nfbne $f1,%a\n"  2
    583 
    584 stmt: NEF4(reg,reg)  "cmpteq $f%0,$f%1,$f1\nfbeq $f1,%a\n"  2
    585 stmt: NEF8(reg,reg)  "cmpteq $f%0,$f%1,$f1\nfbeq $f1,%a\n"  2
    586 stmt: GEF4(reg,reg)  "cmptlt $f%0,$f%1,$f1\nfbeq $f1,%a\n"  2
    587 stmt: GEF8(reg,reg)  "cmptlt $f%0,$f%1,$f1\nfbeq $f1,%a\n"  2
    588 stmt: GTF4(reg,reg)  "cmptle $f%0,$f%1,$f1\nfbeq $f1,%a\n"  2
    589 stmt: GTF8(reg,reg)  "cmptle $f%0,$f%1,$f1\nfbeq $f1,%a\n"  2
    590 
    591 ar:   ADDRGP8     "%a"
    592 ar:   reg    "($%0)"
    593 
    594 reg:  CALLF4(ar)  "jsr $26,%0\nldgp $gp,0($26)\n"  2
    595 reg:  CALLF8(ar)  "jsr $26,%0\nldgp $gp,0($26)\n"  2
    596 reg:  CALLI4(ar)  "jsr $26,%0\nldgp $gp,0($26)\n"  2
    597 reg:  CALLI8(ar)  "jsr $26,%0\nldgp $gp,0($26)\n"  2
    598 reg:  CALLP8(ar)  "jsr $26,%0\nldgp $gp,0($26)\n"  2
    599 reg:  CALLU4(ar)  "jsr $26,%0\nldgp $gp,0($26)\n"  2
    600 reg:  CALLU8(ar)  "jsr $26,%0\nldgp $gp,0($26)\n"  2
    601 stmt: CALLV(ar)  "jsr $26,%0\nldgp $gp,0($26)\n"  2
    602 
    603 stmt: RETF4(reg)  "# ret\n"  1
    604 stmt: RETF8(reg)  "# ret\n"  1
    605 stmt: RETI4(reg)  "# ret\n"  1
    606 stmt: RETU4(reg)  "# ret\n"  1
    607 stmt: RETI8(reg)  "# ret\n"  1
    608 stmt: RETU8(reg)  "# ret\n"  1
    609 stmt: RETP8(reg)  "# ret\n"  1
    610 stmt: RETV(reg)   "# ret\n"  1
    611 
    612 stmt: ARGF4(reg)  "# arg\n"  1
    613 stmt: ARGF8(reg)  "# arg\n"  1
    614 stmt: ARGI4(reg)  "# arg\n"  1
    615 stmt: ARGI8(reg)  "# arg\n"  1
    616 stmt: ARGP8(reg)  "# arg\n"  1
    617 stmt: ARGU4(reg)  "# arg\n"  1
    618 stmt: ARGU8(reg)  "# arg\n"  1
    619 
    620 stmt: ARGB(INDIRB(reg))       "# argb %0\n"      1
    621 stmt: ASGNB(reg,INDIRB(reg))  "# asgnb %0 %1\n"  1
    622 
    623 %%
    624 static void progend(void){}
    625 
    626 static void progbeg(int argc, char *argv[]) {
    627         int i;
    628 
    629         {
    630                 union {
    631                         char c;
    632                         int i;
    633                 } u;
    634                 u.i = 0;
    635                 u.c = 1;
    636                 swap = ((int)(u.i == 1)) != IR->little_endian;
    637         }
    638         parseflags(argc, argv);
    639 
    640         for (i = 0; i < 32; i++)
    641                 freg[i] = mkreg("%d", i, 1, FREG);
    642         for (i = 0; i < 32; i++)
    643                 ireg[i]  = mkreg("%d", i, 1, IREG);
    644         ireg[29]->x.name = "gp";
    645         ireg[30]->x.name = "sp";
    646         fregw = mkwildcard(freg);
    647         iregw = mkwildcard(ireg);
    648 
    649         tmask[IREG] = INTTMP; tmask[FREG] = FLTTMP;
    650         vmask[IREG] = INTVAR; vmask[FREG] = FLTVAR;
    651 
    652         blkreg = mkreg("1", 1, 0xf, IREG);
    653 
    654 }
    655 
    656 static Symbol rmap(int opk) {
    657         switch (optype(opk)) {
    658         case I: case U: case P: case B:
    659                 return iregw;
    660         case F:
    661                 return fregw;
    662         default:
    663                 return 0;
    664         }
    665 }
    666 
    667 static Symbol argreg(int offset, int ty) {
    668         if (offset >= 48)
    669                 return NULL;
    670         else if (ty == F)
    671                 return freg[(offset/8) + 16];
    672         else
    673                 return ireg[(offset/8) + 16];
    674 }
    675 
    676 static void target(Node p) {
    677         assert(p);
    678         switch (specific(p->op)) {
    679         case CNST+I: case CNST+U: case CNST+P:
    680                 if (range(p, 0, 0) == 0) {
    681                         setreg(p, ireg[31]);
    682                         p->x.registered = 1;
    683                 }
    684                 break;
    685         case CNST+F:
    686                 if (p->syms[0]->u.c.v.d == 0) {
    687                         setreg(p, freg[31]);
    688                         p->x.registered = 1;
    689                 }
    690                 break;
    691 
    692         case CALL+V:
    693                 rtarget(p, 0, ireg[27]);
    694                 break;
    695         case CALL+F:
    696                 rtarget(p, 0, ireg[27]);
    697                 setreg(p, freg[0]);
    698                 break;
    699         case CALL+I: case CALL+P: case CALL+U:
    700                 rtarget(p, 0, ireg[27]);
    701                 setreg(p, ireg[0]);
    702                 break;
    703         case RET+F:
    704                 rtarget(p, 0, freg[0]);
    705                 break;
    706         case RET+I: case RET+U: case RET+P:
    707                 rtarget(p, 0, ireg[0]);
    708                 break;
    709 
    710         case ARG+F: case ARG+I: case ARG+P: case ARG+U: {
    711                 Symbol q = argreg(p->syms[2]->u.c.v.i, optype(p->op));
    712                 if (q)
    713                         rtarget(p, 0, q);
    714                 break;
    715                 }
    716 
    717 
    718         case ASGN+B: rtarget(p->kids[1], 0, blkreg); break;
    719         case ARG+B:  rtarget(p->kids[0], 0, blkreg); break;
    720 
    721         }
    722 }
    723 
    724 static void clobber(Node p) {
    725         assert(p);
    726         switch (specific(p->op)) {
    727         case ASGN+I: case ASGN+U:
    728                 if (opsize(p->op) <= 2)
    729                         spill(1<<24, IREG, p);
    730                 break;
    731 
    732         case DIV+I: case DIV+U: case MOD+I: case MOD+U:
    733                 spill(((1<<27)|(3<<24))&~p->syms[RX]->x.regnode->mask, IREG, p);
    734                 break;
    735 
    736         case CALL+F:
    737                 spill(INTTMP | INTRET, IREG, p);
    738                 spill(FLTTMP,          FREG, p);
    739                 break;
    740         case CALL+I: case CALL+P: case CALL+U:
    741                 spill(INTTMP,          IREG, p);
    742                 spill(FLTTMP | FLTRET, FREG, p);
    743                 break;
    744         case CALL+V:
    745                 spill(INTTMP | INTRET, IREG, p);
    746                 spill(FLTTMP | FLTRET, FREG, p);
    747                 break;
    748 
    749         }
    750 }
    751 
    752 static void emit2(Node p) {
    753         int dst, n, src, sz, ty;
    754         static int ty0;
    755         Symbol q;
    756 
    757         switch (specific(p->op)) {
    758         case ARG+F: case ARG+I: case ARG+P: case ARG+U:
    759                 ty = optype(p->op);
    760                 sz = opsize(p->op);
    761                 q = argreg(p->syms[2]->u.c.v.i, ty);
    762                 src = getregnum(p->x.kids[0]);
    763                 if (q)
    764                         break;
    765                 else if (ty == F && sz == 4)
    766                         print("sts $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48);
    767                 else if (ty == F && sz == 8)
    768                         print("stt $f%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48);
    769                 else if (sz == 4)
    770                         print("stq $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48);
    771                 else if (sz == 8)
    772                         print("stq $%d,%d($sp)\n", src, p->syms[2]->u.c.v.i - 48);
    773                 else
    774                         assert(0);
    775                 break;
    776 
    777         case ASGN+B:
    778                 dalign = salign = p->syms[1]->u.c.v.i;
    779                 blkcopy(getregnum(p->x.kids[0]), 0,
    780                         getregnum(p->x.kids[1]), 0,
    781                         p->syms[0]->u.c.v.i, tmpregs);
    782                 break;
    783 
    784 
    785         case ARG+B: {
    786                 int doff = p->syms[2]->u.c.v.i, soff = 0, sreg = getregnum(p->x.kids[0]);
    787                 dalign = 8;
    788                 salign = p->syms[1]->u.c.v.i;
    789                 n = p->syms[0]->u.c.v.i;
    790                 for ( ; doff <= 40 && n > 0; doff += 8) {
    791                         print("uldq $%d,%d($%d)\n", (doff/8)+16, soff, sreg);
    792                         soff += 8;
    793                         n -= 8;
    794                 }
    795                 if (n > 0)
    796                         blkcopy(30, doff - 48, sreg, soff, n, tmpregs);
    797                 break;
    798                 }
    799 
    800         }
    801 }
    802 
    803 static void doarg(Node p) {
    804         p->syms[2] = intconst(mkactual(8, roundup(p->syms[0]->u.c.v.i,8)));
    805 }
    806 
    807 static void local(Symbol p) {
    808         if (askregvar(p, rmap(ttob(p->type))) == 0)
    809                 mkauto(p);
    810 }
    811 
    812 static int bitcount(unsigned mask) {
    813         unsigned i, n = 0;
    814 
    815         for (i = 1; i; i <<= 1)
    816                 if (mask&i)
    817                         n++;
    818         return n;
    819 }
    820 
    821 static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
    822         int i, sizeargs, saved, sizefsave, sizeisave, varargs;
    823         Symbol r, argregs[6];
    824 
    825         usedmask[0] = usedmask[1] = 0;
    826         freemask[0] = freemask[1] = ~(unsigned)0;
    827         maxargoffset = offset = maxoffset = 0;
    828 
    829         for (i = 0; callee[i]; i++)
    830                 ;
    831         varargs = variadic(f->type)
    832                 || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0;
    833         if (varargs)
    834                 sizeargs = 2*48;
    835         else
    836                 sizeargs = 48;
    837 
    838         for (i = 0; callee[i]; i++) {
    839                 Symbol p = callee[i];
    840                 Symbol q = caller[i];
    841                 assert(q);
    842                 if (isfloat(p->type) && varargs) {
    843                         p->x.offset = q->x.offset = offset - 2*48;
    844                         p->x.name = q->x.name = stringd(offset - 2*48);
    845                 } else {
    846                         p->x.offset = q->x.offset = offset - 48;
    847                         p->x.name = q->x.name = stringd(offset - 48);
    848                 }
    849                 offset = roundup(offset, q->type->align);
    850                 r = argreg(offset, optype(ttob(q->type)));
    851                 if (i < 6)
    852                         argregs[i] = r;
    853                 offset = roundup(offset + q->type->size, 8);
    854                 if (varargs)
    855                         p->sclass = AUTO;
    856                 else if (r && ncalls == 0 && !isstruct(q->type) && !p->addressed
    857 ) {
    858                         p->sclass = q->sclass = REGISTER;
    859                         askregvar(p, r);
    860                         assert(p->x.regnode && p->x.regnode->vbl == p);
    861                         q->x = p->x;
    862                         q->type = p->type;
    863                 } else if (askregvar(p, rmap(ttob(p->type)))
    864                            && r != NULL /*
    865                            && (isint(p->type) || p->type == q->type) */
    866 ) {
    867                         assert(q->sclass != REGISTER);
    868                         p->sclass = q->sclass = REGISTER;
    869                         q->type = p->type;
    870                 }
    871 
    872         }
    873         assert(!caller[i]);
    874 
    875         offset = sizeargs + 8;
    876         gencode(caller, callee);
    877         usedmask[IREG] &= ~(INTTMP|(0x3f<<16)|INTRET);
    878         usedmask[FREG] &= ~(FLTTMP|(0x3f<<16)|FLTRET);
    879         if (ncalls || usedmask[IREG] || usedmask[FREG])
    880                 usedmask[IREG] |= 1<<26;
    881         sizefsave = 8*bitcount(usedmask[FREG]);
    882         sizeisave = 8*bitcount(usedmask[IREG]);
    883         if (maxargoffset > 48)
    884                 maxargoffset -= 48;
    885         else
    886                 maxargoffset = 0;
    887         if (maxoffset < sizeargs)
    888                 maxoffset = sizeargs;
    889         framesize = roundup(maxargoffset + sizefsave + sizeisave + maxoffset, 16);
    890         segment(CODE);
    891         print(".ent %s\n", f->x.name);
    892         print("%s:\n", f->x.name);
    893         print("ldgp $gp,0($27)\n");
    894         i = maxargoffset + sizefsave - framesize;
    895         if (framesize > 0)
    896                 print("lda $sp,%d($sp)\n", -framesize);
    897         if (usedmask[FREG])
    898                 print(".fmask 0x%x,%d\n", usedmask[FREG], i - 8);
    899         if (usedmask[IREG])
    900                 print(".mask 0x%x,%d\n",  usedmask[IREG], i + sizeisave - 8);
    901         print(".frame $sp,%d,$26,%d\n", framesize, sizeargs);
    902 
    903         saved = maxargoffset;
    904         for (i = 2; i <= 9; i++)
    905                 if (usedmask[FREG]&(1<<i)) {
    906                         print("stt $f%d,%d($sp)\n", i, saved);
    907                         saved += 8;
    908                 }
    909 
    910         for (i = 9; i <= 26; i++)
    911                 if (usedmask[IREG]&(1<<i)) {
    912                         print("stq $%d,%d($sp)\n", i, saved);
    913                         saved += 8;
    914                 }
    915         for (i = 0; i < 6 && callee[i]; i++) {
    916                 r = argregs[i];
    917                 if (r && r->x.regnode != callee[i]->x.regnode) {
    918                         Symbol out = callee[i];
    919                         Symbol in  = caller[i];
    920                         int rn = r->x.regnode->number;
    921                         int rs = r->x.regnode->set;
    922                         int tyin = ttob(in->type);
    923 
    924                         assert(out && in && r && r->x.regnode);
    925                         assert(out->sclass != REGISTER || out->x.regnode);
    926                         if (out->sclass == REGISTER) {
    927                                 if (rs == FREG)
    928                                         print("fmov $f%d,$f%d\n", rn, out->x.regnode->number);
    929                                 else
    930                                         print("mov $%d,$%d\n", rn, out->x.regnode->number);
    931 
    932                         } else {
    933                                 int off = in->x.offset + framesize;
    934                                 if (rs == FREG && tyin == F+sizeop(8))
    935                                         print("stt $f%d,%d($sp)\n", rn, off);
    936                                 else if (rs == FREG && tyin == F+sizeop(4))
    937                                         print("sts $f%d,%d($sp)\n", rn, off);
    938                                 else {
    939                                         int i, n = (in->type->size + 7)/8;
    940                                         for (i = rn; i < rn+n && i <= 21; i++)
    941                                                 print("stq $%d,%d($sp)\n", i, off + (i-rn)*8);
    942                                 }
    943 
    944                         }
    945 
    946                 }
    947         }
    948         if (varargs && callee[i-1]) {
    949                 i = callee[i-1]->x.offset + roundup(callee[i-1]->type->size, 8);
    950                 for (i = (48+i)/8; i < 6; i++) {
    951                         print("stq $%d,%d($sp)\n",  i + 16, framesize -   48 + 8*i);
    952                         print("stt $f%d,%d($sp)\n", i + 16, framesize - 2*48 + 8*i);
    953                 }
    954         }
    955         print(".prologue 1\n");
    956 
    957         emitcode();
    958         saved = maxargoffset;
    959         for (i = 2; i <= 9; i++)
    960                 if (usedmask[FREG]&(1<<i)) {
    961                         print("ldt $f%d,%d($sp)\n", i, saved);
    962                         saved += 8;
    963                 }
    964         for (i = 9; i <= 26; i++)
    965                 if (usedmask[IREG]&(1<<i)) {
    966                         print("ldq $%d,%d($sp)\n", i, saved);
    967                         saved += 8;
    968                 }
    969         if (framesize > 0)
    970                 print("lda $sp,%d($sp)\n", framesize);
    971         print("ret\n");
    972         print(".end %s\n", f->x.name);
    973 
    974 }
    975 
    976 static void defconst(int suffix, int size, Value v) {
    977         if (suffix == F && size == 4) {
    978                 float f = v.d;
    979                 print(".long 0x%x\n", *(unsigned *)&f);
    980         } else if (suffix == F && size == 8) {
    981                 double d = v.d;
    982                 unsigned *p = (unsigned *)&d;
    983                 print(".long 0x%x\n.long 0x%x\n", p[swap], p[!swap]);
    984         } else if (suffix == P)
    985                 print(".quad 0x%X\n", v.p);
    986         else if (size == 1)
    987                 print(".byte 0x%x\n", suffix == I ? v.i : v.u);
    988         else if (size == 2)
    989                 print(".word 0x%x\n", suffix == I ? v.i&0xFFFF : v.u&0xFFFF);
    990         else if (size == 4)
    991                 print(".long 0x%x\n", suffix == I ? v.i : v.u);
    992         else if (size == 8)
    993                 print(".quad 0x%X\n", suffix == I ? v.i : v.u);
    994 
    995 }
    996 
    997 static void defaddress(Symbol p) {
    998         print(".quad %s\n", p->x.name);
    999 }
   1000 
   1001 static void defstring(int n, char *str) {
   1002         char *s;
   1003 
   1004         for (s = str; s < str + n; s++)
   1005                 print(".byte %d\n", (*s)&0377);
   1006 }
   1007 
   1008 static void export(Symbol p) {
   1009         print(".globl %s\n", p->x.name);
   1010 }
   1011 
   1012 static void import(Symbol p) {
   1013         if (!isfunc(p->type))
   1014                 print(".extern %s %d\n", p->name, p->type->size);
   1015 }
   1016 
   1017 static void defsymbol(Symbol p) {
   1018         if (p->scope >= LOCAL && p->sclass == STATIC)
   1019                 p->x.name = stringf("L.%d", genlabel(1));
   1020         else if (p->generated)
   1021                 p->x.name = stringf("L.%s", p->name);
   1022         else
   1023                 assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
   1024                 p->x.name = p->name;
   1025 }
   1026 
   1027 static void address(Symbol q, Symbol p, long n) {
   1028         if (p->scope == GLOBAL
   1029         || p->sclass == STATIC || p->sclass == EXTERN)
   1030                 q->x.name = stringf("%s%s%D", p->x.name,
   1031                         n >= 0 ? "+" : "", n);
   1032         else {
   1033                 assert(n <= INT_MAX && n >= INT_MIN);
   1034                 q->x.offset = p->x.offset + n;
   1035                 q->x.name = stringd(q->x.offset);
   1036         }
   1037 }
   1038 
   1039 static void global(Symbol p) {
   1040         if (p->u.seg == DATA || p->u.seg == LIT) {
   1041                 assert(p->type->align <= 8);
   1042                 print(".align %c\n", ".01.2...3"[p->type->align]);
   1043                 print("%s:\n", p->x.name);
   1044         } else if (p->sclass == STATIC || Aflag >= 2)
   1045                 print(".lcomm %s,%d\n", p->x.name, p->type->size);
   1046         else
   1047                 print( ".comm %s,%d\n", p->x.name, p->type->size);
   1048 }
   1049 
   1050 static void segment(int n) {
   1051         cseg = n;
   1052         switch (n) {
   1053         case DATA: print(".sdata\n"); break;
   1054         case CODE: print(".text\n");  break;
   1055         case LIT:  print(".rdata\n"); break;
   1056         }
   1057 }
   1058 
   1059 static void space(int n) {
   1060         if (cseg != BSS)
   1061                 print(".space %d\n", n);
   1062 }
   1063 
   1064 static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) {
   1065         int lab = genlabel(1);
   1066 
   1067         print("addq $%d,%d,$%d\n",   sreg, size&~7, sreg);
   1068         print("addq $%d,%d,$%d\n",   dreg, size&~7, tmps[2]);
   1069         blkcopy(tmps[2], doff, sreg, soff, size&7, tmps);
   1070         print("L.%d:\n", lab);
   1071         print("addq $%d,%d,$%d\n",    sreg, -8, sreg);
   1072         print("addq $%d,%d,$%d\n", tmps[2], -8, tmps[2]);
   1073         blkcopy(tmps[2], doff, sreg, soff, 8, tmps);
   1074         print("cmpult $%d,$%d,$23\nbne $23,L.%d\n", dreg, tmps[2], lab);
   1075 }
   1076 
   1077 static void blkfetch(int size, int off, int reg, int tmp) {
   1078         assert(size == 1 || size == 2 || size == 4 || size == 8);
   1079         if (size == 1)
   1080                 print("ldb $%d,%d($%d)\n",  tmp, off, reg);
   1081         else if (size == 2)
   1082                 print("ldw $%d,%d($%d)\n",  tmp, off, reg);
   1083         else if (salign >= size && size == 4)
   1084                 print("ldl $%d,%d($%d)\n",  tmp, off, reg);
   1085         else if (salign >= size && size == 8)
   1086                 print("ldq $%d,%d($%d)\n",  tmp, off, reg);
   1087         else if (size == 4)
   1088                 print("uldl $%d,%d($%d)\n", tmp, off, reg);
   1089         else
   1090                 print("uldq $%d,%d($%d)\n", tmp, off, reg);
   1091 }
   1092 
   1093 static void blkstore(int size, int off, int reg, int tmp) {
   1094         assert(size == 1 || size == 2 || size == 4 || size == 8);
   1095         if (size == 1)
   1096                 print("stb $%d,%d($%d)\n",  tmp, off, reg);
   1097         else if (size == 2)
   1098                 print("stw $%d,%d($%d)\n",  tmp, off, reg);
   1099         else if (dalign >= size && size == 4)
   1100                 print("stl $%d,%d($%d)\n",  tmp, off, reg);
   1101         else if (dalign >= size && size == 8)
   1102                 print("stq $%d,%d($%d)\n",  tmp, off, reg);
   1103         else if (size == 4)
   1104                 print("ustl $%d,%d($%d)\n", tmp, off, reg);
   1105         else
   1106                 print("ustq $%d,%d($%d)\n", tmp, off, reg);
   1107 }
   1108 
   1109 /* stabinit - initialize stab output */
   1110 static void stabinit(char *file, int argc, char *argv[]) {
   1111         if (file) {
   1112                 print(".file 2,\"%s\"\n", file);
   1113                 currentfile = file;
   1114         }
   1115 }
   1116 
   1117 /* stabline - emit stab entry for source coordinate *cp */
   1118 static void stabline(Coordinate *cp) {
   1119         if (cp->file && cp->file != currentfile) {
   1120                 print(".file 2,\"%s\"\n", cp->file);
   1121                 currentfile = cp->file;
   1122         }
   1123         print(".loc 2,%d\n", cp->y);
   1124 }
   1125 
   1126 /* stabsym - output a stab entry for symbol p */
   1127 static void stabsym(Symbol p) {
   1128         if (p == cfunc && IR->stabline)
   1129                 (*IR->stabline)(&p->src);
   1130 }
   1131 Interface alphaIR = {
   1132         1, 1, 0,  /* char */
   1133         2, 2, 0,  /* short */
   1134         4, 4, 0,  /* int */
   1135         8, 8, 0,  /* long */
   1136         8, 8, 0,  /* long long */
   1137         4, 4, 1,  /* float */
   1138         8, 8, 1,  /* double */
   1139         8, 8, 1,  /* long double */
   1140         8, 8, 0,  /* T * */
   1141         0, 1, 0,  /* struct */
   1142 
   1143         1,      /* little_endian */
   1144         0,  /* mulops_calls */
   1145         0,  /* wants_callb */
   1146         1,  /* wants_argb */
   1147         1,  /* left_to_right */
   1148         0,  /* wants_dag */
   1149         0,  /* unsigned_char */
   1150         address,
   1151         blockbeg,
   1152         blockend,
   1153         defaddress,
   1154         defconst,
   1155         defstring,
   1156         defsymbol,
   1157         emit,
   1158         export,
   1159         function,
   1160         gen,
   1161         global,
   1162         import,
   1163         local,
   1164         progbeg,
   1165         progend,
   1166         segment,
   1167         space,
   1168         0, 0, 0, stabinit, stabline, stabsym, 0,
   1169         {
   1170                 1,      /* max_unaligned_load */
   1171                 rmap,
   1172                 blkfetch, blkstore, blkloop,
   1173                 _label,
   1174                 _rule,
   1175                 _nts,
   1176                 _kids,
   1177                 _string,
   1178                 _templates,
   1179                 _isinstruction,
   1180                 _ntname,
   1181                 emit2,
   1182                 doarg,
   1183                 target,
   1184                 clobber,
   1185 
   1186         }
   1187 
   1188 };
   1189 
   1190 
   1191 static char rcsid[] = "$Id: alpha.md 145 2001-10-17 21:53:10Z timo $";
   1192