1 // cmd/9a/a.y from Vita Nuova.
3 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
4 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
5 // Portions Copyright © 1997-1999 Vita Nuova Limited
6 // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
7 // Portions Copyright © 2004,2006 Bruce Ellis
8 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
9 // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
10 // Portions Copyright © 2009 The Go Authors. All rights reserved.
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to deal
14 // in the Software without restriction, including without limitation the rights
15 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 // copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
19 // The above copyright notice and this permission notice shall be included in
20 // all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 . "cmd/internal/obj/ppc64"
55 %token <lval> LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
56 %token <lval> LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
57 %token <lval> LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
58 %token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH
59 %token <lval> LREG LFREG LR LCR LF LFPSCR
60 %token <lval> LLR LCTR LSPR LSPREG LSEG LMSR
61 %token <lval> LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
62 %token <lval> LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
65 %token <sym> LNAME LLAB LVAR
66 %type <lval> con expr pointer offset sreg
67 %type <addr> addr rreg regaddr name creg freg xlreg lr ctr
68 %type <addr> imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
76 $1 = asm.LabelLookup($1);
77 if $1.Type == LLAB && $1.Value != int64(asm.PC) {
78 yyerror("redeclaration of %s", $1.Labelname)
81 $1.Value = int64(asm.PC);
92 yyerror("redeclaration of %s", $1.Name)
106 * load ints and bytes
110 outcode(int($1), &$2, NREG, &$4);
112 | LMOVW addr ',' rreg
114 outcode(int($1), &$2, NREG, &$4);
116 | LMOVW regaddr ',' rreg
118 outcode(int($1), &$2, NREG, &$4);
120 | LMOVB rreg ',' rreg
122 outcode(int($1), &$2, NREG, &$4);
124 | LMOVB addr ',' rreg
126 outcode(int($1), &$2, NREG, &$4);
128 | LMOVB regaddr ',' rreg
130 outcode(int($1), &$2, NREG, &$4);
135 | LFMOV addr ',' freg
137 outcode(int($1), &$2, NREG, &$4);
139 | LFMOV regaddr ',' freg
141 outcode(int($1), &$2, NREG, &$4);
143 | LFMOV fimm ',' freg
145 outcode(int($1), &$2, NREG, &$4);
147 | LFMOV freg ',' freg
149 outcode(int($1), &$2, NREG, &$4);
151 | LFMOV freg ',' addr
153 outcode(int($1), &$2, NREG, &$4);
155 | LFMOV freg ',' regaddr
157 outcode(int($1), &$2, NREG, &$4);
160 * store ints and bytes
162 | LMOVW rreg ',' addr
164 outcode(int($1), &$2, NREG, &$4);
166 | LMOVW rreg ',' regaddr
168 outcode(int($1), &$2, NREG, &$4);
170 | LMOVB rreg ',' addr
172 outcode(int($1), &$2, NREG, &$4);
174 | LMOVB rreg ',' regaddr
176 outcode(int($1), &$2, NREG, &$4);
181 | LMOVW freg ',' addr
183 outcode(int($1), &$2, NREG, &$4);
185 | LMOVW freg ',' regaddr
187 outcode(int($1), &$2, NREG, &$4);
190 * floating point status
192 | LMOVW fpscr ',' freg
194 outcode(int($1), &$2, NREG, &$4);
196 | LMOVW freg ',' fpscr
198 outcode(int($1), &$2, NREG, &$4);
200 | LMOVW freg ',' imm ',' fpscr
202 outgcode(int($1), &$2, NREG, &$4, &$6);
204 | LMOVW fpscr ',' creg
206 outcode(int($1), &$2, NREG, &$4);
208 | LMOVW imm ',' fpscrf
210 outcode(int($1), &$2, NREG, &$4);
214 outcode(int($1), &$2, int($4), &nullgen);
217 * field moves (mtcrf)
219 | LMOVW rreg ',' imm ',' lcr
221 outgcode(int($1), &$2, NREG, &$4, &$6);
223 | LMOVW rreg ',' creg
225 outcode(int($1), &$2, NREG, &$4);
229 outcode(int($1), &$2, NREG, &$4);
233 * logical instructions
237 | LADDW rreg ',' sreg ',' rreg
239 outcode(int($1), &$2, int($4), &$6);
241 | LADDW imm ',' sreg ',' rreg
243 outcode(int($1), &$2, int($4), &$6);
245 | LADDW rreg ',' imm ',' rreg
247 outgcode(int($1), &$2, NREG, &$4, &$6);
249 | LADDW rreg ',' rreg
251 outcode(int($1), &$2, NREG, &$4);
255 outcode(int($1), &$2, NREG, &$4);
257 | LLOGW rreg ',' sreg ',' rreg
259 outcode(int($1), &$2, int($4), &$6);
261 | LLOGW rreg ',' rreg
263 outcode(int($1), &$2, NREG, &$4);
265 | LSHW rreg ',' sreg ',' rreg
267 outcode(int($1), &$2, int($4), &$6);
271 outcode(int($1), &$2, NREG, &$4);
273 | LSHW imm ',' sreg ',' rreg
275 outcode(int($1), &$2, int($4), &$6);
279 outcode(int($1), &$2, NREG, &$4);
283 outcode(int($1), &$2, NREG, &$4);
287 outcode(int($1), &$2, NREG, &$2);
290 * multiply-accumulate
292 | LMA rreg ',' sreg ',' rreg
294 outcode(int($1), &$2, int($4), &$6);
297 * move immediate: macro for cau+or, addi, addis, and other combinations
301 outcode(int($1), &$2, NREG, &$4);
303 | LMOVW ximm ',' rreg
305 outcode(int($1), &$2, NREG, &$4);
308 * condition register operations
310 | LCROP cbit ',' cbit
312 outcode(int($1), &$2, int($4.Reg), &$4);
314 | LCROP cbit ',' con ',' cbit
316 outcode(int($1), &$2, int($4), &$6);
319 * condition register moves
320 * move from machine state register
322 | LMOVW creg ',' creg
324 outcode(int($1), &$2, NREG, &$4);
328 outcode(int($1), &$2, NREG, &$4);
332 outcode(int($1), &$2, NREG, &$4);
336 outcode(int($1), &$2, NREG, &$4);
338 | LMOVW xlreg ',' rreg
340 outcode(int($1), &$2, NREG, &$4);
342 | LMOVW rreg ',' xlreg
344 outcode(int($1), &$2, NREG, &$4);
348 outcode(int($1), &$2, NREG, &$4);
352 outcode(int($1), &$2, NREG, &$4);
355 * branch, branch conditional
356 * branch conditional register
357 * branch conditional to count register
361 outcode(int($1), &nullgen, NREG, &$2);
365 outcode(int($1), &nullgen, NREG, &$2);
369 outcode(int($1), &nullgen, NREG, &$3);
373 outcode(int($1), &nullgen, NREG, &$3);
377 outcode(int($1), &nullgen, NREG, &$3);
379 | LBRA ',' '(' xlreg ')'
381 outcode(int($1), &nullgen, NREG, &$4);
385 outcode(int($1), &$2, NREG, &$4);
389 outcode(int($1), &$2, NREG, &$4);
391 | LBRA creg ',' '(' xlreg ')'
393 outcode(int($1), &$2, NREG, &$5);
397 outcode(int($1), &nullgen, int($2), &$4);
401 outcode(int($1), &nullgen, int($2), &$4);
403 | LBRA con ',' '(' xlreg ')'
405 outcode(int($1), &nullgen, int($2), &$5);
407 | LBRA con ',' con ',' rel
413 outcode(int($1), &g, int($4), &$6);
415 | LBRA con ',' con ',' addr
421 outcode(int($1), &g, int($4), &$6);
423 | LBRA con ',' con ',' '(' xlreg ')'
429 outcode(int($1), &g, int($4), &$7);
434 | LTRAP rreg ',' sreg
436 outcode(int($1), &$2, int($4), &nullgen);
440 outcode(int($1), &$2, int($4), &nullgen);
444 outcode(int($1), &$2, NREG, &nullgen);
448 outcode(int($1), &nullgen, NREG, &nullgen);
451 * floating point operate
453 | LFCONV freg ',' freg
455 outcode(int($1), &$2, NREG, &$4);
457 | LFADD freg ',' freg
459 outcode(int($1), &$2, NREG, &$4);
461 | LFADD freg ',' freg ',' freg
463 outcode(int($1), &$2, int($4.Reg), &$6);
465 | LFMA freg ',' freg ',' freg ',' freg
467 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
469 | LFCMP freg ',' freg
471 outcode(int($1), &$2, NREG, &$4);
473 | LFCMP freg ',' freg ',' creg
475 outcode(int($1), &$2, int($6.Reg), &$4);
482 outcode(int($1), &$2, NREG, &$4);
486 outcode(int($1), &$2, NREG, &$4);
488 | LCMP rreg ',' rreg ',' creg
490 outcode(int($1), &$2, int($6.Reg), &$4);
492 | LCMP rreg ',' imm ',' creg
494 outcode(int($1), &$2, int($6.Reg), &$4);
499 | LRLWM imm ',' rreg ',' imm ',' rreg
501 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
503 | LRLWM imm ',' rreg ',' mask ',' rreg
505 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
507 | LRLWM rreg ',' rreg ',' imm ',' rreg
509 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
511 | LRLWM rreg ',' rreg ',' mask ',' rreg
513 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
516 * load/store multiple
518 | LMOVMW addr ',' rreg
520 outcode(int($1), &$2, NREG, &$4);
522 | LMOVMW rreg ',' addr
524 outcode(int($1), &$2, NREG, &$4);
527 * various indexed load/store
528 * indexed unary (eg, cache clear)
530 | LXLD regaddr ',' rreg
532 outcode(int($1), &$2, NREG, &$4);
534 | LXLD regaddr ',' imm ',' rreg
536 outgcode(int($1), &$2, NREG, &$4, &$6);
538 | LXST rreg ',' regaddr
540 outcode(int($1), &$2, NREG, &$4);
542 | LXST rreg ',' imm ',' regaddr
544 outgcode(int($1), &$2, NREG, &$4, &$6);
546 | LXMV regaddr ',' rreg
548 outcode(int($1), &$2, NREG, &$4);
550 | LXMV rreg ',' regaddr
552 outcode(int($1), &$2, NREG, &$4);
556 outcode(int($1), &$2, NREG, &nullgen);
563 outcode(int($1), &nullgen, NREG, &nullgen);
567 outcode(int($1), &$2, NREG, &nullgen);
571 outcode(int($1), &$2, NREG, &nullgen);
575 outcode(int($1), &nullgen, NREG, &$3);
579 outcode(int($1), &nullgen, NREG, &$3);
581 | LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
583 outcode(int($1), &$2, NREG, &nullgen);
590 outcode(int($1), &$2, NREG, &nullgen);
594 outcode(int($1), &$2, NREG, &nullgen);
601 if $2.Type_ != D_CONST || $4.Type_ != D_CONST {
602 yyerror("arguments to PCDATA must be integer constants")
604 outcode(int($1), &$2, NREG, &$4);
609 | LFUNCDAT imm ',' addr
611 if $2.Type_ != D_CONST {
612 yyerror("index for FUNCDATA must be integer constant")
614 if $4.Type_ != D_EXTERN && $4.Type_ != D_STATIC && $4.Type_ != D_OREG {
615 yyerror("value for FUNCDATA must be symbol reference")
617 outcode(int($1), &$2, NREG, &$4);
624 outcode(int($1), &nullgen, NREG, &nullgen);
632 outcode(int($1), &$2, NREG, &$4);
634 | LTEXT name ',' con ',' imm
637 $6.Offset &= 0xffffffff;
638 $6.Offset |= -obj.ArgsSizeUnknown << 32;
639 outcode(int($1), &$2, int($4), &$6);
641 | LTEXT name ',' con ',' imm '-' con
644 $6.Offset &= 0xffffffff;
645 $6.Offset |= ($8 & 0xffffffff) << 32;
646 outcode(int($1), &$2, int($4), &$6);
651 | LDATA name '/' con ',' imm
653 outcode(int($1), &$2, int($4), &$6);
655 | LDATA name '/' con ',' ximm
657 outcode(int($1), &$2, int($4), &$6);
659 | LDATA name '/' con ',' fimm
661 outcode(int($1), &$2, int($4), &$6);
668 outcode(int($1), &nullgen, NREG, &nullgen);
676 $$.Offset = $1 + int64(asm.PC);
680 $1 = asm.LabelLookup($1);
682 if asm.Pass == 2 && $1.Type != LLAB {
683 yyerror("undefined label: %s", $1.Labelname)
686 $$.Offset = $1.Value + $2;
714 $$.Reg = NREG; /* whole register */
742 $$.Type_ = int16($1);
809 if(mb < 0 || mb > 31 || me < 0 || me > 31){
810 yyerror("illegal mask start/end value(s)");
815 v = (^uint32(0)>>uint(mb)) & (^uint32(0)<<uint(31-me))
817 v = (^uint32(0)>>uint(me+1)) & (^uint32(0)<<uint(31-(mb-1)))
819 $$.Offset = int64(v);
860 if $$ < 0 || $$ >= NREG {
861 print("register value out of range\n")
874 | '(' sreg '+' sreg ')'
902 | LNAME offset '(' pointer ')'
907 $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
910 | LNAME '<' '>' offset '(' LSB ')'
915 $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);