PageRenderTime 101ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 2ms

/mingw-w64-v2.0.999/binutils/src/gas/config/tc-score.c

#
C | 7836 lines | 6458 code | 908 blank | 470 comment | 2126 complexity | 7adf69ea0a3da2cdbcb9cd17f1ce3ffe MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, LGPL-3.0, Unlicense, GPL-2.0, LGPL-2.0, BSD-3-Clause, GPL-3.0
  1. /* tc-score.c -- Assembler for Score
  2. Copyright 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
  3. Contributed by:
  4. Brain.lin (brain.lin@sunplusct.com)
  5. Mei Ligang (ligang@sunnorth.com.cn)
  6. Pei-Lin Tsai (pltsai@sunplus.com)
  7. This file is part of GAS, the GNU Assembler.
  8. GAS is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 3, or (at your option)
  11. any later version.
  12. GAS is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING. If not, write to the Free
  18. Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
  19. 02110-1301, USA. */
  20. #include "tc-score7.c"
  21. static void s3_s_score_bss (int ignore ATTRIBUTE_UNUSED);
  22. static void s3_s_score_text (int ignore);
  23. static void s3_score_s_section (int ignore);
  24. static void s3_s_change_sec (int sec);
  25. static void s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED);
  26. static void s3_s_score_ent (int aent);
  27. static void s3_s_score_frame (int ignore ATTRIBUTE_UNUSED);
  28. static void s3_s_score_end (int x ATTRIBUTE_UNUSED);
  29. static void s3_s_score_set (int x ATTRIBUTE_UNUSED);
  30. static void s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED);
  31. static void s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED);
  32. static void s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED);
  33. static void s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED);
  34. static void s3_s_score_lcomm (int bytes_p);
  35. static void s_score_bss (int ignore ATTRIBUTE_UNUSED);
  36. static void s_score_text (int ignore);
  37. static void s_section (int ignore);
  38. static void s_change_sec (int sec);
  39. static void s_score_mask (int reg_type ATTRIBUTE_UNUSED);
  40. static void s_score_ent (int aent);
  41. static void s_score_frame (int ignore ATTRIBUTE_UNUSED);
  42. static void s_score_end (int x ATTRIBUTE_UNUSED);
  43. static void s_score_set (int x ATTRIBUTE_UNUSED);
  44. static void s_score_cpload (int ignore ATTRIBUTE_UNUSED);
  45. static void s_score_cprestore (int ignore ATTRIBUTE_UNUSED);
  46. static void s_score_gpword (int ignore ATTRIBUTE_UNUSED);
  47. static void s_score_cpadd (int ignore ATTRIBUTE_UNUSED);
  48. static void s_score_lcomm (int bytes_p);
  49. /* s3: hooks. */
  50. static void s3_md_number_to_chars (char *buf, valueT val, int n);
  51. static valueT s3_md_chars_to_number (char *buf, int n);
  52. static void s3_assemble (char *str);
  53. static void s3_operand (expressionS *);
  54. static void s3_begin (void);
  55. static void s3_number_to_chars (char *buf, valueT val, int n);
  56. static char *s3_atof (int type, char *litP, int *sizeP);
  57. static void s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED);
  58. static void s3_validate_fix (fixS *fixP);
  59. static int s3_force_relocation (struct fix *fixp);
  60. static bfd_boolean s3_fix_adjustable (fixS * fixP);
  61. static void s3_elf_final_processing (void);
  62. static int s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED);
  63. static int s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED);
  64. static void s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp);
  65. static long s3_pcrel_from (fixS * fixP);
  66. static valueT s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size);
  67. static void s3_apply_fix (fixS *fixP, valueT *valP, segT seg);
  68. static arelent **s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp);
  69. /* s3: utils. */
  70. static void s3_do_ldst_insn (char *);
  71. static void s3_do_crdcrscrsimm5 (char *);
  72. static void s3_do_ldst_unalign (char *);
  73. static void s3_do_ldst_atomic (char *);
  74. static void s3_do_ldst_cop (char *);
  75. static void s3_do_macro_li_rdi32 (char *);
  76. static void s3_do_macro_la_rdi32 (char *);
  77. static void s3_do_macro_rdi32hi (char *);
  78. static void s3_do_macro_rdi32lo (char *);
  79. static void s3_do_macro_mul_rdrsrs (char *);
  80. static void s3_do_macro_bcmp (char *);
  81. static void s3_do_macro_bcmpz (char *);
  82. static void s3_do_macro_ldst_label (char *);
  83. static void s3_do_branch (char *);
  84. static void s3_do_jump (char *);
  85. static void s3_do_empty (char *);
  86. static void s3_do16_int (char *);
  87. static void s3_do_rdrsrs (char *);
  88. static void s3_do_rdsi16 (char *);
  89. static void s3_do_rdrssi14 (char *);
  90. static void s3_do_sub_rdsi16 (char *);
  91. static void s3_do_sub_rdi16 (char *);
  92. static void s3_do_sub_rdrssi14 (char *);
  93. static void s3_do_rdrsi5 (char *);
  94. static void s3_do_rdrsi14 (char *);
  95. static void s3_do_rdi16 (char *);
  96. static void s3_do_ldis (char *);
  97. static void s3_do_xrsi5 (char *);
  98. static void s3_do_rdrs (char *);
  99. static void s3_do_rdxrs (char *);
  100. static void s3_do_rsrs (char *);
  101. static void s3_do_rdcrs (char *);
  102. static void s3_do_rdsrs (char *);
  103. static void s3_do_rd (char *);
  104. static void s3_do16_dsp (char *);
  105. static void s3_do16_dsp2 (char *);
  106. static void s3_do_dsp (char *);
  107. static void s3_do_dsp2 (char *);
  108. static void s3_do_dsp3 (char *);
  109. static void s3_do_rs (char *);
  110. static void s3_do_i15 (char *);
  111. static void s3_do_xi5x (char *);
  112. static void s3_do_ceinst (char *);
  113. static void s3_do_cache (char *);
  114. static void s3_do16_rdrs2 (char *);
  115. static void s3_do16_br (char *);
  116. static void s3_do16_brr (char *);
  117. static void s3_do_ltb (char *);
  118. static void s3_do16_mv_cmp (char *);
  119. static void s3_do16_addi (char *);
  120. static void s3_do16_cmpi (char *);
  121. static void s3_do16_rdi5 (char *);
  122. static void s3_do16_xi5 (char *);
  123. static void s3_do16_ldst_insn (char *);
  124. static void s3_do16_slli_srli (char *);
  125. static void s3_do16_ldiu (char *);
  126. static void s3_do16_push_pop (char *);
  127. static void s3_do16_rpush (char *);
  128. static void s3_do16_rpop (char *);
  129. static void s3_do16_branch (char *);
  130. static void s3_do_lw48 (char *);
  131. static void s3_do_sw48 (char *);
  132. static void s3_do_ldi48 (char *);
  133. static void s3_do_sdbbp48 (char *);
  134. static void s3_do_and48 (char *);
  135. static void s3_do_or48 (char *);
  136. static void s3_do_mbitclr (char *);
  137. static void s3_do_mbitset (char *);
  138. static void s3_do_rdi16_pic (char *);
  139. static void s3_do_addi_s_pic (char *);
  140. static void s3_do_addi_u_pic (char *);
  141. static void s3_do_lw_pic (char *);
  142. #define MARCH_SCORE3 "score3"
  143. #define MARCH_SCORE3D "score3d"
  144. #define MARCH_SCORE7 "score7"
  145. #define MARCH_SCORE7D "score7d"
  146. #define MARCH_SCORE5 "score5"
  147. #define MARCH_SCORE5U "score5u"
  148. #define SCORE_BI_ENDIAN
  149. #ifdef SCORE_BI_ENDIAN
  150. #define OPTION_EB (OPTION_MD_BASE + 0)
  151. #define OPTION_EL (OPTION_MD_BASE + 1)
  152. #else
  153. #if TARGET_BYTES_BIG_ENDIAN
  154. #define OPTION_EB (OPTION_MD_BASE + 0)
  155. #else
  156. #define OPTION_EL (OPTION_MD_BASE + 1)
  157. #endif
  158. #endif
  159. #define OPTION_FIXDD (OPTION_MD_BASE + 2)
  160. #define OPTION_NWARN (OPTION_MD_BASE + 3)
  161. #define OPTION_SCORE5 (OPTION_MD_BASE + 4)
  162. #define OPTION_SCORE5U (OPTION_MD_BASE + 5)
  163. #define OPTION_SCORE7 (OPTION_MD_BASE + 6)
  164. #define OPTION_R1 (OPTION_MD_BASE + 7)
  165. #define OPTION_O0 (OPTION_MD_BASE + 8)
  166. #define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9)
  167. #define OPTION_PIC (OPTION_MD_BASE + 10)
  168. #define OPTION_MARCH (OPTION_MD_BASE + 11)
  169. #define OPTION_SCORE3 (OPTION_MD_BASE + 12)
  170. /* This array holds the chars that always start a comment. If the
  171. pre-processor is disabled, these aren't very useful. */
  172. const char comment_chars[] = "#";
  173. const char line_comment_chars[] = "#";
  174. const char line_separator_chars[] = ";";
  175. /* Chars that can be used to separate mant from exp in floating point numbers. */
  176. const char EXP_CHARS[] = "eE";
  177. const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
  178. #ifdef OBJ_ELF
  179. /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
  180. symbolS *GOT_symbol;
  181. #endif
  182. const pseudo_typeS md_pseudo_table[] =
  183. {
  184. {"bss", s_score_bss, 0},
  185. {"text", s_score_text, 0},
  186. {"word", cons, 4},
  187. {"long", cons, 4},
  188. {"extend", float_cons, 'x'},
  189. {"ldouble", float_cons, 'x'},
  190. {"packed", float_cons, 'p'},
  191. {"end", s_score_end, 0},
  192. {"ent", s_score_ent, 0},
  193. {"frame", s_score_frame, 0},
  194. {"rdata", s_change_sec, 'r'},
  195. {"sdata", s_change_sec, 's'},
  196. {"set", s_score_set, 0},
  197. {"mask", s_score_mask, 'R'},
  198. {"dword", cons, 8},
  199. {"lcomm", s_score_lcomm, 1},
  200. {"section", s_section, 0},
  201. {"cpload", s_score_cpload, 0},
  202. {"cprestore", s_score_cprestore, 0},
  203. {"gpword", s_score_gpword, 0},
  204. {"cpadd", s_score_cpadd, 0},
  205. {0, 0, 0}
  206. };
  207. const char *md_shortopts = "nO::g::G:";
  208. struct option md_longopts[] =
  209. {
  210. #ifdef OPTION_EB
  211. {"EB" , no_argument, NULL, OPTION_EB},
  212. #endif
  213. #ifdef OPTION_EL
  214. {"EL" , no_argument, NULL, OPTION_EL},
  215. #endif
  216. {"FIXDD" , no_argument, NULL, OPTION_FIXDD},
  217. {"NWARN" , no_argument, NULL, OPTION_NWARN},
  218. {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
  219. {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
  220. {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
  221. {"USE_R1" , no_argument, NULL, OPTION_R1},
  222. {"O0" , no_argument, NULL, OPTION_O0},
  223. {"V" , no_argument, NULL, OPTION_SCORE_VERSION},
  224. {"KPIC" , no_argument, NULL, OPTION_PIC},
  225. {"march=" , required_argument, NULL, OPTION_MARCH},
  226. {"SCORE3" , no_argument, NULL, OPTION_SCORE3},
  227. {NULL , no_argument, NULL, 0}
  228. };
  229. size_t md_longopts_size = sizeof (md_longopts);
  230. #define s3_GP 28
  231. #define s3_PIC_CALL_REG 29
  232. #define s3_MAX_LITERAL_POOL_SIZE 1024
  233. #define s3_FAIL 0x80000000
  234. #define s3_SUCCESS 0
  235. #define s3_INSN48_SIZE 6
  236. #define s3_INSN_SIZE 4
  237. #define s3_INSN16_SIZE 2
  238. #define s3_RELAX_INST_NUM 3
  239. /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */
  240. #define s3_BAD_ARGS _("bad arguments to instruction")
  241. #define s3_ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions")
  242. #define s3_ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu")
  243. #define s3_ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction")
  244. #define s3_BAD_SKIP_COMMA s3_BAD_ARGS
  245. #define s3_BAD_GARBAGE _("garbage following instruction");
  246. #define s3_skip_whitespace(str) while (*(str) == ' ') ++(str)
  247. /* The name of the readonly data section. */
  248. #define s3_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
  249. ? ".data" \
  250. : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
  251. ? ".rdata" \
  252. : OUTPUT_FLAVOR == bfd_target_coff_flavour \
  253. ? ".rdata" \
  254. : OUTPUT_FLAVOR == bfd_target_elf_flavour \
  255. ? ".rodata" \
  256. : (abort (), ""))
  257. #define s3_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
  258. ((relax_substateT) \
  259. (((old) << 23) \
  260. | ((new) << 16) \
  261. | ((type) << 9) \
  262. | ((reloc1) << 5) \
  263. | ((reloc2) << 1) \
  264. | ((opt) ? 1 : 0)))
  265. #define s3_RELAX_OLD(i) (((i) >> 23) & 0x7f)
  266. #define s3_RELAX_NEW(i) (((i) >> 16) & 0x7f)
  267. #define s3_RELAX_TYPE(i) (((i) >> 9) & 0x7f)
  268. #define s3_RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf)
  269. #define s3_RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf)
  270. #define s3_RELAX_OPT(i) ((i) & 1)
  271. #define s3_SET_INSN_ERROR(s) (s3_inst.error = (s))
  272. #define s3_INSN_IS_PCE_P(s) (strstr (str, "||") != NULL)
  273. #define s3_INSN_IS_48_P(s) (strstr (str, "48") != NULL)
  274. #define s3_GET_INSN_CLASS(type) (s3_get_insn_class_from_type (type))
  275. #define s3_GET_INSN_SIZE(type) ((s3_GET_INSN_CLASS (type) == INSN_CLASS_16) \
  276. ? s3_INSN16_SIZE : (s3_GET_INSN_CLASS (type) == INSN_CLASS_48) \
  277. ? s3_INSN48_SIZE : s3_INSN_SIZE)
  278. #define s3_MAX_LITTLENUMS 6
  279. #define s3_INSN_NAME_LEN 16
  280. /* Relax will need some padding for alignment. */
  281. #define s3_RELAX_PAD_BYTE 3
  282. #define s3_USE_GLOBAL_POINTER_OPT 1
  283. /* Enumeration matching entries in table above. */
  284. enum s3_score_reg_type
  285. {
  286. s3_REG_TYPE_SCORE = 0,
  287. #define s3_REG_TYPE_FIRST s3_REG_TYPE_SCORE
  288. s3_REG_TYPE_SCORE_SR = 1,
  289. s3_REG_TYPE_SCORE_CR = 2,
  290. s3_REG_TYPE_MAX = 3
  291. };
  292. enum s3_score_pic_level
  293. {
  294. s3_NO_PIC,
  295. s3_PIC
  296. };
  297. static enum s3_score_pic_level s3_score_pic = s3_NO_PIC;
  298. enum s3_insn_type_for_dependency
  299. {
  300. s3_D_mtcr,
  301. s3_D_all_insn
  302. };
  303. struct s3_insn_to_dependency
  304. {
  305. char *insn_name;
  306. enum s3_insn_type_for_dependency type;
  307. };
  308. struct s3_data_dependency
  309. {
  310. enum s3_insn_type_for_dependency pre_insn_type;
  311. char pre_reg[6];
  312. enum s3_insn_type_for_dependency cur_insn_type;
  313. char cur_reg[6];
  314. int bubblenum_7;
  315. int bubblenum_3;
  316. int warn_or_error; /* warning - 0; error - 1 */
  317. };
  318. static const struct s3_insn_to_dependency s3_insn_to_dependency_table[] =
  319. {
  320. /* move spectial instruction. */
  321. {"mtcr", s3_D_mtcr},
  322. };
  323. static const struct s3_data_dependency s3_data_dependency_table[] =
  324. {
  325. /* Status regiser. */
  326. {s3_D_mtcr, "cr0", s3_D_all_insn, "", 5, 1, 0},
  327. };
  328. /* Used to contain constructed error messages. */
  329. static char s3_err_msg[255];
  330. static int s3_fix_data_dependency = 0;
  331. static int s3_warn_fix_data_dependency = 1;
  332. static int s3_in_my_get_expression = 0;
  333. /* Default, pop warning message when using r1. */
  334. static int s3_nor1 = 1;
  335. /* Default will do instruction relax, -O0 will set s3_g_opt = 0. */
  336. static unsigned int s3_g_opt = 1;
  337. /* The size of the small data section. */
  338. static unsigned int s3_g_switch_value = 8;
  339. static segT s3_pdr_seg;
  340. struct s3_score_it
  341. {
  342. char name[s3_INSN_NAME_LEN];
  343. bfd_vma instruction;
  344. bfd_vma relax_inst;
  345. int size;
  346. int relax_size;
  347. enum score_insn_type type;
  348. char str[s3_MAX_LITERAL_POOL_SIZE];
  349. const char *error;
  350. int bwarn;
  351. char reg[s3_INSN_NAME_LEN];
  352. struct
  353. {
  354. bfd_reloc_code_real_type type;
  355. expressionS exp;
  356. int pc_rel;
  357. }reloc;
  358. };
  359. static struct s3_score_it s3_inst;
  360. typedef struct s3_proc
  361. {
  362. symbolS *isym;
  363. unsigned long reg_mask;
  364. unsigned long reg_offset;
  365. unsigned long fpreg_mask;
  366. unsigned long leaf;
  367. unsigned long frame_offset;
  368. unsigned long frame_reg;
  369. unsigned long pc_reg;
  370. } s3_procS;
  371. static s3_procS s3_cur_proc;
  372. static s3_procS *s3_cur_proc_ptr;
  373. static int s3_numprocs;
  374. /* Structure for a hash table entry for a register. */
  375. struct s3_reg_entry
  376. {
  377. const char *name;
  378. int number;
  379. };
  380. static const struct s3_reg_entry s3_score_rn_table[] =
  381. {
  382. {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
  383. {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
  384. {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
  385. {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
  386. {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
  387. {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
  388. {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
  389. {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
  390. {NULL, 0}
  391. };
  392. static const struct s3_reg_entry s3_score_srn_table[] =
  393. {
  394. {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
  395. {NULL, 0}
  396. };
  397. static const struct s3_reg_entry s3_score_crn_table[] =
  398. {
  399. {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
  400. {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
  401. {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
  402. {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
  403. {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
  404. {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
  405. {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
  406. {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
  407. {NULL, 0}
  408. };
  409. struct s3_reg_map
  410. {
  411. const struct s3_reg_entry *names;
  412. int max_regno;
  413. struct hash_control *htab;
  414. const char *expected;
  415. };
  416. static struct s3_reg_map s3_all_reg_maps[] =
  417. {
  418. {s3_score_rn_table, 31, NULL, N_("S+core register expected")},
  419. {s3_score_srn_table, 2, NULL, N_("S+core special-register expected")},
  420. {s3_score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
  421. };
  422. static struct hash_control *s3_score_ops_hsh = NULL;
  423. static struct hash_control *s3_dependency_insn_hsh = NULL;
  424. struct s3_datafield_range
  425. {
  426. int data_type;
  427. int bits;
  428. int range[2];
  429. };
  430. static struct s3_datafield_range s3_score_df_range[] =
  431. {
  432. {_IMM4, 4, {0, (1 << 4) - 1}}, /* ( 0 ~ 15 ) */
  433. {_IMM5, 5, {0, (1 << 5) - 1}}, /* ( 0 ~ 31 ) */
  434. {_IMM8, 8, {0, (1 << 8) - 1}}, /* ( 0 ~ 255 ) */
  435. {_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 16383) */
  436. {_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */
  437. {_IMM16, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */
  438. {_SIMM10, 10, {-(1 << 9), (1 << 9) - 1}}, /* ( -512 ~ 511 ) */
  439. {_SIMM12, 12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */
  440. {_SIMM14, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */
  441. {_SIMM15, 15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */
  442. {_SIMM16, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
  443. {_SIMM14_NEG, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */
  444. {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* (-65535 ~ 0 ) */
  445. {_SIMM16_NEG, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
  446. {_IMM20, 20, {0, (1 << 20) - 1}},
  447. {_IMM25, 25, {0, (1 << 25) - 1}},
  448. {_DISP8div2, 8, {-(1 << 8), (1 << 8) - 1}}, /* ( -256 ~ 255 ) */
  449. {_DISP11div2, 11, {0, 0}},
  450. {_DISP19div2, 19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */
  451. {_DISP24div2, 24, {0, 0}},
  452. {_VALUE, 32, {0, ((unsigned int)1 << 31) - 1}},
  453. {_VALUE_HI16, 16, {0, (1 << 16) - 1}},
  454. {_VALUE_LO16, 16, {0, (1 << 16) - 1}},
  455. {_VALUE_LDST_LO16, 16, {0, (1 << 16) - 1}},
  456. {_SIMM16_LA, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
  457. {_IMM5_RSHIFT_1, 5, {0, (1 << 6) - 1}}, /* ( 0 ~ 63 ) */
  458. {_IMM5_RSHIFT_2, 5, {0, (1 << 7) - 1}}, /* ( 0 ~ 127 ) */
  459. {_SIMM16_LA_POS, 16, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */
  460. {_IMM5_RANGE_8_31, 5, {8, 31}}, /* But for cop0 the valid data : (8 ~ 31). */
  461. {_IMM10_RSHIFT_2, 10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */
  462. {_SIMM10, 10, {0, (1 << 10) - 1}}, /* ( -1024 ~ 1023 ) */
  463. {_SIMM12, 12, {0, (1 << 12) - 1}}, /* ( -2048 ~ 2047 ) */
  464. {_SIMM14, 14, {0, (1 << 14) - 1}}, /* ( -8192 ~ 8191 ) */
  465. {_SIMM15, 15, {0, (1 << 15) - 1}}, /* (-16384 ~ 16383) */
  466. {_SIMM16, 16, {0, (1 << 16) - 1}}, /* (-65536 ~ 65536) */
  467. {_SIMM14_NEG, 14, {0, (1 << 16) - 1}}, /* ( -8191 ~ 8192 ) */
  468. {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
  469. {_SIMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
  470. {_IMM20, 20, {0, (1 << 20) - 1}}, /* (-32768 ~ 32767) */
  471. {_IMM25, 25, {0, (1 << 25) - 1}}, /* (-32768 ~ 32767) */
  472. {_GP_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 65535) */
  473. {_GP_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 65535) */
  474. {_SIMM16_pic, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */
  475. {_IMM16_LO16_pic, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */
  476. {_IMM16_pic, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */
  477. {_SIMM5, 5, {-(1 << 4), (1 << 4) - 1}}, /* ( -16 ~ 15 ) */
  478. {_SIMM6, 6, {-(1 << 5), (1 << 5) - 1}}, /* ( -32 ~ 31 ) */
  479. {_IMM32, 32, {0, 0xfffffff}},
  480. {_SIMM32, 32, {-0x80000000, 0x7fffffff}},
  481. {_IMM11, 11, {0, (1 << 11) - 1}},
  482. };
  483. struct s3_asm_opcode
  484. {
  485. /* Instruction name. */
  486. const char *template_name;
  487. /* Instruction Opcode. */
  488. bfd_vma value;
  489. /* Instruction bit mask. */
  490. bfd_vma bitmask;
  491. /* Relax instruction opcode. 0x8000 imply no relaxation. */
  492. bfd_vma relax_value;
  493. /* Instruction type. */
  494. enum score_insn_type type;
  495. /* Function to call to parse args. */
  496. void (*parms) (char *);
  497. };
  498. static const struct s3_asm_opcode s3_score_ldst_insns[] =
  499. {
  500. {"lw", 0x20000000, 0x3e000000, 0x1000, Rd_rvalueRs_SI15, s3_do_ldst_insn},
  501. {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn},
  502. {"lw", 0x0e000000, 0x3e000007, 0x0040, Rd_rvalueRs_postSI12, s3_do_ldst_insn},
  503. {"lh", 0x22000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn},
  504. {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn},
  505. {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn},
  506. {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn},
  507. {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn},
  508. {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn},
  509. {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn},
  510. {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn},
  511. {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn},
  512. {"sw", 0x28000000, 0x3e000000, 0x2000, Rd_lvalueRs_SI15, s3_do_ldst_insn},
  513. {"sw", 0x06000004, 0x3e000007, 0x0060, Rd_lvalueRs_preSI12, s3_do_ldst_insn},
  514. {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn},
  515. {"sh", 0x2a000000, 0x3e000000, 0x8000, Rd_lvalueRs_SI15, s3_do_ldst_insn},
  516. {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s3_do_ldst_insn},
  517. {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn},
  518. {"lbu", 0x2c000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn},
  519. {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn},
  520. {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn},
  521. {"sb", 0x2e000000, 0x3e000000, 0x8000, Rd_lvalueRs_SI15, s3_do_ldst_insn},
  522. {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s3_do_ldst_insn},
  523. {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn},
  524. };
  525. static const struct s3_asm_opcode s3_score_insns[] =
  526. {
  527. {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_dsp3},
  528. {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_dsp3},
  529. {"add", 0x00000010, 0x3e0003ff, 0x4800, Rd_Rs_Rs, s3_do_rdrsrs},
  530. {"add.c", 0x00000011, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  531. {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2},
  532. {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  533. {"addc.c", 0x00000013, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  534. {"addi", 0x02000000, 0x3e0e0001, 0x5c00, Rd_SI16, s3_do_rdsi16},
  535. {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdsi16},
  536. {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdi16},
  537. {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdi16},
  538. {"addi!", 0x5c00, 0x7c00, 0x8000, Rd_SI6, s3_do16_addi},
  539. {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_rdrssi14},
  540. {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_rdrssi14},
  541. /* add.c <-> add!. */
  542. {"add!", 0x4800, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2},
  543. {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdsi16},
  544. {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdsi16},
  545. {"subis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdi16},
  546. {"subis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdi16},
  547. {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_sub_rdrssi14},
  548. {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_sub_rdrssi14},
  549. {"and", 0x00000020, 0x3e0003ff, 0x4b00, Rd_Rs_Rs, s3_do_rdrsrs},
  550. {"and.c", 0x00000021, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  551. {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16},
  552. {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16},
  553. {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16},
  554. {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16},
  555. {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14},
  556. {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14},
  557. /* and.c <-> and!. */
  558. {"and!", 0x4b00, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2},
  559. {"bcs", 0x08000000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  560. {"bcc", 0x08000400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  561. {"bcnz", 0x08003800, 0x3e007c01, 0x3200, PC_DISP19div2, s3_do_branch},
  562. {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  563. {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  564. {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  565. {"bcnz!", 0x3200, 0x7f00, 0x08003800, PC_DISP8div2, s3_do16_branch},
  566. {"beq", 0x08001000, 0x3e007c01, 0x3800, PC_DISP19div2, s3_do_branch},
  567. {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  568. {"beq!", 0x3800, 0x7e00, 0x08001000, PC_DISP8div2, s3_do16_branch},
  569. {"bgtu", 0x08000800, 0x3e007c01, 0x3400, PC_DISP19div2, s3_do_branch},
  570. {"bgt", 0x08001800, 0x3e007c01, 0x3c00, PC_DISP19div2, s3_do_branch},
  571. {"bge", 0x08002000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  572. {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  573. {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  574. {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  575. {"bgtu!", 0x3400, 0x7e00, 0x08000800, PC_DISP8div2, s3_do16_branch},
  576. {"bgt!", 0x3c00, 0x7e00, 0x08001800, PC_DISP8div2, s3_do16_branch},
  577. {"bitclr", 0x00000028, 0x3e0003ff, 0x5000, Rd_Rs_I5, s3_do_rdrsi5},
  578. {"bitclr.c", 0x00000029, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  579. {"mbitclr", 0x00000064, 0x3e00007e, 0x8000, Ra_I9_I5, s3_do_mbitclr},
  580. {"mbitset", 0x0000006c, 0x3e00007e, 0x8000, Ra_I9_I5, s3_do_mbitset},
  581. {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2},
  582. {"bitset", 0x0000002a, 0x3e0003ff, 0x5200, Rd_Rs_I5, s3_do_rdrsi5},
  583. {"bitset.c", 0x0000002b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  584. {"bittst.c", 0x0000002d, 0x3e0003ff, 0x5400, x_Rs_I5, s3_do_xrsi5},
  585. {"bittgl", 0x0000002e, 0x3e0003ff, 0x5600, Rd_Rs_I5, s3_do_rdrsi5},
  586. {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  587. {"bitclr!", 0x5000, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5},
  588. {"bitset!", 0x5200, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5},
  589. {"bittst!", 0x5400, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5},
  590. {"bittgl!", 0x5600, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5},
  591. {"bleu", 0x08000c00, 0x3e007c01, 0x3600, PC_DISP19div2, s3_do_branch},
  592. {"ble", 0x08001c00, 0x3e007c01, 0x3e00, PC_DISP19div2, s3_do_branch},
  593. {"blt", 0x08002400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  594. {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  595. {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  596. {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  597. {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  598. {"bleu!", 0x3600, 0x7e00, 0x08000c00, PC_DISP8div2, s3_do16_branch},
  599. {"ble!", 0x3e00, 0x7e00, 0x08001c00, PC_DISP8div2, s3_do16_branch},
  600. {"bmi", 0x08002800, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  601. {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  602. {"bne", 0x08001400, 0x3e007c01, 0x3a00, PC_DISP19div2, s3_do_branch},
  603. {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  604. {"bne!", 0x3a00, 0x7e00, 0x08001400, PC_DISP8div2, s3_do16_branch},
  605. {"bpl", 0x08002c00, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  606. {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  607. {"brcs", 0x00000008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  608. {"brcc", 0x00000408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  609. {"brgtu", 0x00000808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  610. {"brleu", 0x00000c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  611. {"breq", 0x00001008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  612. {"brne", 0x00001408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  613. {"brgt", 0x00001808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  614. {"brle", 0x00001c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  615. {"brge", 0x00002008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  616. {"brlt", 0x00002408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  617. {"brmi", 0x00002808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  618. {"brpl", 0x00002c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  619. {"brvs", 0x00003008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  620. {"brvc", 0x00003408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  621. {"brcnz", 0x00003808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  622. {"br", 0x00003c08, 0x3e007fff, 0x0080, x_Rs_x, s3_do_rs},
  623. {"brcsl", 0x00000009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  624. {"brccl", 0x00000409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  625. {"brgtul", 0x00000809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  626. {"brleul", 0x00000c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  627. {"breql", 0x00001009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  628. {"brnel", 0x00001409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  629. {"brgtl", 0x00001809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  630. {"brlel", 0x00001c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  631. {"brgel", 0x00002009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  632. {"brltl", 0x00002409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  633. {"brmil", 0x00002809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  634. {"brpll", 0x00002c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  635. {"brvsl", 0x00003009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  636. {"brvcl", 0x00003409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  637. {"brcnzl", 0x00003809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs},
  638. {"brl", 0x00003c09, 0x3e007fff, 0x00a0, x_Rs_x, s3_do_rs},
  639. {"br!", 0x0080, 0x7fe0, 0x8000, x_Rs, s3_do16_br},
  640. {"brl!", 0x00a0, 0x7fe0, 0x8000, x_Rs, s3_do16_br},
  641. {"brr!", 0x00c0, 0x7fe0, 0x8000, x_Rs, s3_do16_brr},
  642. {"bvs", 0x08003000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  643. {"bvc", 0x08003400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  644. {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  645. {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch},
  646. {"b!", 0x3000, 0x7e00, 0x08003c00, PC_DISP8div2, s3_do16_branch},
  647. {"b", 0x08003c00, 0x3e007c01, 0x3000, PC_DISP19div2, s3_do_branch},
  648. {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, s3_do_cache},
  649. {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, s3_do_ceinst},
  650. {"clz", 0x0000001c, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  651. {"cmp.c", 0x00300019, 0x3ff003ff, 0x4400, x_Rs_Rs, s3_do_rsrs},
  652. {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, s3_do_rs},
  653. {"cmpi.c", 0x02040001, 0x3e0e0001, 0x6000, Rd_SI16, s3_do_rdsi16},
  654. /* cmp.c <-> cmp!. */
  655. {"cmp!", 0x4400, 0x7c00, 0x8000, Rd_Rs, s3_do16_mv_cmp},
  656. {"cmpi!", 0x6000, 0x7c00, 0x8000, Rd_SI5, s3_do16_cmpi},
  657. {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5},
  658. {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5},
  659. {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5},
  660. {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty},
  661. {"disint!", 0x00e0, 0xffe1, 0x8000, NO16_OPD, s3_do16_int},
  662. {"enint!", 0x00e1, 0xffe1, 0x8000, NO16_OPD, s3_do16_int},
  663. {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  664. {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  665. {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  666. {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  667. {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  668. {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  669. {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  670. {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  671. {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, s3_do_jump},
  672. {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, s3_do_jump},
  673. {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, s3_do_ldst_atomic},
  674. {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, s3_do_ldst_unalign},
  675. {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s3_do_ldst_unalign},
  676. {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s3_do_ldst_unalign},
  677. {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop},
  678. {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop},
  679. {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop},
  680. /* s3_inst.relax */
  681. {"ldi", 0x020c0000, 0x3e0e0000, 0x6400, Rd_SI16, s3_do_rdsi16},
  682. {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, s3_do_ldis},
  683. /* ldi <-> ldiu!. */
  684. {"ldiu!", 0x6400, 0x7c00, 0x8000, Rd_I5, s3_do16_ldiu},
  685. /*ltbb! , ltbh! ltbw! */
  686. {"ltbw", 0x00000032, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb},
  687. {"ltbh", 0x00000132, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb},
  688. {"ltbb", 0x00000332, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb},
  689. {"lw!", 0x1000, 0x7000, 0x8000, Rd_rvalueRs, s3_do16_ldst_insn},
  690. {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd},
  691. {"mfcel!", 0x7100, 0x7ff0, 0x00000448, x_Rs, s3_do16_dsp},
  692. {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  693. {"mad.f!", 0x7400, 0x7f00, 0x38000080, Rd_Rs, s3_do16_dsp2},
  694. {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  695. {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  696. {"madh.fs!", 0x7b00, 0x7f00, 0x380002c3, Rd_Rs, s3_do16_dsp2},
  697. {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  698. {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  699. {"madl.fs!", 0x7a00, 0x7f00, 0x380000c2, Rd_Rs, s3_do16_dsp2},
  700. {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  701. {"madu!", 0x7500, 0x7f00, 0x38000020, Rd_Rs, s3_do16_dsp2},
  702. {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  703. {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2},
  704. {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  705. {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  706. {"mazh.f!", 0x7900, 0x7f00, 0x3800038c, Rd_Rs, s3_do16_dsp2},
  707. {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  708. {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  709. {"mazl.f!", 0x7800, 0x7f00, 0x38000182, Rd_Rs, s3_do16_dsp2},
  710. {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd},
  711. {"mfceh!", 0x7110, 0x7ff0, 0x00000848, x_Rs, s3_do16_dsp},
  712. {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  713. {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, s3_do_rdsrs},
  714. {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  715. {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  716. {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  717. {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  718. {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  719. {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  720. {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  721. {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2},
  722. {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  723. {"msb.f!", 0x7600, 0x7f00, 0x38000081, Rd_Rs, s3_do16_dsp2},
  724. {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  725. {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  726. {"msbh.fs!", 0x7f00, 0x7f00, 0x380002c5, Rd_Rs, s3_do16_dsp2},
  727. {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  728. {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  729. {"msbl.fs!", 0x7e00, 0x7f00, 0x380000c4, Rd_Rs, s3_do16_dsp2},
  730. {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  731. {"msbu!", 0x7700, 0x7f00, 0x38000021, Rd_Rs, s3_do16_dsp2},
  732. {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  733. {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  734. {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  735. {"mszh.f!", 0x7d00, 0x7f00, 0x38000385, Rd_Rs, s3_do16_dsp2},
  736. {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  737. {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp},
  738. {"mszl.f!", 0x7c00, 0x7f00, 0x38000184, Rd_Rs, s3_do16_dsp2},
  739. {"mtcel!", 0x7000, 0x7ff0, 0x0000044a, x_Rs, s3_do16_dsp},
  740. {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd},
  741. {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd},
  742. {"mtceh!", 0x7010, 0x7ff0, 0x0000084a, x_Rs, s3_do16_dsp},
  743. {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  744. {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, s3_do_rdsrs},
  745. {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  746. {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  747. {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  748. {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  749. {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  750. {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  751. {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs},
  752. {"mul.f!", 0x7200, 0x7f00, 0x00000041, Rd_Rs, s3_do16_dsp2},
  753. {"mulu!", 0x7300, 0x7f00, 0x00000042, Rd_Rs, s3_do16_dsp2},
  754. {"mulr.l", 0x00000140, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  755. {"mulr.h", 0x00000240, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  756. {"mulr", 0x00000340, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  757. {"mulr.lf", 0x00000141, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  758. {"mulr.hf", 0x00000241, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  759. {"mulr.f", 0x00000341, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  760. {"mulur.l", 0x00000142, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  761. {"mulur.h", 0x00000242, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  762. {"mulur", 0x00000342, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  763. {"divr.q", 0x00000144, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  764. {"divr.r", 0x00000244, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  765. {"divr", 0x00000344, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  766. {"divur.q", 0x00000146, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  767. {"divur.r", 0x00000246, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  768. {"divur", 0x00000346, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs},
  769. {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  770. {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  771. {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  772. {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  773. {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  774. {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  775. {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  776. {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  777. {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  778. {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  779. {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  780. {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  781. {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  782. {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  783. /* mv <-> mv!. */
  784. {"mv", 0x00003c56, 0x3e007fff, 0x4000, Rd_Rs_x, s3_do_rdrs},
  785. {"mv!", 0x4000, 0x7c00, 0x8000, Rd_Rs, s3_do16_mv_cmp},
  786. {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, s3_do_rdxrs},
  787. {"neg.c", 0x0000001f, 0x3e0003ff, 0x8000, Rd_x_Rs, s3_do_rdxrs},
  788. {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, s3_do_empty},
  789. {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  790. {"not.c", 0x00000025, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs},
  791. {"nop!", 0x0000, 0x7fff, 0x8000, NO16_OPD, s3_do_empty},
  792. {"or", 0x00000022, 0x3e0003ff, 0x4a00, Rd_Rs_Rs, s3_do_rdrsrs},
  793. {"or.c", 0x00000023, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  794. {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16},
  795. {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16},
  796. {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16},
  797. {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16},
  798. {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14},
  799. {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14},
  800. /* or.c <-> or!. */
  801. {"or!", 0x4a00, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2},
  802. {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty},
  803. {"pop!", 0x0040, 0x7fe0, 0x8000, Rd_rvalueRs, s3_do16_push_pop},
  804. {"push!", 0x0060, 0x7fe0, 0x8000, Rd_lvalueRs, s3_do16_push_pop},
  805. {"rpop!", 0x6800, 0x7c00, 0x8000, Rd_I5, s3_do16_rpop},
  806. {"rpush!", 0x6c00, 0x7c00, 0x8000, Rd_I5, s3_do16_rpush},
  807. {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  808. {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  809. {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  810. {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  811. {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  812. {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  813. {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  814. {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  815. {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  816. {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  817. {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  818. {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  819. {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty},
  820. {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, s3_do_ldst_atomic},
  821. {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s3_do_ldst_unalign},
  822. {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s3_do_ldst_unalign},
  823. {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, s3_do_ldst_unalign},
  824. {"sdbbp", 0x00000006, 0x3e0003ff, 0x0020, x_I5_x, s3_do_xi5x},
  825. {"sdbbp!", 0x0020, 0x7fe0, 0x8000, Rd_I5, s3_do16_xi5},
  826. {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty},
  827. {"rti", 0x0c0000e4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty},
  828. {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  829. {"sll.c", 0x00000031, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  830. {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2},
  831. {"slli", 0x00000070, 0x3e0003ff, 0x5800, Rd_Rs_I5, s3_do_rdrsi5},
  832. {"slli.c", 0x00000071, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  833. /* slli.c <-> slli!. */
  834. {"slli!", 0x5800, 0x7e00, 0x8000, Rd_I5, s3_do16_slli_srli},
  835. {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  836. {"srl.c", 0x00000035, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  837. {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  838. {"sra.c", 0x00000037, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  839. {"srli", 0x00000074, 0x3e0003ff, 0x5a00, Rd_Rs_I5, s3_do_rdrsi5},
  840. {"srli.c", 0x00000075, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  841. {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  842. {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5},
  843. /* srli.c <-> srli!. */
  844. {"srli!", 0x5a00, 0x7e00, 0x8000, Rd_Rs, s3_do16_slli_srli},
  845. {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop},
  846. {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop},
  847. {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop},
  848. {"sub", 0x00000014, 0x3e0003ff, 0x4900, Rd_Rs_Rs, s3_do_rdrsrs},
  849. {"sub.c", 0x00000015, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  850. {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2},
  851. {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  852. {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  853. /* sub.c <-> sub!. */
  854. {"sub!", 0x4900, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2},
  855. {"sw!", 0x2000, 0x7000, 0x8000, Rd_lvalueRs, s3_do16_ldst_insn},
  856. {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, s3_do_i15},
  857. {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  858. {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  859. {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  860. {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  861. {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  862. {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  863. {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  864. {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  865. {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  866. {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  867. {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  868. {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  869. {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  870. {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  871. {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x},
  872. {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  873. {"xor.c", 0x00000027, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs},
  874. /* Macro instruction. */
  875. {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s3_do_macro_li_rdi32},
  876. /* la reg, imm32 -->(1) ldi reg, simm16
  877. (2) ldis reg, %HI(imm32)
  878. ori reg, %LO(imm32)
  879. la reg, symbol -->(1) lis reg, %HI(imm32)
  880. ori reg, %LO(imm32) */
  881. {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s3_do_macro_la_rdi32},
  882. {"bcmpeqz", 0x0000004c, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmpz},
  883. {"bcmpeq", 0x0000004c, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmp},
  884. {"bcmpnez", 0x0000004e, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmpz},
  885. {"bcmpne", 0x0000004e, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmp},
  886. {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  887. {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  888. {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  889. {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  890. {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  891. {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  892. {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  893. {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  894. {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  895. {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs},
  896. {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label},
  897. {"lbu", INSN_LBU, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label},
  898. {"lh", INSN_LH, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label},
  899. {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label},
  900. {"lw", INSN_LW, 0x00000000, 0x1000, Insn_Type_SYN, s3_do_macro_ldst_label},
  901. {"sb", INSN_SB, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label},
  902. {"sh", INSN_SH, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label},
  903. {"sw", INSN_SW, 0x00000000, 0x2000, Insn_Type_SYN, s3_do_macro_ldst_label},
  904. /* Assembler use internal. */
  905. {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s3_do_macro_rdi32hi},
  906. {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_macro_rdi32lo},
  907. {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s3_do_rdi16_pic},
  908. {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_addi_s_pic},
  909. {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_addi_u_pic},
  910. {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, s3_do_lw_pic},
  911. /* 48-bit instructions. */
  912. {"sdbbp48", 0x000000000000LL, 0x1c000000001fLL, 0x8000, Rd_I32, s3_do_sdbbp48},
  913. {"ldi48", 0x000000000001LL, 0x1c000000001fLL, 0x8000, Rd_I32, s3_do_ldi48},
  914. {"lw48", 0x000000000002LL, 0x1c000000001fLL, 0x8000, Rd_I30, s3_do_lw48},
  915. {"sw48", 0x000000000003LL, 0x1c000000001fLL, 0x8000, Rd_I30, s3_do_sw48},
  916. {"andri48", 0x040000000000LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_and48},
  917. {"andri48.c", 0x040000000001LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_and48},
  918. {"orri48", 0x040000000002LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_or48},
  919. {"orri48.c", 0x040000000003LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_or48},
  920. };
  921. #define s3_SCORE3_PIPELINE 3
  922. static int s3_university_version = 0;
  923. static int s3_vector_size = s3_SCORE3_PIPELINE;
  924. static struct s3_score_it s3_dependency_vector[s3_SCORE3_PIPELINE];
  925. static int s3_score3d = 1;
  926. static int
  927. s3_end_of_line (char *str)
  928. {
  929. int retval = s3_SUCCESS;
  930. s3_skip_whitespace (str);
  931. if (*str != '\0')
  932. {
  933. retval = (int) s3_FAIL;
  934. if (!s3_inst.error)
  935. s3_inst.error = s3_BAD_GARBAGE;
  936. }
  937. return retval;
  938. }
  939. static int
  940. s3_score_reg_parse (char **ccp, struct hash_control *htab)
  941. {
  942. char *start = *ccp;
  943. char c;
  944. char *p;
  945. struct s3_reg_entry *reg;
  946. p = start;
  947. if (!ISALPHA (*p) || !is_name_beginner (*p))
  948. return (int) s3_FAIL;
  949. c = *p++;
  950. while (ISALPHA (c) || ISDIGIT (c) || c == '_')
  951. c = *p++;
  952. *--p = 0;
  953. reg = (struct s3_reg_entry *) hash_find (htab, start);
  954. *p = c;
  955. if (reg)
  956. {
  957. *ccp = p;
  958. return reg->number;
  959. }
  960. return (int) s3_FAIL;
  961. }
  962. /* If shift <= 0, only return reg. */
  963. static int
  964. s3_reg_required_here (char **str, int shift, enum s3_score_reg_type reg_type)
  965. {
  966. static char buff[s3_MAX_LITERAL_POOL_SIZE];
  967. int reg = (int) s3_FAIL;
  968. char *start = *str;
  969. if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[reg_type].htab)) != (int) s3_FAIL)
  970. {
  971. if (reg_type == s3_REG_TYPE_SCORE)
  972. {
  973. if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0))
  974. {
  975. as_warn (_("Using temp register(r1)"));
  976. s3_inst.bwarn = 1;
  977. }
  978. }
  979. if (shift >= 0)
  980. {
  981. if (reg_type == s3_REG_TYPE_SCORE_CR)
  982. strcpy (s3_inst.reg, s3_score_crn_table[reg].name);
  983. else if (reg_type == s3_REG_TYPE_SCORE_SR)
  984. strcpy (s3_inst.reg, s3_score_srn_table[reg].name);
  985. else
  986. strcpy (s3_inst.reg, "");
  987. s3_inst.instruction |= (bfd_vma) reg << shift;
  988. }
  989. }
  990. else
  991. {
  992. *str = start;
  993. sprintf (buff, _("register expected, not '%.100s'"), start);
  994. s3_inst.error = buff;
  995. }
  996. return reg;
  997. }
  998. static int
  999. s3_skip_past_comma (char **str)
  1000. {
  1001. char *p = *str;
  1002. char c;
  1003. int comma = 0;
  1004. while ((c = *p) == ' ' || c == ',')
  1005. {
  1006. p++;
  1007. if (c == ',' && comma++)
  1008. {
  1009. s3_inst.error = s3_BAD_SKIP_COMMA;
  1010. return (int) s3_FAIL;
  1011. }
  1012. }
  1013. if ((c == '\0') || (comma == 0))
  1014. {
  1015. s3_inst.error = s3_BAD_SKIP_COMMA;
  1016. return (int) s3_FAIL;
  1017. }
  1018. *str = p;
  1019. return comma ? s3_SUCCESS : (int) s3_FAIL;
  1020. }
  1021. static void
  1022. s3_do_rdrsrs (char *str)
  1023. {
  1024. int reg;
  1025. s3_skip_whitespace (str);
  1026. if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  1027. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1028. || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1029. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1030. || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1031. || s3_end_of_line (str) == (int) s3_FAIL)
  1032. {
  1033. return;
  1034. }
  1035. else
  1036. {
  1037. /* Check mulr, mulur rd is even number. */
  1038. if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340
  1039. || (s3_inst.instruction & 0x3e0003ff) == 0x00000342)
  1040. && (reg % 2))
  1041. {
  1042. s3_inst.error = _("rd must be even number.");
  1043. return;
  1044. }
  1045. if ((((s3_inst.instruction >> 15) & 0x10) == 0)
  1046. && (((s3_inst.instruction >> 10) & 0x10) == 0)
  1047. && (((s3_inst.instruction >> 20) & 0x10) == 0)
  1048. && (s3_inst.relax_inst != 0x8000)
  1049. && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf)))
  1050. {
  1051. s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) )
  1052. | (((s3_inst.instruction >> 15) & 0xf) << 4);
  1053. s3_inst.relax_size = 2;
  1054. }
  1055. else
  1056. {
  1057. s3_inst.relax_inst = 0x8000;
  1058. }
  1059. }
  1060. }
  1061. static int
  1062. s3_walk_no_bignums (symbolS * sp)
  1063. {
  1064. if (symbol_get_value_expression (sp)->X_op == O_big)
  1065. return 1;
  1066. if (symbol_get_value_expression (sp)->X_add_symbol)
  1067. return (s3_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
  1068. || (symbol_get_value_expression (sp)->X_op_symbol
  1069. && s3_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
  1070. return 0;
  1071. }
  1072. static int
  1073. s3_my_get_expression (expressionS * ep, char **str)
  1074. {
  1075. char *save_in;
  1076. save_in = input_line_pointer;
  1077. input_line_pointer = *str;
  1078. s3_in_my_get_expression = 1;
  1079. (void) expression (ep);
  1080. s3_in_my_get_expression = 0;
  1081. if (ep->X_op == O_illegal)
  1082. {
  1083. *str = input_line_pointer;
  1084. input_line_pointer = save_in;
  1085. s3_inst.error = _("illegal expression");
  1086. return (int) s3_FAIL;
  1087. }
  1088. /* Get rid of any bignums now, so that we don't generate an error for which
  1089. we can't establish a line number later on. Big numbers are never valid
  1090. in instructions, which is where this routine is always called. */
  1091. if (ep->X_op == O_big
  1092. || (ep->X_add_symbol
  1093. && (s3_walk_no_bignums (ep->X_add_symbol)
  1094. || (ep->X_op_symbol && s3_walk_no_bignums (ep->X_op_symbol)))))
  1095. {
  1096. s3_inst.error = _("invalid constant");
  1097. *str = input_line_pointer;
  1098. input_line_pointer = save_in;
  1099. return (int) s3_FAIL;
  1100. }
  1101. if ((ep->X_add_symbol != NULL)
  1102. && (s3_inst.type != PC_DISP19div2)
  1103. && (s3_inst.type != PC_DISP8div2)
  1104. && (s3_inst.type != PC_DISP24div2)
  1105. && (s3_inst.type != PC_DISP11div2)
  1106. && (s3_inst.type != Insn_Type_SYN)
  1107. && (s3_inst.type != Rd_rvalueRs_SI15)
  1108. && (s3_inst.type != Rd_lvalueRs_SI15)
  1109. && (s3_inst.type != Insn_internal)
  1110. && (s3_inst.type != Rd_I30)
  1111. && (s3_inst.type != Rd_I32)
  1112. && (s3_inst.type != Insn_BCMP))
  1113. {
  1114. s3_inst.error = s3_BAD_ARGS;
  1115. *str = input_line_pointer;
  1116. input_line_pointer = save_in;
  1117. return (int) s3_FAIL;
  1118. }
  1119. *str = input_line_pointer;
  1120. input_line_pointer = save_in;
  1121. return s3_SUCCESS;
  1122. }
  1123. /* Check if an immediate is valid. If so, convert it to the right format. */
  1124. static bfd_signed_vma
  1125. s3_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p)
  1126. {
  1127. switch (data_type)
  1128. {
  1129. case _VALUE_HI16:
  1130. {
  1131. bfd_signed_vma val_hi = ((val & 0xffff0000) >> 16);
  1132. if (s3_score_df_range[data_type].range[0] <= val_hi
  1133. && val_hi <= s3_score_df_range[data_type].range[1])
  1134. return val_hi;
  1135. }
  1136. break;
  1137. case _VALUE_LO16:
  1138. {
  1139. bfd_signed_vma val_lo = (val & 0xffff);
  1140. if (s3_score_df_range[data_type].range[0] <= val_lo
  1141. && val_lo <= s3_score_df_range[data_type].range[1])
  1142. return val_lo;
  1143. }
  1144. break;
  1145. case _SIMM14:
  1146. if (hex_p == 1)
  1147. {
  1148. if (!(val >= -0x2000 && val <= 0x3fff))
  1149. {
  1150. return (int) s3_FAIL;
  1151. }
  1152. }
  1153. else
  1154. {
  1155. if (!(val >= -8192 && val <= 8191))
  1156. {
  1157. return (int) s3_FAIL;
  1158. }
  1159. }
  1160. return val;
  1161. break;
  1162. case _SIMM16_NEG:
  1163. if (hex_p == 1)
  1164. {
  1165. if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
  1166. {
  1167. return (int) s3_FAIL;
  1168. }
  1169. }
  1170. else
  1171. {
  1172. if (!(val >= -32767 && val <= 32768))
  1173. {
  1174. return (int) s3_FAIL;
  1175. }
  1176. }
  1177. val = -val;
  1178. return val;
  1179. break;
  1180. case _IMM5_MULTI_LOAD:
  1181. if (val >= 2 && val <= 32)
  1182. {
  1183. if (val == 32)
  1184. val = 0;
  1185. return val;
  1186. }
  1187. return (int) s3_FAIL;
  1188. case _IMM32:
  1189. if (val >= 0 && val <= 0xffffffff)
  1190. {
  1191. return val;
  1192. }
  1193. else
  1194. {
  1195. return (int) s3_FAIL;
  1196. }
  1197. default:
  1198. if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
  1199. val = -val;
  1200. if (s3_score_df_range[data_type].range[0] <= val
  1201. && val <= s3_score_df_range[data_type].range[1])
  1202. return val;
  1203. break;
  1204. }
  1205. return (int) s3_FAIL;
  1206. }
  1207. static int
  1208. s3_data_op2 (char **str, int shift, enum score_data_type data_type)
  1209. {
  1210. bfd_signed_vma value;
  1211. char data_exp[s3_MAX_LITERAL_POOL_SIZE];
  1212. char *dataptr;
  1213. int cnt = 0;
  1214. char *pp = NULL;
  1215. s3_skip_whitespace (*str);
  1216. s3_inst.error = NULL;
  1217. dataptr = * str;
  1218. /* Set hex_p to zero. */
  1219. int hex_p = 0;
  1220. while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s3_MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */
  1221. {
  1222. data_exp[cnt] = *dataptr;
  1223. dataptr++;
  1224. cnt++;
  1225. }
  1226. data_exp[cnt] = '\0';
  1227. pp = (char *)&data_exp;
  1228. if (*dataptr == '|') /* process PCE */
  1229. {
  1230. if (s3_my_get_expression (&s3_inst.reloc.exp, &pp) == (int) s3_FAIL)
  1231. return (int) s3_FAIL;
  1232. s3_end_of_line (pp);
  1233. if (s3_inst.error != 0)
  1234. return (int) s3_FAIL; /* to ouptut_inst to printf out the error */
  1235. *str = dataptr;
  1236. }
  1237. else /* process 16 bit */
  1238. {
  1239. if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL)
  1240. {
  1241. return (int) s3_FAIL;
  1242. }
  1243. dataptr = (char *)data_exp;
  1244. for (; *dataptr != '\0'; dataptr++)
  1245. {
  1246. *dataptr = TOLOWER (*dataptr);
  1247. if (*dataptr == '!' || *dataptr == ' ')
  1248. break;
  1249. }
  1250. dataptr = (char *)data_exp;
  1251. if ((dataptr != NULL)
  1252. && (((strstr (dataptr, "0x")) != NULL)
  1253. || ((strstr (dataptr, "0X")) != NULL)))
  1254. {
  1255. hex_p = 1;
  1256. if ((data_type != _SIMM16_LA)
  1257. && (data_type != _VALUE_HI16)
  1258. && (data_type != _VALUE_LO16)
  1259. && (data_type != _IMM16)
  1260. && (data_type != _IMM15)
  1261. && (data_type != _IMM14)
  1262. && (data_type != _IMM4)
  1263. && (data_type != _IMM5)
  1264. && (data_type != _IMM5_MULTI_LOAD)
  1265. && (data_type != _IMM11)
  1266. && (data_type != _IMM8)
  1267. && (data_type != _IMM5_RSHIFT_1)
  1268. && (data_type != _IMM5_RSHIFT_2)
  1269. && (data_type != _SIMM14)
  1270. && (data_type != _SIMM14_NEG)
  1271. && (data_type != _SIMM16_NEG)
  1272. && (data_type != _IMM10_RSHIFT_2)
  1273. && (data_type != _GP_IMM15)
  1274. && (data_type != _SIMM5)
  1275. && (data_type != _SIMM6)
  1276. && (data_type != _IMM32)
  1277. && (data_type != _SIMM32))
  1278. {
  1279. data_type += 24;
  1280. }
  1281. }
  1282. if ((s3_inst.reloc.exp.X_add_number == 0)
  1283. && (s3_inst.type != Insn_Type_SYN)
  1284. && (s3_inst.type != Rd_rvalueRs_SI15)
  1285. && (s3_inst.type != Rd_lvalueRs_SI15)
  1286. && (s3_inst.type != Insn_internal)
  1287. && (((*dataptr >= 'a') && (*dataptr <= 'z'))
  1288. || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
  1289. || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
  1290. || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
  1291. {
  1292. s3_inst.error = s3_BAD_ARGS;
  1293. return (int) s3_FAIL;
  1294. }
  1295. }
  1296. if ((s3_inst.reloc.exp.X_add_symbol)
  1297. && ((data_type == _SIMM16)
  1298. || (data_type == _SIMM16_NEG)
  1299. || (data_type == _IMM16_NEG)
  1300. || (data_type == _SIMM14)
  1301. || (data_type == _SIMM14_NEG)
  1302. || (data_type == _IMM5)
  1303. || (data_type == _IMM5_MULTI_LOAD)
  1304. || (data_type == _IMM11)
  1305. || (data_type == _IMM14)
  1306. || (data_type == _IMM20)
  1307. || (data_type == _IMM16)
  1308. || (data_type == _IMM15)
  1309. || (data_type == _IMM4)))
  1310. {
  1311. s3_inst.error = s3_BAD_ARGS;
  1312. return (int) s3_FAIL;
  1313. }
  1314. if (s3_inst.reloc.exp.X_add_symbol)
  1315. {
  1316. switch (data_type)
  1317. {
  1318. case _SIMM16_LA:
  1319. return (int) s3_FAIL;
  1320. case _VALUE_HI16:
  1321. s3_inst.reloc.type = BFD_RELOC_HI16_S;
  1322. s3_inst.reloc.pc_rel = 0;
  1323. break;
  1324. case _VALUE_LO16:
  1325. s3_inst.reloc.type = BFD_RELOC_LO16;
  1326. s3_inst.reloc.pc_rel = 0;
  1327. break;
  1328. case _GP_IMM15:
  1329. s3_inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
  1330. s3_inst.reloc.pc_rel = 0;
  1331. break;
  1332. case _SIMM16_pic:
  1333. case _IMM16_LO16_pic:
  1334. s3_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
  1335. s3_inst.reloc.pc_rel = 0;
  1336. break;
  1337. default:
  1338. s3_inst.reloc.type = BFD_RELOC_32;
  1339. s3_inst.reloc.pc_rel = 0;
  1340. break;
  1341. }
  1342. }
  1343. else
  1344. {
  1345. if (data_type == _IMM16_pic)
  1346. {
  1347. s3_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
  1348. s3_inst.reloc.pc_rel = 0;
  1349. }
  1350. if (data_type == _SIMM16_LA && s3_inst.reloc.exp.X_unsigned == 1)
  1351. {
  1352. value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
  1353. if (value == (int) s3_FAIL) /* for advance to check if this is ldis */
  1354. if ((s3_inst.reloc.exp.X_add_number & 0xffff) == 0)
  1355. {
  1356. s3_inst.instruction |= 0x8000000;
  1357. s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
  1358. return s3_SUCCESS;
  1359. }
  1360. }
  1361. else
  1362. {
  1363. value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, hex_p);
  1364. }
  1365. if (value == (int) s3_FAIL)
  1366. {
  1367. if (data_type == _IMM32)
  1368. {
  1369. sprintf (s3_err_msg,
  1370. _("invalid constant: %d bit expression not in range %u..%u"),
  1371. s3_score_df_range[data_type].bits,
  1372. 0, (unsigned)0xffffffff);
  1373. }
  1374. else if (data_type == _IMM5_MULTI_LOAD)
  1375. {
  1376. sprintf (s3_err_msg,
  1377. _("invalid constant: %d bit expression not in range %u..%u"),
  1378. 5, 2, 32);
  1379. }
  1380. else if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
  1381. {
  1382. sprintf (s3_err_msg,
  1383. _("invalid constant: %d bit expression not in range %d..%d"),
  1384. s3_score_df_range[data_type].bits,
  1385. s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
  1386. }
  1387. else
  1388. {
  1389. sprintf (s3_err_msg,
  1390. _("invalid constant: %d bit expression not in range %d..%d"),
  1391. s3_score_df_range[data_type].bits,
  1392. -s3_score_df_range[data_type].range[1], -s3_score_df_range[data_type].range[0]);
  1393. }
  1394. s3_inst.error = s3_err_msg;
  1395. return (int) s3_FAIL;
  1396. }
  1397. if (((s3_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
  1398. && data_type != _IMM5_MULTI_LOAD)
  1399. {
  1400. value &= (1 << s3_score_df_range[data_type].bits) - 1;
  1401. }
  1402. s3_inst.instruction |= value << shift;
  1403. }
  1404. if ((s3_inst.instruction & 0x3e000000) == 0x30000000)
  1405. {
  1406. if ((((s3_inst.instruction >> 20) & 0x1F) != 0)
  1407. && (((s3_inst.instruction >> 20) & 0x1F) != 1)
  1408. && (((s3_inst.instruction >> 20) & 0x1F) != 2)
  1409. && (((s3_inst.instruction >> 20) & 0x1F) != 0x10))
  1410. {
  1411. s3_inst.error = _("invalid constant: bit expression not defined");
  1412. return (int) s3_FAIL;
  1413. }
  1414. }
  1415. return s3_SUCCESS;
  1416. }
  1417. /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */
  1418. static void
  1419. s3_do_rdsi16 (char *str)
  1420. {
  1421. s3_skip_whitespace (str);
  1422. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1423. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1424. || s3_data_op2 (&str, 1, _SIMM16) == (int) s3_FAIL
  1425. || s3_end_of_line (str) == (int) s3_FAIL)
  1426. return;
  1427. /* ldi.->ldiu! only for imm5 */
  1428. if ((s3_inst.instruction & 0x20c0000) == 0x20c0000)
  1429. {
  1430. if ((s3_inst.instruction & 0x1ffc0) != 0)
  1431. {
  1432. s3_inst.relax_inst = 0x8000;
  1433. }
  1434. else
  1435. {
  1436. s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f;
  1437. s3_inst.relax_inst |= (((s3_inst.instruction >> 20)& 0x1f) <<5);
  1438. s3_inst.relax_size = 2;
  1439. }
  1440. }
  1441. /*cmpi.c */
  1442. else if ((s3_inst.instruction & 0x02040001) == 0x02040001)
  1443. {
  1444. /* imm <=0x3f (5 bit<<1)*/
  1445. if (((s3_inst.instruction & 0x1ffe0) == 0)
  1446. || (((s3_inst.instruction & 0x1ffe0) == 0x1ffe0)
  1447. && (s3_inst.instruction & 0x003e) != 0))
  1448. {
  1449. s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f;
  1450. s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0x1f) << 5);
  1451. s3_inst.relax_size = 2;
  1452. }
  1453. else
  1454. {
  1455. s3_inst.relax_inst =0x8000;
  1456. }
  1457. }
  1458. /* addi */
  1459. else if (((s3_inst.instruction & 0x2000000) == 0x02000000) && (s3_inst.relax_inst!=0x8000))
  1460. {
  1461. /* rd : 0-16 ; imm <=0x7f (6 bit<<1)*/
  1462. if ((((s3_inst.instruction >> 20) & 0x10) != 0x10)
  1463. && (((s3_inst.instruction & 0x1ffc0) == 0)
  1464. || (((s3_inst.instruction & 0x1ffc0) == 0x1ffc0)
  1465. && (s3_inst.instruction & 0x007e) != 0)))
  1466. {
  1467. s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f;
  1468. s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6);
  1469. s3_inst.relax_size = 2;
  1470. }
  1471. else
  1472. {
  1473. s3_inst.relax_inst =0x8000;
  1474. }
  1475. }
  1476. else if (((s3_inst.instruction >> 20) & 0x10) == 0x10)
  1477. {
  1478. s3_inst.relax_inst = 0x8000;
  1479. }
  1480. }
  1481. static void
  1482. s3_do_ldis (char *str)
  1483. {
  1484. s3_skip_whitespace (str);
  1485. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1486. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1487. || s3_data_op2 (&str, 1, _IMM16) == (int) s3_FAIL
  1488. || s3_end_of_line (str) == (int) s3_FAIL)
  1489. return;
  1490. }
  1491. /* Handle subi/subi.c. */
  1492. static void
  1493. s3_do_sub_rdsi16 (char *str)
  1494. {
  1495. s3_skip_whitespace (str);
  1496. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1497. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1498. && s3_data_op2 (&str, 1, _SIMM16_NEG) != (int) s3_FAIL)
  1499. s3_end_of_line (str);
  1500. }
  1501. /* Handle subis/subis.c. */
  1502. static void
  1503. s3_do_sub_rdi16 (char *str)
  1504. {
  1505. s3_skip_whitespace (str);
  1506. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1507. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1508. && s3_data_op2 (&str, 1, _IMM16_NEG) != (int) s3_FAIL)
  1509. s3_end_of_line (str);
  1510. }
  1511. /* Handle addri/addri.c. */
  1512. static void
  1513. s3_do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
  1514. {
  1515. s3_skip_whitespace (str);
  1516. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1517. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1518. && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1519. && s3_skip_past_comma (&str) != (int) s3_FAIL)
  1520. s3_data_op2 (&str, 1, _SIMM14);
  1521. }
  1522. /* Handle subri.c/subri. */
  1523. static void
  1524. s3_do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */
  1525. {
  1526. s3_skip_whitespace (str);
  1527. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1528. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1529. && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1530. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1531. && s3_data_op2 (&str, 1, _SIMM14_NEG) != (int) s3_FAIL)
  1532. s3_end_of_line (str);
  1533. }
  1534. /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c.
  1535. 0~((2^14)-1) */
  1536. static void
  1537. s3_do_rdrsi5 (char *str)
  1538. {
  1539. s3_skip_whitespace (str);
  1540. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1541. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1542. || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1543. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1544. || s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL
  1545. || s3_end_of_line (str) == (int) s3_FAIL)
  1546. return;
  1547. if ((((s3_inst.instruction >> 20) & 0x1f) == ((s3_inst.instruction >> 15) & 0x1f))
  1548. && (s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0))
  1549. {
  1550. s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f) ) | (((s3_inst.instruction >> 15) & 0xf) << 5);
  1551. s3_inst.relax_size = 2;
  1552. }
  1553. else
  1554. s3_inst.relax_inst = 0x8000;
  1555. }
  1556. /* Handle andri/orri/andri.c/orri.c.
  1557. 0 ~ ((2^14)-1) */
  1558. static void
  1559. s3_do_rdrsi14 (char *str)
  1560. {
  1561. s3_skip_whitespace (str);
  1562. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1563. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1564. && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1565. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1566. && s3_data_op2 (&str, 1, _IMM14) != (int) s3_FAIL)
  1567. s3_end_of_line (str);
  1568. }
  1569. /* Handle bittst.c. */
  1570. static void
  1571. s3_do_xrsi5 (char *str)
  1572. {
  1573. s3_skip_whitespace (str);
  1574. if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1575. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1576. || s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL
  1577. || s3_end_of_line (str) == (int) s3_FAIL)
  1578. return;
  1579. if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0))
  1580. {
  1581. s3_inst.relax_inst |= ((s3_inst.instruction >> 10) & 0x1f) | (((s3_inst.instruction >> 15) & 0xf) << 5);
  1582. s3_inst.relax_size = 2;
  1583. }
  1584. else
  1585. s3_inst.relax_inst = 0x8000;
  1586. }
  1587. /* Handle addis/andi/ori/andis/oris/ldis. */
  1588. static void
  1589. s3_do_rdi16 (char *str)
  1590. {
  1591. s3_skip_whitespace (str);
  1592. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1593. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1594. || s3_data_op2 (&str, 1, _IMM16) == (int) s3_FAIL
  1595. || s3_end_of_line (str) == (int) s3_FAIL)
  1596. return;
  1597. /* ldis */
  1598. if ((s3_inst.instruction & 0x3e0e0000) == 0x0a0c0000)
  1599. {
  1600. /* rd : 0-16 ;imm =0 -> can transform to addi!*/
  1601. if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && ((s3_inst.instruction & 0x1ffff)==0))
  1602. {
  1603. s3_inst.relax_inst =0x5400; /* ldiu! */
  1604. s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f;
  1605. s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 5);
  1606. s3_inst.relax_size = 2;
  1607. }
  1608. else
  1609. {
  1610. s3_inst.relax_inst =0x8000;
  1611. }
  1612. }
  1613. /* addis */
  1614. else if ((s3_inst.instruction & 0x3e0e0001) == 0x0a000000)
  1615. {
  1616. /* rd : 0-16 ;imm =0 -> can transform to addi!*/
  1617. if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && ((s3_inst.instruction & 0x1ffff)==0))
  1618. {
  1619. s3_inst.relax_inst =0x5c00; /* addi! */
  1620. s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f;
  1621. s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6);
  1622. s3_inst.relax_size = 2;
  1623. }
  1624. else
  1625. {
  1626. s3_inst.relax_inst =0x8000;
  1627. }
  1628. }
  1629. }
  1630. static void
  1631. s3_do_macro_rdi32hi (char *str)
  1632. {
  1633. s3_skip_whitespace (str);
  1634. /* Do not handle s3_end_of_line(). */
  1635. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1636. && s3_skip_past_comma (&str) != (int) s3_FAIL)
  1637. s3_data_op2 (&str, 1, _VALUE_HI16);
  1638. }
  1639. static void
  1640. s3_do_macro_rdi32lo (char *str)
  1641. {
  1642. s3_skip_whitespace (str);
  1643. /* Do not handle s3_end_of_line(). */
  1644. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1645. && s3_skip_past_comma (&str) != (int) s3_FAIL)
  1646. s3_data_op2 (&str, 1, _VALUE_LO16);
  1647. }
  1648. /* Handle ldis_pic. */
  1649. static void
  1650. s3_do_rdi16_pic (char *str)
  1651. {
  1652. s3_skip_whitespace (str);
  1653. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1654. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1655. && s3_data_op2 (&str, 1, _IMM16_pic) != (int) s3_FAIL)
  1656. s3_end_of_line (str);
  1657. }
  1658. /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */
  1659. static void
  1660. s3_do_addi_s_pic (char *str)
  1661. {
  1662. s3_skip_whitespace (str);
  1663. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1664. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1665. && s3_data_op2 (&str, 1, _SIMM16_pic) != (int) s3_FAIL)
  1666. s3_end_of_line (str);
  1667. }
  1668. /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */
  1669. static void
  1670. s3_do_addi_u_pic (char *str)
  1671. {
  1672. s3_skip_whitespace (str);
  1673. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1674. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1675. && s3_data_op2 (&str, 1, _IMM16_LO16_pic) != (int) s3_FAIL)
  1676. s3_end_of_line (str);
  1677. }
  1678. /* Handle mfceh/mfcel/mtceh/mtchl. */
  1679. static void
  1680. s3_do_rd (char *str)
  1681. {
  1682. s3_skip_whitespace (str);
  1683. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL)
  1684. s3_end_of_line (str);
  1685. }
  1686. /* Handle br{cond},cmpzteq.c ,cmpztmi.c ,cmpz.c */
  1687. static void
  1688. s3_do_rs (char *str)
  1689. {
  1690. s3_skip_whitespace (str);
  1691. if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1692. || s3_end_of_line (str) == (int) s3_FAIL)
  1693. return;
  1694. if ((s3_inst.relax_inst != 0x8000) )
  1695. {
  1696. s3_inst.relax_inst |= ((s3_inst.instruction >> 15) &0x1f);
  1697. s3_inst.relax_size = 2;
  1698. }
  1699. else
  1700. s3_inst.relax_inst = 0x8000;
  1701. }
  1702. static void
  1703. s3_do_i15 (char *str)
  1704. {
  1705. s3_skip_whitespace (str);
  1706. if (s3_data_op2 (&str, 10, _IMM15) != (int) s3_FAIL)
  1707. s3_end_of_line (str);
  1708. }
  1709. static void
  1710. s3_do_xi5x (char *str)
  1711. {
  1712. s3_skip_whitespace (str);
  1713. if (s3_data_op2 (&str, 15, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
  1714. return;
  1715. if (s3_inst.relax_inst != 0x8000)
  1716. {
  1717. s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f);
  1718. s3_inst.relax_size = 2;
  1719. }
  1720. }
  1721. static void
  1722. s3_do_rdrs (char *str)
  1723. {
  1724. s3_skip_whitespace (str);
  1725. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1726. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1727. || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1728. || s3_end_of_line (str) == (int) s3_FAIL)
  1729. return;
  1730. if (s3_inst.relax_inst != 0x8000)
  1731. {
  1732. if (((s3_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv!*/
  1733. {
  1734. /* mv! rd : 5bit , ra : 5bit */
  1735. s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f) | (((s3_inst.instruction >> 20) & 0x1f) << 5);
  1736. s3_inst.relax_size = 2;
  1737. }
  1738. else if ((((s3_inst.instruction >> 15) & 0x10) == 0x0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
  1739. {
  1740. s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 4)
  1741. | (((s3_inst.instruction >> 20) & 0xf) << 8);
  1742. s3_inst.relax_size = 2;
  1743. }
  1744. else
  1745. {
  1746. s3_inst.relax_inst = 0x8000;
  1747. }
  1748. }
  1749. }
  1750. /* Handle mfcr/mtcr. */
  1751. static void
  1752. s3_do_rdcrs (char *str)
  1753. {
  1754. s3_skip_whitespace (str);
  1755. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1756. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1757. && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) != (int) s3_FAIL)
  1758. s3_end_of_line (str);
  1759. }
  1760. /* Handle mfsr/mtsr. */
  1761. static void
  1762. s3_do_rdsrs (char *str)
  1763. {
  1764. s3_skip_whitespace (str);
  1765. /* mfsr */
  1766. if ((s3_inst.instruction & 0xff) == 0x50)
  1767. {
  1768. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1769. && s3_skip_past_comma (&str) != (int) s3_FAIL
  1770. && s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_SR) != (int) s3_FAIL)
  1771. s3_end_of_line (str);
  1772. }
  1773. else
  1774. {
  1775. if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL
  1776. && s3_skip_past_comma (&str) != (int) s3_FAIL)
  1777. s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_SR);
  1778. }
  1779. }
  1780. /* Handle neg. */
  1781. static void
  1782. s3_do_rdxrs (char *str)
  1783. {
  1784. s3_skip_whitespace (str);
  1785. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1786. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1787. || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1788. || s3_end_of_line (str) == (int) s3_FAIL)
  1789. return;
  1790. if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 10) & 0x10) == 0)
  1791. && (((s3_inst.instruction >> 20) & 0x10) == 0))
  1792. {
  1793. s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) << 4) | (((s3_inst.instruction >> 20) & 0xf) << 8);
  1794. s3_inst.relax_size = 2;
  1795. }
  1796. else
  1797. s3_inst.relax_inst = 0x8000;
  1798. }
  1799. /* Handle cmp.c/cmp<cond>. */
  1800. static void
  1801. s3_do_rsrs (char *str)
  1802. {
  1803. s3_skip_whitespace (str);
  1804. if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1805. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1806. || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1807. || s3_end_of_line (str) == (int) s3_FAIL)
  1808. return;
  1809. if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
  1810. {
  1811. s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
  1812. s3_inst.relax_size = 2;
  1813. }
  1814. else
  1815. s3_inst.relax_inst = 0x8000;
  1816. }
  1817. static void
  1818. s3_do_ceinst (char *str)
  1819. {
  1820. char *strbak;
  1821. strbak = str;
  1822. s3_skip_whitespace (str);
  1823. if (s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL
  1824. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1825. || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1826. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1827. || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1828. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1829. || s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL
  1830. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1831. || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
  1832. || s3_end_of_line (str) == (int) s3_FAIL)
  1833. {
  1834. return;
  1835. }
  1836. else
  1837. {
  1838. str = strbak;
  1839. if (s3_data_op2 (&str, 0, _IMM25) == (int) s3_FAIL)
  1840. return;
  1841. }
  1842. }
  1843. static int
  1844. s3_reglow_required_here (char **str, int shift)
  1845. {
  1846. static char buff[s3_MAX_LITERAL_POOL_SIZE];
  1847. int reg;
  1848. char *start = *str;
  1849. if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[s3_REG_TYPE_SCORE].htab)) != (int) s3_FAIL)
  1850. {
  1851. if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0))
  1852. {
  1853. as_warn (_("Using temp register(r1)"));
  1854. s3_inst.bwarn = 1;
  1855. }
  1856. if (reg < 16)
  1857. {
  1858. if (shift >= 0)
  1859. s3_inst.instruction |= (bfd_vma) reg << shift;
  1860. return reg;
  1861. }
  1862. }
  1863. /* Restore the start point, we may have got a reg of the wrong class. */
  1864. *str = start;
  1865. sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
  1866. s3_inst.error = buff;
  1867. return (int) s3_FAIL;
  1868. }
  1869. /* Handle add!/and!/or!/sub!. */
  1870. static void
  1871. s3_do16_rdrs2 (char *str)
  1872. {
  1873. s3_skip_whitespace (str);
  1874. if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL
  1875. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1876. || s3_reglow_required_here (&str, 0) == (int) s3_FAIL
  1877. || s3_end_of_line (str) == (int) s3_FAIL)
  1878. {
  1879. return;
  1880. }
  1881. }
  1882. /* Handle br!/brl!. */
  1883. static void
  1884. s3_do16_br (char *str)
  1885. {
  1886. s3_skip_whitespace (str);
  1887. if (s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1888. || s3_end_of_line (str) == (int) s3_FAIL)
  1889. {
  1890. return;
  1891. }
  1892. }
  1893. /* Handle brr!. */
  1894. static void
  1895. s3_do16_brr (char *str)
  1896. {
  1897. int rd = 0;
  1898. s3_skip_whitespace (str);
  1899. if ((rd = s3_reg_required_here (&str, 0,s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  1900. || s3_end_of_line (str) == (int) s3_FAIL)
  1901. {
  1902. return;
  1903. }
  1904. }
  1905. /*Handle ltbw / ltbh / ltbb */
  1906. static void
  1907. s3_do_ltb (char *str)
  1908. {
  1909. s3_skip_whitespace (str);
  1910. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1911. || s3_skip_past_comma (&str) == (int) s3_FAIL)
  1912. {
  1913. return;
  1914. }
  1915. s3_skip_whitespace (str);
  1916. if (*str++ != '[')
  1917. {
  1918. s3_inst.error = _("missing [");
  1919. return;
  1920. }
  1921. if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  1922. || s3_skip_past_comma (&str) == (int) s3_FAIL
  1923. || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  1924. {
  1925. return;
  1926. }
  1927. s3_skip_whitespace (str);
  1928. if (*str++ != ']')
  1929. {
  1930. s3_inst.error = _("missing ]");
  1931. return;
  1932. }
  1933. }
  1934. /* We need to be able to fix up arbitrary expressions in some statements.
  1935. This is so that we can handle symbols that are an arbitrary distance from
  1936. the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
  1937. which returns part of an address in a form which will be valid for
  1938. a data instruction. We do this by pushing the expression into a symbol
  1939. in the expr_section, and creating a fix for that. */
  1940. static fixS *
  1941. s3_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
  1942. {
  1943. fixS *new_fix;
  1944. switch (exp->X_op)
  1945. {
  1946. case O_constant:
  1947. case O_symbol:
  1948. case O_add:
  1949. case O_subtract:
  1950. new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
  1951. break;
  1952. default:
  1953. new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
  1954. break;
  1955. }
  1956. return new_fix;
  1957. }
  1958. static void
  1959. s3_init_dependency_vector (void)
  1960. {
  1961. int i;
  1962. for (i = 0; i < s3_vector_size; i++)
  1963. memset (&s3_dependency_vector[i], '\0', sizeof (s3_dependency_vector[i]));
  1964. return;
  1965. }
  1966. static enum s3_insn_type_for_dependency
  1967. s3_dependency_type_from_insn (char *insn_name)
  1968. {
  1969. char name[s3_INSN_NAME_LEN];
  1970. const struct s3_insn_to_dependency *tmp;
  1971. strcpy (name, insn_name);
  1972. tmp = (const struct s3_insn_to_dependency *) hash_find (s3_dependency_insn_hsh, name);
  1973. if (tmp)
  1974. return tmp->type;
  1975. return s3_D_all_insn;
  1976. }
  1977. static int
  1978. s3_check_dependency (char *pre_insn, char *pre_reg,
  1979. char *cur_insn, char *cur_reg, int *warn_or_error)
  1980. {
  1981. int bubbles = 0;
  1982. unsigned int i;
  1983. enum s3_insn_type_for_dependency pre_insn_type;
  1984. enum s3_insn_type_for_dependency cur_insn_type;
  1985. pre_insn_type = s3_dependency_type_from_insn (pre_insn);
  1986. cur_insn_type = s3_dependency_type_from_insn (cur_insn);
  1987. for (i = 0; i < sizeof (s3_data_dependency_table) / sizeof (s3_data_dependency_table[0]); i++)
  1988. {
  1989. if ((pre_insn_type == s3_data_dependency_table[i].pre_insn_type)
  1990. && (s3_D_all_insn == s3_data_dependency_table[i].cur_insn_type
  1991. || cur_insn_type == s3_data_dependency_table[i].cur_insn_type)
  1992. && (strcmp (s3_data_dependency_table[i].pre_reg, "") == 0
  1993. || strcmp (s3_data_dependency_table[i].pre_reg, pre_reg) == 0)
  1994. && (strcmp (s3_data_dependency_table[i].cur_reg, "") == 0
  1995. || strcmp (s3_data_dependency_table[i].cur_reg, cur_reg) == 0))
  1996. {
  1997. bubbles = s3_data_dependency_table[i].bubblenum_3;
  1998. *warn_or_error = s3_data_dependency_table[i].warn_or_error;
  1999. break;
  2000. }
  2001. }
  2002. return bubbles;
  2003. }
  2004. static void
  2005. s3_build_one_frag (struct s3_score_it one_inst)
  2006. {
  2007. char *p;
  2008. int relaxable_p = s3_g_opt;
  2009. int relax_size = 0;
  2010. /* Start a new frag if frag_now is not empty. */
  2011. if (frag_now_fix () != 0)
  2012. {
  2013. if (!frag_now->tc_frag_data.is_insn)
  2014. frag_wane (frag_now);
  2015. frag_new (0);
  2016. }
  2017. frag_grow (20);
  2018. p = frag_more (one_inst.size);
  2019. s3_md_number_to_chars (p, one_inst.instruction, one_inst.size);
  2020. #ifdef OBJ_ELF
  2021. dwarf2_emit_insn (one_inst.size);
  2022. #endif
  2023. relaxable_p &= (one_inst.relax_size != 0);
  2024. relax_size = relaxable_p ? one_inst.relax_size : 0;
  2025. p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0,
  2026. s3_RELAX_ENCODE (one_inst.size, one_inst.relax_size,
  2027. one_inst.type, 0, 0, relaxable_p),
  2028. NULL, 0, NULL);
  2029. if (relaxable_p)
  2030. s3_md_number_to_chars (p, one_inst.relax_inst, relax_size);
  2031. }
  2032. static void
  2033. s3_handle_dependency (struct s3_score_it *theinst)
  2034. {
  2035. int i;
  2036. int warn_or_error = 0; /* warn - 0; error - 1 */
  2037. int bubbles = 0;
  2038. int remainder_bubbles = 0;
  2039. char cur_insn[s3_INSN_NAME_LEN];
  2040. char pre_insn[s3_INSN_NAME_LEN];
  2041. struct s3_score_it nop_inst;
  2042. struct s3_score_it pflush_inst;
  2043. nop_inst.instruction = 0x0000;
  2044. nop_inst.size = 2;
  2045. nop_inst.relax_inst = 0x80008000;
  2046. nop_inst.relax_size = 4;
  2047. nop_inst.type = NO16_OPD;
  2048. pflush_inst.instruction = 0x8000800a;
  2049. pflush_inst.size = 4;
  2050. pflush_inst.relax_inst = 0x8000;
  2051. pflush_inst.relax_size = 0;
  2052. pflush_inst.type = NO_OPD;
  2053. /* pflush will clear all data dependency. */
  2054. if (strcmp (theinst->name, "pflush") == 0)
  2055. {
  2056. s3_init_dependency_vector ();
  2057. return;
  2058. }
  2059. /* Push current instruction to s3_dependency_vector[0]. */
  2060. for (i = s3_vector_size - 1; i > 0; i--)
  2061. memcpy (&s3_dependency_vector[i], &s3_dependency_vector[i - 1], sizeof (s3_dependency_vector[i]));
  2062. memcpy (&s3_dependency_vector[0], theinst, sizeof (s3_dependency_vector[i]));
  2063. /* There is no dependency between nop and any instruction. */
  2064. if (strcmp (s3_dependency_vector[0].name, "nop") == 0
  2065. || strcmp (s3_dependency_vector[0].name, "nop!") == 0)
  2066. return;
  2067. strcpy (cur_insn, s3_dependency_vector[0].name);
  2068. for (i = 1; i < s3_vector_size; i++)
  2069. {
  2070. /* The element of s3_dependency_vector is NULL. */
  2071. if (s3_dependency_vector[i].name[0] == '\0')
  2072. continue;
  2073. strcpy (pre_insn, s3_dependency_vector[i].name);
  2074. bubbles = s3_check_dependency (pre_insn, s3_dependency_vector[i].reg,
  2075. cur_insn, s3_dependency_vector[0].reg, &warn_or_error);
  2076. remainder_bubbles = bubbles - i + 1;
  2077. if (remainder_bubbles > 0)
  2078. {
  2079. int j;
  2080. if (s3_fix_data_dependency == 1)
  2081. {
  2082. if (remainder_bubbles <= 2)
  2083. {
  2084. if (s3_warn_fix_data_dependency)
  2085. as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"),
  2086. s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
  2087. s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
  2088. remainder_bubbles, bubbles);
  2089. for (j = (s3_vector_size - 1); (j - remainder_bubbles) > 0; j--)
  2090. memcpy (&s3_dependency_vector[j], &s3_dependency_vector[j - remainder_bubbles],
  2091. sizeof (s3_dependency_vector[j]));
  2092. for (j = 1; j <= remainder_bubbles; j++)
  2093. {
  2094. memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
  2095. /* Insert nop!. */
  2096. s3_build_one_frag (nop_inst);
  2097. }
  2098. }
  2099. else
  2100. {
  2101. if (s3_warn_fix_data_dependency)
  2102. as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"),
  2103. s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
  2104. s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
  2105. bubbles);
  2106. for (j = 1; j < s3_vector_size; j++)
  2107. memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j]));
  2108. /* Insert pflush. */
  2109. s3_build_one_frag (pflush_inst);
  2110. }
  2111. }
  2112. else
  2113. {
  2114. if (warn_or_error)
  2115. {
  2116. as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
  2117. s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
  2118. s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
  2119. remainder_bubbles, bubbles);
  2120. }
  2121. else
  2122. {
  2123. as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"),
  2124. s3_dependency_vector[i].name, s3_dependency_vector[i].reg,
  2125. s3_dependency_vector[0].name, s3_dependency_vector[0].reg,
  2126. remainder_bubbles, bubbles);
  2127. }
  2128. }
  2129. }
  2130. }
  2131. }
  2132. static enum insn_class
  2133. s3_get_insn_class_from_type (enum score_insn_type type)
  2134. {
  2135. enum insn_class retval = (int) s3_FAIL;
  2136. switch (type)
  2137. {
  2138. case Rd_I4:
  2139. case Rd_I5:
  2140. case Rd_rvalueBP_I5:
  2141. case Rd_lvalueBP_I5:
  2142. case Rd_I8:
  2143. case PC_DISP8div2:
  2144. case PC_DISP11div2:
  2145. case Rd_Rs:
  2146. case Rd_HighRs:
  2147. case Rd_lvalueRs:
  2148. case Rd_rvalueRs:
  2149. case x_Rs:
  2150. case Rd_LowRs:
  2151. case NO16_OPD:
  2152. case Rd_SI5:
  2153. case Rd_SI6:
  2154. retval = INSN_CLASS_16;
  2155. break;
  2156. case Rd_Rs_I5:
  2157. case x_Rs_I5:
  2158. case x_I5_x:
  2159. case Rd_Rs_I14:
  2160. case I15:
  2161. case Rd_I16:
  2162. case Rd_SI16:
  2163. case Rd_rvalueRs_SI10:
  2164. case Rd_lvalueRs_SI10:
  2165. case Rd_rvalueRs_preSI12:
  2166. case Rd_rvalueRs_postSI12:
  2167. case Rd_lvalueRs_preSI12:
  2168. case Rd_lvalueRs_postSI12:
  2169. case Rd_Rs_SI14:
  2170. case Rd_rvalueRs_SI15:
  2171. case Rd_lvalueRs_SI15:
  2172. case PC_DISP19div2:
  2173. case PC_DISP24div2:
  2174. case Rd_Rs_Rs:
  2175. case x_Rs_x:
  2176. case x_Rs_Rs:
  2177. case Rd_Rs_x:
  2178. case Rd_x_Rs:
  2179. case Rd_x_x:
  2180. case OP5_rvalueRs_SI15:
  2181. case I5_Rs_Rs_I5_OP5:
  2182. case x_rvalueRs_post4:
  2183. case Rd_rvalueRs_post4:
  2184. case Rd_x_I5:
  2185. case Rd_lvalueRs_post4:
  2186. case x_lvalueRs_post4:
  2187. case Rd_Rs_Rs_imm:
  2188. case NO_OPD:
  2189. case Rd_lvalue32Rs:
  2190. case Rd_rvalue32Rs:
  2191. case Insn_GP:
  2192. case Insn_PIC:
  2193. case Insn_internal:
  2194. case Insn_BCMP:
  2195. case Ra_I9_I5:
  2196. retval = INSN_CLASS_32;
  2197. break;
  2198. case Insn_Type_PCE:
  2199. retval = INSN_CLASS_PCE;
  2200. break;
  2201. case Insn_Type_SYN:
  2202. retval = INSN_CLASS_SYN;
  2203. break;
  2204. case Rd_I30:
  2205. case Rd_I32:
  2206. retval = INSN_CLASS_48;
  2207. break;
  2208. default:
  2209. abort ();
  2210. break;
  2211. }
  2212. return retval;
  2213. }
  2214. /* Type of p-bits:
  2215. 48-bit instruction: 1, 1, 0.
  2216. 32-bit instruction: 1, 0.
  2217. 16-bit instruction: 0. */
  2218. static bfd_vma
  2219. s3_adjust_paritybit (bfd_vma m_code, enum insn_class i_class)
  2220. {
  2221. bfd_vma result = 0;
  2222. bfd_vma m_code_high = 0;
  2223. unsigned long m_code_middle = 0;
  2224. unsigned long m_code_low = 0;
  2225. bfd_vma pb_high = 0;
  2226. unsigned long pb_middle = 0;
  2227. unsigned long pb_low = 0;
  2228. if (i_class == INSN_CLASS_48)
  2229. {
  2230. pb_high = 0x800000000000LL;
  2231. pb_middle = 0x80000000;
  2232. pb_low = 0x00000000;
  2233. m_code_high = m_code & 0x1fffc0000000LL;
  2234. m_code_middle = m_code & 0x3fff8000;
  2235. m_code_low = m_code & 0x00007fff;
  2236. result = pb_high | (m_code_high << 2) |
  2237. pb_middle | (m_code_middle << 1) |
  2238. pb_low | m_code_low;
  2239. }
  2240. else if (i_class == INSN_CLASS_32 || i_class == INSN_CLASS_SYN)
  2241. {
  2242. pb_high = 0x80000000;
  2243. pb_low = 0x00000000;
  2244. m_code_high = m_code & 0x3fff8000;
  2245. m_code_low = m_code & 0x00007fff;
  2246. result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
  2247. }
  2248. else if (i_class == INSN_CLASS_16)
  2249. {
  2250. pb_high = 0;
  2251. pb_low = 0;
  2252. m_code_high = m_code & 0x3fff8000;
  2253. m_code_low = m_code & 0x00007fff;
  2254. result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
  2255. }
  2256. else if (i_class == INSN_CLASS_PCE)
  2257. {
  2258. /* Keep original. */
  2259. pb_high = 0;
  2260. pb_low = 0x00008000;
  2261. m_code_high = m_code & 0x3fff8000;
  2262. m_code_low = m_code & 0x00007fff;
  2263. result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
  2264. }
  2265. else
  2266. {
  2267. abort ();
  2268. }
  2269. return result;
  2270. }
  2271. static void
  2272. s3_gen_insn_frag (struct s3_score_it *part_1, struct s3_score_it *part_2)
  2273. {
  2274. char *p;
  2275. bfd_boolean pce_p = FALSE;
  2276. int relaxable_p = s3_g_opt;
  2277. int relax_size = 0;
  2278. struct s3_score_it *inst1 = part_1;
  2279. struct s3_score_it *inst2 = part_2;
  2280. struct s3_score_it backup_inst1;
  2281. pce_p = (inst2) ? TRUE : FALSE;
  2282. memcpy (&backup_inst1, inst1, sizeof (struct s3_score_it));
  2283. /* Adjust instruction opcode and to be relaxed instruction opcode. */
  2284. if (pce_p)
  2285. {
  2286. backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
  2287. | (inst2->instruction & 0x7FFF);
  2288. backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
  2289. backup_inst1.relax_inst = 0x8000;
  2290. backup_inst1.size = s3_INSN_SIZE;
  2291. backup_inst1.relax_size = 0;
  2292. backup_inst1.type = Insn_Type_PCE;
  2293. }
  2294. else
  2295. {
  2296. backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction,
  2297. s3_GET_INSN_CLASS (backup_inst1.type));
  2298. }
  2299. if (backup_inst1.relax_size != 0)
  2300. {
  2301. enum insn_class tmp;
  2302. tmp = (backup_inst1.size == s3_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
  2303. backup_inst1.relax_inst = s3_adjust_paritybit (backup_inst1.relax_inst, tmp);
  2304. }
  2305. /* Check data dependency. */
  2306. s3_handle_dependency (&backup_inst1);
  2307. /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
  2308. data produced by .ascii etc. Doing this is to make one instruction per frag. */
  2309. if (frag_now_fix () != 0)
  2310. {
  2311. if (!frag_now->tc_frag_data.is_insn)
  2312. frag_wane (frag_now);
  2313. frag_new (0);
  2314. }
  2315. /* Here, we must call frag_grow in order to keep the instruction frag type is
  2316. rs_machine_dependent.
  2317. For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
  2318. acturally will call frag_wane.
  2319. Calling frag_grow first will create a new frag_now which free size is 20 that is enough
  2320. for frag_var. */
  2321. frag_grow (20);
  2322. p = frag_more (backup_inst1.size);
  2323. s3_md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
  2324. #ifdef OBJ_ELF
  2325. dwarf2_emit_insn (backup_inst1.size);
  2326. #endif
  2327. /* Generate fixup structure. */
  2328. if (pce_p)
  2329. {
  2330. if (inst1->reloc.type != BFD_RELOC_NONE)
  2331. s3_fix_new_score (frag_now, p - frag_now->fr_literal,
  2332. inst1->size, &inst1->reloc.exp,
  2333. inst1->reloc.pc_rel, inst1->reloc.type);
  2334. if (inst2->reloc.type != BFD_RELOC_NONE)
  2335. s3_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
  2336. inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
  2337. }
  2338. else
  2339. {
  2340. if (backup_inst1.reloc.type != BFD_RELOC_NONE)
  2341. s3_fix_new_score (frag_now, p - frag_now->fr_literal,
  2342. backup_inst1.size, &backup_inst1.reloc.exp,
  2343. backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
  2344. }
  2345. /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */
  2346. relaxable_p &= (backup_inst1.relax_size != 0);
  2347. relax_size = relaxable_p ? backup_inst1.relax_size : 0;
  2348. p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0,
  2349. s3_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
  2350. backup_inst1.type, 0, 0, relaxable_p),
  2351. backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
  2352. if (relaxable_p)
  2353. s3_md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
  2354. memcpy (inst1, &backup_inst1, sizeof (struct s3_score_it));
  2355. }
  2356. static void
  2357. s3_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
  2358. {
  2359. char c;
  2360. char *p;
  2361. char *operator = insnstr;
  2362. const struct s3_asm_opcode *opcode;
  2363. /* Parse operator and operands. */
  2364. s3_skip_whitespace (operator);
  2365. for (p = operator; *p != '\0'; p++)
  2366. if ((*p == ' ') || (*p == '!'))
  2367. break;
  2368. if (*p == '!')
  2369. p++;
  2370. c = *p;
  2371. *p = '\0';
  2372. opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator);
  2373. *p = c;
  2374. memset (&s3_inst, '\0', sizeof (s3_inst));
  2375. sprintf (s3_inst.str, "%s", insnstr);
  2376. if (opcode)
  2377. {
  2378. s3_inst.instruction = opcode->value;
  2379. s3_inst.relax_inst = opcode->relax_value;
  2380. s3_inst.type = opcode->type;
  2381. s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type);
  2382. s3_inst.relax_size = 0;
  2383. s3_inst.bwarn = 0;
  2384. sprintf (s3_inst.name, "%s", opcode->template_name);
  2385. strcpy (s3_inst.reg, "");
  2386. s3_inst.error = NULL;
  2387. s3_inst.reloc.type = BFD_RELOC_NONE;
  2388. (*opcode->parms) (p);
  2389. /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */
  2390. if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p))
  2391. s3_gen_insn_frag (&s3_inst, NULL);
  2392. }
  2393. else
  2394. s3_inst.error = _("unrecognized opcode");
  2395. }
  2396. static void
  2397. s3_parse_48_inst (char *insnstr, bfd_boolean gen_frag_p)
  2398. {
  2399. char c;
  2400. char *p;
  2401. char *operator = insnstr;
  2402. const struct s3_asm_opcode *opcode;
  2403. /* Parse operator and operands. */
  2404. s3_skip_whitespace (operator);
  2405. for (p = operator; *p != '\0'; p++)
  2406. if (*p == ' ')
  2407. break;
  2408. c = *p;
  2409. *p = '\0';
  2410. opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator);
  2411. *p = c;
  2412. memset (&s3_inst, '\0', sizeof (s3_inst));
  2413. sprintf (s3_inst.str, "%s", insnstr);
  2414. if (opcode)
  2415. {
  2416. s3_inst.instruction = opcode->value;
  2417. s3_inst.relax_inst = opcode->relax_value;
  2418. s3_inst.type = opcode->type;
  2419. s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type);
  2420. s3_inst.relax_size = 0;
  2421. s3_inst.bwarn = 0;
  2422. sprintf (s3_inst.name, "%s", opcode->template_name);
  2423. strcpy (s3_inst.reg, "");
  2424. s3_inst.error = NULL;
  2425. s3_inst.reloc.type = BFD_RELOC_NONE;
  2426. (*opcode->parms) (p);
  2427. /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */
  2428. if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p))
  2429. s3_gen_insn_frag (&s3_inst, NULL);
  2430. }
  2431. else
  2432. s3_inst.error = _("unrecognized opcode");
  2433. }
  2434. static int
  2435. s3_append_insn (char *str, bfd_boolean gen_frag_p)
  2436. {
  2437. int retval = s3_SUCCESS;
  2438. s3_parse_16_32_inst (str, gen_frag_p);
  2439. if (s3_inst.error)
  2440. {
  2441. retval = (int) s3_FAIL;
  2442. as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
  2443. s3_inst.error = NULL;
  2444. }
  2445. return retval;
  2446. }
  2447. static void
  2448. s3_do16_mv_cmp (char *str)
  2449. {
  2450. s3_skip_whitespace (str);
  2451. if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  2452. || s3_skip_past_comma (&str) == (int) s3_FAIL
  2453. || s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  2454. || s3_end_of_line (str) == (int) s3_FAIL)
  2455. {
  2456. return;
  2457. }
  2458. }
  2459. static void
  2460. s3_do16_cmpi (char *str)
  2461. {
  2462. s3_skip_whitespace (str);
  2463. if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  2464. || s3_skip_past_comma (&str) == (int) s3_FAIL
  2465. || s3_data_op2 (&str, 0, _SIMM5) == (int) s3_FAIL
  2466. || s3_end_of_line (str) == (int) s3_FAIL)
  2467. {
  2468. return;
  2469. }
  2470. }
  2471. static void
  2472. s3_do16_addi (char *str)
  2473. {
  2474. s3_skip_whitespace (str);
  2475. if (s3_reglow_required_here (&str, 6) == (int) s3_FAIL
  2476. || s3_skip_past_comma (&str) == (int) s3_FAIL
  2477. || s3_data_op2 (&str, 0, _SIMM6) == (int) s3_FAIL
  2478. || s3_end_of_line (str) == (int) s3_FAIL)
  2479. {
  2480. return;
  2481. }
  2482. }
  2483. /* Handle bitclr! / bitset! / bittst! / bittgl! */
  2484. static void
  2485. s3_do16_rdi5 (char *str)
  2486. {
  2487. s3_skip_whitespace (str);
  2488. if (s3_reglow_required_here (&str, 5) == (int) s3_FAIL
  2489. || s3_skip_past_comma (&str) == (int) s3_FAIL
  2490. || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
  2491. || s3_end_of_line (str) == (int) s3_FAIL)
  2492. return;
  2493. else
  2494. {
  2495. s3_inst.relax_inst |= (((s3_inst.instruction >>5) & 0xf) << 20)
  2496. | (((s3_inst.instruction >> 5) & 0xf) << 15) | (((s3_inst.instruction ) & 0x1f) << 10);
  2497. s3_inst.relax_size = 4;
  2498. }
  2499. }
  2500. /* Handle sdbbp!. */
  2501. static void
  2502. s3_do16_xi5 (char *str)
  2503. {
  2504. s3_skip_whitespace (str);
  2505. if (s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
  2506. return;
  2507. }
  2508. /* Check that an immediate is word alignment or half word alignment.
  2509. If so, convert it to the right format. */
  2510. static int
  2511. s3_validate_immediate_align (int val, unsigned int data_type)
  2512. {
  2513. if (data_type == _IMM5_RSHIFT_1)
  2514. {
  2515. if (val % 2)
  2516. {
  2517. s3_inst.error = _("address offset must be half word alignment");
  2518. return (int) s3_FAIL;
  2519. }
  2520. }
  2521. else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
  2522. {
  2523. if (val % 4)
  2524. {
  2525. s3_inst.error = _("address offset must be word alignment");
  2526. return (int) s3_FAIL;
  2527. }
  2528. }
  2529. return s3_SUCCESS;
  2530. }
  2531. static int
  2532. s3_exp_ldst_offset (char **str, int shift, unsigned int data_type)
  2533. {
  2534. char *dataptr;
  2535. dataptr = * str;
  2536. if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
  2537. && (data_type != _SIMM16_LA)
  2538. && (data_type != _VALUE_HI16)
  2539. && (data_type != _VALUE_LO16)
  2540. && (data_type != _IMM16)
  2541. && (data_type != _IMM15)
  2542. && (data_type != _IMM14)
  2543. && (data_type != _IMM4)
  2544. && (data_type != _IMM5)
  2545. && (data_type != _IMM8)
  2546. && (data_type != _IMM5_RSHIFT_1)
  2547. && (data_type != _IMM5_RSHIFT_2)
  2548. && (data_type != _SIMM14_NEG)
  2549. && (data_type != _IMM10_RSHIFT_2))
  2550. {
  2551. data_type += 24;
  2552. }
  2553. if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL)
  2554. return (int) s3_FAIL;
  2555. if (s3_inst.reloc.exp.X_op == O_constant)
  2556. {
  2557. /* Need to check the immediate align. */
  2558. int value = s3_validate_immediate_align (s3_inst.reloc.exp.X_add_number, data_type);
  2559. if (value == (int) s3_FAIL)
  2560. return (int) s3_FAIL;
  2561. value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
  2562. if (value == (int) s3_FAIL)
  2563. {
  2564. if (data_type < 30)
  2565. sprintf (s3_err_msg,
  2566. _("invalid constant: %d bit expression not in range %d..%d"),
  2567. s3_score_df_range[data_type].bits,
  2568. s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
  2569. else
  2570. sprintf (s3_err_msg,
  2571. _("invalid constant: %d bit expression not in range %d..%d"),
  2572. s3_score_df_range[data_type - 24].bits,
  2573. s3_score_df_range[data_type - 24].range[0], s3_score_df_range[data_type - 24].range[1]);
  2574. s3_inst.error = s3_err_msg;
  2575. return (int) s3_FAIL;
  2576. }
  2577. if (data_type == _IMM5_RSHIFT_1)
  2578. {
  2579. value >>= 1;
  2580. }
  2581. else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
  2582. {
  2583. value >>= 2;
  2584. }
  2585. if (s3_score_df_range[data_type].range[0] != 0)
  2586. {
  2587. value &= (1 << s3_score_df_range[data_type].bits) - 1;
  2588. }
  2589. s3_inst.instruction |= value << shift;
  2590. }
  2591. else
  2592. {
  2593. s3_inst.reloc.pc_rel = 0;
  2594. }
  2595. return s3_SUCCESS;
  2596. }
  2597. static void
  2598. s3_do_ldst_insn (char *str)
  2599. {
  2600. int pre_inc = 0;
  2601. int conflict_reg;
  2602. int value;
  2603. char * temp;
  2604. char *dataptr;
  2605. int reg;
  2606. int ldst_idx = 0;
  2607. s3_skip_whitespace (str);
  2608. if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  2609. || (s3_skip_past_comma (&str) == (int) s3_FAIL))
  2610. return;
  2611. /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */
  2612. if (*str == '[')
  2613. {
  2614. str++;
  2615. s3_skip_whitespace (str);
  2616. if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  2617. return;
  2618. /* Conflicts can occur on stores as well as loads. */
  2619. conflict_reg = (conflict_reg == reg);
  2620. s3_skip_whitespace (str);
  2621. temp = str + 1; /* The latter will process decimal/hex expression. */
  2622. /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */
  2623. if (*str == ']')
  2624. {
  2625. str++;
  2626. if (*str == '+')
  2627. {
  2628. str++;
  2629. /* ld/sw rD, [rA]+, simm12. */
  2630. if (s3_skip_past_comma (&str) == s3_SUCCESS)
  2631. {
  2632. if ((s3_exp_ldst_offset (&str, 3, _SIMM12) == (int) s3_FAIL)
  2633. || (s3_end_of_line (str) == (int) s3_FAIL))
  2634. return;
  2635. if (conflict_reg)
  2636. {
  2637. unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
  2638. if ((ldst_func == INSN_LH)
  2639. || (ldst_func == INSN_LHU)
  2640. || (ldst_func == INSN_LW)
  2641. || (ldst_func == INSN_LB)
  2642. || (ldst_func == INSN_LBU))
  2643. {
  2644. s3_inst.error = _("register same as write-back base");
  2645. return;
  2646. }
  2647. }
  2648. ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
  2649. s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
  2650. s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
  2651. /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */
  2652. if ((s3_inst.instruction & 0x3e000007) == 0x0e000000)
  2653. {
  2654. /* rs = r0, offset = 4 */
  2655. if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
  2656. && (((s3_inst.instruction >> 3) & 0xfff) == 4))
  2657. {
  2658. /* Relax to pop!. */
  2659. s3_inst.relax_inst = 0x0040 | ((s3_inst.instruction >> 20) & 0x1f);
  2660. s3_inst.relax_size = 2;
  2661. }
  2662. }
  2663. return;
  2664. }
  2665. /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */
  2666. else
  2667. {
  2668. s3_SET_INSN_ERROR (NULL);
  2669. if (s3_end_of_line (str) == (int) s3_FAIL)
  2670. {
  2671. return;
  2672. }
  2673. pre_inc = 1;
  2674. value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM12, 0);
  2675. value &= (1 << s3_score_df_range[_SIMM12].bits) - 1;
  2676. ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
  2677. s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
  2678. s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
  2679. s3_inst.instruction |= value << 3;
  2680. s3_inst.relax_inst = 0x8000;
  2681. return;
  2682. }
  2683. }
  2684. /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */
  2685. else
  2686. {
  2687. if (s3_end_of_line (str) == (int) s3_FAIL)
  2688. return;
  2689. ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
  2690. s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
  2691. s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
  2692. /* lbu rd, [rs] -> lbu! rd, [rs] */
  2693. if (ldst_idx == INSN_LBU)
  2694. {
  2695. s3_inst.relax_inst = INSN16_LBU;
  2696. }
  2697. else if (ldst_idx == INSN_LH)
  2698. {
  2699. s3_inst.relax_inst = INSN16_LH;
  2700. }
  2701. else if (ldst_idx == INSN_LW)
  2702. {
  2703. s3_inst.relax_inst = INSN16_LW;
  2704. }
  2705. else if (ldst_idx == INSN_SB)
  2706. {
  2707. s3_inst.relax_inst = INSN16_SB;
  2708. }
  2709. else if (ldst_idx == INSN_SH)
  2710. {
  2711. s3_inst.relax_inst = INSN16_SH;
  2712. }
  2713. else if (ldst_idx == INSN_SW)
  2714. {
  2715. s3_inst.relax_inst = INSN16_SW;
  2716. }
  2717. else
  2718. {
  2719. s3_inst.relax_inst = 0x8000;
  2720. }
  2721. /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */
  2722. /* if ((ldst_idx == INSN_LBU)
  2723. || (ldst_idx == INSN_LH)
  2724. || (ldst_idx == INSN_LW)
  2725. || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))*/
  2726. if ( (ldst_idx == INSN_LW)|| (ldst_idx == INSN_SW))
  2727. {
  2728. /* ra only 3 bit , rd only 4 bit for lw! and sw! */
  2729. if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
  2730. {
  2731. s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 8) |
  2732. (((s3_inst.instruction >> 15) & 0x7) << 5);
  2733. s3_inst.relax_size = 2;
  2734. }
  2735. }
  2736. return;
  2737. }
  2738. }
  2739. /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */
  2740. else
  2741. {
  2742. if (s3_skip_past_comma (&str) == (int) s3_FAIL)
  2743. {
  2744. s3_inst.error = _("pre-indexed expression expected");
  2745. return;
  2746. }
  2747. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
  2748. return;
  2749. s3_skip_whitespace (str);
  2750. if (*str++ != ']')
  2751. {
  2752. s3_inst.error = _("missing ]");
  2753. return;
  2754. }
  2755. s3_skip_whitespace (str);
  2756. /* ld/sw rD, [rA, simm12]+. */
  2757. if (*str == '+')
  2758. {
  2759. str++;
  2760. pre_inc = 1;
  2761. if (conflict_reg)
  2762. {
  2763. unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
  2764. if ((ldst_func == INSN_LH)
  2765. || (ldst_func == INSN_LHU)
  2766. || (ldst_func == INSN_LW)
  2767. || (ldst_func == INSN_LB)
  2768. || (ldst_func == INSN_LBU))
  2769. {
  2770. s3_inst.error = _("register same as write-back base");
  2771. return;
  2772. }
  2773. }
  2774. }
  2775. if (s3_end_of_line (str) == (int) s3_FAIL)
  2776. return;
  2777. if (s3_inst.reloc.exp.X_op == O_constant)
  2778. {
  2779. unsigned int data_type;
  2780. if (pre_inc == 1)
  2781. data_type = _SIMM12;
  2782. else
  2783. data_type = _SIMM15;
  2784. dataptr = temp;
  2785. if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
  2786. && (data_type != _SIMM16_LA)
  2787. && (data_type != _VALUE_HI16)
  2788. && (data_type != _VALUE_LO16)
  2789. && (data_type != _IMM16)
  2790. && (data_type != _IMM15)
  2791. && (data_type != _IMM14)
  2792. && (data_type != _IMM4)
  2793. && (data_type != _IMM5)
  2794. && (data_type != _IMM8)
  2795. && (data_type != _IMM5_RSHIFT_1)
  2796. && (data_type != _IMM5_RSHIFT_2)
  2797. && (data_type != _SIMM14_NEG)
  2798. && (data_type != _IMM10_RSHIFT_2))
  2799. {
  2800. data_type += 24;
  2801. }
  2802. value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
  2803. if (value == (int) s3_FAIL)
  2804. {
  2805. if (data_type < 30)
  2806. sprintf (s3_err_msg,
  2807. _("invalid constant: %d bit expression not in range %d..%d"),
  2808. s3_score_df_range[data_type].bits,
  2809. s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
  2810. else
  2811. sprintf (s3_err_msg,
  2812. _("invalid constant: %d bit expression not in range %d..%d"),
  2813. s3_score_df_range[data_type - 24].bits,
  2814. s3_score_df_range[data_type - 24].range[0],
  2815. s3_score_df_range[data_type - 24].range[1]);
  2816. s3_inst.error = s3_err_msg;
  2817. return;
  2818. }
  2819. value &= (1 << s3_score_df_range[data_type].bits) - 1;
  2820. ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
  2821. s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
  2822. s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
  2823. if (pre_inc == 1)
  2824. s3_inst.instruction |= value << 3;
  2825. else
  2826. s3_inst.instruction |= value;
  2827. /* lw rD, [rA, simm15] */
  2828. if ((s3_inst.instruction & 0x3e000000) == 0x20000000)
  2829. {
  2830. /* rD in [r0 - r15]. , ra in [r0-r7] */
  2831. if ((((s3_inst.instruction >> 15) & 0x18) == 0)
  2832. && (((s3_inst.instruction >> 20) & 0x10) == 0))
  2833. {
  2834. /* simm = [bit 7], lw -> lw!. */
  2835. if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
  2836. {
  2837. s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0x7) << 5)
  2838. | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
  2839. s3_inst.relax_size = 2;
  2840. }
  2841. else
  2842. {
  2843. s3_inst.relax_inst = 0x8000;
  2844. }
  2845. }
  2846. else
  2847. {
  2848. s3_inst.relax_inst = 0x8000;
  2849. }
  2850. }
  2851. /* sw rD, [rA, simm15] */
  2852. else if ((s3_inst.instruction & 0x3e000000) == 0x28000000)
  2853. {
  2854. /* rD is in [r0 - r15] and ra in [r0-r7] */
  2855. if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
  2856. {
  2857. /* simm15 =7 bit , sw -> sw!. */
  2858. if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0))
  2859. {
  2860. s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 5)
  2861. | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2);
  2862. s3_inst.relax_size = 2;
  2863. }
  2864. /* rA = r2, sw -> swp!. */
  2865. else
  2866. {
  2867. s3_inst.relax_inst = 0x8000;
  2868. }
  2869. }
  2870. else
  2871. {
  2872. s3_inst.relax_inst = 0x8000;
  2873. }
  2874. }
  2875. /* sw rD, [rA, simm15]+ sw pre. */
  2876. else if ((s3_inst.instruction & 0x3e000007) == 0x06000004)
  2877. {
  2878. /* simm15 = -4. and ra==r0 */
  2879. if ((((s3_inst.instruction >> 15) & 0x1f) == 0)
  2880. && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc))
  2881. {
  2882. /* sw -> push!. */
  2883. s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f);
  2884. s3_inst.relax_size = 2;
  2885. }
  2886. else
  2887. {
  2888. s3_inst.relax_inst = 0x8000;
  2889. }
  2890. }
  2891. else
  2892. {
  2893. s3_inst.relax_inst = 0x8000;
  2894. }
  2895. return;
  2896. }
  2897. else
  2898. {
  2899. /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
  2900. s3_inst.reloc.pc_rel = 0;
  2901. }
  2902. }
  2903. }
  2904. else
  2905. {
  2906. s3_inst.error = s3_BAD_ARGS;
  2907. }
  2908. }
  2909. /* Handle cache. */
  2910. static void
  2911. s3_do_cache (char *str)
  2912. {
  2913. s3_skip_whitespace (str);
  2914. if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
  2915. {
  2916. return;
  2917. }
  2918. else
  2919. {
  2920. int cache_op;
  2921. cache_op = (s3_inst.instruction >> 20) & 0x1F;
  2922. sprintf (s3_inst.name, "cache %d", cache_op);
  2923. }
  2924. if (*str == '[')
  2925. {
  2926. str++;
  2927. s3_skip_whitespace (str);
  2928. if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  2929. return;
  2930. s3_skip_whitespace (str);
  2931. /* cache op, [rA] */
  2932. if (s3_skip_past_comma (&str) == (int) s3_FAIL)
  2933. {
  2934. s3_SET_INSN_ERROR (NULL);
  2935. if (*str != ']')
  2936. {
  2937. s3_inst.error = _("missing ]");
  2938. return;
  2939. }
  2940. str++;
  2941. }
  2942. /* cache op, [rA, simm15] */
  2943. else
  2944. {
  2945. if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL)
  2946. {
  2947. return;
  2948. }
  2949. s3_skip_whitespace (str);
  2950. if (*str++ != ']')
  2951. {
  2952. s3_inst.error = _("missing ]");
  2953. return;
  2954. }
  2955. }
  2956. if (s3_end_of_line (str) == (int) s3_FAIL)
  2957. return;
  2958. }
  2959. else
  2960. {
  2961. s3_inst.error = s3_BAD_ARGS;
  2962. }
  2963. }
  2964. static void
  2965. s3_do_crdcrscrsimm5 (char *str)
  2966. {
  2967. char *strbak;
  2968. strbak = str;
  2969. s3_skip_whitespace (str);
  2970. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
  2971. || s3_skip_past_comma (&str) == (int) s3_FAIL
  2972. || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
  2973. || s3_skip_past_comma (&str) == (int) s3_FAIL
  2974. || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL
  2975. || s3_skip_past_comma (&str) == (int) s3_FAIL)
  2976. {
  2977. str = strbak;
  2978. /* cop1 cop_code20. */
  2979. if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL)
  2980. return;
  2981. }
  2982. else
  2983. {
  2984. if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL)
  2985. return;
  2986. }
  2987. s3_end_of_line (str);
  2988. }
  2989. /* Handle ldc/stc. */
  2990. static void
  2991. s3_do_ldst_cop (char *str)
  2992. {
  2993. s3_skip_whitespace (str);
  2994. if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL)
  2995. || (s3_skip_past_comma (&str) == (int) s3_FAIL))
  2996. return;
  2997. if (*str == '[')
  2998. {
  2999. str++;
  3000. s3_skip_whitespace (str);
  3001. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  3002. return;
  3003. s3_skip_whitespace (str);
  3004. if (*str++ != ']')
  3005. {
  3006. if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL)
  3007. return;
  3008. s3_skip_whitespace (str);
  3009. if (*str++ != ']')
  3010. {
  3011. s3_inst.error = _("missing ]");
  3012. return;
  3013. }
  3014. }
  3015. s3_end_of_line (str);
  3016. }
  3017. else
  3018. s3_inst.error = s3_BAD_ARGS;
  3019. }
  3020. static void
  3021. s3_do16_ldst_insn (char *str)
  3022. {
  3023. int conflict_reg = 0;
  3024. s3_skip_whitespace (str);
  3025. if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
  3026. return;
  3027. if (*str == '[')
  3028. {
  3029. str++;
  3030. s3_skip_whitespace (str);
  3031. if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL)
  3032. return;
  3033. if (conflict_reg&0x8)
  3034. {
  3035. sprintf (s3_err_msg, _("invalid register number: %d is not in [r0--r7]"),conflict_reg);
  3036. s3_inst.error = s3_err_msg;
  3037. return;
  3038. }
  3039. s3_skip_whitespace (str);
  3040. if (*str == ']')
  3041. {
  3042. str++;
  3043. if (s3_end_of_line (str) == (int) s3_FAIL)
  3044. return;
  3045. }
  3046. else
  3047. {
  3048. if (s3_skip_past_comma (&str) == (int) s3_FAIL)
  3049. {
  3050. s3_inst.error = _("comma is expected");
  3051. return;
  3052. }
  3053. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
  3054. return;
  3055. s3_skip_whitespace (str);
  3056. if (*str++ != ']')
  3057. {
  3058. s3_inst.error = _("missing ]");
  3059. return;
  3060. }
  3061. if (s3_end_of_line (str) == (int) s3_FAIL)
  3062. return;
  3063. if (s3_inst.reloc.exp.X_op == O_constant)
  3064. {
  3065. int value;
  3066. unsigned int data_type;
  3067. data_type = _IMM5_RSHIFT_2;
  3068. value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0);
  3069. if (value == (int) s3_FAIL)
  3070. {
  3071. if (data_type < 30)
  3072. sprintf (s3_err_msg,
  3073. _("invalid constant: %d bit expression not in range %d..%d"),
  3074. s3_score_df_range[data_type].bits,
  3075. s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]);
  3076. s3_inst.error = s3_err_msg;
  3077. return;
  3078. }
  3079. if (value & 0x3)
  3080. {
  3081. sprintf (s3_err_msg, _("invalid constant: %d is not word align integer"),value);
  3082. s3_inst.error = s3_err_msg;
  3083. return;
  3084. }
  3085. value >>= 2;
  3086. s3_inst.instruction |= value;
  3087. }
  3088. }
  3089. }
  3090. else
  3091. {
  3092. sprintf (s3_err_msg, _("missing ["));
  3093. s3_inst.error = s3_err_msg;
  3094. return;
  3095. }
  3096. }
  3097. static void
  3098. s3_do_lw48 (char *str)
  3099. {
  3100. bfd_signed_vma val = 0;
  3101. s3_skip_whitespace (str);
  3102. if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  3103. || (s3_skip_past_comma (&str) == (int) s3_FAIL))
  3104. return;
  3105. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
  3106. || s3_end_of_line (str) == (int) s3_FAIL)
  3107. {
  3108. return;
  3109. }
  3110. /* Check word align for lw48 rd, value. */
  3111. if ((s3_inst.reloc.exp.X_add_symbol == NULL)
  3112. && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
  3113. {
  3114. s3_inst.error = _("invalid constant: 32 bit expression not word align");
  3115. return;
  3116. }
  3117. /* Check and set offset. */
  3118. val = s3_inst.reloc.exp.X_add_number;
  3119. if ((s3_inst.reloc.exp.X_add_symbol == NULL)
  3120. && (!(val >= 0 && val <= 0xffffffffLL)))
  3121. {
  3122. s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
  3123. return;
  3124. }
  3125. val &= 0xffffffff;
  3126. val >>= 2;
  3127. s3_inst.instruction |= (val << 7);
  3128. /* Set reloc type. */
  3129. s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
  3130. }
  3131. static void
  3132. s3_do_sw48 (char *str)
  3133. {
  3134. bfd_signed_vma val = 0;
  3135. s3_skip_whitespace (str);
  3136. if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  3137. || (s3_skip_past_comma (&str) == (int) s3_FAIL))
  3138. return;
  3139. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
  3140. || s3_end_of_line (str) == (int) s3_FAIL)
  3141. {
  3142. return;
  3143. }
  3144. /* Check word align for lw48 rd, value. */
  3145. if ((s3_inst.reloc.exp.X_add_symbol == NULL)
  3146. && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0))
  3147. {
  3148. s3_inst.error = _("invalid constant: 32 bit expression not word align");
  3149. return;
  3150. }
  3151. /* Check and set offset. */
  3152. val = s3_inst.reloc.exp.X_add_number;
  3153. if ((s3_inst.reloc.exp.X_add_symbol == NULL)
  3154. && (!(val >= 0 && val <= 0xffffffffLL)))
  3155. {
  3156. s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]");
  3157. return;
  3158. }
  3159. val &= 0xffffffff;
  3160. val >>= 2;
  3161. s3_inst.instruction |= (val << 7);
  3162. /* Set reloc type. */
  3163. s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30;
  3164. }
  3165. static void
  3166. s3_do_ldi48 (char *str)
  3167. {
  3168. bfd_signed_vma val;
  3169. s3_skip_whitespace (str);
  3170. if (s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  3171. || s3_skip_past_comma (&str) == (int) s3_FAIL)
  3172. return;
  3173. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
  3174. || s3_end_of_line (str) == (int) s3_FAIL)
  3175. {
  3176. return;
  3177. }
  3178. /* Check and set offset. */
  3179. val = s3_inst.reloc.exp.X_add_number;
  3180. if (!(val >= -0xffffffffLL && val <= 0xffffffffLL))
  3181. {
  3182. s3_inst.error = _("invalid constant: 32 bit expression not in range [-0x80000000, 0x7fffffff]");
  3183. return;
  3184. }
  3185. val &= 0xffffffff;
  3186. s3_inst.instruction |= (val << 5);
  3187. /* Set reloc type. */
  3188. s3_inst.reloc.type = BFD_RELOC_SCORE_IMM32;
  3189. }
  3190. static void
  3191. s3_do_sdbbp48 (char *str)
  3192. {
  3193. s3_skip_whitespace (str);
  3194. if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL)
  3195. return;
  3196. }
  3197. static void
  3198. s3_do_and48 (char *str)
  3199. {
  3200. s3_skip_whitespace (str);
  3201. if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
  3202. || s3_skip_past_comma (&str) == (int) s3_FAIL
  3203. || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
  3204. || s3_skip_past_comma (&str) == (int) s3_FAIL
  3205. || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
  3206. || s3_end_of_line (str) == (int) s3_FAIL)
  3207. return;
  3208. }
  3209. static void
  3210. s3_do_or48 (char *str)
  3211. {
  3212. s3_skip_whitespace (str);
  3213. if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL
  3214. || s3_skip_past_comma (&str) == (int) s3_FAIL
  3215. || s3_reglow_required_here (&str, 34) == (int) s3_FAIL
  3216. || s3_skip_past_comma (&str) == (int) s3_FAIL
  3217. || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL
  3218. || s3_end_of_line (str) == (int) s3_FAIL)
  3219. return;
  3220. }
  3221. static void
  3222. s3_do_mbitclr (char *str)
  3223. {
  3224. int val;
  3225. s3_skip_whitespace (str);
  3226. if (*str != '[')
  3227. {
  3228. sprintf (s3_err_msg, _("missing ["));
  3229. s3_inst.error = s3_err_msg;
  3230. return;
  3231. }
  3232. str++;
  3233. s3_inst.instruction &= 0x0;
  3234. if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  3235. || (s3_skip_past_comma (&str) == (int) s3_FAIL)
  3236. || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
  3237. return;
  3238. /* Get imm11 and refill opcode. */
  3239. val = s3_inst.instruction & 0x7ff;
  3240. val >>= 2;
  3241. s3_inst.instruction &= 0x000f8000;
  3242. s3_inst.instruction |= 0x00000064;
  3243. if (*str != ']')
  3244. {
  3245. sprintf (s3_err_msg, _("missing ]"));
  3246. s3_inst.error = s3_err_msg;
  3247. return;
  3248. }
  3249. str++;
  3250. if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
  3251. || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
  3252. return;
  3253. /* Set imm11 to opcode. */
  3254. s3_inst.instruction |= (val & 0x1)
  3255. | (((val >> 1 ) & 0x7) << 7)
  3256. | (((val >> 4 ) & 0x1f) << 20);
  3257. }
  3258. static void
  3259. s3_do_mbitset (char *str)
  3260. {
  3261. int val;
  3262. s3_skip_whitespace (str);
  3263. if (*str != '[')
  3264. {
  3265. sprintf (s3_err_msg, _("missing ["));
  3266. s3_inst.error = s3_err_msg;
  3267. return;
  3268. }
  3269. str++;
  3270. s3_inst.instruction &= 0x0;
  3271. if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  3272. || (s3_skip_past_comma (&str) == (int) s3_FAIL)
  3273. || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL))
  3274. return;
  3275. /* Get imm11 and refill opcode. */
  3276. val = s3_inst.instruction & 0x7ff;
  3277. val >>= 2;
  3278. s3_inst.instruction &= 0x000f8000;
  3279. s3_inst.instruction |= 0x0000006c;
  3280. if (*str != ']')
  3281. {
  3282. sprintf (s3_err_msg, _("missing ]"));
  3283. s3_inst.error = s3_err_msg;
  3284. return;
  3285. }
  3286. str++;
  3287. if ((s3_skip_past_comma (&str) == (int) s3_FAIL)
  3288. || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL))
  3289. return;
  3290. /* Set imm11 to opcode. */
  3291. s3_inst.instruction |= (val & 0x1)
  3292. | (((val >> 1 ) & 0x7) << 7)
  3293. | (((val >> 4 ) & 0x1f) << 20);
  3294. }
  3295. static void
  3296. s3_do16_slli_srli (char *str)
  3297. {
  3298. s3_skip_whitespace (str);
  3299. if ((s3_reglow_required_here (&str, 5) == (int) s3_FAIL)
  3300. || (s3_skip_past_comma (&str) == (int) s3_FAIL)
  3301. || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
  3302. || s3_end_of_line (str) == (int) s3_FAIL)
  3303. return;
  3304. }
  3305. static void
  3306. s3_do16_ldiu (char *str)
  3307. {
  3308. s3_skip_whitespace (str);
  3309. if ((s3_reg_required_here (&str, 5,s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  3310. || (s3_skip_past_comma (&str) == (int) s3_FAIL)
  3311. || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL
  3312. || s3_end_of_line (str) == (int) s3_FAIL)
  3313. return;
  3314. }
  3315. static void
  3316. s3_do16_push_pop (char *str)
  3317. {
  3318. s3_skip_whitespace (str);
  3319. if ((s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  3320. || s3_end_of_line (str) == (int) s3_FAIL)
  3321. return;
  3322. }
  3323. static void
  3324. s3_do16_rpush (char *str)
  3325. {
  3326. int reg;
  3327. int val;
  3328. s3_skip_whitespace (str);
  3329. if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
  3330. || s3_skip_past_comma (&str) == (int) s3_FAIL
  3331. || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
  3332. || s3_end_of_line (str) == (int) s3_FAIL)
  3333. return;
  3334. /* 0: indicate 32.
  3335. 1: invalide value.
  3336. 2: to 31: normal value. */
  3337. val = s3_inst.instruction & 0x1f;
  3338. if (val == 1)
  3339. {
  3340. s3_inst.error = _("imm5 should >= 2");
  3341. return;
  3342. }
  3343. if (reg >= 32)
  3344. {
  3345. s3_inst.error = _("reg should <= 31");
  3346. return;
  3347. }
  3348. }
  3349. static void
  3350. s3_do16_rpop (char *str)
  3351. {
  3352. int reg;
  3353. int val;
  3354. s3_skip_whitespace (str);
  3355. if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL
  3356. || s3_skip_past_comma (&str) == (int) s3_FAIL
  3357. || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL
  3358. || s3_end_of_line (str) == (int) s3_FAIL)
  3359. return;
  3360. /* 0: indicate 32.
  3361. 1: invalide value.
  3362. 2: to 31: normal value. */
  3363. val = s3_inst.instruction & 0x1f;
  3364. if (val == 1)
  3365. {
  3366. s3_inst.error = _("imm5 should >= 2");
  3367. return;
  3368. }
  3369. if (reg >= 32)
  3370. {
  3371. s3_inst.error = _("reg should <= 31");
  3372. return;
  3373. }
  3374. else
  3375. {
  3376. if ((reg + val) <= 32)
  3377. reg = reg + val - 1;
  3378. else
  3379. reg = reg + val - 33;
  3380. s3_inst.instruction &= 0x7c1f;
  3381. s3_inst.instruction |= (reg << 5);
  3382. return;
  3383. }
  3384. }
  3385. /* Handle lcb/lcw/lce/scb/scw/sce. */
  3386. static void
  3387. s3_do_ldst_unalign (char *str)
  3388. {
  3389. int conflict_reg;
  3390. if (s3_university_version == 1)
  3391. {
  3392. s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
  3393. return;
  3394. }
  3395. s3_skip_whitespace (str);
  3396. /* lcb/scb [rA]+. */
  3397. if (*str == '[')
  3398. {
  3399. str++;
  3400. s3_skip_whitespace (str);
  3401. if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  3402. return;
  3403. if (*str++ == ']')
  3404. {
  3405. if (*str++ != '+')
  3406. {
  3407. s3_inst.error = _("missing +");
  3408. return;
  3409. }
  3410. }
  3411. else
  3412. {
  3413. s3_inst.error = _("missing ]");
  3414. return;
  3415. }
  3416. if (s3_end_of_line (str) == (int) s3_FAIL)
  3417. return;
  3418. }
  3419. /* lcw/lce/scb/sce rD, [rA]+. */
  3420. else
  3421. {
  3422. if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  3423. || (s3_skip_past_comma (&str) == (int) s3_FAIL))
  3424. {
  3425. return;
  3426. }
  3427. s3_skip_whitespace (str);
  3428. if (*str++ == '[')
  3429. {
  3430. int reg;
  3431. s3_skip_whitespace (str);
  3432. if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  3433. {
  3434. return;
  3435. }
  3436. /* Conflicts can occur on stores as well as loads. */
  3437. conflict_reg = (conflict_reg == reg);
  3438. s3_skip_whitespace (str);
  3439. if (*str++ == ']')
  3440. {
  3441. unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK;
  3442. if (*str++ == '+')
  3443. {
  3444. if (conflict_reg)
  3445. {
  3446. as_warn (_("%s register same as write-back base"),
  3447. ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
  3448. ? _("destination") : _("source")));
  3449. }
  3450. }
  3451. else
  3452. {
  3453. s3_inst.error = _("missing +");
  3454. return;
  3455. }
  3456. if (s3_end_of_line (str) == (int) s3_FAIL)
  3457. return;
  3458. }
  3459. else
  3460. {
  3461. s3_inst.error = _("missing ]");
  3462. return;
  3463. }
  3464. }
  3465. else
  3466. {
  3467. s3_inst.error = s3_BAD_ARGS;
  3468. return;
  3469. }
  3470. }
  3471. }
  3472. /* Handle alw/asw. */
  3473. static void
  3474. s3_do_ldst_atomic (char *str)
  3475. {
  3476. if (s3_university_version == 1)
  3477. {
  3478. s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC;
  3479. return;
  3480. }
  3481. s3_skip_whitespace (str);
  3482. if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL)
  3483. || (s3_skip_past_comma (&str) == (int) s3_FAIL))
  3484. {
  3485. return;
  3486. }
  3487. else
  3488. {
  3489. s3_skip_whitespace (str);
  3490. if (*str++ == '[')
  3491. {
  3492. int reg;
  3493. s3_skip_whitespace (str);
  3494. if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  3495. {
  3496. return;
  3497. }
  3498. s3_skip_whitespace (str);
  3499. if (*str++ != ']')
  3500. {
  3501. s3_inst.error = _("missing ]");
  3502. return;
  3503. }
  3504. s3_end_of_line (str);
  3505. }
  3506. else
  3507. s3_inst.error = s3_BAD_ARGS;
  3508. }
  3509. }
  3510. static void
  3511. s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
  3512. struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num,
  3513. symbolS *add_symbol)
  3514. {
  3515. int i;
  3516. char *p;
  3517. fixS *fixp = NULL;
  3518. fixS *cur_fixp = NULL;
  3519. long where;
  3520. struct s3_score_it inst_main;
  3521. memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it));
  3522. /* Adjust instruction opcode and to be relaxed instruction opcode. */
  3523. inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
  3524. inst_main.type = Insn_PIC;
  3525. for (i = 0; i < var_num; i++)
  3526. {
  3527. inst_main.relax_size += var_insts[i].size;
  3528. var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction,
  3529. s3_GET_INSN_CLASS (var_insts[i].type));
  3530. }
  3531. /* Check data dependency. */
  3532. s3_handle_dependency (&inst_main);
  3533. /* Start a new frag if frag_now is not empty. */
  3534. if (frag_now_fix () != 0)
  3535. {
  3536. if (!frag_now->tc_frag_data.is_insn)
  3537. {
  3538. frag_wane (frag_now);
  3539. }
  3540. frag_new (0);
  3541. }
  3542. frag_grow (20);
  3543. /* Write fr_fix part. */
  3544. p = frag_more (inst_main.size);
  3545. s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
  3546. if (inst_main.reloc.type != BFD_RELOC_NONE)
  3547. fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
  3548. &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
  3549. frag_now->tc_frag_data.fixp = fixp;
  3550. cur_fixp = frag_now->tc_frag_data.fixp;
  3551. #ifdef OBJ_ELF
  3552. dwarf2_emit_insn (inst_main.size);
  3553. #endif
  3554. where = p - frag_now->fr_literal + inst_main.size;
  3555. for (i = 0; i < var_num; i++)
  3556. {
  3557. if (i > 0)
  3558. where += var_insts[i - 1].size;
  3559. if (var_insts[i].reloc.type != BFD_RELOC_NONE)
  3560. {
  3561. fixp = s3_fix_new_score (frag_now, where, var_insts[i].size,
  3562. &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
  3563. var_insts[i].reloc.type);
  3564. if (fixp)
  3565. {
  3566. if (cur_fixp)
  3567. {
  3568. cur_fixp->fx_next = fixp;
  3569. cur_fixp = cur_fixp->fx_next;
  3570. }
  3571. else
  3572. {
  3573. frag_now->tc_frag_data.fixp = fixp;
  3574. cur_fixp = frag_now->tc_frag_data.fixp;
  3575. }
  3576. }
  3577. }
  3578. }
  3579. p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
  3580. s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
  3581. 0, inst_main.size, 0), add_symbol, 0, NULL);
  3582. /* Write fr_var part.
  3583. no calling s3_gen_insn_frag, no fixS will be generated. */
  3584. for (i = 0; i < var_num; i++)
  3585. {
  3586. s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
  3587. p += var_insts[i].size;
  3588. }
  3589. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  3590. s3_inst.bwarn = -1;
  3591. }
  3592. /* Build a relax frag for la instruction when generating s3_PIC,
  3593. external symbol first and local symbol second. */
  3594. static void
  3595. s3_build_la_pic (int reg_rd, expressionS exp)
  3596. {
  3597. symbolS *add_symbol = exp.X_add_symbol;
  3598. offsetT add_number = exp.X_add_number;
  3599. struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
  3600. struct s3_score_it var_insts[s3_RELAX_INST_NUM];
  3601. int fix_num = 0;
  3602. int var_num = 0;
  3603. char tmp[s3_MAX_LITERAL_POOL_SIZE];
  3604. int r1_bak;
  3605. r1_bak = s3_nor1;
  3606. s3_nor1 = 0;
  3607. if (add_number == 0)
  3608. {
  3609. fix_num = 1;
  3610. var_num = 2;
  3611. /* For an external symbol, only one insn is generated;
  3612. For a local symbol, two insns are generated. */
  3613. /* Fix part
  3614. For an external symbol: lw rD, <sym>($gp)
  3615. (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */
  3616. sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
  3617. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  3618. return;
  3619. if (reg_rd == s3_PIC_CALL_REG)
  3620. s3_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
  3621. memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
  3622. /* Var part
  3623. For a local symbol :
  3624. lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
  3625. addi rD, <sym> (BFD_RELOC_GOT_LO16) */
  3626. s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
  3627. memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
  3628. sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
  3629. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  3630. return;
  3631. memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
  3632. s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
  3633. }
  3634. else if (add_number >= -0x8000 && add_number <= 0x7fff)
  3635. {
  3636. /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
  3637. sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
  3638. if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
  3639. return;
  3640. /* Insn 2 */
  3641. fix_num = 1;
  3642. var_num = 1;
  3643. /* Fix part
  3644. For an external symbol: addi rD, <constant> */
  3645. sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
  3646. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  3647. return;
  3648. memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
  3649. /* Var part
  3650. For a local symbol: addi rD, <sym>+<constant> (BFD_RELOC_GOT_LO16) */
  3651. sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
  3652. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  3653. return;
  3654. memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
  3655. s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
  3656. }
  3657. else
  3658. {
  3659. int hi = (add_number >> 16) & 0x0000FFFF;
  3660. int lo = add_number & 0x0000FFFF;
  3661. /* Insn 1: lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15) */
  3662. sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
  3663. if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
  3664. return;
  3665. /* Insn 2 */
  3666. fix_num = 1;
  3667. var_num = 1;
  3668. /* Fix part
  3669. For an external symbol: ldis r1, HI%<constant> */
  3670. sprintf (tmp, "ldis r1, %d", hi);
  3671. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  3672. return;
  3673. memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
  3674. /* Var part
  3675. For a local symbol: ldis r1, HI%<constant>
  3676. but, if lo is outof 16 bit, make hi plus 1 */
  3677. if ((lo < -0x8000) || (lo > 0x7fff))
  3678. {
  3679. hi += 1;
  3680. }
  3681. sprintf (tmp, "ldis_pic r1, %d", hi);
  3682. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  3683. return;
  3684. memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
  3685. s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
  3686. /* Insn 3 */
  3687. fix_num = 1;
  3688. var_num = 1;
  3689. /* Fix part
  3690. For an external symbol: ori r1, LO%<constant> */
  3691. sprintf (tmp, "ori r1, %d", lo);
  3692. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  3693. return;
  3694. memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
  3695. /* Var part
  3696. For a local symbol: addi r1, <sym>+LO%<constant> (BFD_RELOC_GOT_LO16) */
  3697. sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
  3698. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  3699. return;
  3700. memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
  3701. s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
  3702. /* Insn 4: add rD, rD, r1 */
  3703. sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
  3704. if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
  3705. return;
  3706. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  3707. s3_inst.bwarn = -1;
  3708. }
  3709. s3_nor1 = r1_bak;
  3710. }
  3711. /* Handle la. */
  3712. static void
  3713. s3_do_macro_la_rdi32 (char *str)
  3714. {
  3715. int reg_rd;
  3716. s3_skip_whitespace (str);
  3717. if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  3718. || s3_skip_past_comma (&str) == (int) s3_FAIL)
  3719. {
  3720. return;
  3721. }
  3722. else
  3723. {
  3724. /* Save str. */
  3725. char *keep_data = str;
  3726. char append_str[s3_MAX_LITERAL_POOL_SIZE];
  3727. /* Check immediate value. */
  3728. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
  3729. {
  3730. s3_inst.error = _("expression error");
  3731. return;
  3732. }
  3733. else if ((s3_inst.reloc.exp.X_add_symbol == NULL)
  3734. && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s3_FAIL))
  3735. {
  3736. s3_inst.error = _("value not in range [0, 0xffffffff]");
  3737. return;
  3738. }
  3739. /* Reset str. */
  3740. str = keep_data;
  3741. /* la rd, simm16. */
  3742. if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
  3743. {
  3744. s3_end_of_line (str);
  3745. return;
  3746. }
  3747. /* la rd, imm32 or la rd, label. */
  3748. else
  3749. {
  3750. s3_SET_INSN_ERROR (NULL);
  3751. /* Reset str. */
  3752. str = keep_data;
  3753. if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
  3754. || (s3_end_of_line (str) == (int) s3_FAIL))
  3755. {
  3756. return;
  3757. }
  3758. else
  3759. {
  3760. if ((s3_score_pic == s3_NO_PIC) || (!s3_inst.reloc.exp.X_add_symbol))
  3761. {
  3762. sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
  3763. if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
  3764. return;
  3765. sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
  3766. if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
  3767. return;
  3768. }
  3769. else
  3770. {
  3771. gas_assert (s3_inst.reloc.exp.X_add_symbol);
  3772. s3_build_la_pic (reg_rd, s3_inst.reloc.exp);
  3773. }
  3774. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  3775. s3_inst.bwarn = -1;
  3776. }
  3777. }
  3778. }
  3779. }
  3780. /* Handle li. */
  3781. static void
  3782. s3_do_macro_li_rdi32 (char *str)
  3783. {
  3784. int reg_rd;
  3785. s3_skip_whitespace (str);
  3786. if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  3787. || s3_skip_past_comma (&str) == (int) s3_FAIL)
  3788. {
  3789. return;
  3790. }
  3791. else
  3792. {
  3793. /* Save str. */
  3794. char *keep_data = str;
  3795. /* Check immediate value. */
  3796. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
  3797. {
  3798. s3_inst.error = _("expression error");
  3799. return;
  3800. }
  3801. else if (!(s3_inst.reloc.exp.X_add_number >= -0xffffffffLL
  3802. && s3_inst.reloc.exp.X_add_number <= 0xffffffffLL))
  3803. {
  3804. s3_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
  3805. return;
  3806. }
  3807. /* Reset str. */
  3808. str = keep_data;
  3809. /* li rd, simm16. */
  3810. if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL)
  3811. {
  3812. s3_end_of_line (str);
  3813. return;
  3814. }
  3815. /* li rd, imm32. */
  3816. else
  3817. {
  3818. char append_str[s3_MAX_LITERAL_POOL_SIZE];
  3819. /* Reset str. */
  3820. str = keep_data;
  3821. if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL)
  3822. || (s3_end_of_line (str) == (int) s3_FAIL))
  3823. {
  3824. return;
  3825. }
  3826. else if (s3_inst.reloc.exp.X_add_symbol)
  3827. {
  3828. s3_inst.error = _("li rd label isn't correct instruction form");
  3829. return;
  3830. }
  3831. else
  3832. {
  3833. sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
  3834. if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
  3835. return;
  3836. else
  3837. {
  3838. sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
  3839. if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
  3840. return;
  3841. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  3842. s3_inst.bwarn = -1;
  3843. }
  3844. }
  3845. }
  3846. }
  3847. }
  3848. /* Handle mul/mulu/div/divu/rem/remu. */
  3849. static void
  3850. s3_do_macro_mul_rdrsrs (char *str)
  3851. {
  3852. int reg_rd;
  3853. int reg_rs1;
  3854. int reg_rs2;
  3855. char *backupstr;
  3856. char append_str[s3_MAX_LITERAL_POOL_SIZE];
  3857. if (s3_university_version == 1)
  3858. as_warn ("%s", s3_ERR_FOR_SCORE5U_MUL_DIV);
  3859. strcpy (append_str, str);
  3860. backupstr = append_str;
  3861. s3_skip_whitespace (backupstr);
  3862. if (((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  3863. || (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
  3864. || ((reg_rs1 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL))
  3865. {
  3866. s3_inst.error = s3_BAD_ARGS;
  3867. return;
  3868. }
  3869. if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
  3870. {
  3871. /* rem/remu rA, rB is error format. */
  3872. if (strcmp (s3_inst.name, "rem") == 0 || strcmp (s3_inst.name, "remu") == 0)
  3873. {
  3874. s3_SET_INSN_ERROR (s3_BAD_ARGS);
  3875. }
  3876. else
  3877. {
  3878. s3_SET_INSN_ERROR (NULL);
  3879. s3_do_rsrs (str);
  3880. }
  3881. return;
  3882. }
  3883. else
  3884. {
  3885. s3_SET_INSN_ERROR (NULL);
  3886. if (((reg_rs2 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  3887. || (s3_end_of_line (backupstr) == (int) s3_FAIL))
  3888. {
  3889. return;
  3890. }
  3891. else
  3892. {
  3893. char append_str1[s3_MAX_LITERAL_POOL_SIZE];
  3894. if (strcmp (s3_inst.name, "rem") == 0)
  3895. {
  3896. sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
  3897. sprintf (append_str1, "mfceh r%d", reg_rd);
  3898. }
  3899. else if (strcmp (s3_inst.name, "remu") == 0)
  3900. {
  3901. sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
  3902. sprintf (append_str1, "mfceh r%d", reg_rd);
  3903. }
  3904. else
  3905. {
  3906. sprintf (append_str, "%s r%d, r%d", s3_inst.name, reg_rs1, reg_rs2);
  3907. sprintf (append_str1, "mfcel r%d", reg_rd);
  3908. }
  3909. /* Output mul/mulu or div/divu or rem/remu. */
  3910. if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL)
  3911. return;
  3912. /* Output mfcel or mfceh. */
  3913. if (s3_append_insn (append_str1, TRUE) == (int) s3_FAIL)
  3914. return;
  3915. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  3916. s3_inst.bwarn = -1;
  3917. }
  3918. }
  3919. }
  3920. static void
  3921. s3_exp_macro_ldst_abs (char *str)
  3922. {
  3923. int reg_rd;
  3924. char *backupstr, *tmp;
  3925. char append_str[s3_MAX_LITERAL_POOL_SIZE];
  3926. char verifystr[s3_MAX_LITERAL_POOL_SIZE];
  3927. struct s3_score_it inst_backup;
  3928. int r1_bak = 0;
  3929. r1_bak = s3_nor1;
  3930. s3_nor1 = 0;
  3931. memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
  3932. strcpy (verifystr, str);
  3933. backupstr = verifystr;
  3934. s3_skip_whitespace (backupstr);
  3935. if ((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  3936. return;
  3937. tmp = backupstr;
  3938. if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL)
  3939. return;
  3940. backupstr = tmp;
  3941. sprintf (append_str, "li r1 %s", backupstr);
  3942. s3_append_insn (append_str, TRUE);
  3943. memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
  3944. sprintf (append_str, " r%d, [r1,0]", reg_rd);
  3945. s3_do_ldst_insn (append_str);
  3946. s3_nor1 = r1_bak;
  3947. }
  3948. /* Handle bcmpeq / bcmpne */
  3949. static void
  3950. s3_do_macro_bcmp (char *str)
  3951. {
  3952. int reg_a , reg_b;
  3953. char keep_data[s3_MAX_LITERAL_POOL_SIZE];
  3954. char* ptemp;
  3955. int i = 0;
  3956. struct s3_score_it inst_expand[2];
  3957. struct s3_score_it inst_main;
  3958. memset (inst_expand, 0, sizeof inst_expand);
  3959. s3_skip_whitespace (str);
  3960. if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  3961. || s3_skip_past_comma (&str) == (int) s3_FAIL
  3962. ||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  3963. || s3_skip_past_comma (&str) == (int) s3_FAIL)
  3964. return;
  3965. ptemp = str;
  3966. while (*ptemp != 0)
  3967. {
  3968. keep_data[i] = *ptemp;
  3969. i++;
  3970. ptemp++;
  3971. }
  3972. keep_data[i] = 0;
  3973. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
  3974. ||reg_b == 0
  3975. || s3_end_of_line (str) == (int) s3_FAIL)
  3976. return;
  3977. else if (s3_inst.reloc.exp.X_add_symbol == 0)
  3978. {
  3979. s3_inst.error = _("lacking label ");
  3980. return;
  3981. }
  3982. else
  3983. {
  3984. char append_str[s3_MAX_LITERAL_POOL_SIZE];
  3985. s3_SET_INSN_ERROR (NULL);
  3986. s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
  3987. s3_inst.reloc.pc_rel = 1;
  3988. bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
  3989. /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
  3990. s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1)
  3991. | ((s3_inst.reloc.exp.X_add_number >> 2) & 0x7) << 7
  3992. | ((s3_inst.reloc.exp.X_add_number >> 5) & 0x1f) << 20;
  3993. /* Check and set offset. */
  3994. if (((val & 0xfffffe00) != 0)
  3995. && ((val & 0xfffffe00) != 0xfffffe00))
  3996. {
  3997. /* support bcmp --> cmp!+beq (bne) */
  3998. if (s3_score_pic == s3_NO_PIC)
  3999. {
  4000. sprintf (&append_str[0], "cmp! r%d, r%d", reg_a, reg_b);
  4001. if (s3_append_insn (&append_str[0], TRUE) == (int) s3_FAIL)
  4002. return;
  4003. if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
  4004. sprintf (&append_str[1], "beq %s", keep_data);
  4005. else
  4006. sprintf (&append_str[1], "bne %s", keep_data);
  4007. if (s3_append_insn (&append_str[1], TRUE) == (int) s3_FAIL)
  4008. return;
  4009. }
  4010. else
  4011. {
  4012. gas_assert (s3_inst.reloc.exp.X_add_symbol);
  4013. }
  4014. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  4015. s3_inst.bwarn = -1;
  4016. return;
  4017. }
  4018. else
  4019. {
  4020. val >>= 1;
  4021. s3_inst.instruction |= (val & 0x1)
  4022. | (((val >> 1) & 0x7) << 7)
  4023. | (((val >> 4) & 0x1f) << 20);
  4024. }
  4025. /* Backup s3_inst. */
  4026. memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
  4027. if (s3_score_pic == s3_NO_PIC)
  4028. {
  4029. sprintf (&append_str[0], "cmp! r%d, r%d", reg_a, reg_b);
  4030. if (s3_append_insn (&append_str[0], FALSE) == (int) s3_FAIL)
  4031. return;
  4032. memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
  4033. if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
  4034. sprintf (&append_str[1], "beq %s", keep_data);
  4035. else
  4036. sprintf (&append_str[1], "bne %s", keep_data);
  4037. if (s3_append_insn (&append_str[1], FALSE) == (int) s3_FAIL)
  4038. return;
  4039. memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
  4040. }
  4041. else
  4042. {
  4043. gas_assert (s3_inst.reloc.exp.X_add_symbol);
  4044. }
  4045. inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
  4046. inst_main.type = Insn_BCMP;
  4047. /* Adjust instruction opcode and to be relaxed instruction opcode. */
  4048. inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
  4049. for (i = 0; i < 2; i++)
  4050. inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
  4051. s3_GET_INSN_CLASS (inst_expand[i].type));
  4052. /* Check data dependency. */
  4053. s3_handle_dependency (&inst_main);
  4054. /* Start a new frag if frag_now is not empty. */
  4055. if (frag_now_fix () != 0)
  4056. {
  4057. if (!frag_now->tc_frag_data.is_insn)
  4058. frag_wane (frag_now);
  4059. frag_new (0);
  4060. }
  4061. frag_grow (20);
  4062. /* Write fr_fix part. */
  4063. char *p;
  4064. p = frag_more (inst_main.size);
  4065. s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
  4066. if (inst_main.reloc.type != BFD_RELOC_NONE)
  4067. {
  4068. s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
  4069. &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
  4070. }
  4071. #ifdef OBJ_ELF
  4072. dwarf2_emit_insn (inst_main.size);
  4073. #endif
  4074. /* s3_GP instruction can not do optimization, only can do relax between
  4075. 1 instruction and 3 instructions. */
  4076. p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
  4077. s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1),
  4078. inst_main.reloc.exp.X_add_symbol, 0, NULL);
  4079. /* Write fr_var part.
  4080. no calling s3_gen_insn_frag, no fixS will be generated. */
  4081. s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
  4082. p += inst_expand[0].size;
  4083. s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
  4084. p += inst_expand[1].size;
  4085. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  4086. s3_inst.bwarn = -1;
  4087. }
  4088. }
  4089. /* Handle bcmpeqz / bcmpnez */
  4090. static void
  4091. s3_do_macro_bcmpz (char *str)
  4092. {
  4093. int reg_a;
  4094. char keep_data[s3_MAX_LITERAL_POOL_SIZE];
  4095. char* ptemp;
  4096. int i = 0;
  4097. struct s3_score_it inst_expand[2];
  4098. struct s3_score_it inst_main;
  4099. memset (inst_expand, 0, sizeof inst_expand);
  4100. s3_skip_whitespace (str);
  4101. if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  4102. || s3_skip_past_comma (&str) == (int) s3_FAIL)
  4103. return;
  4104. ptemp = str;
  4105. while (*ptemp != 0)
  4106. {
  4107. keep_data[i] = *ptemp;
  4108. i++;
  4109. ptemp++;
  4110. }
  4111. keep_data[i] = 0;
  4112. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
  4113. || s3_end_of_line (str) == (int) s3_FAIL)
  4114. return;
  4115. else if (s3_inst.reloc.exp.X_add_symbol == 0)
  4116. {
  4117. s3_inst.error = _("lacking label ");
  4118. return;
  4119. }
  4120. else
  4121. {
  4122. char append_str[s3_MAX_LITERAL_POOL_SIZE];
  4123. s3_SET_INSN_ERROR (NULL);
  4124. s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
  4125. s3_inst.reloc.pc_rel = 1;
  4126. bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
  4127. /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
  4128. s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number>>1) & 0x1) | ((s3_inst.reloc.exp.X_add_number>>2) & 0x7)<<7 |((s3_inst.reloc.exp.X_add_number>>5) & 0x1f)<<20;
  4129. /* Check and set offset. */
  4130. if (((val & 0xfffffe00) != 0)
  4131. && ((val & 0xfffffe00) != 0xfffffe00))
  4132. {
  4133. if (s3_score_pic == s3_NO_PIC)
  4134. {
  4135. sprintf (&append_str[0], "cmpi! r%d,0", reg_a);
  4136. if (s3_append_insn (&append_str[0], TRUE) == (int) s3_FAIL)
  4137. return;
  4138. if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
  4139. sprintf (&append_str[1], "beq %s", keep_data);
  4140. else
  4141. sprintf (&append_str[1], "bne %s", keep_data);
  4142. if (s3_append_insn (&append_str[1], TRUE) == (int) s3_FAIL)
  4143. return;
  4144. }
  4145. else
  4146. {
  4147. gas_assert (s3_inst.reloc.exp.X_add_symbol);
  4148. }
  4149. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  4150. s3_inst.bwarn = -1;
  4151. return;
  4152. }
  4153. else
  4154. {
  4155. val >>= 1;
  4156. s3_inst.instruction |= (val & 0x1)
  4157. | (((val >> 1) & 0x7) << 7)
  4158. | (((val >> 4) & 0x1f) << 20);
  4159. }
  4160. /* Backup s3_inst. */
  4161. memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
  4162. if (s3_score_pic == s3_NO_PIC)
  4163. {
  4164. sprintf (&append_str[0], "cmpi! r%d, 0", reg_a);
  4165. if (s3_append_insn (&append_str[0], FALSE) == (int) s3_FAIL)
  4166. return;
  4167. memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it));
  4168. if ((inst_main.instruction & 0x3e00007e) == 0x0000004c)
  4169. sprintf (&append_str[1], "beq %s", keep_data);
  4170. else
  4171. sprintf (&append_str[1], "bne %s", keep_data);
  4172. if (s3_append_insn (&append_str[1], FALSE) == (int) s3_FAIL)
  4173. return;
  4174. memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it));
  4175. }
  4176. else
  4177. {
  4178. gas_assert (s3_inst.reloc.exp.X_add_symbol);
  4179. }
  4180. inst_main.relax_size = inst_expand[0].size + inst_expand[1].size;
  4181. inst_main.type = Insn_BCMP;
  4182. /* Adjust instruction opcode and to be relaxed instruction opcode. */
  4183. inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
  4184. for (i = 0; i < 2; i++)
  4185. inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction ,
  4186. s3_GET_INSN_CLASS (inst_expand[i].type));
  4187. /* Check data dependency. */
  4188. s3_handle_dependency (&inst_main);
  4189. /* Start a new frag if frag_now is not empty. */
  4190. if (frag_now_fix () != 0)
  4191. {
  4192. if (!frag_now->tc_frag_data.is_insn)
  4193. frag_wane (frag_now);
  4194. frag_new (0);
  4195. }
  4196. frag_grow (20);
  4197. /* Write fr_fix part. */
  4198. char *p;
  4199. p = frag_more (inst_main.size);
  4200. s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
  4201. if (inst_main.reloc.type != BFD_RELOC_NONE)
  4202. {
  4203. s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
  4204. &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
  4205. }
  4206. #ifdef OBJ_ELF
  4207. dwarf2_emit_insn (inst_main.size);
  4208. #endif
  4209. /* s3_GP instruction can not do optimization, only can do relax between
  4210. 1 instruction and 3 instructions. */
  4211. p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
  4212. s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1),
  4213. inst_main.reloc.exp.X_add_symbol, 0, NULL);
  4214. /* Write fr_var part.
  4215. no calling s3_gen_insn_frag, no fixS will be generated. */
  4216. s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
  4217. p += inst_expand[0].size;
  4218. s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
  4219. p += inst_expand[1].size;
  4220. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  4221. s3_inst.bwarn = -1;
  4222. }
  4223. }
  4224. static int
  4225. s3_nopic_need_relax (symbolS * sym, int before_relaxing)
  4226. {
  4227. if (sym == NULL)
  4228. return 0;
  4229. else if (s3_USE_GLOBAL_POINTER_OPT && s3_g_switch_value > 0)
  4230. {
  4231. const char *symname;
  4232. const char *segname;
  4233. /* Find out whether this symbol can be referenced off the $gp
  4234. register. It can be if it is smaller than the -G size or if
  4235. it is in the .sdata or .sbss section. Certain symbols can
  4236. not be referenced off the $gp, although it appears as though
  4237. they can. */
  4238. symname = S_GET_NAME (sym);
  4239. if (symname != (const char *)NULL
  4240. && (strcmp (symname, "eprol") == 0
  4241. || strcmp (symname, "etext") == 0
  4242. || strcmp (symname, "_gp") == 0
  4243. || strcmp (symname, "edata") == 0
  4244. || strcmp (symname, "_fbss") == 0
  4245. || strcmp (symname, "_fdata") == 0
  4246. || strcmp (symname, "_ftext") == 0
  4247. || strcmp (symname, "end") == 0
  4248. || strcmp (symname, GP_DISP_LABEL) == 0))
  4249. {
  4250. return 1;
  4251. }
  4252. else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
  4253. /* We must defer this decision until after the whole file has been read,
  4254. since there might be a .extern after the first use of this symbol. */
  4255. || (before_relaxing
  4256. && S_GET_VALUE (sym) == 0)
  4257. || (S_GET_VALUE (sym) != 0
  4258. && S_GET_VALUE (sym) <= s3_g_switch_value)))
  4259. {
  4260. return 0;
  4261. }
  4262. segname = segment_name (S_GET_SEGMENT (sym));
  4263. return (strcmp (segname, ".sdata") != 0
  4264. && strcmp (segname, ".sbss") != 0
  4265. && strncmp (segname, ".sdata.", 7) != 0
  4266. && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
  4267. }
  4268. /* We are not optimizing for the $gp register. */
  4269. else
  4270. return 1;
  4271. }
  4272. /* Build a relax frag for lw/st instruction when generating s3_PIC,
  4273. external symbol first and local symbol second. */
  4274. static void
  4275. s3_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
  4276. {
  4277. symbolS *add_symbol = exp.X_add_symbol;
  4278. int add_number = exp.X_add_number;
  4279. struct s3_score_it fix_insts[s3_RELAX_INST_NUM];
  4280. struct s3_score_it var_insts[s3_RELAX_INST_NUM];
  4281. int fix_num = 0;
  4282. int var_num = 0;
  4283. char tmp[s3_MAX_LITERAL_POOL_SIZE];
  4284. int r1_bak;
  4285. r1_bak = s3_nor1;
  4286. s3_nor1 = 0;
  4287. if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
  4288. {
  4289. fix_num = 1;
  4290. var_num = 2;
  4291. /* For an external symbol, two insns are generated;
  4292. For a local symbol, three insns are generated. */
  4293. /* Fix part
  4294. For an external symbol: lw rD, <sym>($gp)
  4295. (BFD_RELOC_SCORE_GOT15) */
  4296. sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
  4297. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  4298. return;
  4299. memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it));
  4300. /* Var part
  4301. For a local symbol :
  4302. lw rD, <sym>($gp) (BFD_RELOC_SCORE_GOT15)
  4303. addi rD, <sym> (BFD_RELOC_GOT_LO16) */
  4304. s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
  4305. memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it));
  4306. sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
  4307. if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL)
  4308. return;
  4309. memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it));
  4310. s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
  4311. /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */
  4312. sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
  4313. if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL)
  4314. return;
  4315. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  4316. s3_inst.bwarn = -1;
  4317. }
  4318. else
  4319. {
  4320. s3_inst.error = _("s3_PIC code offset overflow (max 16 signed bits)");
  4321. return;
  4322. }
  4323. s3_nor1 = r1_bak;
  4324. }
  4325. static void
  4326. s3_do_macro_ldst_label (char *str)
  4327. {
  4328. int i;
  4329. int ldst_gp_p = 0;
  4330. int reg_rd;
  4331. int r1_bak;
  4332. char *backup_str;
  4333. char *label_str;
  4334. char *absolute_value;
  4335. char append_str[3][s3_MAX_LITERAL_POOL_SIZE];
  4336. char verifystr[s3_MAX_LITERAL_POOL_SIZE];
  4337. struct s3_score_it inst_backup;
  4338. struct s3_score_it inst_expand[3];
  4339. struct s3_score_it inst_main;
  4340. memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it));
  4341. strcpy (verifystr, str);
  4342. backup_str = verifystr;
  4343. s3_skip_whitespace (backup_str);
  4344. if ((reg_rd = s3_reg_required_here (&backup_str, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  4345. return;
  4346. if (s3_skip_past_comma (&backup_str) == (int) s3_FAIL)
  4347. return;
  4348. label_str = backup_str;
  4349. /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */
  4350. if (*backup_str == '[')
  4351. {
  4352. s3_inst.type = Rd_rvalueRs_preSI12;
  4353. s3_do_ldst_insn (str);
  4354. return;
  4355. }
  4356. /* Ld/st rD, imm. */
  4357. absolute_value = backup_str;
  4358. s3_inst.type = Rd_rvalueRs_SI15;
  4359. if (s3_my_get_expression (&s3_inst.reloc.exp, &backup_str) == (int) s3_FAIL)
  4360. {
  4361. s3_inst.error = _("expression error");
  4362. return;
  4363. }
  4364. else if ((s3_inst.reloc.exp.X_add_symbol == NULL)
  4365. && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s3_FAIL))
  4366. {
  4367. s3_inst.error = _("value not in range [0, 0x7fffffff]");
  4368. return;
  4369. }
  4370. else if (s3_end_of_line (backup_str) == (int) s3_FAIL)
  4371. {
  4372. s3_inst.error = _("end on line error");
  4373. return;
  4374. }
  4375. else
  4376. {
  4377. if (s3_inst.reloc.exp.X_add_symbol == 0)
  4378. {
  4379. memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it));
  4380. s3_exp_macro_ldst_abs (str);
  4381. return;
  4382. }
  4383. }
  4384. /* Ld/st rD, label. */
  4385. s3_inst.type = Rd_rvalueRs_SI15;
  4386. backup_str = absolute_value;
  4387. if ((s3_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s3_FAIL)
  4388. || (s3_end_of_line (backup_str) == (int) s3_FAIL))
  4389. {
  4390. return;
  4391. }
  4392. else
  4393. {
  4394. if (s3_inst.reloc.exp.X_add_symbol == 0)
  4395. {
  4396. if (!s3_inst.error)
  4397. s3_inst.error = s3_BAD_ARGS;
  4398. return;
  4399. }
  4400. if (s3_score_pic == s3_PIC)
  4401. {
  4402. int ldst_idx = 0;
  4403. ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
  4404. s3_build_lwst_pic (reg_rd, s3_inst.reloc.exp,
  4405. s3_score_ldst_insns[ldst_idx * 3 + 0].template_name);
  4406. return;
  4407. }
  4408. else
  4409. {
  4410. if ((s3_inst.reloc.exp.X_add_number <= 0x3fff)
  4411. && (s3_inst.reloc.exp.X_add_number >= -0x4000)
  4412. && (!s3_nopic_need_relax (s3_inst.reloc.exp.X_add_symbol, 1)))
  4413. {
  4414. int ldst_idx = 0;
  4415. /* Assign the real opcode. */
  4416. ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK;
  4417. s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
  4418. s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + 0].value;
  4419. s3_inst.instruction |= reg_rd << 20;
  4420. s3_inst.instruction |= s3_GP << 15;
  4421. s3_inst.relax_inst = 0x8000;
  4422. s3_inst.relax_size = 0;
  4423. ldst_gp_p = 1;
  4424. }
  4425. }
  4426. }
  4427. /* Backup s3_inst. */
  4428. memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it));
  4429. r1_bak = s3_nor1;
  4430. s3_nor1 = 0;
  4431. /* Determine which instructions should be output. */
  4432. sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
  4433. sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
  4434. sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
  4435. /* Generate three instructions.
  4436. la r1, label
  4437. ld/st rd, [r1, 0] */
  4438. for (i = 0; i < 3; i++)
  4439. {
  4440. if (s3_append_insn (append_str[i], FALSE) == (int) s3_FAIL)
  4441. return;
  4442. memcpy (&inst_expand[i], &s3_inst, sizeof (struct s3_score_it));
  4443. }
  4444. if (ldst_gp_p)
  4445. {
  4446. char *p;
  4447. /* Adjust instruction opcode and to be relaxed instruction opcode. */
  4448. inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
  4449. /* relax lw rd, label -> ldis rs, imm16
  4450. ori rd, imm16
  4451. lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */
  4452. if (inst_expand[2].relax_size == 0)
  4453. inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
  4454. else
  4455. inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].relax_size;
  4456. inst_main.type = Insn_GP;
  4457. for (i = 0; i < 3; i++)
  4458. inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction,
  4459. s3_GET_INSN_CLASS (inst_expand[i].type));
  4460. /* Check data dependency. */
  4461. s3_handle_dependency (&inst_main);
  4462. /* Start a new frag if frag_now is not empty. */
  4463. if (frag_now_fix () != 0)
  4464. {
  4465. if (!frag_now->tc_frag_data.is_insn)
  4466. frag_wane (frag_now);
  4467. frag_new (0);
  4468. }
  4469. frag_grow (20);
  4470. /* Write fr_fix part. */
  4471. p = frag_more (inst_main.size);
  4472. s3_md_number_to_chars (p, inst_main.instruction, inst_main.size);
  4473. if (inst_main.reloc.type != BFD_RELOC_NONE)
  4474. {
  4475. s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
  4476. &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
  4477. }
  4478. #ifdef OBJ_ELF
  4479. dwarf2_emit_insn (inst_main.size);
  4480. #endif
  4481. /* s3_GP instruction can not do optimization, only can do relax between
  4482. 1 instruction and 3 instructions. */
  4483. p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0,
  4484. s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
  4485. inst_main.reloc.exp.X_add_symbol, 0, NULL);
  4486. /* Write fr_var part.
  4487. no calling s3_gen_insn_frag, no fixS will be generated. */
  4488. s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
  4489. p += inst_expand[0].size;
  4490. s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
  4491. p += inst_expand[1].size;
  4492. /* relax lw rd, label -> ldis rs, imm16
  4493. ori rd, imm16
  4494. lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */
  4495. if (inst_expand[2].relax_size == 0)
  4496. s3_md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
  4497. else
  4498. s3_md_number_to_chars (p, inst_expand[2].relax_inst, inst_expand[2].relax_size);
  4499. }
  4500. else
  4501. {
  4502. s3_gen_insn_frag (&inst_expand[0], NULL);
  4503. s3_gen_insn_frag (&inst_expand[1], NULL);
  4504. s3_gen_insn_frag (&inst_expand[2], NULL);
  4505. }
  4506. s3_nor1 = r1_bak;
  4507. /* Set bwarn as -1, so macro instruction itself will not be generated frag. */
  4508. s3_inst.bwarn = -1;
  4509. }
  4510. static void
  4511. s3_do_lw_pic (char *str)
  4512. {
  4513. int reg_rd;
  4514. s3_skip_whitespace (str);
  4515. if (((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  4516. || (s3_skip_past_comma (&str) == (int) s3_FAIL)
  4517. || (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL)
  4518. || (s3_end_of_line (str) == (int) s3_FAIL))
  4519. {
  4520. return;
  4521. }
  4522. else
  4523. {
  4524. if (s3_inst.reloc.exp.X_add_symbol == 0)
  4525. {
  4526. if (!s3_inst.error)
  4527. s3_inst.error = s3_BAD_ARGS;
  4528. return;
  4529. }
  4530. s3_inst.instruction |= s3_GP << 15;
  4531. s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
  4532. }
  4533. }
  4534. static void
  4535. s3_do_empty (char *str)
  4536. {
  4537. str = str;
  4538. if (s3_university_version == 1)
  4539. {
  4540. if (((s3_inst.instruction & 0x3e0003ff) == 0x0c000004)
  4541. || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000024)
  4542. || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000044)
  4543. || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000064))
  4544. {
  4545. s3_inst.error = s3_ERR_FOR_SCORE5U_MMU;
  4546. return;
  4547. }
  4548. }
  4549. if (s3_end_of_line (str) == (int) s3_FAIL)
  4550. return;
  4551. if (s3_inst.relax_inst != 0x8000)
  4552. {
  4553. if (s3_inst.type == NO_OPD)
  4554. {
  4555. s3_inst.relax_size = 2;
  4556. }
  4557. else
  4558. {
  4559. s3_inst.relax_size = 4;
  4560. }
  4561. }
  4562. }
  4563. static void
  4564. s3_do16_int (char *str)
  4565. {
  4566. s3_skip_whitespace (str);
  4567. return;
  4568. }
  4569. static void
  4570. s3_do_jump (char *str)
  4571. {
  4572. char *save_in;
  4573. s3_skip_whitespace (str);
  4574. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
  4575. || s3_end_of_line (str) == (int) s3_FAIL)
  4576. return;
  4577. if (s3_inst.reloc.exp.X_add_symbol == 0)
  4578. {
  4579. s3_inst.error = _("lacking label ");
  4580. return;
  4581. }
  4582. if (!(s3_inst.reloc.exp.X_add_number >= -16777216
  4583. && s3_inst.reloc.exp.X_add_number <= 16777215))
  4584. {
  4585. s3_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
  4586. return;
  4587. }
  4588. save_in = input_line_pointer;
  4589. input_line_pointer = str;
  4590. s3_inst.reloc.type = BFD_RELOC_SCORE_JMP;
  4591. s3_inst.reloc.pc_rel = 1;
  4592. input_line_pointer = save_in;
  4593. }
  4594. static void
  4595. s3_do_branch (char *str)
  4596. {
  4597. if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
  4598. || s3_end_of_line (str) == (int) s3_FAIL)
  4599. {
  4600. return;
  4601. }
  4602. else if (s3_inst.reloc.exp.X_add_symbol == 0)
  4603. {
  4604. s3_inst.error = _("lacking label ");
  4605. return;
  4606. }
  4607. else if (!(s3_inst.reloc.exp.X_add_number >= -524288
  4608. && s3_inst.reloc.exp.X_add_number <= 524287))
  4609. {
  4610. s3_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
  4611. return;
  4612. }
  4613. s3_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
  4614. s3_inst.reloc.pc_rel = 1;
  4615. /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
  4616. s3_inst.instruction |= (s3_inst.reloc.exp.X_add_number & 0x3fe) | ((s3_inst.reloc.exp.X_add_number & 0xffc00) << 5);
  4617. /* Compute 16 bit branch instruction. */
  4618. if ((s3_inst.relax_inst != 0x8000)
  4619. && (s3_inst.reloc.exp.X_add_number >= -512 && s3_inst.reloc.exp.X_add_number <= 511))
  4620. {
  4621. s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);/*b! :disp 9 bit */
  4622. s3_inst.relax_size = 2;
  4623. }
  4624. else
  4625. {
  4626. s3_inst.relax_inst = 0x8000;
  4627. }
  4628. }
  4629. static void
  4630. s3_do16_branch (char *str)
  4631. {
  4632. if ((s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
  4633. || s3_end_of_line (str) == (int) s3_FAIL))
  4634. {
  4635. ;
  4636. }
  4637. else if (s3_inst.reloc.exp.X_add_symbol == 0)
  4638. {
  4639. s3_inst.error = _("lacking label");
  4640. }
  4641. else if (!(s3_inst.reloc.exp.X_add_number >= -512
  4642. && s3_inst.reloc.exp.X_add_number <= 511))
  4643. {
  4644. s3_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
  4645. }
  4646. else
  4647. {
  4648. s3_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
  4649. s3_inst.reloc.pc_rel = 1;
  4650. s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);
  4651. s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number ) & 0x1ff);
  4652. s3_inst.relax_size = 4;
  4653. }
  4654. }
  4655. /* Return true if the given symbol should be considered local for s3_PIC. */
  4656. static bfd_boolean
  4657. s3_pic_need_relax (symbolS *sym, asection *segtype)
  4658. {
  4659. asection *symsec;
  4660. bfd_boolean linkonce;
  4661. /* Handle the case of a symbol equated to another symbol. */
  4662. while (symbol_equated_reloc_p (sym))
  4663. {
  4664. symbolS *n;
  4665. /* It's possible to get a loop here in a badly written
  4666. program. */
  4667. n = symbol_get_value_expression (sym)->X_add_symbol;
  4668. if (n == sym)
  4669. break;
  4670. sym = n;
  4671. }
  4672. symsec = S_GET_SEGMENT (sym);
  4673. /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
  4674. linkonce = FALSE;
  4675. if (symsec != segtype && ! S_IS_LOCAL (sym))
  4676. {
  4677. if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
  4678. linkonce = TRUE;
  4679. /* The GNU toolchain uses an extension for ELF: a section
  4680. beginning with the magic string .gnu.linkonce is a linkonce
  4681. section. */
  4682. if (strncmp (segment_name (symsec), ".gnu.linkonce",
  4683. sizeof ".gnu.linkonce" - 1) == 0)
  4684. linkonce = TRUE;
  4685. }
  4686. /* This must duplicate the test in adjust_reloc_syms. */
  4687. return (!bfd_is_und_section (symsec)
  4688. && !bfd_is_abs_section (symsec)
  4689. && !bfd_is_com_section (symsec)
  4690. && !linkonce
  4691. #ifdef OBJ_ELF
  4692. /* A global or weak symbol is treated as external. */
  4693. && (OUTPUT_FLAVOR != bfd_target_elf_flavour
  4694. || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
  4695. #endif
  4696. );
  4697. }
  4698. static void
  4699. s3_parse_pce_inst (char *insnstr)
  4700. {
  4701. char c;
  4702. char *p;
  4703. char first[s3_MAX_LITERAL_POOL_SIZE];
  4704. char second[s3_MAX_LITERAL_POOL_SIZE];
  4705. struct s3_score_it pec_part_1;
  4706. /* Get first part string of PCE. */
  4707. p = strstr (insnstr, "||");
  4708. c = *p;
  4709. *p = '\0';
  4710. sprintf (first, "%s", insnstr);
  4711. /* Get second part string of PCE. */
  4712. *p = c;
  4713. p += 2;
  4714. sprintf (second, "%s", p);
  4715. s3_parse_16_32_inst (first, FALSE);
  4716. if (s3_inst.error)
  4717. return;
  4718. memcpy (&pec_part_1, &s3_inst, sizeof (s3_inst));
  4719. s3_parse_16_32_inst (second, FALSE);
  4720. if (s3_inst.error)
  4721. return;
  4722. if ( ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN_SIZE))
  4723. || ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN16_SIZE))
  4724. || ((pec_part_1.size == s3_INSN16_SIZE) && (s3_inst.size == s3_INSN_SIZE)))
  4725. {
  4726. s3_inst.error = _("pce instruction error (16 bit || 16 bit)'");
  4727. sprintf (s3_inst.str, insnstr);
  4728. return;
  4729. }
  4730. if (!s3_inst.error)
  4731. s3_gen_insn_frag (&pec_part_1, &s3_inst);
  4732. }
  4733. /* s3: dsp. */
  4734. static void
  4735. s3_do16_dsp (char *str)
  4736. {
  4737. int rd = 0;
  4738. /* Check 3d. */
  4739. if (s3_score3d == 0)
  4740. {
  4741. s3_inst.error = _("score3d instruction.");
  4742. return;
  4743. }
  4744. s3_skip_whitespace (str);
  4745. if ((rd = s3_reglow_required_here (&str, 0)) == (int) s3_FAIL
  4746. || s3_end_of_line (str) == (int) s3_FAIL)
  4747. {
  4748. return;
  4749. }
  4750. else
  4751. {
  4752. s3_inst.relax_inst |= rd << 20;
  4753. s3_inst.relax_size = 4;
  4754. }
  4755. }
  4756. static void
  4757. s3_do16_dsp2 (char *str)
  4758. {
  4759. /* Check 3d. */
  4760. if (s3_score3d == 0)
  4761. {
  4762. s3_inst.error = _("score3d instruction.");
  4763. return;
  4764. }
  4765. s3_skip_whitespace (str);
  4766. if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL
  4767. || s3_skip_past_comma (&str) == (int) s3_FAIL
  4768. || s3_reglow_required_here (&str, 0) == (int) s3_FAIL
  4769. || s3_end_of_line (str) == (int) s3_FAIL)
  4770. {
  4771. return;
  4772. }
  4773. else
  4774. {
  4775. s3_inst.relax_inst |= (((s3_inst.instruction >> 8) & 0xf) << 20)
  4776. | (((s3_inst.instruction >> 8) & 0xf) << 15) | (((s3_inst.instruction >> 4) & 0xf) << 10);
  4777. s3_inst.relax_size = 4;
  4778. }
  4779. }
  4780. static void
  4781. s3_do_dsp (char *str)
  4782. {
  4783. /* Check 3d. */
  4784. if (s3_score3d == 0)
  4785. {
  4786. s3_inst.error = _("score3d instruction.");
  4787. return;
  4788. }
  4789. s3_skip_whitespace (str);
  4790. if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  4791. || s3_skip_past_comma (&str) == (int) s3_FAIL
  4792. || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  4793. || s3_end_of_line (str) == (int) s3_FAIL)
  4794. return;
  4795. if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
  4796. {
  4797. s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
  4798. s3_inst.relax_size = 2;
  4799. }
  4800. else
  4801. s3_inst.relax_inst = 0x8000;
  4802. }
  4803. static void
  4804. s3_do_dsp2 (char *str)
  4805. {
  4806. int reg;
  4807. /* Check 3d. */
  4808. if (s3_score3d == 0)
  4809. {
  4810. s3_inst.error = _("score3d instruction.");
  4811. return;
  4812. }
  4813. s3_skip_whitespace (str);
  4814. if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  4815. || s3_skip_past_comma (&str) == (int) s3_FAIL
  4816. || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  4817. || s3_skip_past_comma (&str) == (int) s3_FAIL
  4818. || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  4819. || s3_end_of_line (str) == (int) s3_FAIL)
  4820. {
  4821. return;
  4822. }
  4823. else
  4824. {
  4825. /* Check mulr, mulur rd is even number. */
  4826. if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340
  4827. || (s3_inst.instruction & 0x3e0003ff) == 0x00000342)
  4828. && (reg % 2))
  4829. {
  4830. s3_inst.error = _("rd must be even number.");
  4831. return;
  4832. }
  4833. if ((((s3_inst.instruction >> 15) & 0x10) == 0)
  4834. && (((s3_inst.instruction >> 10) & 0x10) == 0)
  4835. && (((s3_inst.instruction >> 20) & 0x10) == 0)
  4836. && (s3_inst.relax_inst != 0x8000)
  4837. && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf)))
  4838. {
  4839. s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) )
  4840. | (((s3_inst.instruction >> 15) & 0xf) << 4);
  4841. s3_inst.relax_size = 2;
  4842. }
  4843. else
  4844. {
  4845. s3_inst.relax_inst = 0x8000;
  4846. }
  4847. }
  4848. }
  4849. static void
  4850. s3_do_dsp3 (char *str)
  4851. {
  4852. /* Check 3d. */
  4853. if (s3_score3d == 0)
  4854. {
  4855. s3_inst.error = _("score3d instruction.");
  4856. return;
  4857. }
  4858. s3_skip_whitespace (str);
  4859. if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  4860. || s3_skip_past_comma (&str) == (int) s3_FAIL
  4861. || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL
  4862. || s3_end_of_line (str) == (int) s3_FAIL)
  4863. return;
  4864. if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) )
  4865. {
  4866. s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5);
  4867. s3_inst.relax_size = 2;
  4868. }
  4869. else
  4870. s3_inst.relax_inst = 0x8000;
  4871. }
  4872. /* If we change section we must dump the literal pool first. */
  4873. static void
  4874. s3_s_score_bss (int ignore ATTRIBUTE_UNUSED)
  4875. {
  4876. subseg_set (bss_section, (subsegT) get_absolute_expression ());
  4877. demand_empty_rest_of_line ();
  4878. }
  4879. static void
  4880. s3_s_score_text (int ignore)
  4881. {
  4882. obj_elf_text (ignore);
  4883. record_alignment (now_seg, 2);
  4884. }
  4885. static void
  4886. s3_score_s_section (int ignore)
  4887. {
  4888. obj_elf_section (ignore);
  4889. if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
  4890. record_alignment (now_seg, 2);
  4891. }
  4892. static void
  4893. s3_s_change_sec (int sec)
  4894. {
  4895. segT seg;
  4896. #ifdef OBJ_ELF
  4897. /* The ELF backend needs to know that we are changing sections, so
  4898. that .previous works correctly. We could do something like check
  4899. for an obj_section_change_hook macro, but that might be confusing
  4900. as it would not be appropriate to use it in the section changing
  4901. functions in read.c, since obj-elf.c intercepts those. FIXME:
  4902. This should be cleaner, somehow. */
  4903. obj_elf_section_change_hook ();
  4904. #endif
  4905. switch (sec)
  4906. {
  4907. case 'r':
  4908. seg = subseg_new (s3_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
  4909. bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
  4910. if (strcmp (TARGET_OS, "elf") != 0)
  4911. record_alignment (seg, 4);
  4912. demand_empty_rest_of_line ();
  4913. break;
  4914. case 's':
  4915. seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
  4916. bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
  4917. if (strcmp (TARGET_OS, "elf") != 0)
  4918. record_alignment (seg, 4);
  4919. demand_empty_rest_of_line ();
  4920. break;
  4921. }
  4922. }
  4923. static void
  4924. s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED)
  4925. {
  4926. long mask, off;
  4927. if (s3_cur_proc_ptr == (s3_procS *) NULL)
  4928. {
  4929. as_warn (_(".mask outside of .ent"));
  4930. demand_empty_rest_of_line ();
  4931. return;
  4932. }
  4933. if (get_absolute_expression_and_terminator (&mask) != ',')
  4934. {
  4935. as_warn (_("Bad .mask directive"));
  4936. --input_line_pointer;
  4937. demand_empty_rest_of_line ();
  4938. return;
  4939. }
  4940. off = get_absolute_expression ();
  4941. s3_cur_proc_ptr->reg_mask = mask;
  4942. s3_cur_proc_ptr->reg_offset = off;
  4943. demand_empty_rest_of_line ();
  4944. }
  4945. static symbolS *
  4946. s3_get_symbol (void)
  4947. {
  4948. int c;
  4949. char *name;
  4950. symbolS *p;
  4951. name = input_line_pointer;
  4952. c = get_symbol_end ();
  4953. p = (symbolS *) symbol_find_or_make (name);
  4954. *input_line_pointer = c;
  4955. return p;
  4956. }
  4957. static long
  4958. s3_get_number (void)
  4959. {
  4960. int negative = 0;
  4961. long val = 0;
  4962. if (*input_line_pointer == '-')
  4963. {
  4964. ++input_line_pointer;
  4965. negative = 1;
  4966. }
  4967. if (!ISDIGIT (*input_line_pointer))
  4968. as_bad (_("expected simple number"));
  4969. if (input_line_pointer[0] == '0')
  4970. {
  4971. if (input_line_pointer[1] == 'x')
  4972. {
  4973. input_line_pointer += 2;
  4974. while (ISXDIGIT (*input_line_pointer))
  4975. {
  4976. val <<= 4;
  4977. val |= hex_value (*input_line_pointer++);
  4978. }
  4979. return negative ? -val : val;
  4980. }
  4981. else
  4982. {
  4983. ++input_line_pointer;
  4984. while (ISDIGIT (*input_line_pointer))
  4985. {
  4986. val <<= 3;
  4987. val |= *input_line_pointer++ - '0';
  4988. }
  4989. return negative ? -val : val;
  4990. }
  4991. }
  4992. if (!ISDIGIT (*input_line_pointer))
  4993. {
  4994. printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
  4995. as_warn (_("invalid number"));
  4996. return -1;
  4997. }
  4998. while (ISDIGIT (*input_line_pointer))
  4999. {
  5000. val *= 10;
  5001. val += *input_line_pointer++ - '0';
  5002. }
  5003. return negative ? -val : val;
  5004. }
  5005. /* The .aent and .ent directives. */
  5006. static void
  5007. s3_s_score_ent (int aent)
  5008. {
  5009. symbolS *symbolP;
  5010. int maybe_text;
  5011. symbolP = s3_get_symbol ();
  5012. if (*input_line_pointer == ',')
  5013. ++input_line_pointer;
  5014. SKIP_WHITESPACE ();
  5015. if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
  5016. s3_get_number ();
  5017. #ifdef BFD_ASSEMBLER
  5018. if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
  5019. maybe_text = 1;
  5020. else
  5021. maybe_text = 0;
  5022. #else
  5023. if (now_seg != data_section && now_seg != bss_section)
  5024. maybe_text = 1;
  5025. else
  5026. maybe_text = 0;
  5027. #endif
  5028. if (!maybe_text)
  5029. as_warn (_(".ent or .aent not in text section."));
  5030. if (!aent && s3_cur_proc_ptr)
  5031. as_warn (_("missing .end"));
  5032. if (!aent)
  5033. {
  5034. s3_cur_proc_ptr = &s3_cur_proc;
  5035. s3_cur_proc_ptr->reg_mask = 0xdeadbeaf;
  5036. s3_cur_proc_ptr->reg_offset = 0xdeadbeaf;
  5037. s3_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
  5038. s3_cur_proc_ptr->leaf = 0xdeafbeaf;
  5039. s3_cur_proc_ptr->frame_offset = 0xdeafbeaf;
  5040. s3_cur_proc_ptr->frame_reg = 0xdeafbeaf;
  5041. s3_cur_proc_ptr->pc_reg = 0xdeafbeaf;
  5042. s3_cur_proc_ptr->isym = symbolP;
  5043. symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
  5044. ++s3_numprocs;
  5045. if (debug_type == DEBUG_STABS)
  5046. stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
  5047. }
  5048. demand_empty_rest_of_line ();
  5049. }
  5050. static void
  5051. s3_s_score_frame (int ignore ATTRIBUTE_UNUSED)
  5052. {
  5053. char *backupstr;
  5054. char str[30];
  5055. long val;
  5056. int i = 0;
  5057. backupstr = input_line_pointer;
  5058. #ifdef OBJ_ELF
  5059. if (s3_cur_proc_ptr == (s3_procS *) NULL)
  5060. {
  5061. as_warn (_(".frame outside of .ent"));
  5062. demand_empty_rest_of_line ();
  5063. return;
  5064. }
  5065. s3_cur_proc_ptr->frame_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
  5066. SKIP_WHITESPACE ();
  5067. s3_skip_past_comma (&backupstr);
  5068. while (*backupstr != ',')
  5069. {
  5070. str[i] = *backupstr;
  5071. i++;
  5072. backupstr++;
  5073. }
  5074. str[i] = '\0';
  5075. val = atoi (str);
  5076. SKIP_WHITESPACE ();
  5077. s3_skip_past_comma (&backupstr);
  5078. s3_cur_proc_ptr->frame_offset = val;
  5079. s3_cur_proc_ptr->pc_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE);
  5080. SKIP_WHITESPACE ();
  5081. s3_skip_past_comma (&backupstr);
  5082. i = 0;
  5083. while (*backupstr != '\n')
  5084. {
  5085. str[i] = *backupstr;
  5086. i++;
  5087. backupstr++;
  5088. }
  5089. str[i] = '\0';
  5090. val = atoi (str);
  5091. s3_cur_proc_ptr->leaf = val;
  5092. SKIP_WHITESPACE ();
  5093. s3_skip_past_comma (&backupstr);
  5094. #endif /* OBJ_ELF */
  5095. while (input_line_pointer != backupstr)
  5096. input_line_pointer++;
  5097. }
  5098. /* The .end directive. */
  5099. static void
  5100. s3_s_score_end (int x ATTRIBUTE_UNUSED)
  5101. {
  5102. symbolS *p;
  5103. int maybe_text;
  5104. /* Generate a .pdr section. */
  5105. segT saved_seg = now_seg;
  5106. subsegT saved_subseg = now_subseg;
  5107. expressionS exp;
  5108. char *fragp;
  5109. if (!is_end_of_line[(unsigned char)*input_line_pointer])
  5110. {
  5111. p = s3_get_symbol ();
  5112. demand_empty_rest_of_line ();
  5113. }
  5114. else
  5115. p = NULL;
  5116. #ifdef BFD_ASSEMBLER
  5117. if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
  5118. maybe_text = 1;
  5119. else
  5120. maybe_text = 0;
  5121. #else
  5122. if (now_seg != data_section && now_seg != bss_section)
  5123. maybe_text = 1;
  5124. else
  5125. maybe_text = 0;
  5126. #endif
  5127. if (!maybe_text)
  5128. as_warn (_(".end not in text section"));
  5129. if (!s3_cur_proc_ptr)
  5130. {
  5131. as_warn (_(".end directive without a preceding .ent directive."));
  5132. demand_empty_rest_of_line ();
  5133. return;
  5134. }
  5135. if (p != NULL)
  5136. {
  5137. gas_assert (S_GET_NAME (p));
  5138. if (strcmp (S_GET_NAME (p), S_GET_NAME (s3_cur_proc_ptr->isym)))
  5139. as_warn (_(".end symbol does not match .ent symbol."));
  5140. if (debug_type == DEBUG_STABS)
  5141. stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
  5142. }
  5143. else
  5144. as_warn (_(".end directive missing or unknown symbol"));
  5145. if ((s3_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
  5146. (s3_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
  5147. (s3_cur_proc_ptr->leaf == 0xdeafbeaf) ||
  5148. (s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
  5149. (s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf));
  5150. else
  5151. {
  5152. (void) frag_now_fix ();
  5153. gas_assert (s3_pdr_seg);
  5154. subseg_set (s3_pdr_seg, 0);
  5155. /* Write the symbol. */
  5156. exp.X_op = O_symbol;
  5157. exp.X_add_symbol = p;
  5158. exp.X_add_number = 0;
  5159. emit_expr (&exp, 4);
  5160. fragp = frag_more (7 * 4);
  5161. md_number_to_chars (fragp, (valueT) s3_cur_proc_ptr->reg_mask, 4);
  5162. md_number_to_chars (fragp + 4, (valueT) s3_cur_proc_ptr->reg_offset, 4);
  5163. md_number_to_chars (fragp + 8, (valueT) s3_cur_proc_ptr->fpreg_mask, 4);
  5164. md_number_to_chars (fragp + 12, (valueT) s3_cur_proc_ptr->leaf, 4);
  5165. md_number_to_chars (fragp + 16, (valueT) s3_cur_proc_ptr->frame_offset, 4);
  5166. md_number_to_chars (fragp + 20, (valueT) s3_cur_proc_ptr->frame_reg, 4);
  5167. md_number_to_chars (fragp + 24, (valueT) s3_cur_proc_ptr->pc_reg, 4);
  5168. subseg_set (saved_seg, saved_subseg);
  5169. }
  5170. s3_cur_proc_ptr = NULL;
  5171. }
  5172. /* Handle the .set pseudo-op. */
  5173. static void
  5174. s3_s_score_set (int x ATTRIBUTE_UNUSED)
  5175. {
  5176. int i = 0;
  5177. char name[s3_MAX_LITERAL_POOL_SIZE];
  5178. char * orig_ilp = input_line_pointer;
  5179. while (!is_end_of_line[(unsigned char)*input_line_pointer])
  5180. {
  5181. name[i] = (char) * input_line_pointer;
  5182. i++;
  5183. ++input_line_pointer;
  5184. }
  5185. name[i] = '\0';
  5186. if (strcmp (name, "nwarn") == 0)
  5187. {
  5188. s3_warn_fix_data_dependency = 0;
  5189. }
  5190. else if (strcmp (name, "fixdd") == 0)
  5191. {
  5192. s3_fix_data_dependency = 1;
  5193. }
  5194. else if (strcmp (name, "nofixdd") == 0)
  5195. {
  5196. s3_fix_data_dependency = 0;
  5197. }
  5198. else if (strcmp (name, "r1") == 0)
  5199. {
  5200. s3_nor1 = 0;
  5201. }
  5202. else if (strcmp (name, "nor1") == 0)
  5203. {
  5204. s3_nor1 = 1;
  5205. }
  5206. else if (strcmp (name, "optimize") == 0)
  5207. {
  5208. s3_g_opt = 1;
  5209. }
  5210. else if (strcmp (name, "volatile") == 0)
  5211. {
  5212. s3_g_opt = 0;
  5213. }
  5214. else if (strcmp (name, "pic") == 0)
  5215. {
  5216. s3_score_pic = s3_PIC;
  5217. }
  5218. else
  5219. {
  5220. input_line_pointer = orig_ilp;
  5221. s_set (0);
  5222. }
  5223. }
  5224. /* Handle the .cpload pseudo-op. This is used when generating s3_PIC code. It sets the
  5225. $gp register for the function based on the function address, which is in the register
  5226. named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
  5227. specially by the linker. The result is:
  5228. ldis gp, %hi(GP_DISP_LABEL)
  5229. ori gp, %low(GP_DISP_LABEL)
  5230. add gp, gp, .cpload argument
  5231. The .cpload argument is normally r29. */
  5232. static void
  5233. s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
  5234. {
  5235. int reg;
  5236. char insn_str[s3_MAX_LITERAL_POOL_SIZE];
  5237. /* If we are not generating s3_PIC code, .cpload is ignored. */
  5238. if (s3_score_pic == s3_NO_PIC)
  5239. {
  5240. s_ignore (0);
  5241. return;
  5242. }
  5243. if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  5244. return;
  5245. demand_empty_rest_of_line ();
  5246. sprintf (insn_str, "ld_i32hi r%d, %s", s3_GP, GP_DISP_LABEL);
  5247. if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
  5248. return;
  5249. sprintf (insn_str, "ld_i32lo r%d, %s", s3_GP, GP_DISP_LABEL);
  5250. if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
  5251. return;
  5252. sprintf (insn_str, "add r%d, r%d, r%d", s3_GP, s3_GP, reg);
  5253. if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
  5254. return;
  5255. }
  5256. /* Handle the .cprestore pseudo-op. This stores $gp into a given
  5257. offset from $sp. The offset is remembered, and after making a s3_PIC
  5258. call $gp is restored from that location. */
  5259. static void
  5260. s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
  5261. {
  5262. int reg;
  5263. int cprestore_offset;
  5264. char insn_str[s3_MAX_LITERAL_POOL_SIZE];
  5265. /* If we are not generating s3_PIC code, .cprestore is ignored. */
  5266. if (s3_score_pic == s3_NO_PIC)
  5267. {
  5268. s_ignore (0);
  5269. return;
  5270. }
  5271. if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
  5272. || s3_skip_past_comma (&input_line_pointer) == (int) s3_FAIL)
  5273. {
  5274. return;
  5275. }
  5276. cprestore_offset = get_absolute_expression ();
  5277. if (cprestore_offset <= 0x3fff)
  5278. {
  5279. sprintf (insn_str, "sw r%d, [r%d, %d]", s3_GP, reg, cprestore_offset);
  5280. if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
  5281. return;
  5282. }
  5283. else
  5284. {
  5285. int r1_bak;
  5286. r1_bak = s3_nor1;
  5287. s3_nor1 = 0;
  5288. sprintf (insn_str, "li r1, %d", cprestore_offset);
  5289. if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
  5290. return;
  5291. sprintf (insn_str, "add r1, r1, r%d", reg);
  5292. if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
  5293. return;
  5294. sprintf (insn_str, "sw r%d, [r1]", s3_GP);
  5295. if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
  5296. return;
  5297. s3_nor1 = r1_bak;
  5298. }
  5299. demand_empty_rest_of_line ();
  5300. }
  5301. /* Handle the .gpword pseudo-op. This is used when generating s3_PIC
  5302. code. It generates a 32 bit s3_GP relative reloc. */
  5303. static void
  5304. s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
  5305. {
  5306. expressionS ex;
  5307. char *p;
  5308. /* When not generating s3_PIC code, this is treated as .word. */
  5309. if (s3_score_pic == s3_NO_PIC)
  5310. {
  5311. cons (4);
  5312. return;
  5313. }
  5314. expression (&ex);
  5315. if (ex.X_op != O_symbol || ex.X_add_number != 0)
  5316. {
  5317. as_bad (_("Unsupported use of .gpword"));
  5318. ignore_rest_of_line ();
  5319. }
  5320. p = frag_more (4);
  5321. s3_md_number_to_chars (p, (valueT) 0, 4);
  5322. fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
  5323. demand_empty_rest_of_line ();
  5324. }
  5325. /* Handle the .cpadd pseudo-op. This is used when dealing with switch
  5326. tables in s3_PIC code. */
  5327. static void
  5328. s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
  5329. {
  5330. int reg;
  5331. char insn_str[s3_MAX_LITERAL_POOL_SIZE];
  5332. /* If we are not generating s3_PIC code, .cpload is ignored. */
  5333. if (s3_score_pic == s3_NO_PIC)
  5334. {
  5335. s_ignore (0);
  5336. return;
  5337. }
  5338. if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
  5339. {
  5340. return;
  5341. }
  5342. demand_empty_rest_of_line ();
  5343. /* Add $gp to the register named as an argument. */
  5344. sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s3_GP);
  5345. if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL)
  5346. return;
  5347. }
  5348. #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
  5349. #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
  5350. do \
  5351. { \
  5352. if ((SIZE) >= 8) \
  5353. (P2VAR) = 3; \
  5354. else if ((SIZE) >= 4) \
  5355. (P2VAR) = 2; \
  5356. else if ((SIZE) >= 2) \
  5357. (P2VAR) = 1; \
  5358. else \
  5359. (P2VAR) = 0; \
  5360. } \
  5361. while (0)
  5362. #endif
  5363. static void
  5364. s3_s_score_lcomm (int bytes_p)
  5365. {
  5366. char *name;
  5367. char c;
  5368. char *p;
  5369. int temp;
  5370. symbolS *symbolP;
  5371. segT current_seg = now_seg;
  5372. subsegT current_subseg = now_subseg;
  5373. const int max_alignment = 15;
  5374. int align = 0;
  5375. segT bss_seg = bss_section;
  5376. int needs_align = 0;
  5377. name = input_line_pointer;
  5378. c = get_symbol_end ();
  5379. p = input_line_pointer;
  5380. *p = c;
  5381. if (name == p)
  5382. {
  5383. as_bad (_("expected symbol name"));
  5384. discard_rest_of_line ();
  5385. return;
  5386. }
  5387. SKIP_WHITESPACE ();
  5388. /* Accept an optional comma after the name. The comma used to be
  5389. required, but Irix 5 cc does not generate it. */
  5390. if (*input_line_pointer == ',')
  5391. {
  5392. ++input_line_pointer;
  5393. SKIP_WHITESPACE ();
  5394. }
  5395. if (is_end_of_line[(unsigned char)*input_line_pointer])
  5396. {
  5397. as_bad (_("missing size expression"));
  5398. return;
  5399. }
  5400. if ((temp = get_absolute_expression ()) < 0)
  5401. {
  5402. as_warn (_("BSS length (%d) < 0 ignored"), temp);
  5403. ignore_rest_of_line ();
  5404. return;
  5405. }
  5406. #if defined (TC_SCORE)
  5407. if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
  5408. {
  5409. /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */
  5410. if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
  5411. {
  5412. bss_seg = subseg_new (".sbss", 1);
  5413. seg_info (bss_seg)->bss = 1;
  5414. #ifdef BFD_ASSEMBLER
  5415. if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
  5416. as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
  5417. #endif
  5418. }
  5419. }
  5420. #endif
  5421. SKIP_WHITESPACE ();
  5422. if (*input_line_pointer == ',')
  5423. {
  5424. ++input_line_pointer;
  5425. SKIP_WHITESPACE ();
  5426. if (is_end_of_line[(unsigned char)*input_line_pointer])
  5427. {
  5428. as_bad (_("missing alignment"));
  5429. return;
  5430. }
  5431. else
  5432. {
  5433. align = get_absolute_expression ();
  5434. needs_align = 1;
  5435. }
  5436. }
  5437. if (!needs_align)
  5438. {
  5439. TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
  5440. /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
  5441. if (align)
  5442. record_alignment (bss_seg, align);
  5443. }
  5444. if (needs_align)
  5445. {
  5446. if (bytes_p)
  5447. {
  5448. /* Convert to a power of 2. */
  5449. if (align != 0)
  5450. {
  5451. unsigned int i;
  5452. for (i = 0; align != 0; align >>= 1, ++i)
  5453. ;
  5454. align = i - 1;
  5455. }
  5456. }
  5457. if (align > max_alignment)
  5458. {
  5459. align = max_alignment;
  5460. as_warn (_("alignment too large; %d assumed"), align);
  5461. }
  5462. else if (align < 0)
  5463. {
  5464. align = 0;
  5465. as_warn (_("alignment negative; 0 assumed"));
  5466. }
  5467. record_alignment (bss_seg, align);
  5468. }
  5469. else
  5470. {
  5471. /* Assume some objects may require alignment on some systems. */
  5472. #if defined (TC_ALPHA) && ! defined (VMS)
  5473. if (temp > 1)
  5474. {
  5475. align = ffs (temp) - 1;
  5476. if (temp % (1 << align))
  5477. abort ();
  5478. }
  5479. #endif
  5480. }
  5481. *p = 0;
  5482. symbolP = symbol_find_or_make (name);
  5483. *p = c;
  5484. if (
  5485. #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
  5486. || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
  5487. #ifdef BFD_ASSEMBLER
  5488. (OUTPUT_FLAVOR != bfd_target_aout_flavour
  5489. || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
  5490. #else
  5491. (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
  5492. #endif
  5493. #endif
  5494. (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
  5495. {
  5496. char *pfrag;
  5497. subseg_set (bss_seg, 1);
  5498. if (align)
  5499. frag_align (align, 0, 0);
  5500. /* Detach from old frag. */
  5501. if (S_GET_SEGMENT (symbolP) == bss_seg)
  5502. symbol_get_frag (symbolP)->fr_symbol = NULL;
  5503. symbol_set_frag (symbolP, frag_now);
  5504. pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
  5505. *pfrag = 0;
  5506. S_SET_SEGMENT (symbolP, bss_seg);
  5507. #ifdef OBJ_COFF
  5508. /* The symbol may already have been created with a preceding
  5509. ".globl" directive -- be careful not to step on storage class
  5510. in that case. Otherwise, set it to static. */
  5511. if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
  5512. {
  5513. S_SET_STORAGE_CLASS (symbolP, C_STAT);
  5514. }
  5515. #endif /* OBJ_COFF */
  5516. #ifdef S_SET_SIZE
  5517. S_SET_SIZE (symbolP, temp);
  5518. #endif
  5519. }
  5520. else
  5521. as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
  5522. subseg_set (current_seg, current_subseg);
  5523. demand_empty_rest_of_line ();
  5524. }
  5525. static void
  5526. s3_insert_reg (const struct s3_reg_entry *r, struct hash_control *htab)
  5527. {
  5528. int i = 0;
  5529. int len = strlen (r->name) + 2;
  5530. char *buf = xmalloc (len);
  5531. char *buf2 = xmalloc (len);
  5532. strcpy (buf + i, r->name);
  5533. for (i = 0; buf[i]; i++)
  5534. {
  5535. buf2[i] = TOUPPER (buf[i]);
  5536. }
  5537. buf2[i] = '\0';
  5538. hash_insert (htab, buf, (void *) r);
  5539. hash_insert (htab, buf2, (void *) r);
  5540. }
  5541. static void
  5542. s3_build_reg_hsh (struct s3_reg_map *map)
  5543. {
  5544. const struct s3_reg_entry *r;
  5545. if ((map->htab = hash_new ()) == NULL)
  5546. {
  5547. as_fatal (_("virtual memory exhausted"));
  5548. }
  5549. for (r = map->names; r->name != NULL; r++)
  5550. {
  5551. s3_insert_reg (r, map->htab);
  5552. }
  5553. }
  5554. /* Iterate over the base tables to create the instruction patterns. */
  5555. static void
  5556. s3_build_score_ops_hsh (void)
  5557. {
  5558. unsigned int i;
  5559. static struct obstack insn_obstack;
  5560. obstack_begin (&insn_obstack, 4000);
  5561. for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++)
  5562. {
  5563. const struct s3_asm_opcode *insn = s3_score_insns + i;
  5564. unsigned len = strlen (insn->template_name);
  5565. struct s3_asm_opcode *new_opcode;
  5566. char *template_name;
  5567. new_opcode = (struct s3_asm_opcode *)
  5568. obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode));
  5569. template_name = (char *) obstack_alloc (& insn_obstack, len + 1);
  5570. strcpy (template_name, insn->template_name);
  5571. new_opcode->template_name = template_name;
  5572. new_opcode->parms = insn->parms;
  5573. new_opcode->value = insn->value;
  5574. new_opcode->relax_value = insn->relax_value;
  5575. new_opcode->type = insn->type;
  5576. new_opcode->bitmask = insn->bitmask;
  5577. hash_insert (s3_score_ops_hsh, new_opcode->template_name,
  5578. (void *) new_opcode);
  5579. }
  5580. }
  5581. static void
  5582. s3_build_dependency_insn_hsh (void)
  5583. {
  5584. unsigned int i;
  5585. static struct obstack dependency_obstack;
  5586. obstack_begin (&dependency_obstack, 4000);
  5587. for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++)
  5588. {
  5589. const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i;
  5590. unsigned len = strlen (tmp->insn_name);
  5591. struct s3_insn_to_dependency *new_i2n;
  5592. new_i2n = (struct s3_insn_to_dependency *)
  5593. obstack_alloc (&dependency_obstack,
  5594. sizeof (struct s3_insn_to_dependency));
  5595. new_i2n->insn_name = (char *) obstack_alloc (&dependency_obstack,
  5596. len + 1);
  5597. strcpy (new_i2n->insn_name, tmp->insn_name);
  5598. new_i2n->type = tmp->type;
  5599. hash_insert (s3_dependency_insn_hsh, new_i2n->insn_name,
  5600. (void *) new_i2n);
  5601. }
  5602. }
  5603. static void
  5604. s_score_bss (int ignore ATTRIBUTE_UNUSED)
  5605. {
  5606. if (score3)
  5607. return s3_s_score_bss (ignore);
  5608. else
  5609. return s7_s_score_bss (ignore);
  5610. }
  5611. static void
  5612. s_score_text (int ignore)
  5613. {
  5614. if (score3)
  5615. return s3_s_score_text (ignore);
  5616. else
  5617. return s7_s_score_text (ignore);
  5618. }
  5619. static void
  5620. s_section (int ignore)
  5621. {
  5622. if (score3)
  5623. return s3_score_s_section (ignore);
  5624. else
  5625. return s7_s_section (ignore);
  5626. }
  5627. static void
  5628. s_change_sec (int sec)
  5629. {
  5630. if (score3)
  5631. return s3_s_change_sec (sec);
  5632. else
  5633. return s7_s_change_sec (sec);
  5634. }
  5635. static void
  5636. s_score_mask (int reg_type ATTRIBUTE_UNUSED)
  5637. {
  5638. if (score3)
  5639. return s3_s_score_mask (reg_type);
  5640. else
  5641. return s7_s_score_mask (reg_type);
  5642. }
  5643. static void
  5644. s_score_ent (int aent)
  5645. {
  5646. if (score3)
  5647. return s3_s_score_ent (aent);
  5648. else
  5649. return s7_s_score_ent (aent);
  5650. }
  5651. static void
  5652. s_score_frame (int ignore ATTRIBUTE_UNUSED)
  5653. {
  5654. if (score3)
  5655. return s3_s_score_frame (ignore);
  5656. else
  5657. return s7_s_score_frame (ignore);
  5658. }
  5659. static void
  5660. s_score_end (int x ATTRIBUTE_UNUSED)
  5661. {
  5662. if (score3)
  5663. return s3_s_score_end (x);
  5664. else
  5665. return s7_s_score_end (x);
  5666. }
  5667. static void
  5668. s_score_set (int x ATTRIBUTE_UNUSED)
  5669. {
  5670. if (score3)
  5671. return s3_s_score_set (x);
  5672. else
  5673. return s7_s_score_set (x);
  5674. }
  5675. static void
  5676. s_score_cpload (int ignore ATTRIBUTE_UNUSED)
  5677. {
  5678. if (score3)
  5679. return s3_s_score_cpload (ignore);
  5680. else
  5681. return s7_s_score_cpload (ignore);
  5682. }
  5683. static void
  5684. s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
  5685. {
  5686. if (score3)
  5687. return s3_s_score_cprestore (ignore);
  5688. else
  5689. return s7_s_score_cprestore (ignore);
  5690. }
  5691. static void
  5692. s_score_gpword (int ignore ATTRIBUTE_UNUSED)
  5693. {
  5694. if (score3)
  5695. return s3_s_score_gpword (ignore);
  5696. else
  5697. return s7_s_score_gpword (ignore);
  5698. }
  5699. static void
  5700. s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
  5701. {
  5702. if (score3)
  5703. return s3_s_score_cpadd (ignore);
  5704. else
  5705. return s7_s_score_cpadd (ignore);
  5706. }
  5707. static void
  5708. s_score_lcomm (int bytes_p)
  5709. {
  5710. if (score3)
  5711. return s3_s_score_lcomm (bytes_p);
  5712. else
  5713. return s7_s_score_lcomm (bytes_p);
  5714. }
  5715. static void
  5716. s3_assemble (char *str)
  5717. {
  5718. know (str);
  5719. know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE);
  5720. memset (&s3_inst, '\0', sizeof (s3_inst));
  5721. if (s3_INSN_IS_PCE_P (str))
  5722. s3_parse_pce_inst (str);
  5723. else if (s3_INSN_IS_48_P (str))
  5724. s3_parse_48_inst (str, TRUE);
  5725. else
  5726. s3_parse_16_32_inst (str, TRUE);
  5727. if (s3_inst.error)
  5728. as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str);
  5729. }
  5730. static void
  5731. s3_operand (expressionS * exp)
  5732. {
  5733. if (s3_in_my_get_expression)
  5734. {
  5735. exp->X_op = O_illegal;
  5736. if (s3_inst.error == NULL)
  5737. {
  5738. s3_inst.error = _("bad expression");
  5739. }
  5740. }
  5741. }
  5742. static void
  5743. s3_begin (void)
  5744. {
  5745. unsigned int i;
  5746. segT seg;
  5747. subsegT subseg;
  5748. if ((s3_score_ops_hsh = hash_new ()) == NULL)
  5749. as_fatal (_("virtual memory exhausted"));
  5750. s3_build_score_ops_hsh ();
  5751. if ((s3_dependency_insn_hsh = hash_new ()) == NULL)
  5752. as_fatal (_("virtual memory exhausted"));
  5753. s3_build_dependency_insn_hsh ();
  5754. for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++)
  5755. s3_build_reg_hsh (s3_all_reg_maps + i);
  5756. /* Initialize dependency vector. */
  5757. s3_init_dependency_vector ();
  5758. bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
  5759. seg = now_seg;
  5760. subseg = now_subseg;
  5761. s3_pdr_seg = subseg_new (".pdr", (subsegT) 0);
  5762. (void)bfd_set_section_flags (stdoutput, s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
  5763. (void)bfd_set_section_alignment (stdoutput, s3_pdr_seg, 2);
  5764. subseg_set (seg, subseg);
  5765. if (s3_USE_GLOBAL_POINTER_OPT)
  5766. bfd_set_gp_size (stdoutput, s3_g_switch_value);
  5767. }
  5768. static void
  5769. s3_number_to_chars (char *buf, valueT val, int n)
  5770. {
  5771. if (target_big_endian)
  5772. number_to_chars_bigendian (buf, val, n);
  5773. else
  5774. number_to_chars_littleendian (buf, val, n);
  5775. }
  5776. static valueT
  5777. s3_normal_chars_to_number (char *buf, int n)
  5778. {
  5779. valueT result = 0;
  5780. unsigned char *where = (unsigned char *)buf;
  5781. if (target_big_endian)
  5782. {
  5783. while (n--)
  5784. {
  5785. result <<= 8;
  5786. result |= (*where++ & 255);
  5787. }
  5788. }
  5789. else
  5790. {
  5791. while (n--)
  5792. {
  5793. result <<= 8;
  5794. result |= (where[n] & 255);
  5795. }
  5796. }
  5797. return result;
  5798. }
  5799. static void
  5800. s3_number_to_chars_littleendian (void *p, valueT data, int n)
  5801. {
  5802. char *buf = (char *) p;
  5803. switch (n)
  5804. {
  5805. case 4:
  5806. md_number_to_chars (buf, data >> 16, 2);
  5807. md_number_to_chars (buf + 2, data, 2);
  5808. break;
  5809. case 6:
  5810. md_number_to_chars (buf, data >> 32, 2);
  5811. md_number_to_chars (buf + 2, data >> 16, 2);
  5812. md_number_to_chars (buf + 4, data, 2);
  5813. break;
  5814. default:
  5815. /* Error routine. */
  5816. as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
  5817. break;
  5818. }
  5819. }
  5820. static valueT
  5821. s3_chars_to_number_littleendian (const void *p, int n)
  5822. {
  5823. char *buf = (char *) p;
  5824. valueT result = 0;
  5825. switch (n)
  5826. {
  5827. case 4:
  5828. result = s3_normal_chars_to_number (buf, 2) << 16;
  5829. result |= s3_normal_chars_to_number (buf + 2, 2);
  5830. break;
  5831. case 6:
  5832. result = s3_normal_chars_to_number (buf, 2) << 32;
  5833. result |= s3_normal_chars_to_number (buf + 2, 2) << 16;
  5834. result |= s3_normal_chars_to_number (buf + 4, 2);
  5835. break;
  5836. default:
  5837. /* Error routine. */
  5838. as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6"));
  5839. break;
  5840. }
  5841. return result;
  5842. }
  5843. static void
  5844. s3_md_number_to_chars (char *buf, valueT val, int n)
  5845. {
  5846. if (!target_big_endian && n >= 4)
  5847. s3_number_to_chars_littleendian (buf, val, n);
  5848. else
  5849. md_number_to_chars (buf, val, n);
  5850. }
  5851. static valueT
  5852. s3_md_chars_to_number (char *buf, int n)
  5853. {
  5854. valueT result = 0;
  5855. if (!target_big_endian && n >= 4)
  5856. result = s3_chars_to_number_littleendian (buf, n);
  5857. else
  5858. result = s3_normal_chars_to_number (buf, n);
  5859. return result;
  5860. }
  5861. static char *
  5862. s3_atof (int type, char *litP, int *sizeP)
  5863. {
  5864. int prec;
  5865. LITTLENUM_TYPE words[s3_MAX_LITTLENUMS];
  5866. char *t;
  5867. int i;
  5868. switch (type)
  5869. {
  5870. case 'f':
  5871. case 'F':
  5872. case 's':
  5873. case 'S':
  5874. prec = 2;
  5875. break;
  5876. case 'd':
  5877. case 'D':
  5878. case 'r':
  5879. case 'R':
  5880. prec = 4;
  5881. break;
  5882. case 'x':
  5883. case 'X':
  5884. case 'p':
  5885. case 'P':
  5886. prec = 6;
  5887. break;
  5888. default:
  5889. *sizeP = 0;
  5890. return _("bad call to MD_ATOF()");
  5891. }
  5892. t = atof_ieee (input_line_pointer, type, words);
  5893. if (t)
  5894. input_line_pointer = t;
  5895. *sizeP = prec * 2;
  5896. if (target_big_endian)
  5897. {
  5898. for (i = 0; i < prec; i++)
  5899. {
  5900. s3_md_number_to_chars (litP, (valueT) words[i], 2);
  5901. litP += 2;
  5902. }
  5903. }
  5904. else
  5905. {
  5906. for (i = 0; i < prec; i += 2)
  5907. {
  5908. s3_md_number_to_chars (litP, (valueT) words[i + 1], 2);
  5909. s3_md_number_to_chars (litP + 2, (valueT) words[i], 2);
  5910. litP += 4;
  5911. }
  5912. }
  5913. return 0;
  5914. }
  5915. static void
  5916. s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
  5917. {
  5918. know (fragp->insn_addr <= s3_RELAX_PAD_BYTE);
  5919. }
  5920. static void
  5921. s3_validate_fix (fixS *fixP)
  5922. {
  5923. fixP->fx_where += fixP->fx_frag->insn_addr;
  5924. }
  5925. static int
  5926. s3_force_relocation (struct fix *fixp)
  5927. {
  5928. int retval = 0;
  5929. if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
  5930. || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
  5931. || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
  5932. || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
  5933. || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
  5934. || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH
  5935. || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP)
  5936. {
  5937. retval = 1;
  5938. }
  5939. return retval;
  5940. }
  5941. static bfd_boolean
  5942. s3_fix_adjustable (fixS * fixP)
  5943. {
  5944. if (fixP->fx_addsy == NULL)
  5945. {
  5946. return 1;
  5947. }
  5948. else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
  5949. && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
  5950. {
  5951. return 0;
  5952. }
  5953. else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
  5954. || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
  5955. || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
  5956. || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
  5957. {
  5958. return 0;
  5959. }
  5960. return 1;
  5961. }
  5962. static void
  5963. s3_elf_final_processing (void)
  5964. {
  5965. unsigned long val = 0;
  5966. if (score3)
  5967. val = E_SCORE_MACH_SCORE3;
  5968. else if (score7)
  5969. val = E_SCORE_MACH_SCORE7;
  5970. elf_elfheader (stdoutput)->e_machine = EM_SCORE;
  5971. elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
  5972. elf_elfheader (stdoutput)->e_flags |= val;
  5973. if (s3_fix_data_dependency == 1)
  5974. {
  5975. elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
  5976. }
  5977. if (s3_score_pic == s3_PIC)
  5978. {
  5979. elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
  5980. }
  5981. }
  5982. static int
  5983. s3_judge_size_before_relax (fragS * fragp, asection *sec)
  5984. {
  5985. int change = 0;
  5986. if (s3_score_pic == s3_NO_PIC)
  5987. change = s3_nopic_need_relax (fragp->fr_symbol, 0);
  5988. else
  5989. change = s3_pic_need_relax (fragp->fr_symbol, sec);
  5990. if (change == 1)
  5991. {
  5992. /* Only at the first time determining whether s3_GP instruction relax should be done,
  5993. return the difference between insntruction size and instruction relax size. */
  5994. if (fragp->fr_opcode == NULL)
  5995. {
  5996. fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype);
  5997. fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
  5998. return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype);
  5999. }
  6000. }
  6001. return 0;
  6002. }
  6003. static int
  6004. s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
  6005. {
  6006. if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
  6007. || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
  6008. return s3_judge_size_before_relax (fragp, sec);
  6009. return 0;
  6010. }
  6011. static int
  6012. s3_relax_branch_inst32 (fragS * fragp)
  6013. {
  6014. fragp->fr_opcode = NULL;
  6015. return 0;
  6016. }
  6017. static int
  6018. s3_relax_branch_inst16 (fragS * fragp)
  6019. {
  6020. int relaxable_p = 0;
  6021. int frag_addr = fragp->fr_address + fragp->insn_addr;
  6022. addressT symbol_address = 0;
  6023. symbolS *s;
  6024. offsetT offset;
  6025. long value;
  6026. unsigned long inst_value;
  6027. relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
  6028. s = fragp->fr_symbol;
  6029. if (s == NULL)
  6030. frag_addr = 0;
  6031. else
  6032. {
  6033. if (s->bsym != 0)
  6034. symbol_address = (addressT) s->sy_frag->fr_address;
  6035. }
  6036. inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE);
  6037. offset = (inst_value & 0x1ff) << 1;
  6038. if ((offset & 0x200) == 0x200)
  6039. offset |= 0xfffffc00;
  6040. value = offset + symbol_address - frag_addr;
  6041. if (relaxable_p
  6042. && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
  6043. && fragp->fr_fix == 2
  6044. && (s->bsym != NULL)
  6045. && (S_IS_DEFINED (s)
  6046. && !S_IS_COMMON (s)
  6047. && !S_IS_EXTERNAL (s)))
  6048. {
  6049. /* Relax branch 32 to branch 16. */
  6050. fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
  6051. fragp->fr_fix = 4;
  6052. return 2;
  6053. }
  6054. else
  6055. return 0;
  6056. }
  6057. static int
  6058. s3_relax_cmpbranch_inst32 (fragS * fragp)
  6059. {
  6060. int relaxable_p = 0;
  6061. symbolS *s;
  6062. /* For sign bit. */
  6063. long offset;
  6064. long frag_addr = fragp->fr_address + fragp->insn_addr;
  6065. long symbol_address = 0;
  6066. long value;
  6067. unsigned long inst_value;
  6068. relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
  6069. s = fragp->fr_symbol;
  6070. if (s == NULL)
  6071. frag_addr = 0;
  6072. else
  6073. {
  6074. if (s->bsym != 0)
  6075. symbol_address = (addressT) s->sy_frag->fr_address;
  6076. }
  6077. inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE);
  6078. offset = (inst_value & 0x1)
  6079. | (((inst_value >> 7) & 0x7) << 1)
  6080. | (((inst_value >> 21) & 0x1f) << 4);
  6081. offset <<= 1;
  6082. if ((offset & 0x200) == 0x200)
  6083. offset |= 0xfffffe00;
  6084. value = offset + symbol_address - frag_addr;
  6085. /* change the order of judging rule is because
  6086. 1.not defined symbol or common sysbol or external symbol will change
  6087. bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode
  6088. 2.if the flow is as before : it will results to recursive loop
  6089. */
  6090. if (fragp->fr_fix == 6)
  6091. {
  6092. /* Have already relaxed! Just return 0 to terminate the loop. */
  6093. return 0;
  6094. }
  6095. /* need to translate when extern or not defind or common sysbol */
  6096. else if ((relaxable_p
  6097. && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00))
  6098. && fragp->fr_fix == 4
  6099. && (s->bsym != NULL))
  6100. || !S_IS_DEFINED (s)
  6101. ||S_IS_COMMON (s)
  6102. ||S_IS_EXTERNAL (s))
  6103. {
  6104. fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
  6105. fragp->fr_fix = 6;
  6106. return 2;
  6107. }
  6108. else
  6109. {
  6110. /* Never relax. Modify fr_opcode to NULL to verify it's value in
  6111. md_apply_fix. */
  6112. fragp->fr_opcode = NULL;
  6113. return 0;
  6114. }
  6115. }
  6116. static int
  6117. s3_relax_other_inst32 (fragS * fragp)
  6118. {
  6119. int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype);
  6120. if (relaxable_p
  6121. && fragp->fr_fix == 4)
  6122. {
  6123. fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
  6124. fragp->fr_fix = 2;
  6125. return -2;
  6126. }
  6127. else
  6128. return 0;
  6129. }
  6130. static int
  6131. s3_relax_gp_and_pic_inst32 (void)
  6132. {
  6133. /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC
  6134. instructions. We don't change relax size here. */
  6135. return 0;
  6136. }
  6137. static int
  6138. s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
  6139. {
  6140. int grows = 0;
  6141. int adjust_align_p = 0;
  6142. /* If the instruction address is odd, make it half word align first. */
  6143. if ((fragp->fr_address) % 2 != 0)
  6144. {
  6145. if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
  6146. {
  6147. fragp->insn_addr = 1;
  6148. grows += 1;
  6149. adjust_align_p = 1;
  6150. }
  6151. }
  6152. switch (s3_RELAX_TYPE (fragp->fr_subtype))
  6153. {
  6154. case PC_DISP19div2:
  6155. grows += s3_relax_branch_inst32 (fragp);
  6156. break;
  6157. case PC_DISP8div2:
  6158. grows += s3_relax_branch_inst16 (fragp);
  6159. break;
  6160. case Insn_BCMP :
  6161. grows += s3_relax_cmpbranch_inst32 (fragp);
  6162. break;
  6163. case Insn_GP:
  6164. case Insn_PIC:
  6165. grows += s3_relax_gp_and_pic_inst32 ();
  6166. break;
  6167. default:
  6168. grows += s3_relax_other_inst32 (fragp);
  6169. break;
  6170. }
  6171. /* newly added */
  6172. if (adjust_align_p && fragp->insn_addr)
  6173. {
  6174. fragp->fr_fix += fragp->insn_addr;
  6175. }
  6176. return grows;
  6177. }
  6178. static void
  6179. s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
  6180. {
  6181. int r_old;
  6182. int r_new;
  6183. char backup[20];
  6184. fixS *fixp;
  6185. r_old = s3_RELAX_OLD (fragp->fr_subtype);
  6186. r_new = s3_RELAX_NEW (fragp->fr_subtype);
  6187. /* fragp->fr_opcode indicates whether this frag should be relaxed. */
  6188. if (fragp->fr_opcode == NULL)
  6189. {
  6190. memcpy (backup, fragp->fr_literal, r_old);
  6191. fragp->fr_fix = r_old;
  6192. }
  6193. else
  6194. {
  6195. memcpy (backup, fragp->fr_literal + r_old, r_new);
  6196. fragp->fr_fix = r_new;
  6197. }
  6198. fixp = fragp->tc_frag_data.fixp;
  6199. while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
  6200. {
  6201. if (fragp->fr_opcode)
  6202. fixp->fx_done = 1;
  6203. fixp = fixp->fx_next;
  6204. }
  6205. while (fixp && fixp->fx_frag == fragp)
  6206. {
  6207. if (fragp->fr_opcode)
  6208. fixp->fx_where -= r_old + fragp->insn_addr;
  6209. else
  6210. fixp->fx_done = 1;
  6211. fixp = fixp->fx_next;
  6212. }
  6213. if (fragp->insn_addr)
  6214. {
  6215. s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
  6216. }
  6217. memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
  6218. fragp->fr_fix += fragp->insn_addr;
  6219. }
  6220. static long
  6221. s3_pcrel_from (fixS * fixP)
  6222. {
  6223. long retval = 0;
  6224. if (fixP->fx_addsy
  6225. && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
  6226. && (fixP->fx_subsy == NULL))
  6227. {
  6228. retval = 0;
  6229. }
  6230. else
  6231. {
  6232. retval = fixP->fx_where + fixP->fx_frag->fr_address;
  6233. }
  6234. return retval;
  6235. }
  6236. static valueT
  6237. s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
  6238. {
  6239. int align = bfd_get_section_alignment (stdoutput, segment);
  6240. return ((size + (1 << align) - 1) & (-1 << align));
  6241. }
  6242. static void
  6243. s3_apply_fix (fixS *fixP, valueT *valP, segT seg)
  6244. {
  6245. offsetT value = *valP;
  6246. offsetT newval;
  6247. offsetT content;
  6248. unsigned short HI, LO;
  6249. char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
  6250. gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
  6251. if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
  6252. {
  6253. if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
  6254. fixP->fx_done = 1;
  6255. }
  6256. /* If this symbol is in a different section then we need to leave it for
  6257. the linker to deal with. Unfortunately, md_pcrel_from can't tell,
  6258. so we have to undo it's effects here. */
  6259. if (fixP->fx_pcrel)
  6260. {
  6261. if (fixP->fx_addsy != NULL
  6262. && S_IS_DEFINED (fixP->fx_addsy)
  6263. && S_GET_SEGMENT (fixP->fx_addsy) != seg)
  6264. value += md_pcrel_from (fixP);
  6265. }
  6266. /* Remember value for emit_reloc. */
  6267. fixP->fx_addnumber = value;
  6268. switch (fixP->fx_r_type)
  6269. {
  6270. case BFD_RELOC_HI16_S:
  6271. if (fixP->fx_done) /* For la rd, imm32. */
  6272. {
  6273. newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6274. HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */
  6275. newval |= (HI & 0x3fff) << 1;
  6276. newval |= ((HI >> 14) & 0x3) << 16;
  6277. s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
  6278. }
  6279. break;
  6280. case BFD_RELOC_LO16:
  6281. if (fixP->fx_done) /* For la rd, imm32. */
  6282. {
  6283. newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6284. LO = (value) & 0xffff;
  6285. newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */
  6286. newval |= ((LO >> 14) & 0x3) << 16;
  6287. s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
  6288. }
  6289. break;
  6290. case BFD_RELOC_SCORE_JMP:
  6291. {
  6292. content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6293. value = fixP->fx_offset;
  6294. content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
  6295. s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
  6296. }
  6297. break;
  6298. case BFD_RELOC_SCORE_IMM30:
  6299. {
  6300. content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
  6301. value = fixP->fx_offset;
  6302. value >>= 2;
  6303. content = (content & ~0x7f7fff7f80LL)
  6304. | (((value & 0xff) >> 0) << 7)
  6305. | (((value & 0x7fff00) >> 8) << 16)
  6306. | (((value & 0x3f800000) >> 23) << 32);
  6307. s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
  6308. break;
  6309. }
  6310. case BFD_RELOC_SCORE_IMM32:
  6311. {
  6312. content = s3_md_chars_to_number (buf, s3_INSN48_SIZE);
  6313. value = fixP->fx_offset;
  6314. content = (content & ~0x7f7fff7fe0LL)
  6315. | ((value & 0x3ff) << 5)
  6316. | (((value >> 10) & 0x7fff) << 16)
  6317. | (((value >> 25) & 0x7f) << 32);
  6318. s3_md_number_to_chars (buf, content, s3_INSN48_SIZE);
  6319. break;
  6320. }
  6321. case BFD_RELOC_SCORE_BRANCH:
  6322. if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
  6323. value = fixP->fx_offset;
  6324. else
  6325. fixP->fx_done = 1;
  6326. content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6327. /* Don't check c-bit. */
  6328. if (fixP->fx_frag->fr_opcode != 0)
  6329. {
  6330. if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
  6331. {
  6332. as_bad_where (fixP->fx_file, fixP->fx_line,
  6333. _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9]"), (unsigned int)value);
  6334. return;
  6335. }
  6336. content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
  6337. content &= 0xfe00;
  6338. content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
  6339. s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
  6340. fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
  6341. fixP->fx_size = 2;
  6342. }
  6343. else
  6344. {
  6345. if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
  6346. {
  6347. as_bad_where (fixP->fx_file, fixP->fx_line,
  6348. _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
  6349. return;
  6350. }
  6351. content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6352. content &= 0xfc00fc01;
  6353. content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
  6354. s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
  6355. }
  6356. break;
  6357. case BFD_RELOC_SCORE16_JMP:
  6358. content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
  6359. content &= 0xf001;
  6360. value = fixP->fx_offset & 0xfff;
  6361. content = (content & 0xfc01) | (value & 0xffe);
  6362. s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
  6363. break;
  6364. case BFD_RELOC_SCORE16_BRANCH:
  6365. content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6366. /* Don't check c-bit. */
  6367. if (fixP->fx_frag->fr_opcode != 0)
  6368. {
  6369. if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
  6370. (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
  6371. value = fixP->fx_offset;
  6372. else
  6373. fixP->fx_done = 1;
  6374. if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
  6375. {
  6376. as_bad_where (fixP->fx_file, fixP->fx_line,
  6377. _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
  6378. return;
  6379. }
  6380. content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6381. content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
  6382. s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
  6383. fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
  6384. fixP->fx_size = 4;
  6385. break;
  6386. }
  6387. else
  6388. {
  6389. /* In differnt section. */
  6390. if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
  6391. (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
  6392. value = fixP->fx_offset;
  6393. else
  6394. fixP->fx_done = 1;
  6395. if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
  6396. {
  6397. as_bad_where (fixP->fx_file, fixP->fx_line,
  6398. _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9]"), (unsigned int)value);
  6399. return;
  6400. }
  6401. content = s3_md_chars_to_number (buf, s3_INSN16_SIZE);
  6402. content = (content & 0xfe00) | ((value >> 1) & 0x1ff);
  6403. s3_md_number_to_chars (buf, content, s3_INSN16_SIZE);
  6404. break;
  6405. }
  6406. break;
  6407. case BFD_RELOC_SCORE_BCMP:
  6408. if (fixP->fx_frag->fr_opcode != 0)
  6409. {
  6410. char *buf_ptr = buf;
  6411. buf_ptr += 2;
  6412. if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
  6413. value = fixP->fx_offset;
  6414. else
  6415. fixP->fx_done = 1;
  6416. /* NOTE!!!
  6417. bcmp -> cmp! and branch, so value -= 2. */
  6418. value -= 2;
  6419. if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
  6420. {
  6421. as_bad_where (fixP->fx_file, fixP->fx_line,
  6422. _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
  6423. return;
  6424. }
  6425. content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE);
  6426. content &= 0xfc00fc01;
  6427. content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
  6428. s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE);
  6429. /* change relocation type to BFD_RELOC_SCORE_BRANCH */
  6430. fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
  6431. fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */
  6432. break;
  6433. }
  6434. else
  6435. {
  6436. if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
  6437. value = fixP->fx_offset;
  6438. else
  6439. fixP->fx_done = 1;
  6440. content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6441. if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00)
  6442. {
  6443. as_bad_where (fixP->fx_file, fixP->fx_line,
  6444. _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9]"), (unsigned int)value);
  6445. return;
  6446. }
  6447. value >>= 1;
  6448. content &= ~0x03e00381;
  6449. content = content
  6450. | (value & 0x1)
  6451. | (((value & 0xe) >> 1) << 7)
  6452. | (((value & 0x1f0) >> 4) << 21);
  6453. s3_md_number_to_chars (buf, content, s3_INSN_SIZE);
  6454. break;
  6455. }
  6456. case BFD_RELOC_8:
  6457. if (fixP->fx_done || fixP->fx_pcrel)
  6458. s3_md_number_to_chars (buf, value, 1);
  6459. #ifdef OBJ_ELF
  6460. else
  6461. {
  6462. value = fixP->fx_offset;
  6463. s3_md_number_to_chars (buf, value, 1);
  6464. }
  6465. #endif
  6466. break;
  6467. case BFD_RELOC_16:
  6468. if (fixP->fx_done || fixP->fx_pcrel)
  6469. s3_md_number_to_chars (buf, value, 2);
  6470. #ifdef OBJ_ELF
  6471. else
  6472. {
  6473. value = fixP->fx_offset;
  6474. s3_md_number_to_chars (buf, value, 2);
  6475. }
  6476. #endif
  6477. break;
  6478. case BFD_RELOC_RVA:
  6479. case BFD_RELOC_32:
  6480. if (fixP->fx_done || fixP->fx_pcrel)
  6481. md_number_to_chars (buf, value, 4);
  6482. #ifdef OBJ_ELF
  6483. else
  6484. {
  6485. value = fixP->fx_offset;
  6486. md_number_to_chars (buf, value, 4);
  6487. }
  6488. #endif
  6489. break;
  6490. case BFD_RELOC_VTABLE_INHERIT:
  6491. fixP->fx_done = 0;
  6492. if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
  6493. S_SET_WEAK (fixP->fx_addsy);
  6494. break;
  6495. case BFD_RELOC_VTABLE_ENTRY:
  6496. fixP->fx_done = 0;
  6497. break;
  6498. case BFD_RELOC_SCORE_GPREL15:
  6499. content = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6500. /* c-bit. */
  6501. if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000))
  6502. fixP->fx_r_type = BFD_RELOC_NONE;
  6503. fixP->fx_done = 0;
  6504. break;
  6505. case BFD_RELOC_SCORE_GOT15:
  6506. case BFD_RELOC_SCORE_DUMMY_HI16:
  6507. case BFD_RELOC_SCORE_GOT_LO16:
  6508. case BFD_RELOC_SCORE_CALL15:
  6509. case BFD_RELOC_GPREL32:
  6510. break;
  6511. case BFD_RELOC_NONE:
  6512. default:
  6513. as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
  6514. }
  6515. }
  6516. static arelent **
  6517. s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
  6518. {
  6519. static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
  6520. arelent *reloc;
  6521. bfd_reloc_code_real_type code;
  6522. char *type;
  6523. reloc = retval[0] = xmalloc (sizeof (arelent));
  6524. retval[1] = NULL;
  6525. reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
  6526. *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  6527. reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  6528. reloc->addend = fixp->fx_offset;
  6529. /* If this is a variant frag, we may need to adjust the existing
  6530. reloc and generate a new one. */
  6531. if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
  6532. {
  6533. /* Update instruction imm bit. */
  6534. offsetT newval;
  6535. unsigned short off;
  6536. char *buf;
  6537. buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
  6538. newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6539. off = fixp->fx_offset >> 16;
  6540. newval |= (off & 0x3fff) << 1;
  6541. newval |= ((off >> 14) & 0x3) << 16;
  6542. s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
  6543. buf += s3_INSN_SIZE;
  6544. newval = s3_md_chars_to_number (buf, s3_INSN_SIZE);
  6545. off = fixp->fx_offset & 0xffff;
  6546. newval |= ((off & 0x3fff) << 1);
  6547. newval |= (((off >> 14) & 0x3) << 16);
  6548. s3_md_number_to_chars (buf, newval, s3_INSN_SIZE);
  6549. retval[1] = xmalloc (sizeof (arelent));
  6550. retval[2] = NULL;
  6551. retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
  6552. *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  6553. retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
  6554. retval[1]->addend = 0;
  6555. retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
  6556. gas_assert (retval[1]->howto != NULL);
  6557. fixp->fx_r_type = BFD_RELOC_HI16_S;
  6558. }
  6559. code = fixp->fx_r_type;
  6560. switch (fixp->fx_r_type)
  6561. {
  6562. case BFD_RELOC_32:
  6563. if (fixp->fx_pcrel)
  6564. {
  6565. code = BFD_RELOC_32_PCREL;
  6566. break;
  6567. }
  6568. case BFD_RELOC_HI16_S:
  6569. case BFD_RELOC_LO16:
  6570. case BFD_RELOC_SCORE_JMP:
  6571. case BFD_RELOC_SCORE_BRANCH:
  6572. case BFD_RELOC_SCORE16_JMP:
  6573. case BFD_RELOC_SCORE16_BRANCH:
  6574. case BFD_RELOC_SCORE_BCMP:
  6575. case BFD_RELOC_VTABLE_ENTRY:
  6576. case BFD_RELOC_VTABLE_INHERIT:
  6577. case BFD_RELOC_SCORE_GPREL15:
  6578. case BFD_RELOC_SCORE_GOT15:
  6579. case BFD_RELOC_SCORE_DUMMY_HI16:
  6580. case BFD_RELOC_SCORE_GOT_LO16:
  6581. case BFD_RELOC_SCORE_CALL15:
  6582. case BFD_RELOC_GPREL32:
  6583. case BFD_RELOC_NONE:
  6584. case BFD_RELOC_SCORE_IMM30:
  6585. case BFD_RELOC_SCORE_IMM32:
  6586. code = fixp->fx_r_type;
  6587. break;
  6588. default:
  6589. type = _("<unknown>");
  6590. as_bad_where (fixp->fx_file, fixp->fx_line,
  6591. _("cannot represent %s relocation in this object file format"), type);
  6592. return NULL;
  6593. }
  6594. reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
  6595. if (reloc->howto == NULL)
  6596. {
  6597. as_bad_where (fixp->fx_file, fixp->fx_line,
  6598. _("cannot represent %s relocation in this object file format1"),
  6599. bfd_get_reloc_code_name (code));
  6600. return NULL;
  6601. }
  6602. /* HACK: Since arm ELF uses Rel instead of Rela, encode the
  6603. vtable entry to be used in the relocation's section offset. */
  6604. if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
  6605. reloc->address = fixp->fx_offset;
  6606. return retval;
  6607. }
  6608. void
  6609. md_assemble (char *str)
  6610. {
  6611. if (score3)
  6612. s3_assemble (str);
  6613. else
  6614. s7_assemble (str);
  6615. }
  6616. /* We handle all bad expressions here, so that we can report the faulty
  6617. instruction in the error message. */
  6618. void
  6619. md_operand (expressionS * exp)
  6620. {
  6621. if (score3)
  6622. s3_operand (exp);
  6623. else
  6624. s7_operand (exp);
  6625. }
  6626. /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
  6627. for use in the a.out file, and stores them in the array pointed to by buf.
  6628. This knows about the endian-ness of the target machine and does
  6629. THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
  6630. 2 (short) and 4 (long) Floating numbers are put out as a series of
  6631. LITTLENUMS (shorts, here at least). */
  6632. void
  6633. md_number_to_chars (char *buf, valueT val, int n)
  6634. {
  6635. if (score3)
  6636. s3_number_to_chars (buf, val, n);
  6637. else
  6638. s7_number_to_chars (buf, val, n);
  6639. }
  6640. /* Turn a string in input_line_pointer into a floating point constant
  6641. of type TYPE, and store the appropriate bytes in *LITP. The number
  6642. of LITTLENUMS emitted is stored in *SIZEP. An error message is
  6643. returned, or NULL on OK.
  6644. Note that fp constants aren't represent in the normal way on the ARM.
  6645. In big endian mode, things are as expected. However, in little endian
  6646. mode fp constants are big-endian word-wise, and little-endian byte-wise
  6647. within the words. For example, (double) 1.1 in big endian mode is
  6648. the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
  6649. the byte sequence 99 99 f1 3f 9a 99 99 99. */
  6650. char *
  6651. md_atof (int type, char *litP, int *sizeP)
  6652. {
  6653. if (score3)
  6654. return s3_atof (type, litP, sizeP);
  6655. else
  6656. return s7_atof (type, litP, sizeP);
  6657. }
  6658. void
  6659. score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
  6660. {
  6661. if (score3)
  6662. s3_frag_check (fragp);
  6663. else
  6664. s7_frag_check (fragp);
  6665. }
  6666. /* Implementation of TC_VALIDATE_FIX.
  6667. Called before md_apply_fix() and after md_convert_frag(). */
  6668. void
  6669. score_validate_fix (fixS *fixP)
  6670. {
  6671. if (score3)
  6672. s3_validate_fix (fixP);
  6673. else
  6674. s7_validate_fix (fixP);
  6675. }
  6676. int
  6677. score_force_relocation (struct fix *fixp)
  6678. {
  6679. if (score3)
  6680. return s3_force_relocation (fixp);
  6681. else
  6682. return s7_force_relocation (fixp);
  6683. }
  6684. /* Implementation of md_frag_check.
  6685. Called after md_convert_frag(). */
  6686. bfd_boolean
  6687. score_fix_adjustable (fixS * fixP)
  6688. {
  6689. if (score3)
  6690. return s3_fix_adjustable (fixP);
  6691. else
  6692. return s7_fix_adjustable (fixP);
  6693. }
  6694. void
  6695. score_elf_final_processing (void)
  6696. {
  6697. if (score3)
  6698. s3_elf_final_processing ();
  6699. else
  6700. s7_elf_final_processing ();
  6701. }
  6702. /* In this function, we determine whether s3_GP instruction should do relaxation,
  6703. for the label being against was known now.
  6704. Doing this here but not in md_relax_frag() can induce iteration times
  6705. in stage of doing relax. */
  6706. int
  6707. md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
  6708. {
  6709. if (score3)
  6710. return s3_estimate_size_before_relax (fragp, sec);
  6711. else
  6712. return s7_estimate_size_before_relax (fragp, sec);
  6713. }
  6714. int
  6715. score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
  6716. {
  6717. if (score3)
  6718. return s3_relax_frag (sec, fragp, stretch);
  6719. else
  6720. return s7_relax_frag (sec, fragp, stretch);
  6721. }
  6722. void
  6723. md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
  6724. {
  6725. if (score3)
  6726. return s3_convert_frag (abfd, sec, fragp);
  6727. else
  6728. return s7_convert_frag (abfd, sec, fragp);
  6729. }
  6730. long
  6731. md_pcrel_from (fixS * fixP)
  6732. {
  6733. if (score3)
  6734. return s3_pcrel_from (fixP);
  6735. else
  6736. return s7_pcrel_from (fixP);
  6737. }
  6738. /* Round up a section size to the appropriate boundary. */
  6739. valueT
  6740. md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
  6741. {
  6742. if (score3)
  6743. return s3_section_align (segment, size);
  6744. else
  6745. return s7_section_align (segment, size);
  6746. }
  6747. void
  6748. md_apply_fix (fixS *fixP, valueT *valP, segT seg)
  6749. {
  6750. if (score3)
  6751. return s3_apply_fix (fixP, valP, seg);
  6752. else
  6753. return s7_apply_fix (fixP, valP, seg);
  6754. }
  6755. /* Translate internal representation of relocation info to BFD target format. */
  6756. arelent **
  6757. tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
  6758. {
  6759. if (score3)
  6760. return s3_gen_reloc (section, fixp);
  6761. else
  6762. return s7_gen_reloc (section, fixp);
  6763. }
  6764. void
  6765. md_begin (void)
  6766. {
  6767. s3_begin ();
  6768. s7_begin ();
  6769. }
  6770. static void
  6771. score_set_mach (const char *arg)
  6772. {
  6773. if (strcmp (arg, MARCH_SCORE3) == 0)
  6774. {
  6775. score3 = 1;
  6776. score7 = 0;
  6777. s3_score3d = 1;
  6778. }
  6779. else if (strcmp (arg, MARCH_SCORE7) == 0)
  6780. {
  6781. score3 = 0;
  6782. score7 = 1;
  6783. s7_score7d = 1;
  6784. s7_university_version = 0;
  6785. s7_vector_size = s7_SCORE7_PIPELINE;
  6786. }
  6787. else if (strcmp (arg, MARCH_SCORE5) == 0)
  6788. {
  6789. score3 = 0;
  6790. score7 = 1;
  6791. s7_score7d = 1;
  6792. s7_university_version = 0;
  6793. s7_vector_size = s7_SCORE5_PIPELINE;
  6794. }
  6795. else if (strcmp (arg, MARCH_SCORE5U) == 0)
  6796. {
  6797. score3 = 0;
  6798. score7 = 1;
  6799. s7_score7d = 1;
  6800. s7_university_version = 1;
  6801. s7_vector_size = s7_SCORE5_PIPELINE;
  6802. }
  6803. else
  6804. {
  6805. as_bad (_("unknown architecture `%s'\n"), arg);
  6806. }
  6807. }
  6808. int
  6809. md_parse_option (int c, char *arg)
  6810. {
  6811. switch (c)
  6812. {
  6813. #ifdef OPTION_EB
  6814. case OPTION_EB:
  6815. target_big_endian = 1;
  6816. break;
  6817. #endif
  6818. #ifdef OPTION_EL
  6819. case OPTION_EL:
  6820. target_big_endian = 0;
  6821. break;
  6822. #endif
  6823. case OPTION_FIXDD:
  6824. s3_fix_data_dependency = 1;
  6825. s7_fix_data_dependency = 1;
  6826. break;
  6827. case OPTION_NWARN:
  6828. s3_warn_fix_data_dependency = 0;
  6829. s7_warn_fix_data_dependency = 0;
  6830. break;
  6831. case OPTION_SCORE5:
  6832. score3 = 0;
  6833. score7 = 1;
  6834. s7_university_version = 0;
  6835. s7_vector_size = s7_SCORE5_PIPELINE;
  6836. break;
  6837. case OPTION_SCORE5U:
  6838. score3 = 0;
  6839. score7 = 1;
  6840. s7_university_version = 1;
  6841. s7_vector_size = s7_SCORE5_PIPELINE;
  6842. break;
  6843. case OPTION_SCORE7:
  6844. score3 = 0;
  6845. score7 = 1;
  6846. s7_score7d = 1;
  6847. s7_university_version = 0;
  6848. s7_vector_size = s7_SCORE7_PIPELINE;
  6849. break;
  6850. case OPTION_SCORE3:
  6851. score3 = 1;
  6852. score7 = 0;
  6853. s3_score3d = 1;
  6854. break;
  6855. case OPTION_R1:
  6856. s3_nor1 = 0;
  6857. s7_nor1 = 0;
  6858. break;
  6859. case 'G':
  6860. s3_g_switch_value = atoi (arg);
  6861. s7_g_switch_value = atoi (arg);
  6862. break;
  6863. case OPTION_O0:
  6864. s3_g_opt = 0;
  6865. s7_g_opt = 0;
  6866. break;
  6867. case OPTION_SCORE_VERSION:
  6868. printf (_("Sunplus-v2-0-0-20060510\n"));
  6869. break;
  6870. case OPTION_PIC:
  6871. s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now. */
  6872. s7_score_pic = s7_PIC;
  6873. s3_g_switch_value = 0; /* Must set -G num as 0 to generate s3_PIC code. */
  6874. s7_g_switch_value = 0; /* Must set -G num as 0 to generate s7_PIC code. */
  6875. break;
  6876. case OPTION_MARCH:
  6877. score_set_mach (arg);
  6878. break;
  6879. default:
  6880. return 0;
  6881. }
  6882. return 1;
  6883. }
  6884. void
  6885. md_show_usage (FILE * fp)
  6886. {
  6887. fprintf (fp, _(" Score-specific assembler options:\n"));
  6888. #ifdef OPTION_EB
  6889. fprintf (fp, _("\
  6890. -EB\t\tassemble code for a big-endian cpu\n"));
  6891. #endif
  6892. #ifdef OPTION_EL
  6893. fprintf (fp, _("\
  6894. -EL\t\tassemble code for a little-endian cpu\n"));
  6895. #endif
  6896. fprintf (fp, _("\
  6897. -FIXDD\t\tassemble code for fix data dependency\n"));
  6898. fprintf (fp, _("\
  6899. -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
  6900. fprintf (fp, _("\
  6901. -SCORE5\t\tassemble code for target is SCORE5\n"));
  6902. fprintf (fp, _("\
  6903. -SCORE5U\tassemble code for target is SCORE5U\n"));
  6904. fprintf (fp, _("\
  6905. -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
  6906. fprintf (fp, _("\
  6907. -SCORE3\t\tassemble code for target is SCORE3\n"));
  6908. fprintf (fp, _("\
  6909. -march=score7\tassemble code for target is SCORE7, this is default setting\n"));
  6910. fprintf (fp, _("\
  6911. -march=score3\tassemble code for target is SCORE3\n"));
  6912. fprintf (fp, _("\
  6913. -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
  6914. fprintf (fp, _("\
  6915. -KPIC\t\tassemble code for PIC\n"));
  6916. fprintf (fp, _("\
  6917. -O0\t\tassembler will not perform any optimizations\n"));
  6918. fprintf (fp, _("\
  6919. -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
  6920. fprintf (fp, _("\
  6921. -V \t\tSunplus release version \n"));
  6922. }