$(eval CLEANABLES += $(OBJDIR)/$D/preprocessed-comm2.y)
$(OBJDIR)/$D/preprocessed-comm2.y: mach/proto/as/comm2.y $(CPPANSI) \
+ mach/$(ARCH)/as/mach1.c \
mach/$(ARCH)/as/mach2.c \
+ mach/$(ARCH)/as/mach3.c \
mach/$(ARCH)/as/mach4.c
@echo PREPROCESS $$@
@mkdir -p $$(dir $$@)
extern void branch_addcmp_lit_reg_instr(int cc, int rd, long va, int rs, struct expr_t* expr);
extern void branch_addcmp_reg_lit_instr(int cc, int rd, int ra, long vs, struct expr_t* expr);
extern void branch_addcmp_lit_lit_instr(int cc, int rd, long va, long vs, struct expr_t* expr);
+extern void lea_stack_instr(int rd, long va, int rs);
+extern void lea_address_instr(int rd, struct expr_t* expr);
\ No newline at end of file
%token <y_word> OP_MISC
%token <y_word> OP_MISCL
%token <y_word> OP_STACK
+%token <y_word> OP_LEA
0, OP_MEM, B8(00000110), "ldhs",
0, OP_MEM, B8(00000111), "sths",
+0, OP_LEA, 0, "lea",
\ No newline at end of file
| OP_MEM CC GPR ',' '(' GPR ')' '+' '+' { mem_postincr_instr($1, $2, $3, $6); }
| OP_MEM GPR ',' expr { mem_address_instr($1, $2, &$4); }
+
+ | OP_LEA GPR ',' absexp '(' GPR ')' { lea_stack_instr($2, $4, $6); }
+ | OP_LEA GPR ',' expr { lea_address_instr($2, &$4); }
;
branch_addcmp_common(B16(11000000,00000000) | (vs<<8), 8, expr);
}
+/* lea, where the source is relative to the stack. */
+
+void lea_stack_instr(int rd, long va, int rs)
+{
+ if (rs != 25)
+ serror("source register must be sp");
+
+ if (!fitx(va, 6))
+ serror("offset too big to encode in instruction");
+ va = maskx(va, 6);
+
+ emit2(B16(00010000,00000000) | (rd<<0) | (va<<5));
+}
+
+/* lea, where the source is an address. */
+
+void lea_address_instr(int rd, struct expr_t* expr)
+{
+ newrelo(expr->typ, RELOVC4);
+ emit2(B16(11100101,00000000) | (rd<<0));
+ emit4(expr->val);
+}
+