/* $Id: mach4.c, v1.9 15-Mar-89 AJM */
-operation : BRANCH optlink expr
- {branch($1, $2, &$3);}
- | DATA1 optcond opts optp REG ',' REG ',' operand
- {data($1, $2|$3|$4|$5<<12|$7<<16, $9.val, $9.typ);}
- | DATA2 optcond opts optp REG ',' operand
- {data($1, $2|$3|$4|$5<<12, $7.val, $7.typ);}
- | DATA3 optcond opts optp REG ',' operand
- {data($1, $2|$3|$4|$5<<16, $7.val, $7.typ);}
- | SDT optcond optt REG ',' address
- {strldr($1|$2|$3|$4<<12,$6);}
- | SDT2 optcond optt REG ',' splitaddress
- {strldr($1|$2|$3|$4<<12,$6);}
- | BDT optcond REG optexc ',' reglist optpsr
- {emit4($1|$2|$3<<16|$4|$6|$7);}
- | SWI optcond expr
- {emit4($1|$2|$3.val);}
- | MUL optcond REG ',' REG ',' REG
- {emit4($1|$2|$3<<16|$5|$7<<8);}
- | MLA optcond REG ',' REG ',' REG ',' REG
- {emit4($1|$2|$3<<16|$5|$7<<8|$9<<12);}
- ;
-
-optlink : {$$=0;}
- | LINK
- {$$=$1;}
- ;
-
-optcond : {$$=0xE0000000;}
- | COND
- {$$=$1;}
- ;
-
-opts : {$$=0;}
- | SET
- {$$=$1;}
- ;
-
-optt : {$$=0;}
- | TRANS
- {$$=$1;}
- ;
-
-optp : {$$=0;}
- | PEE
- {$$=$1;}
- ;
-
-optexc : {$$=0;}
- | '<'
- {$$=0x00200000;}
- ;
-
-optpsr : {$$=0;}
- | '^'
- {$$=0x00400000;}
- ;
-
-operand : REG optshift
- {$$.val = $1|$2; $$.typ = S_REG;}
- | '#'expr
- {$$ = $2;}
- ;
-
-optshift : ',' SHIFT shftcnt
- {$$ = $2|$3;}
- | ',' RRX
- {$$ = $2;}
- |
- {$$ = 0;}
- ;
-
-aoptshift : ',' SHIFT '#' expr
- {$$ = $2|calcshft($4.val, $4.typ, $<y_word>0);}
- | ',' RRX
- {$$ = $2;}
- |
- {$$ = 0;}
- ;
-
-shftcnt : '#' expr
- {$$ = calcshft($2.val, $2.typ, $<y_word>0);}
- | REG
- {$$ = $1<<8|0x10;}
- ;
-
-address : expr
- {success = 0; $$ = $1.val;}
- | '[' REG ']'
- {success = 1; $$ = 0x01000000|$2<<16;}
- | '[' REG ',' offset ']' optexc
- {success = 1; $$ = 0x01000000|$2<<16|$4|$6;}
- | '[' REG ']' ',' offset
- {success = 1; $$ = $2<<16|$5;}
- ;
-
-offset : '#' expr
- {$$ = calcoffset($2.val);}
- | optsign REG aoptshift
- {$$ = 0x02000000|$1|$2|$3;}
- ;
-
-splitaddress : expr
- {success = 0; $$ = $1.val;}
- | '[' REG ']'
- {success = 1; $$ = 0x01000000|$2<<16;}
- | '[' REG ',' splitoffset ']' optexc
- {success = 1; $$ = 0x01000000|$2<<16|$4|$6;}
- | '[' REG ']' ',' splitoffset
- {success = 1; $$ = $2<<16|$5;}
- ;
-
-splitoffset : '#' expr
- {$$ = splitoffset($2.val);}
- ;
-
-optsign : {$$ = 0x00800000;}
- | '+'
- {$$ = 0x00800000;}
- | '-'
- {$$ = 0x0;}
- ;
-
-reglist : '{' rlist '}'
- {$$ = $2;}
- ;
-
-rlist : REG
- {$$ = 1<<$1;}
- | rlist ',' REG
- {$$ = $1|1<<$3;}
- | REG '-' REG
- {
- for ($$ = 0; $1 <= $3; $1++)
- $$ |= (1<<$1);
- }
- ;
+operation
+ : BRANCH optlink expr { branch($1, $2, &$3); }
+ | DATA1 optcond opts optp REG ',' REG ',' operand { data($1, $2 | $3 | $4 | $5<<12|$7<<16, $9.val, $9.typ); }
+ | DATA2 optcond opts optp REG ',' operand { data($1, $2 | $3 | $4 | $5<<12, $7.val, $7.typ); }
+ | DATA3 optcond opts optp REG ',' operand { data($1, $2 | $3 | $4 | $5<<16, $7.val, $7.typ); }
+ | SDT optcond optt REG ',' address { emit4($1 | $2 | $3 | $4<<12 | $6); }
+ | SDT2 optcond optt REG ',' splitaddress { emit4($1 | $2 | $3 | $4<<12 | $6); }
+ | SDT optcond optt REG ',' expr { strldr($1 | $2 | $3 | $4<<12, &$6); }
+ | SDT2 optcond optt REG ',' expr { strldr($1 | $2 | $3 | $4<<12, &$6); }
+ | BDT optcond REG optexc ',' reglist optpsr { emit4($1 | $2 | $3<<16 |$4 | $6 | $7); }
+ | SWI optcond expr { emit4($1 | $2 | $3.val); }
+ | MUL optcond REG ',' REG ',' REG { emit4($1 | $2 | $3<<16 |$5 | $7<<8); }
+ | MLA optcond REG ',' REG ',' REG ',' REG { emit4($1 | $2 | $3<<16 |$5 | $7<<8 | $9<<12); }
+ ;
+
+optlink
+ : { $$=0; }
+ | LINK { $$=$1; }
+ ;
+
+optcond
+ : { $$=0xE0000000; }
+ | COND { $$=$1; }
+ ;
+
+opts
+ : { $$=0; }
+ | SET { $$=$1; }
+ ;
+
+optt
+ : { $$=0; }
+ | TRANS { $$=$1; }
+ ;
+
+optp
+ : { $$=0; }
+ | PEE { $$=$1; }
+ ;
+
+optexc
+ : { $$=0; }
+ | '<' { $$=0x00200000; }
+ ;
+
+optpsr
+ : { $$=0; }
+ | '^' { $$=0x00400000; }
+ ;
+
+operand
+ : REG optshift { $$.val = $1|$2; $$.typ = S_REG; }
+ | '#'expr { $$ = $2; }
+ ;
+
+optshift
+ : ',' SHIFT shftcnt { $$ = $2|$3; }
+ | ',' RRX { $$ = $2; }
+ | { $$ = 0; }
+ ;
+
+aoptshift
+ : ',' SHIFT '#' expr { $$ = $2|calcshft($4.val, $4.typ, $<y_word>0); }
+ | ',' RRX { $$ = $2; }
+ | { $$ = 0; }
+ ;
+
+shftcnt
+ : '#' expr { $$ = calcshft($2.val, $2.typ, $<y_word>0); }
+ | REG { $$ = $1<<8|0x10; }
+ ;
+
+address
+ : '[' REG ']' { $$ = 0x01000000|$2<<16; }
+ | '[' REG ',' offset ']' optexc { $$ = 0x01000000|$2<<16|$4|$6; }
+ | '[' REG ']' ',' offset { $$ = $2<<16|$5; }
+ ;
+
+offset
+ : '#' expr { $$ = calcoffset($2.val); }
+ | optsign REG aoptshift { $$ = 0x02000000|$1|$2|$3; }
+ ;
+
+splitaddress
+ : '[' REG ']' { $$ = 0x01000000|$2<<16; }
+ | '[' REG ',' splitoffset ']' optexc { $$ = 0x01000000|$2<<16|$4|$6; }
+ | '[' REG ']' ',' splitoffset { $$ = $2<<16|$5; }
+ ;
+
+splitoffset
+ : '#' expr { $$ = splitoffset($2.val); }
+ ;
+
+optsign
+ : { $$ = 0x00800000; }
+ | '+' { $$ = 0x00800000; }
+ | '-' { $$ = 0x0; }
+ ;
+
+reglist
+ : '{' rlist '}' { $$ = $2; }
+ ;
+
+rlist
+ : REG { $$ = 1<<$1; }
+ | rlist ',' REG { $$ = $1|1<<$3; }
+ | REG '-' REG
+ {
+ for ($$ = 0; $1 <= $3; $1++)
+ $$ |= (1<<$1);
+ }
+ ;
+
+// vim: set ts=4 sw=4 expandtab :
return 0;
}
-/* This routine deals with STR and LDR instructions */
-
-void strldr(uint32_t opc, valu_t val)
+void strldr(uint32_t opc, struct expr_t* expr)
{
+ quad type = expr->typ & S_TYP;
uint32_t d;
+
+ /* Sanity checking. */
- /* If the expression was a register, then just output it and save 24
- bytes */
-
- if (success)
+ if (type == S_ABS)
+ serror("can't use absolute addresses here");
+
+ if (type == DOTTYP)
{
- emit4(opc | val);
- return;
- }
+ /* Reference to code in this section. */
- d = val - DOTVAL - 8;
- if (fitu(d, 12))
- { /* If it's +ve */
- emit4(opc | d | 0x018F0000); /* PC rel, up bit */
- return;
- }
+ uint32_t d = expr->val - DOTVAL - 8;
+ if (fitu(d, 12))
+ { /* If it's +ve */
+ emit4(opc | d | 0x018F0000); /* PC rel, up bit */
+ return;
+ }
- d = -d;
- if (fitu(d, 12))
- { /* If it's -ve */
- emit4(opc | d | 0x010F0000); /* PC rel, no up bit */
- return;
+ d = -d;
+ if (fitu(d, 12))
+ { /* If it's -ve */
+ emit4(opc | d | 0x010F0000); /* PC rel, no up bit */
+ return;
+ }
+
+ serror("displacement to near constant is too big");
}
- serror("displacement overflow: 0x%x", d);
- return;
+ serror("cannot directly address symbols in another section");
}
word_t calcshft(valu_t val, short typ, word_t styp)