as.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #include <string.h>
  2. #include <ctype.h>
  3. #include <stdio.h>
  4. #include "as.h"
  5. #include "arg_type.h"
  6. process_label() {}
  7. process_mnemonic( m)
  8. char *m;
  9. {
  10. for ( ; *m != '\0'; m++)
  11. if ( *m == '.')
  12. *m = '_';
  13. }
  14. process_operand( str, op)
  15. register char *str;
  16. register struct t_operand *op;
  17. {
  18. char *glob_lbl(), *strchr();
  19. op->type = 0;
  20. switch ( *str) {
  21. case '#' : op->type = IS_IMMEDIATE;
  22. op->expr = str+1;
  23. if ( *(op->expr) != '$') { /* #1 */
  24. op->val = atoi( str+1);
  25. if ( 1 <= op->val && op->val <= 8 ) {
  26. op->type = IS_QUICK;
  27. op->lbl = NULL;
  28. }
  29. }
  30. else
  31. if ( arg_type( str+1) == STRING) { /* #$1+$2 */
  32. op->lbl = op->expr;
  33. *(op->lbl+2) = '\0';
  34. op->expr = op->lbl+3;
  35. }
  36. else /* #$1 */
  37. op->lbl = NULL;
  38. break;
  39. case '(' : if ( strchr( str+1, ',') == NULL)
  40. if ( is_reg( str+1)) {
  41. op->reg = reg_val( str+1);
  42. if ( *(str+4) == '+') /* (sp)+ */
  43. op->type = IS_INCR;
  44. else /* (a0) */
  45. op->type = IS_IND_REG;
  46. }
  47. else {
  48. op->type = IS_IND_MEM;
  49. op->expr = str+1;
  50. for ( str++; *++str != ')';)
  51. ;
  52. *str = '\0';
  53. if ( *(op->expr) == '$')
  54. if ( arg_type( op->expr) == STRING) {
  55. /* ($1+$2) */
  56. op->lbl = op->expr;
  57. if ( strlen( op->lbl) == 2)
  58. op->expr = "0";
  59. else {
  60. *(op->lbl+2) = '\0';
  61. op->expr = op->lbl+3;
  62. }
  63. }
  64. else /* ($1) */
  65. op->lbl = NULL;
  66. else if ( isdigit( *(op->expr))) /* (1) */
  67. op->lbl = NULL;
  68. else { /* (.trppc) */
  69. op->lbl = glob_lbl( op->expr);
  70. op->expr = "0";
  71. }
  72. }
  73. else
  74. if ( *(str+1) == '[') {
  75. op->type = IS_IND_IND;
  76. op->expr = str+2;
  77. for ( str += 2; *++str != ',';)
  78. ;
  79. *str++ = '\0';
  80. for ( ; *str == ' '; str++)
  81. ;
  82. op->reg = reg_val( str);
  83. for ( ; *str++ != ']';)
  84. ;
  85. if ( *str == ')') /* ([$1, a6]) */
  86. op->expr2 = 0;
  87. else { /* ([8,a6],8) */
  88. for ( ; *str++ != ',';)
  89. ;
  90. for ( ; *str == ' '; str++)
  91. ;
  92. op->expr2 = atoi( str);
  93. }
  94. }
  95. else {
  96. op->expr = str+1;
  97. for ( str++; *++str != ',';)
  98. ;
  99. *str++ = '\0';
  100. for ( ; *str == ' '; str++)
  101. ;
  102. op->reg = reg_val( str);
  103. if ( *(str+2) == ')') { /* (4, a0) */
  104. int i = atoi(op->expr);
  105. if ((*(op->expr) == '-' ||
  106. isdigit(*(op->expr))) &&
  107. i <= 32767 && i >= -32768) {
  108. op->type = IS_IND_REG_DISPL;
  109. }
  110. else op->type = IS_IND_REG_EDISPL;
  111. }
  112. else { /* (0, sp, d0.l*1) */
  113. op->type = IS_3_OPS;
  114. for ( str++; *++str != ',';)
  115. ;
  116. for ( ; *str == ' '; str++)
  117. ;
  118. op->reg2 = reg_val( str);
  119. for ( ; *str++ != '*';)
  120. ;
  121. op->scale = atoi( str);
  122. }
  123. }
  124. break;
  125. case '-' : op->type = IS_DECR; /* -(sp) */
  126. op->reg = reg_val( str+2);
  127. break;
  128. case '$' : op->type = IS_GLOB_LBL; /* $1 */
  129. op->lbl = str;
  130. op->expr ="0";
  131. break;
  132. default : if ( is_reg( str)) {
  133. op->reg = reg_val( str);
  134. if ( *(str+2) == ':') { /* d2:d1 */
  135. op->type = IS_REG_PAIR;
  136. op->reg2 = reg_val( str+3);
  137. }
  138. else /* a6 */
  139. op->type = ( *str == 'd' ? IS_D_REG : IS_A_REG);
  140. }
  141. else if ( isdigit( *str)) { /* 1f */
  142. op->type = IS_LOC_LBL;
  143. op->lbl = str;
  144. op->expr = "0";
  145. *(str+1) ='\0';
  146. }
  147. else { /* .strhp */
  148. op->type = IS_GLOB_LBL;
  149. op->lbl = glob_lbl( str);
  150. *(str+1) ='\0';
  151. op->expr = "0";
  152. }
  153. }
  154. }
  155. int reg_val( reg)
  156. char *reg;
  157. {
  158. return( *reg == 's' ? 7 : atoi( reg+1));
  159. }
  160. int is_reg( str)
  161. register char *str;
  162. {
  163. switch ( *str) {
  164. case 'a' :
  165. case 'd' : return( isdigit( *(str+1)));
  166. case 's' : return( *(str+1) == 'p');
  167. default : return( 0);
  168. }
  169. }
  170. char *glob_lbl( lbl)
  171. char *lbl;
  172. {
  173. char *gl, *Malloc();
  174. gl = Malloc( strlen( lbl) + 3);
  175. sprintf( gl, "\"%s\"", lbl);
  176. return( gl);
  177. }
  178. /******************************************************************************/
  179. int mode_reg( eaddr)
  180. register struct t_operand *eaddr;
  181. {
  182. switch ( eaddr->type) {
  183. case IS_A_REG : return( 0x08 | eaddr->reg);
  184. case IS_D_REG : return( 0x00 | eaddr->reg);
  185. case IS_IND_REG : return( 0x10 | eaddr->reg);
  186. case IS_INCR : return( 0x18 | eaddr->reg);
  187. case IS_DECR : return( 0x20 | eaddr->reg);
  188. case IS_IND_MEM : return( 0x39);
  189. case IS_IND_IND : return( 0x30 | eaddr->reg);
  190. case IS_IND_REG_DISPL : return( 0x28 | eaddr->reg);
  191. case IS_IND_REG_EDISPL: return( 0x30 | eaddr->reg);
  192. case IS_GLOB_LBL : return( 0x39);
  193. case IS_3_OPS : if ( isdigit( *(eaddr->expr)) &&
  194. atoi( eaddr->expr) < 128)
  195. return( 0x30 | eaddr->reg);
  196. else
  197. fprintf( stderr, "FOUT in IS_3_OPS\n");
  198. break;
  199. case IS_QUICK :
  200. case IS_IMMEDIATE : return( 0x3c);
  201. default : fprintf( stderr,
  202. "mode_reg(), wrong operand %d\n",
  203. eaddr->type);
  204. abort();
  205. break;
  206. }
  207. }
  208. code_extension( eaddr)
  209. register struct t_operand *eaddr;
  210. {
  211. switch ( eaddr->type) {
  212. case IS_IND_MEM : if ( eaddr->lbl == NULL)
  213. @text4( %$( eaddr->expr));
  214. else
  215. @reloc4( %$( eaddr->lbl),
  216. %$( eaddr->expr),
  217. ABSOLUTE);
  218. break;
  219. case IS_IND_IND : if ( eaddr->expr2 == 0) {
  220. @text2( 0x161);
  221. @text2( %$(eaddr->expr));
  222. }
  223. else {
  224. @text2( 0x162);
  225. @text2( %$(eaddr->expr));
  226. @text2( %d(eaddr->expr2));
  227. }
  228. break;
  229. case IS_IND_REG_DISPL : @text2( %$( eaddr->expr));
  230. break;
  231. case IS_IND_REG_EDISPL :@text2(0x0170);
  232. @text4( %$( eaddr->expr));
  233. break;
  234. case IS_GLOB_LBL : @reloc4( %$(eaddr->lbl),
  235. %$(eaddr->expr),
  236. ABSOLUTE);
  237. break;
  238. case IS_3_OPS : if ( isdigit( *(eaddr->expr)) &&
  239. atoi( eaddr->expr) < 128) {
  240. @text2( %d( 0x0800 |
  241. ( eaddr->reg2 << 12) |
  242. ( two_log( eaddr->scale)<<9) |
  243. atoi( eaddr->expr)));
  244. }
  245. else
  246. fprintf( stderr, "FOUT in IS_3_OPS\n");
  247. break;
  248. case IS_QUICK :
  249. case IS_IMMEDIATE : if ( eaddr->lbl != NULL)
  250. @reloc4( %$(eaddr->lbl),
  251. %$(eaddr->expr),
  252. ABSOLUTE);
  253. else
  254. @text4( %$(eaddr->expr));
  255. }
  256. }
  257. int reg_mode( eaddr)
  258. struct t_operand *eaddr;
  259. {
  260. int mr;
  261. mr = mode_reg( eaddr);
  262. return( ((mr & 0x7) << 3) | ((mr & 0x38) >> 3));
  263. }
  264. code_opcode( opcode, field1, field2, eaddr)
  265. int opcode, field1, field2;
  266. struct t_operand *eaddr;
  267. {
  268. @text2( %d(((opcode & 0xf) << 12) | ((field1 & 0x7) << 9) |
  269. ((field2 & 0x7) << 6) | (mode_reg(eaddr) & 0x3f)));
  270. }
  271. /* The attempts to optimize the instruction size when it cannot be done
  272. at code-expander generation time is actually quite dangerous, because
  273. it may not happen between references to and definitions of (corresponding)
  274. local labels. The reason for this is that these offsets are computed
  275. at code-expander generation time. Unfortunately, no warning is given,
  276. so this has to be checked by hand.
  277. */
  278. code_instr( opcode, field1, field2, eaddr)
  279. int opcode, field1, field2;
  280. struct t_operand *eaddr;
  281. {
  282. if (eaddr->type == IS_IND_REG_EDISPL) {
  283. @__instr_code(%d(((opcode & 0xf) << 12) | ((field1 & 0x7) << 9) |
  284. ((field2 & 0x7) << 6)),
  285. %d(eaddr->reg), %$(eaddr->expr));
  286. }
  287. else {
  288. code_opcode( opcode, field1, field2, eaddr);
  289. code_extension( eaddr);
  290. }
  291. }
  292. code_move( size, src, dst)
  293. int size;
  294. struct t_operand *src, *dst;
  295. {
  296. if (src->type == IS_IND_REG_EDISPL) {
  297. if (dst->type == IS_IND_REG_EDISPL) {
  298. @__moveXX(%d( ((size & 0x3) << 12)),
  299. %d(dst->reg), %$(dst->expr),
  300. %d(src->reg), %$(src->expr));
  301. }
  302. else {
  303. @__instr_code(%d( ((size & 0x3) << 12)|((reg_mode( dst) & 0x3f) << 6)),
  304. %d(src->reg), %$(src->expr));
  305. }
  306. }
  307. else if (dst->type == IS_IND_REG_EDISPL) {
  308. @__move_X(%d( ((size & 0x3) << 12) | (mode_reg( src) & 0x3f)),
  309. %d(dst->reg), %$(dst->expr));
  310. }
  311. else {
  312. @text2( %d( ((size & 0x3) << 12) | ((reg_mode( dst) & 0x3f) << 6) |
  313. (mode_reg( src) & 0x3f)));
  314. code_extension( src);
  315. code_extension( dst);
  316. }
  317. }
  318. code_dist4( dst)
  319. struct t_operand *dst;
  320. {
  321. @reloc4( %$(dst->lbl), %$(dst->expr) + 4, PC_REL);
  322. }
  323. int two_log( nr)
  324. register int nr;
  325. {
  326. register int log;
  327. for ( log = 0; nr >= 2; nr >>= 1)
  328. log++;
  329. return( log);
  330. }