📄 tc-h8300.c
字号:
if (*src != ')' && '(') { as_bad (_("expected @(exp, reg16)")); return; } *ptr = src + 1; return; } len = parse_reg (src, &mode, &num, direction); if (len) { src += len; if (*src == '+') { src++; if ((mode & SIZE) != PSIZE) as_bad (_("Wrong size pointer register for architecture.")); op->mode = RSINC; op->reg = num; *ptr = src; return; } if ((mode & SIZE) != PSIZE) as_bad (_("Wrong size pointer register for architecture.")); op->mode = direction | IND | PSIZE; op->reg = num; *ptr = src; return; } else { /* must be a symbol */ op->mode = ABS | direction; src = parse_exp (src, &op->exp); *ptr = colonmod24 (op, src); return; } } if (*src == '#') { src++; op->mode = IMM; src = parse_exp (src, &op->exp); *ptr = skip_colonthing (src, &op->exp, &op->mode); return; } else if (strncmp (src, "mach", 4) == 0 || strncmp (src, "macl", 4) == 0) { op->reg = src[3] == 'l'; op->mode = MACREG; *ptr = src + 4; return; } else { src = parse_exp (src, &op->exp); /* Trailing ':' size ? */ if (*src == ':') { if (src[1] == '1' && src[2] == '6') { op->mode = PCREL | L_16; src += 3; } else if (src[1] == '8') { op->mode = PCREL | L_8; src += 2; } else { as_bad (_("expect :8 or :16 here")); } } else { op->mode = PCREL | bsize; } *ptr = src; }}static char *get_operands (noperands, op_end, operand) unsigned int noperands; char *op_end; struct h8_op *operand;{ char *ptr = op_end; switch (noperands) { case 0: operand[0].mode = 0; operand[1].mode = 0; break; case 1: ptr++; get_operand (&ptr, operand + 0, 0, SRC); if (*ptr == ',') { ptr++; get_operand (&ptr, operand + 1, 1, DST); } else { operand[1].mode = 0; } break; case 2: ptr++; get_operand (&ptr, operand + 0, 0, SRC); if (*ptr == ',') ptr++; get_operand (&ptr, operand + 1, 1, DST); break; default: abort (); } return ptr;}/* Passed a pointer to a list of opcodes which use different addressing modes, return the opcode which matches the opcodes provided. */static struct h8_opcode *get_specific (opcode, operands, size) struct h8_opcode *opcode; struct h8_op *operands; int size;{ struct h8_opcode *this_try = opcode; int found = 0; unsigned int this_index = opcode->idx; /* There's only one ldm/stm and it's easier to just get out quick for them. */ if (strcmp (opcode->name, "stm.l") == 0 || strcmp (opcode->name, "ldm.l") == 0) return this_try; while (this_index == opcode->idx && !found) { found = 1; this_try = opcode++; if (this_try->noperands == 0) { int this_size; this_size = this_try->how & SN; if (this_size != size && (this_size != SB || size != SN)) found = 0; } else { unsigned int i; for (i = 0; i < this_try->noperands && found; i++) { op_type op = this_try->args.nib[i]; int x = operands[i].mode; if ((op & (DISP | REG)) == (DISP | REG) && ((x & (DISP | REG)) == (DISP | REG))) { dispreg = operands[i].reg; } else if (op & REG) { if (!(x & REG)) found = 0; if (x & L_P) x = (x & ~L_P) | (Hmode ? L_32 : L_16); if (op & L_P) op = (op & ~L_P) | (Hmode ? L_32 : L_16); opsize = op & SIZE; /* The size of the reg is v important. */ if ((op & SIZE) != (x & SIZE)) found = 0; } else if ((op & ABSJMP) && (x & ABS)) { operands[i].mode &= ~ABS; operands[i].mode |= ABSJMP; /* But it may not be 24 bits long. */ if (!Hmode) { operands[i].mode &= ~SIZE; operands[i].mode |= L_16; } } else if ((op & (KBIT | DBIT)) && (x & IMM)) { /* This is ok if the immediate value is sensible. */ } else if (op & PCREL) { /* The size of the displacement is important. */ if ((op & SIZE) != (x & SIZE)) found = 0; } else if ((op & (DISP | IMM | ABS)) && (op & (DISP | IMM | ABS)) == (x & (DISP | IMM | ABS))) { /* Promote a L_24 to L_32 if it makes us match. */ if ((x & L_24) && (op & L_32)) { x &= ~L_24; x |= L_32; } /* Promote an L8 to L_16 if it makes us match. */ if (op & ABS && op & L_8 && op & DISP) { if (x & L_16) found = 1; } else if ((x & SIZE) != 0 && ((op & SIZE) != (x & SIZE))) found = 0; } else if ((op & MACREG) != (x & MACREG)) { found = 0; } else if ((op & MODE) != (x & MODE)) { found = 0; } } } } if (found) return this_try; else return 0;}static voidcheck_operand (operand, width, string) struct h8_op *operand; unsigned int width; char *string;{ if (operand->exp.X_add_symbol == 0 && operand->exp.X_op_symbol == 0) { /* No symbol involved, let's look at offset, it's dangerous if any of the high bits are not 0 or ff's, find out by oring or anding with the width and seeing if the answer is 0 or all fs. */ if ((operand->exp.X_add_number & ~width) != 0 && (operand->exp.X_add_number | width) != (~0)) { if (width == 255 && (operand->exp.X_add_number & 0xff00) == 0xff00) { /* Just ignore this one - which happens when trying to fit a 16 bit address truncated into an 8 bit address of something like bset. */ } else { as_warn (_("operand %s0x%lx out of range."), string, (unsigned long) operand->exp.X_add_number); } } }}/* RELAXMODE has one of 3 values: 0 Output a "normal" reloc, no relaxing possible for this insn/reloc 1 Output a relaxable 24bit absolute mov.w address relocation (may relax into a 16bit absolute address). 2 Output a relaxable 16/24 absolute mov.b address relocation (may relax into an 8bit absolute address). */static voiddo_a_fix_imm (offset, operand, relaxmode) int offset; struct h8_op *operand; int relaxmode;{ int idx; int size; int where; char *t = operand->mode & IMM ? "#" : "@"; if (operand->exp.X_add_symbol == 0) { char *bytes = frag_now->fr_literal + offset; switch (operand->mode & SIZE) { case L_2: check_operand (operand, 0x3, t); bytes[0] |= (operand->exp.X_add_number) << 4; break; case L_3: check_operand (operand, 0x7, t); bytes[0] |= (operand->exp.X_add_number) << 4; break; case L_8: check_operand (operand, 0xff, t); bytes[0] = operand->exp.X_add_number; break; case L_16: check_operand (operand, 0xffff, t); bytes[0] = operand->exp.X_add_number >> 8; bytes[1] = operand->exp.X_add_number >> 0; break; case L_24: check_operand (operand, 0xffffff, t); bytes[0] = operand->exp.X_add_number >> 16; bytes[1] = operand->exp.X_add_number >> 8; bytes[2] = operand->exp.X_add_number >> 0; break; case L_32: /* This should be done with bfd. */ bytes[0] = operand->exp.X_add_number >> 24; bytes[1] = operand->exp.X_add_number >> 16; bytes[2] = operand->exp.X_add_number >> 8; bytes[3] = operand->exp.X_add_number >> 0; if (relaxmode != 0) { idx = (relaxmode == 2) ? R_MOV24B1 : R_MOVL1; fix_new_exp (frag_now, offset, 4, &operand->exp, 0, idx); } break; } } else { switch (operand->mode & SIZE) { case L_24: case L_32: size = 4; where = (operand->mode & SIZE) == L_24 ? -1 : 0; if (relaxmode == 2) idx = R_MOV24B1; else if (relaxmode == 1) idx = R_MOVL1; else idx = R_RELLONG; break; default: as_bad (_("Can't work out size of operand.\n")); case L_16: size = 2; where = 0; if (relaxmode == 2) idx = R_MOV16B1; else idx = R_RELWORD; operand->exp.X_add_number = ((operand->exp.X_add_number & 0xffff) ^ 0x8000) - 0x8000; break; case L_8: size = 1; where = 0; idx = R_RELBYTE; operand->exp.X_add_number = ((operand->exp.X_add_number & 0xff) ^ 0x80) - 0x80; } fix_new_exp (frag_now, offset + where, size, &operand->exp, 0, idx); }}/* Now we know what sort of opcodes it is, let's build the bytes. */static voidbuild_bytes (this_try, operand) struct h8_opcode *this_try; struct h8_op *operand;{ unsigned int i; char *output = frag_more (this_try->length); op_type *nibble_ptr = this_try->data.nib; op_type c; unsigned int nibble_count = 0; int absat; int immat; int nib; int movb = 0; char asnibbles[30]; char *p = asnibbles; if (!(this_try->inbase || Hmode)) as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"), this_try->name); while (*nibble_ptr != E) { int d; c = *nibble_ptr++; d = (c & (DST | SRC_IN_DST)) != 0; if (c < 16) { nib = c; } else { if (c & (REG | IND | INC | DEC)) { nib = operand[d].reg; } else if ((c & DISPREG) == (DISPREG)) { nib = dispreg; } else if (c & ABS) { operand[d].mode = c; absat = nibble_count / 2; nib = 0; } else if (c & (IMM | PCREL | ABS | ABSJMP | DISP)) { operand[d].mode = c; immat = nibble_count / 2; nib = 0; } else if (c & IGNORE) { nib = 0; } else if (c & DBIT) { switch (operand[0].exp.X_add_number) { case 1: nib = c; break; case 2: nib = 0x8 | c; break; default: as_bad (_("Need #1 or #2 here")); } } else if (c & KBIT) { switch (operand[0].exp.X_add_number) { case 1: nib = 0; break; case 2: nib = 8; break; case 4: if (!Hmode) as_warn (_("#4 not valid on H8/300.")); nib = 9; break; default: as_bad (_("Need #1 or #2 here")); break; } /* Stop it making a fix. */ operand[0].mode = 0; } if (c & MEMRELAX) { operand[d].mode |= MEMRELAX; } if (c & B31) { nib |= 0x8; } if (c & MACREG) { if (operand[0].mode == MACREG) /* stmac has mac[hl] as the first operand. */ nib = 2 + operand[0].reg; else /* ldmac has mac[hl] as the second operand. */ nib = 2 + operand[1].reg; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -