📄 tc-h8500.c
字号:
return; } else { /* must be a symbol */ *ptr = skip_colonthing (exp_unsigned, src, op, ispage ? ABS24 : ABS16, ABS8, ABS16, ABS24); return; } } if (*src == '#') { src++; *ptr = skip_colonthing (exp_sandu, src, op, IMM16, IMM8, IMM16, ABS24); return; } else { *ptr = skip_colonthing (exp_signed, src, op, ispage ? ABS24 : PCREL8, PCREL8, PCREL16, ABS24); }}static char *get_operands (info, args, operand) h8500_opcode_info *info; char *args; h8500_operand_info *operand;{ char *ptr = args; switch (info->nargs) { case 0: operand[0].type = 0; operand[1].type = 0; break; case 1: ptr++; get_operand (&ptr, operand + 0, info->name[0] == 'p'); operand[1].type = 0; break; case 2: ptr++; get_operand (&ptr, operand + 0, 0); if (*ptr == ',') ptr++; get_operand (&ptr, operand + 1, 0); 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. */int pcrel8; /* Set when we've seen a pcrel operand */static h8500_opcode_info *get_specific (opcode, operands) h8500_opcode_info *opcode; h8500_operand_info *operands;{ h8500_opcode_info *this_try = opcode; int found = 0; unsigned int noperands = opcode->nargs; unsigned int this_index = opcode->idx; while (this_index == opcode->idx && !found) { unsigned int i; this_try = opcode++; /* look at both operands needed by the opcodes and provided by the user*/ for (i = 0; i < noperands; i++) { h8500_operand_info *user = operands + i; switch (this_try->arg_type[i]) { case FPIND_D8: /* Opcode needs (disp:8,fp) */ if (user->type == RNIND_D8 && user->reg == 6) { displacement = user->exp; continue; } break; case RDIND_D16: if (user->type == RNIND_D16) { displacement = user->exp; rd = user->reg; continue; } break; case RDIND_D8: if (user->type == RNIND_D8) { displacement = user->exp; rd = user->reg; continue; } break; case RNIND_D16: case RNIND_D8: if (user->type == this_try->arg_type[i]) { displacement = user->exp; rn = user->reg; continue; } break; case SPDEC: if (user->type == RNDEC && user->reg == 7) { continue; } break; case SPINC: if (user->type == RNINC && user->reg == 7) { continue; } break; case ABS16: if (user->type == ABS16) { absolute = user->exp; continue; } break; case ABS8: if (user->type == ABS8) { absolute = user->exp; continue; } break; case ABS24: if (user->type == ABS24) { absolute = user->exp; continue; } break; case CRB: if ((user->type == CRB || user->type == CR) && user->reg != 0) { crb = user->reg; continue; } break; case CRW: if ((user->type == CRW || user->type == CR) && user->reg == 0) { crw = user->reg; continue; } break; case DISP16: if (user->type == DISP16) { displacement = user->exp; continue; } break; case DISP8: if (user->type == DISP8) { displacement = user->exp; continue; } break; case FP: if (user->type == RN && user->reg == 6) { continue; } break; case PCREL16: if (user->type == PCREL16) { displacement = user->exp; continue; } break; case PCREL8: if (user->type == PCREL8) { displacement = user->exp; pcrel8 = 1; continue; } break; case IMM16: if (user->type == IMM16 || user->type == IMM8) { immediate_inpage = user->page; immediate = user->exp; continue; } break; case RLIST: case IMM8: if (user->type == IMM8) { immediate_inpage = user->page; immediate = user->exp; continue; } break; case IMM4: if (user->type == IMM8) { immediate_inpage = user->page; immediate = user->exp; continue; } break; case QIM: if (user->type == IMM8 && user->exp.X_op == O_constant && (user->exp.X_add_number == -2 || user->exp.X_add_number == -1 || user->exp.X_add_number == 1 || user->exp.X_add_number == 2)) { immediate_inpage = user->page; immediate = user->exp; continue; } break; case RD: if (user->type == RN) { rd = user->reg; continue; } break; case RS: if (user->type == RN) { rs = user->reg; continue; } break; case RDIND: if (user->type == RNIND) { rd = user->reg; continue; } break; case RNINC: case RNIND: case RNDEC: case RN: if (user->type == this_try->arg_type[i]) { rn = user->reg; continue; } break; case SP: if (user->type == RN && user->reg == 7) { continue; } break; default: printf (_("unhandled %d\n"), this_try->arg_type[i]); break; } /* If we get here this didn't work out */ goto fail; } found = 1; fail:; } if (found) return this_try; else return 0;}intcheck (operand, low, high) expressionS *operand; int low; int high;{ if (operand->X_op != O_constant || operand->X_add_number < low || operand->X_add_number > high) { as_bad (_("operand must be absolute in range %d..%d"), low, high); } return operand->X_add_number;}static voidinsert (output, index, exp, reloc, pcrel) char *output; int index; expressionS *exp; int reloc; int pcrel;{ fix_new_exp (frag_now, output - frag_now->fr_literal + index, 4, /* always say size is 4, but we know better */ exp, pcrel, reloc);}voidbuild_relaxable_instruction (opcode, operand) h8500_opcode_info *opcode; h8500_operand_info *operand;{ /* All relaxable instructions start life as two bytes but can become three bytes long if a lonely branch and up to 9 bytes if long scb. */ char *p; int len; int type; if (opcode->bytes[0].contents == 0x01) { type = SCB_F; } else if (opcode->bytes[0].contents == 0x06 || opcode->bytes[0].contents == 0x07) { type = SCB_TST; } else { type = BRANCH; } p = frag_var (rs_machine_dependent, md_relax_table[C (type, WORD_DISP)].rlx_length, len = md_relax_table[C (type, BYTE_DISP)].rlx_length, C (type, UNDEF_BYTE_DISP), displacement.X_add_symbol, displacement.X_add_number, 0); p[0] = opcode->bytes[0].contents; if (type != BRANCH) { p[1] = opcode->bytes[1].contents | rs; }}/* Now we know what sort of opcodes it is, let's build the bytes. */static voidbuild_bytes (opcode, operand) h8500_opcode_info *opcode; h8500_operand_info *operand;{ int index; if (pcrel8) { pcrel8 = 0; build_relaxable_instruction (opcode, operand); } else { char *output = frag_more (opcode->length); memset (output, 0, opcode->length); for (index = 0; index < opcode->length; index++) { output[index] = opcode->bytes[index].contents; switch (opcode->bytes[index].insert) { default: printf (_("failed for %d\n"), opcode->bytes[index].insert); break; case 0: break; case RN: output[index] |= rn; break; case RD: case RDIND: output[index] |= rd; break; case RS: output[index] |= rs; break; case DISP16: insert (output, index, &displacement, R_H8500_IMM16, 0); index++; break; case DISP8: case FPIND_D8: insert (output, index, &displacement, R_H8500_IMM8, 0); break; case IMM16: { int p; switch (immediate_inpage) { case 'p': p = R_H8500_HIGH16; break; case 'h': p = R_H8500_HIGH16; break; default: p = R_H8500_IMM16; break; } insert (output, index, &immediate, p, 0); } index++; break; case RLIST: case IMM8: if (immediate_inpage) insert (output, index, &immediate, R_H8500_HIGH8, 0); else insert (output, index, &immediate, R_H8500_IMM8, 0); break; case PCREL16: insert (output, index, &displacement, R_H8500_PCREL16, 1); index++; break; case PCREL8: insert (output, index, &displacement, R_H8500_PCREL8, 1); break; case IMM4: output[index] |= check (&immediate, 0, 15); break; case CR: output[index] |= cr; if (cr == 0) output[0] |= 0x8; else output[0] &= ~0x8; break; case CRB: output[index] |= crb; output[0] &= ~0x8; break; case CRW: output[index] |= crw; output[0] |= 0x8; break; case ABS24: insert (output, index, &absolute, R_H8500_IMM24, 0); index += 2; break; case ABS16: insert (output, index, &absolute, R_H8500_IMM16, 0); index++; break; case ABS8: insert (output, index, &absolute, R_H8500_IMM8, 0); break; case QIM: switch (immediate.X_add_number) { case -2: output[index] |= 0x5; break; case -1: output[index] |= 0x4; break; case 1: output[index] |= 0; break; case 2: output[index] |= 1; break; } break; } } }}/* This is the guts of the machine-dependent assembler. STR points to a machine dependent instruction. This function is supposed to emit the frags/bytes it assembles to. */voidmd_assemble (str) char *str;{ char *op_start; char *op_end; h8500_operand_info operand[2]; h8500_opcode_info *opcode; h8500_opcode_info *prev_opcode; char name[11]; int nlen = 0; /* Drop leading whitespace. */ while (*str == ' ') str++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -