Fix load and store instructions.
authorDavid Given <dg@cowlark.com>
Tue, 6 Sep 2016 21:58:25 +0000 (23:58 +0200)
committerDavid Given <dg@cowlark.com>
Tue, 6 Sep 2016 21:58:25 +0000 (23:58 +0200)
--HG--
branch : default-branch

mach/arm/as/mach0.c
mach/arm/as/mach1.c
mach/arm/as/mach4.c
mach/arm/as/mach5.c

index ffce764..123d08e 100644 (file)
@@ -18,6 +18,8 @@
 #undef word_t
 #define word_t uint32_t
 
+typedef uint32_t quad;
+
 #undef ALIGNWORD
 #define ALIGNWORD      4
 
index f1eb84a..c552ed2 100644 (file)
@@ -1,6 +1,5 @@
 /* $Header; mach1.c, v1.1 06-Mar-89 AJM */
 extern word_t opcode;
-extern int success;    /* LDR/STR address failure flag */
 
-extern void strldr(uint32_t opc, valu_t val);
+extern void strldr(uint32_t opc, struct expr_t* expr);
 
index c3874ee..4f3f597 100644 (file)
 /* $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 :
index 97b0365..73f5067 100644 (file)
@@ -179,37 +179,38 @@ word_t splitoffset(valu_t val)
        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)