static void newfix (int ptr, bfd_reloc_code_real_type type, int size, expressionS *operand) { fixS *fixP; /* Size is in nibbles. */ if (operand->X_add_symbol || operand->X_op_symbol || operand->X_add_number) { int is_pcrel; switch(type) { case BFD_RELOC_8_PCREL: case BFD_RELOC_Z8K_CALLR: case BFD_RELOC_Z8K_DISP7: is_pcrel = 1; break; default: is_pcrel = 0; break; } fixP = fix_new_exp (frag_now, ptr, size / 2, operand, is_pcrel, type); if (is_pcrel) fixP->fx_no_overflow = 1; } }
void pj_cons_fix_new_pj (fragS *frag, int where, int nbytes, expressionS *exp) { static int rv[5][2] = { { 0, 0 }, { BFD_RELOC_8, BFD_RELOC_8 }, { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 }, { 0, 0 }, { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }}; fix_new_exp (frag, where, nbytes, exp, 0, pending_reloc ? pending_reloc : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]); pending_reloc = 0; }
fixS * gas_cgen_record_fixup_exp (fragS *frag, int where, const CGEN_INSN *insn, int length, const CGEN_OPERAND *operand, int opinfo, expressionS *exp) { fixS *fixP; /* It may seem strange to use operand->attrs and not insn->attrs here, but it is the operand that has a pc relative relocation. */ fixP = fix_new_exp (frag, where, length / 8, exp, CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR), (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + (int) operand->type)); fixP->fx_cgen.insn = insn; fixP->fx_cgen.opinfo = opinfo; fixP->fx_cgen.field = NULL; fixP->fx_cgen.msb_field_p = 0; return fixP; }
void md_assemble (char *str) { char *op_start; char *op_end; moxie_opc_info_t *opcode; char *p; char pend; unsigned short iword = 0; int nlen = 0; /* Drop leading whitespace. */ while (*str == ' ') str++; /* Find the op code end. */ op_start = str; for (op_end = str; *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' '; op_end++) nlen++; pend = *op_end; *op_end = 0; if (nlen == 0) as_bad (_("can't find opcode ")); opcode = (moxie_opc_info_t *) hash_find (opcode_hash_control, op_start); *op_end = pend; if (opcode == NULL) { as_bad (_("unknown opcode %s"), op_start); return; } p = frag_more (2); switch (opcode->itype) { case MOXIE_F2_A8V: iword = (1<<15) | (opcode->opcode << 12); while (ISSPACE (*op_end)) op_end++; { expressionS arg; int reg; reg = parse_register_operand (&op_end); iword += (reg << 8); if (*op_end != ',') as_warn (_("expecting comma delimited register operands")); op_end++; op_end = parse_exp_save_ilp (op_end, &arg); fix_new_exp (frag_now, ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal), 1, &arg, 0, BFD_RELOC_8); } break; case MOXIE_F1_AB: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { int dest, src; dest = parse_register_operand (&op_end); if (*op_end != ',') as_warn (_("expecting comma delimited register operands")); op_end++; src = parse_register_operand (&op_end); iword += (dest << 4) + src; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); } break; case MOXIE_F1_A4: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *where; int regnum; regnum = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; iword += (regnum << 4); if (*op_end != ',') { as_bad (_("expecting comma delimited operands")); ignore_rest_of_line (); return; } op_end++; op_end = parse_exp_save_ilp (op_end, &arg); where = frag_more (4); fix_new_exp (frag_now, (where - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } break; case MOXIE_F1_M: case MOXIE_F1_4: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *where; op_end = parse_exp_save_ilp (op_end, &arg); where = frag_more (4); fix_new_exp (frag_now, (where - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } break; case MOXIE_F1_NARG: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); break; case MOXIE_F1_A: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { int reg; reg = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); iword += (reg << 4); } break; case MOXIE_F1_ABi: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { int a, b; a = parse_register_operand (&op_end); if (*op_end != ',') as_warn (_("expecting comma delimited register operands")); op_end++; if (*op_end != '(') { as_bad (_("expecting indirect register `($rA)'")); ignore_rest_of_line (); return; } op_end++; b = parse_register_operand (&op_end); if (*op_end != ')') { as_bad (_("missing closing parenthesis")); ignore_rest_of_line (); return; } op_end++; iword += (a << 4) + b; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); } break; case MOXIE_F1_AiB: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { int a, b; if (*op_end != '(') { as_bad (_("expecting indirect register `($rA)'")); ignore_rest_of_line (); return; } op_end++; a = parse_register_operand (&op_end); if (*op_end != ')') { as_bad (_("missing closing parenthesis")); ignore_rest_of_line (); return; } op_end++; if (*op_end != ',') as_warn (_("expecting comma delimited register operands")); op_end++; b = parse_register_operand (&op_end); iword += (a << 4) + b; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); } break; case MOXIE_F1_4A: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *where; int a; op_end = parse_exp_save_ilp (op_end, &arg); where = frag_more (4); fix_new_exp (frag_now, (where - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); if (*op_end != ',') { as_bad (_("expecting comma delimited operands")); ignore_rest_of_line (); return; } op_end++; a = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); iword += (a << 4); } break; case MOXIE_F1_ABi2: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *offset; int a, b; a = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; if (*op_end != ',') { as_bad (_("expecting comma delimited operands")); ignore_rest_of_line (); return; } op_end++; op_end = parse_exp_save_ilp (op_end, &arg); offset = frag_more (2); fix_new_exp (frag_now, (offset - frag_now->fr_literal), 2, &arg, 0, BFD_RELOC_16); if (*op_end != '(') { as_bad (_("expecting indirect register `($rX)'")); ignore_rest_of_line (); return; } op_end++; b = parse_register_operand (&op_end); if (*op_end != ')') { as_bad (_("missing closing parenthesis")); ignore_rest_of_line (); return; } op_end++; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); iword += (a << 4) + b; } break; case MOXIE_F1_AiB2: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *offset; int a, b; op_end = parse_exp_save_ilp (op_end, &arg); offset = frag_more (2); fix_new_exp (frag_now, (offset - frag_now->fr_literal), 2, &arg, 0, BFD_RELOC_16); if (*op_end != '(') { as_bad (_("expecting indirect register `($rX)'")); ignore_rest_of_line (); return; } op_end++; a = parse_register_operand (&op_end); if (*op_end != ')') { as_bad (_("missing closing parenthesis")); ignore_rest_of_line (); return; } op_end++; if (*op_end != ',') { as_bad (_("expecting comma delimited operands")); ignore_rest_of_line (); return; } op_end++; b = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); iword += (a << 4) + b; } break; case MOXIE_F2_NARG: iword = opcode->opcode << 12; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); break; case MOXIE_F3_PCREL: iword = (3<<14) | (opcode->opcode << 10); while (ISSPACE (*op_end)) op_end++; { expressionS arg; op_end = parse_exp_save_ilp (op_end, &arg); fix_new_exp (frag_now, (p - frag_now->fr_literal), 2, &arg, TRUE, BFD_RELOC_MOXIE_10_PCREL); } break; default: abort (); } md_number_to_chars (p, iword, 2); while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); if (pending_reloc) as_bad (_("Something forgot to clean up\n")); }
/* Convert the instructions into frags and bytes */ void md_assemble(char *str) { char *op_start; char *op_end; char op_name[10]; const bexkat1_opc_info_t *opcode; char *p; char pend; unsigned int iword; int nlen = 0; int regnum; expressionS arg; int offset; while (*str == ' ') str++; // mark opcode op_start = str; for (op_end = str; *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' '; op_end++) nlen++; pend = *op_end; *op_end = 0; strncpy(op_name, op_start, 10); *op_end = pend; if (nlen == 0) as_bad(_("can't find opcode ")); while (ISSPACE(*op_end)) op_end++; opcode = (bexkat1_opc_info_t *) hash_find(opcode_hash_control, op_name); if (opcode == NULL) { as_bad(_("unknown opcode %s"), op_name); return; } iword = (opcode->type << 28) | (opcode->opcode << 24) | opcode->size; p = frag_more(4); switch (opcode->type) { case BEXKAT1_INH: if (opcode->args == 0) { md_number_to_chars(p, iword, 4); } if (opcode->args == 1) { op_end = parse_exp_save_ilp(op_end, &arg); if (opcode->size) { md_number_to_chars(p, iword, 4); p = frag_more(4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } else { if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset < -16384 || offset > 16383) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } } break; case BEXKAT1_PUSH: if (opcode->args == 1 && opcode->opcode == 2) // bsr goto branch; if (opcode->args == 1) { if (opcode->size) { op_end = parse_exp_save_ilp(op_end, &arg); md_number_to_chars(p, iword, 4); p = frag_more(4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } else { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A md_number_to_chars(p, iword, 4); } } if (opcode->args == 2) { if (*op_end != '(') op_end = parse_exp_save_ilp(op_end, &arg); else { // Implicit 0 offset to allow for indirect arg.X_op = O_constant; arg.X_add_number = 0; } if (*op_end != '(') { as_bad(_("missing open paren: %s"), op_end); ignore_rest_of_line(); return; } op_end++; // burn paren while (ISSPACE(*op_end)) op_end++; regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A if (*op_end != ')') { as_bad(_("missing close paren: %s"), op_end); ignore_rest_of_line(); return; } op_end++; if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset < -16384 || offset > 16383) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } break; case BEXKAT1_POP: if (opcode->args == 0) { md_number_to_chars(p, iword, 4); } if (opcode->args == 1) { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A md_number_to_chars(p, iword, 4); } break; case BEXKAT1_MOV: if (opcode->opcode == 0) { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A md_number_to_chars(p, iword, 4); break; } /* __attribute__((fallthrough)); */ case BEXKAT1_CMP: case BEXKAT1_FPU: case BEXKAT1_FP: case BEXKAT1_ALU: case BEXKAT1_INT: case BEXKAT1_INTU: if (opcode->args > 1) { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A if (*op_end != ',') { as_bad(_("missing comma: %s"), op_end); return; } op_end++; while (ISSPACE(*op_end)) op_end++; } regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 16; // B if (opcode->args > 2) { if (*op_end != ',') { as_bad(_("missing comma: %s"), op_end); return; } op_end++; while (ISSPACE(*op_end)) op_end++; if (opcode->opcode < 8) { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 12; // C md_number_to_chars(p, iword, 4); } else { op_end = parse_exp_save_ilp(op_end, &arg); if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset < -16384 || offset > 16383) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } } else { md_number_to_chars(p, iword, 4); } break; branch: case BEXKAT1_BRANCH: md_number_to_chars(p, iword, 4); op_end = parse_exp_save_ilp(op_end, &arg); if (target_big_endian) fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, TRUE, BFD_RELOC_BEXKAT1_15_PCREL); else fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, TRUE, BFD_RELOC_BEXKAT1_15_PCREL); break; case BEXKAT1_LOAD: case BEXKAT1_STORE: // A, regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A if (*op_end != ',') { as_bad(_("missing comma: %s"), op_end); return; } op_end++; while (ISSPACE(*op_end)) op_end++; /* __attribute__((fallthrough)); */ case BEXKAT1_JUMP: if (opcode->size) { // big address md_number_to_chars(p, iword, 4); op_end = parse_exp_save_ilp(op_end, &arg); p = frag_more(4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } else { // exp(B) if (*op_end != '(') op_end = parse_exp_save_ilp(op_end, &arg); else { // Implicit 0 offset to allow for indirect arg.X_op = O_constant; arg.X_add_number = 0; } if (*op_end != '(') { as_bad(_("missing open paren: %s"), op_end); ignore_rest_of_line(); return; } op_end++; // burn paren while (ISSPACE(*op_end)) op_end++; regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 16; // B if (*op_end != ')') { as_bad(_("missing close paren: %s"), op_end); ignore_rest_of_line(); return; } op_end++; if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset < -16384 || offset > 16383) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } break; case BEXKAT1_LDI: regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A if (*op_end != ',') { as_bad(_("missing comma: %s"), op_end); return; } op_end++; while (ISSPACE(*op_end)) op_end++; op_end = parse_exp_save_ilp(op_end, &arg); if (opcode->size) { md_number_to_chars(p, iword, 4); p = frag_more(4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } else { if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset >= 32768) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } break; } while (ISSPACE(*op_end)) op_end++; if (*op_end != 0) as_warn("extra stuff on line ignored %s %c", op_start, *op_end); if (pending_reloc) as_bad("Something forgot to clean up\n"); return; }