Fellows,
I added some polymorph instructions to assembler.
They are jump instructions which either long jumps or short jumps depending on 
a jump distance. So, they are:


COND    EXPL       SHORT JUMP   LONG JUMP
===============================================
eq      ==      -> jeq          jne +4; br lab
ne      !=      -> jne          jeq +4; br lab

lt      <       -> jl           jge +4; br lab
ltnoov  <       -> jn           jn +2; jmp +4; br lab
ltu     <       -> jlo          lhs +4; br lab
le      <=      -> NOT IMPLEMENTED
leu     <=      -> NOT IMPLEMENTED

gt      >       -> NOT IMPLEMENTED
gtu     >       -> NOT IMPLEMENTED
ge      >=      -> jge          jl +4; br lab
genoov  >=      -> NOT IMPLEMENTED
geu     >=      -> jhs          jlo +4; br lab
===============================================

New opcodes are (BranchEQ -> beq; and so on...)
  beq,bne,blt,bltn,bltu,bge,bgeu
They usefull for comparisons, presented in a table above.

Also, we add 'jump' instruction:
        jump    UNCOND  -> jmp          br lab

These instructions use pc relative mode.
For example, 
        jump label
will be converted to
        jmp label       ; if jump distance can be fit 10 bits,
or to 
        br label        ; if not

another instruction:
        bltn    label
will be
        jn label        ; short
or
        jn +2
        jmp +4
        br label        ; if jump distance is long


Not implemented insns can be obtained as a combination of any of above.
For example, bgt (> on signed) can be 
        beq     .Lskip1
        bge     label
.Lskip1:

Another one, bgtu:
        beq     .Lskip2
        bqeu    label
.Lskip2:



Why? cause this will simplify gcc a lot!

Patch against gas/ attached.

To apply this patch do:
1. Obtain binutils-2.15 of current from cvs
2. $ cd binutils-XXX
   $ patch < msp.diff


Have fun.
Let me know if something goes wrong.

Cheers,
~d

P.S. profiling changes can be found in there as well.
Index: include/opcode/msp430.h
===================================================================
RCS file: /cvs/src/src/include/opcode/msp430.h,v
retrieving revision 1.1
diff -c -3 -p -r1.1 msp430.h
*** include/opcode/msp430.h	30 Dec 2002 19:25:12 -0000	1.1
--- include/opcode/msp430.h	17 Aug 2004 16:32:10 -0000
*************** static struct msp430_opcode_s msp430_opc
*** 103,111 ****
--- 103,187 ----
    MSP_INSN (rra,   2, 1, 0x1100, 0xff80),
    MSP_INSN (swpb,  2, 1, 0x1080, 0xffc0),
    MSP_INSN (rrc,   2, 1, 0x1000, 0xff80),
+   MSP_INSN (beq,   4, 0, 0,0),
+   MSP_INSN (bne,   4, 1, 0,0),
+   MSP_INSN (blt,   4, 2, 0,0),
+   MSP_INSN (bltu,  4, 3, 0,0),
+   MSP_INSN (bge,   4, 4, 0,0),
+   MSP_INSN (bgeu,  4, 5, 0,0),
+   MSP_INSN (bltn,  4, 6, 0,0),
+   MSP_INSN (jump,  4, 7, 0,0),
  
    /* End of instruction set.  */
    { NULL, 0, 0, 0, 0 }
  };
  
+ /*
+   GCC uses the some condition codes which we'll implement as
+   new _ralaxable_ instructions.
+   NOT IMPLEMENTED means that gcc implements it as a sequence of
+ 		  some instructions. For example:
+ 		    ble -> jeq, jl.
+ 
+   
+ COND	EXPL	   SHORT JUMP	LONG JUMP
+ ===============================================
+ eq	==	-> jeq 		jne +4; br lab
+ ne	!=	-> jne 		jeq +4; br lab
+ 
+ lt	<	-> jl 		jge +4;	br lab 
+ ltnoov	<	-> jn 		jn +2; jmp +4; br lab
+ ltu	<	-> jlo 		lhs +4; br lab
+ le	<=	-> NOT IMPLEMENTED
+ leu	<=	-> NOT IMPLEMENTED
+ 
+ gt	>	-> NOT IMPLEMENTED
+ gtu	>	-> NOT IMPLEMENTED
+ ge	>=	-> jge 		jl +4; br lab
+ genoov	>=	-> NOT IMPLEMENTED
+ geu	>=	-> jhs 		jlo +4; br lab
+ ===============================================
+ 
+ Therefore, new opcodes are (BranchEQ -> beq; and so on...)
+   beq,bne,blt,bltn,bltu,bge,bgeu
+ Also, we add 'jump' instruction:
+ jump	UNCOND	-> jmp		br lab
+ they will have fmt == 4, and insn_opnumb == number of instruction.
+ We will parse them during assembly
+ 
+  */
+ 
+ struct rcodes_s {
+   char *name;
+   int  index;	/* corresponding insn_opnumb */
+   int  nlen;	/* opcode length in words if jump is short enough */
+   int  sop;	/* opcode if jump length is short */
+   int  smask;	/* operand mask */
+ 		/* for long opcodes no mask required */
+   long llen;	/* long opcode length in words */
+   long lpos;	/* label position */
+   long lop0;	/* opcode 1 _word_ (16 bits) */
+   long lop1;	/* opcode second word */
+   long lop2;	/* opcode third word */
+   long lop3;	/* opcode fourth word (not necessary now, may be later) */
+ };
+ 
+ #define MSP430_RLC(n,i,sop,o1) \
+   {#n,i,4,sop,0xfc00,3,2,(o1+2),0x4010,0,0}
+ 
+ struct rcodes_s msp430_rcodes[] = 
+ {
+   MSP430_RLC(beq,0,0x2400,0x2000),
+   MSP430_RLC(bne,1,0x2000,0x2400),
+   MSP430_RLC(blt,2,0x3800,0x3400),
+   MSP430_RLC(bltu,3,0x2800,0x2c00),
+   MSP430_RLC(bge,4,0x3400,0x3800),
+   MSP430_RLC(bgeu,5,0x2c00,0x2800),
+   {"bltn",6,6,0x3000,0xfc00,4,3,0x3000+1,0x3c00+2,0x4010,0},
+   {"jump",7,4,0x3c00,0xfc00,2,1,0x4010,0,0,0},
+   {0,0,0,0,0,0,0,0,0,0,0}
+ };
+ 
+ #undef MSP430_RLC
+ 
  #endif
Index: gas/config/tc-msp430.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-msp430.c,v
retrieving revision 1.10
diff -c -3 -p -r1.10 tc-msp430.c
*** gas/config/tc-msp430.c	26 Jul 2004 12:29:02 -0000	1.10
--- gas/config/tc-msp430.c	17 Aug 2004 16:32:10 -0000
*************** static unsigned int msp430_operands
*** 46,65 ****
    PARAMS ((struct msp430_opcode_s *, char *));
  static int msp430_srcoperand
    PARAMS ((struct msp430_operand_s *, char *, int, int *));
! static int msp430_dstoperand
    PARAMS ((struct msp430_operand_s *, char *, int));
! static char *parse_exp
    PARAMS ((char *, expressionS *));
! static inline char *skip_space
    PARAMS ((char *));
! static int check_reg
!   PARAMS ((char *));
! static void msp430_set_arch
    PARAMS ((int));
! static void show_mcu_list
    PARAMS ((FILE *));
! static void del_spaces
    PARAMS ((char *));
  
  #define MAX_OP_LEN	256
  
--- 46,116 ----
    PARAMS ((struct msp430_opcode_s *, char *));
  static int msp430_srcoperand
    PARAMS ((struct msp430_operand_s *, char *, int, int *));
! static int msp430_dstoperand 
    PARAMS ((struct msp430_operand_s *, char *, int));
! static char *parse_exp 
    PARAMS ((char *, expressionS *));
! static inline char *skip_space PARAMS ((char *));
! static int check_reg 
    PARAMS ((char *));
! static void msp430_set_arch 
    PARAMS ((int));
! static void show_mcu_list 
    PARAMS ((FILE *));
! static void del_spaces 
    PARAMS ((char *));
+ static void msp430_profiler 
+   PARAMS ((int));
+ static char *extract_operand 
+   PARAMS ((char *, char *, int));
+ 
+ /* Relaxations */
+ /* what */
+ #define STATE_UNCOND_BRANCH	1	/* jump */
+ #define STATE_NOOV_BRANCH	3	/* bltn */
+ #define STATE_SIMPLE_BRANCH	2
+ 
+ #define CNRL	2
+ #define CUBL	4
+ #define CNOL	8
+ #define CSBL	6
+ 
+ /* length */
+ #define STATE_BITS10	1	/* wild guess. short jump */
+ #define STATE_WORD	2	/* 2 bytes addr more */
+ #define STATE_UNDEF	3	/* cannot handle this yet. convert to word mode */
+ 
+ #define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+ #define RELAX_STATE(s) ((s)&3)
+ #define RELAX_LEN(s)	(s>>2)
+ #define RELAX_NEXT(a,b)	ENCODE_RELAX(a,b+1)
+ 
+ relax_typeS md_relax_table[] = {
+   /* unused */
+   {1, 1, 0, 0},
+   {1, 1, 0, 0},
+   {1, 1, 0, 0},
+   {1, 1, 0, 0},
+ 
+   /* unconditional jump */
+   {1, 1, 8, 5},
+   {1024, -1024, CNRL, RELAX_NEXT (STATE_UNCOND_BRANCH, STATE_BITS10)},	/* state 10 bits displ */
+   {0, 0, CUBL, RELAX_NEXT (STATE_UNCOND_BRANCH, STATE_WORD)},		/* state word */
+   {1, 1, CUBL, 0},							/* state undef */
+ 
+   /* simple branches */
+   {0, 0, 8, 9},
+   {1024, -1024, CNRL, RELAX_NEXT (STATE_SIMPLE_BRANCH, STATE_BITS10)},	/* state 10 bits displ */
+   {0, 0, CSBL, RELAX_NEXT (STATE_SIMPLE_BRANCH, STATE_WORD)},		/* state word */
+   {1, 1, CSBL, 0},
+ 
+   /* blt no overflow branch */
+   {1, 1, 8, 13},
+   {1024, -1024, CNRL, RELAX_NEXT (STATE_NOOV_BRANCH, STATE_BITS10)},	/* state 10 bits displ */
+   {0, 0, CNOL, RELAX_NEXT (STATE_NOOV_BRANCH, STATE_WORD)},		/* state word */
+   {1, 1, CNOL, 0}
+ };
+ 
  
  #define MAX_OP_LEN	256
  
*************** struct mcu_type_s
*** 88,114 ****
  #define CHECK_RELOC_MSP430 		((imm_op || byte_op)?BFD_RELOC_MSP430_16_BYTE:BFD_RELOC_MSP430_16)
  #define CHECK_RELOC_MSP430_PCREL	((imm_op || byte_op)?BFD_RELOC_MSP430_16_PCREL_BYTE:BFD_RELOC_MSP430_16_PCREL)
  
! static struct mcu_type_s mcu_types[] =
! {
!   {"msp1",       MSP430_ISA_11, bfd_mach_msp11},
!   {"msp2",       MSP430_ISA_14, bfd_mach_msp14},
    {"msp430x110", MSP430_ISA_11, bfd_mach_msp11},
    {"msp430x112", MSP430_ISA_11, bfd_mach_msp11},
!   {"msp430x1101",MSP430_ISA_110, bfd_mach_msp110},
!   {"msp430x1111",MSP430_ISA_110, bfd_mach_msp110},
!   {"msp430x1121",MSP430_ISA_110, bfd_mach_msp110},
!   {"msp430x1122",MSP430_ISA_11, bfd_mach_msp110},
!   {"msp430x1132",MSP430_ISA_11, bfd_mach_msp110},
  
    {"msp430x122", MSP430_ISA_12, bfd_mach_msp12},
    {"msp430x123", MSP430_ISA_12, bfd_mach_msp12},
!   {"msp430x1222",MSP430_ISA_12, bfd_mach_msp12},
!   {"msp430x1232",MSP430_ISA_12, bfd_mach_msp12},
  
    {"msp430x133", MSP430_ISA_13, bfd_mach_msp13},
    {"msp430x135", MSP430_ISA_13, bfd_mach_msp13},
!   {"msp430x1331",MSP430_ISA_13, bfd_mach_msp13},
!   {"msp430x1351",MSP430_ISA_13, bfd_mach_msp13},
    {"msp430x147", MSP430_ISA_14, bfd_mach_msp14},
    {"msp430x148", MSP430_ISA_14, bfd_mach_msp14},
    {"msp430x149", MSP430_ISA_14, bfd_mach_msp14},
--- 139,164 ----
  #define CHECK_RELOC_MSP430 		((imm_op || byte_op)?BFD_RELOC_MSP430_16_BYTE:BFD_RELOC_MSP430_16)
  #define CHECK_RELOC_MSP430_PCREL	((imm_op || byte_op)?BFD_RELOC_MSP430_16_PCREL_BYTE:BFD_RELOC_MSP430_16_PCREL)
  
! static struct mcu_type_s mcu_types[] = {
!   {"msp1", MSP430_ISA_11, bfd_mach_msp11},
!   {"msp2", MSP430_ISA_14, bfd_mach_msp14},
    {"msp430x110", MSP430_ISA_11, bfd_mach_msp11},
    {"msp430x112", MSP430_ISA_11, bfd_mach_msp11},
!   {"msp430x1101", MSP430_ISA_110, bfd_mach_msp110},
!   {"msp430x1111", MSP430_ISA_110, bfd_mach_msp110},
!   {"msp430x1121", MSP430_ISA_110, bfd_mach_msp110},
!   {"msp430x1122", MSP430_ISA_11, bfd_mach_msp110},
!   {"msp430x1132", MSP430_ISA_11, bfd_mach_msp110},
  
    {"msp430x122", MSP430_ISA_12, bfd_mach_msp12},
    {"msp430x123", MSP430_ISA_12, bfd_mach_msp12},
!   {"msp430x1222", MSP430_ISA_12, bfd_mach_msp12},
!   {"msp430x1232", MSP430_ISA_12, bfd_mach_msp12},
  
    {"msp430x133", MSP430_ISA_13, bfd_mach_msp13},
    {"msp430x135", MSP430_ISA_13, bfd_mach_msp13},
!   {"msp430x1331", MSP430_ISA_13, bfd_mach_msp13},
!   {"msp430x1351", MSP430_ISA_13, bfd_mach_msp13},
    {"msp430x147", MSP430_ISA_14, bfd_mach_msp14},
    {"msp430x148", MSP430_ISA_14, bfd_mach_msp14},
    {"msp430x149", MSP430_ISA_14, bfd_mach_msp14},
*************** static struct mcu_type_s default_mcu =
*** 166,174 ****
  
  static struct mcu_type_s *msp430_mcu = &default_mcu;
  
! const pseudo_typeS md_pseudo_table[] =
! {
    {"arch", msp430_set_arch, 0},
    {NULL, NULL, 0}
  };
  
--- 216,224 ----
  
  static struct mcu_type_s *msp430_mcu = &default_mcu;
  
! const pseudo_typeS md_pseudo_table[] = {
    {"arch", msp430_set_arch, 0},
+   {"profiler", msp430_profiler, 0},
    {NULL, NULL, 0}
  };
  
*************** const pseudo_typeS md_pseudo_table[] =
*** 176,183 ****
  
  const char *md_shortopts = "m:";
  
! struct option md_longopts[] =
! {
    {"mmcu", required_argument, NULL, OPTION_MMCU},
    {NULL, no_argument, NULL, 0}
  };
--- 226,232 ----
  
  const char *md_shortopts = "m:";
  
! struct option md_longopts[] = {
    {"mmcu", required_argument, NULL, OPTION_MMCU},
    {NULL, no_argument, NULL, 0}
  };
*************** show_mcu_list (stream)
*** 199,205 ****
  }
  
  void
! md_show_usage (FILE *stream)
  {
    fprintf (stream,
  	   _("MSP430 options:\n"
--- 248,254 ----
  }
  
  void
! md_show_usage (FILE * stream)
  {
    fprintf (stream,
  	   _("MSP430 options:\n"
*************** msp430_set_arch (dummy)
*** 263,268 ****
--- 312,548 ----
    bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach);
  }
  
+ /*
+    Profiling capability:
+    It is a performance hit to use gcc's profiling approach for this tiny target.
+    Even more -- jtag hardware facility does not perform any profiling functions.
+    However we've got gdb's built-in simulator where we can do anything.
+    Therefore my suggestion is:
+    
+    We define new section ".profiler" which holds all profiling information.
+    We define new pseudo operation .profiler which will instruct assembler to 
+    add new profile entry to the object file. Profile should take place at the
+    present address.
+    
+    Pseudo-op format:
+ 
+       .profiler flags,function_to_profile [, cycle_corrector, extra]
+    
+    where 'flags' is a combination of the following chars:
+ 	    s - function entry
+ 	    x - function exit
+ 	    i - function is in init section
+ 	    f - function is in fini section
+ 	    l - library call
+ 	    c - libc standard call
+ 	    d - stack value demand
+ 	    I - interrupt service routine
+ 	    P - prologue start
+ 	    p - prologue end
+ 	    E - epilogue start
+ 	    e - epilogue end
+ 	    j - long jump/ sjlj unwind
+ 	    a - an arbitrary code fragment
+ 	  '""' optional: "sil" == sil
+ 	    
+       function_to_profile - function address
+       cycle_corrector   - a value which should be added to the cycle
+ 				      counter, zero if omitted
+       extra - some extra parameter, TBD, zero if omitted.
+       
+       For example:
+       ------------------------------
+ 	.global fxx
+ 	.type fxx,@function
+       fxx:
+       .LFrameOffset_fxx=0x08
+       .profiler "scdP", fxx	; function entry.
+ 				; we also demand stack value to be saved
+ 	push r11
+ 	push r10
+ 	push r9
+ 	push r8
+       .profiler "cdp",fxx,0, .LFrameOffset_fxx	; check stack value at this point
+ 						; (this is a prologue end)
+ 						; note, that spare var filled with the farme size
+ 	mov r15,r8
+ 	....
+       .profiler cdE,fxx		; check stack
+ 	pop r8
+ 	pop r9
+ 	pop r10
+ 	pop r11
+       .profiler xcde,fxx,3	; exit adds 3 to the cycle counter
+       ret				; cause 'ret' insn takes 3 cycles
+       -------------------------------
+ 
+       This profiling approach does not produce any overhead and 
+       absolutely harmless.
+       So, even profiled code can be uploaded to the MCU.
+  */
+ #define MSP430_PROFILER_FLAG_ENTRY	1	/* s */
+ #define MSP430_PROFILER_FLAG_EXIT	2	/* x */
+ #define MSP430_PROFILER_FLAG_INITSECT	4	/* i */
+ #define MSP430_PROFILER_FLAG_FINISECT	8	/* f */
+ #define MSP430_PROFILER_FLAG_LIBCALL	0x10	/* l */
+ #define MSP430_PROFILER_FLAG_STDCALL	0x20	/* c */
+ #define MSP430_PROFILER_FLAG_STACKDMD	0x40	/* d */
+ #define MSP430_PROFILER_FLAG_ISR	0x80	/* I */
+ #define MSP430_PROFILER_FLAG_PROLSTART	0x100	/* P */
+ #define MSP430_PROFILER_FLAG_PROLEND	0x200	/* p */
+ #define MSP430_PROFILER_FLAG_EPISTART	0x400	/* E */
+ #define MSP430_PROFILER_FLAG_EPIEND	0x800	/* e */
+ #define MSP430_PROFILER_FLAG_JUMP	0x1000	/* j */
+ #define MSP430_PROFILER_FLAG_FRAGMENT	0x2000	/* a */
+ 
+ static void
+ msp430_profiler (dummy)
+      int dummy ATTRIBUTE_UNUSED;
+ {
+   char __s[1024];
+   char __f[32];
+   char *str = __s;
+   char *flags = __f;
+   int p_flags = 0;
+   char *halt;
+   expressionS exp, exp1;
+   int ops = 0, left;
+   char *s;
+   segT seg;
+   int subseg;
+ 
+ 
+   s = input_line_pointer;
+ 
+   while (*s && *s != '\n')
+     {
+       if (*s == ',')
+ 	ops++;
+       s++;
+     }
+ 
+   left = 3 - ops;
+ 
+   if (ops < 1)
+     {
+       as_bad (_(".profiler pseudo requires at least three operands"));
+       return;
+     }
+ 
+   input_line_pointer = extract_operand (input_line_pointer, flags, 32);
+ 
+   while (*flags)
+     {
+       switch (*flags)
+ 	{
+ 	case '"':
+ 	  break;
+ 	case 'a':
+ 	  p_flags |= MSP430_PROFILER_FLAG_FRAGMENT;
+ 	  break;
+ 	case 'j':
+ 	  p_flags |= MSP430_PROFILER_FLAG_JUMP;
+ 	  break;
+ 	case 'P':
+ 	  p_flags |= MSP430_PROFILER_FLAG_PROLSTART;
+ 	  break;
+ 	case 'p':
+ 	  p_flags |= MSP430_PROFILER_FLAG_PROLEND;
+ 	  break;
+ 	case 'E':
+ 	  p_flags |= MSP430_PROFILER_FLAG_EPISTART;
+ 	  break;
+ 	case 'e':
+ 	  p_flags |= MSP430_PROFILER_FLAG_EPIEND;
+ 	  break;
+ 	case 's':
+ 	  p_flags |= MSP430_PROFILER_FLAG_ENTRY;
+ 	  break;
+ 	case 'x':
+ 	  p_flags |= MSP430_PROFILER_FLAG_EXIT;
+ 	  break;
+ 	case 'i':
+ 	  p_flags |= MSP430_PROFILER_FLAG_INITSECT;
+ 	  break;
+ 	case 'f':
+ 	  p_flags |= MSP430_PROFILER_FLAG_FINISECT;
+ 	  break;
+ 	case 'l':
+ 	  p_flags |= MSP430_PROFILER_FLAG_LIBCALL;
+ 	  break;
+ 	case 'c':
+ 	  p_flags |= MSP430_PROFILER_FLAG_STDCALL;
+ 	  break;
+ 	case 'd':
+ 	  p_flags |= MSP430_PROFILER_FLAG_STACKDMD;
+ 	  break;
+ 	case 'I':
+ 	  p_flags |= MSP430_PROFILER_FLAG_ISR;
+ 	  break;
+ 	default:
+ 	  as_warn (_("Unknown flag - ignored."));
+ 	  break;
+ 	}
+       flags++;
+     }
+ 
+   if ((p_flags & 3) == 3)
+     {
+       as_bad (_("Ambigious flags combination."));
+       return;
+     }
+ 
+   /* generate temp symbol which denotes current location */
+   if (now_seg == absolute_section)	/* paranoja ? */
+     {
+       exp1.X_op = O_constant;
+       exp1.X_add_number = abs_section_offset;
+       as_warn (_("Profiling in absolute section? Hm..."));
+     }
+   else
+     {
+       exp1.X_op = O_symbol;
+       exp1.X_add_symbol = symbol_temp_new_now ();
+       exp1.X_add_number = 0;
+     }
+ 
+   /* generate a symbol which holds flags value */
+   exp.X_op = O_constant;
+   exp.X_add_number = p_flags;
+ 
+   /* save current section */
+   seg = now_seg;
+   subseg = now_subseg;
+ 
+   /* now turn to .profiler section */
+   obj_elf_change_section (".profiler", SHT_PROGBITS, SHF_MASKPROC, 0, 0, 0, 0);
+ 
+   /* save flags */
+   emit_expr (&exp, 2);
+ 
+   /* save label value */
+   emit_expr (&exp1, 2);
+ 
+   while (ops--)
+     {
+       /* now get profiling info */
+       halt = extract_operand (input_line_pointer, str, 1024);
+       /* process like ".word xxx" directive */
+       parse_exp (str, &exp);
+       emit_expr (&exp, 2);
+       input_line_pointer = halt;
+     }
+ 
+   /* fill the rest with zeros */
+   exp.X_op = O_constant;
+   exp.X_add_number = 0;
+   while (left--)
+     emit_expr (&exp, 2);
+ 
+   /* return to current section */
+   subseg_set (seg, subseg);
+ }
+ 
  int
  md_parse_option (c, arg)
       int c;
*************** md_parse_option (c, arg)
*** 289,294 ****
--- 569,575 ----
  	as_fatal (_("redefinition of mcu type %s' to %s'"),
  		  msp430_mcu->name, mcu_types[i].name);
        return 1;
+       break;
      }
  
    return 0;
*************** extract_cmd (char *from, char *to, int l
*** 363,369 ****
  {
    int size = 0;
  
!   while (*from && ! ISSPACE (*from) && *from != '.' && limit > size)
      {
        *(to + size) = *from;
        from++;
--- 644,650 ----
  {
    int size = 0;
  
!   while (*from && !ISSPACE (*from) && *from != '.' && limit > size)
      {
        *(to + size) = *from;
        from++;
*************** md_atof (type, litP, sizeP)
*** 420,433 ****
    return NULL;
  }
  
- void
- md_convert_frag (abfd, sec, fragP)
-      bfd *abfd ATTRIBUTE_UNUSED;
-      asection *sec ATTRIBUTE_UNUSED;
-      fragS *fragP ATTRIBUTE_UNUSED;
- {
-   abort ();
- }
  
  void
  md_begin ()
--- 701,706 ----
*************** md_begin ()
*** 439,444 ****
--- 712,718 ----
      hash_insert (msp430_hash, opcode->name, (char *) opcode);
  
    bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach);
+ 
  }
  
  void
*************** msp430_operands (opcode, line)
*** 514,520 ****
      byte_op = 0;
  
    /* skip .[bwBW].  */
!   while (! ISSPACE (*line) && *line)
      line++;
  
    if (opcode->insn_opnumb && (!*line || *line == '\n'))
--- 788,794 ----
      byte_op = 0;
  
    /* skip .[bwBW].  */
!   while (!ISSPACE (*line) && *line)
      line++;
  
    if (opcode->insn_opnumb && (!*line || *line == '\n'))
*************** msp430_operands (opcode, line)
*** 579,585 ****
  	    res += msp430_dstoperand (&op2, l2, opcode->bin_opcode);
  
  	    if (res)
! 	      break;	/* An error occurred.  All warnings were done before.  */
  
  	    bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
  
--- 853,859 ----
  	    res += msp430_dstoperand (&op2, l2, opcode->bin_opcode);
  
  	    if (res)
! 	      break;		/* An error occurred.  All warnings were done before.  */
  
  	    bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
  
*************** msp430_operands (opcode, line)
*** 703,709 ****
        line = extract_operand (line, l1, sizeof (l1));
        res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
        if (res)
! 	break;		/* Error in operand.  */
  
        bin |= op1.reg | (op1.am << 4);
        __is = 1 + op1.ol;
--- 977,983 ----
        line = extract_operand (line, l1, sizeof (l1));
        res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
        if (res)
! 	break;			/* Error in operand.  */
  
        bin |= op1.reg | (op1.am << 4);
        __is = 1 + op1.ol;
*************** msp430_operands (opcode, line)
*** 810,815 ****
--- 1084,1177 ----
  	}
        break;
  
+     case 4:			/* extended jumps */
+       line = extract_operand (line, l1, sizeof (l1));
+       if (l1[0])
+ 	{
+ 	  char *m = l1;
+ 	  expressionS exp;
+ 
+ 	  if (*m == '#'		/* ignore absolute addressing. make it PC relative anyway  */
+ 	      || *m == '$')
+ 	    m++;
+ 
+ 	  parse_exp (m, &exp);
+ 	  if (exp.X_op == O_constant)
+ 	    {
+ 	      int x = exp.X_add_number;
+ 
+ 	      if (x & 1)
+ 		{
+ 		  as_warn (_("Even number required. Rounded to %d"), x + 1);
+ 		  x++;
+ 		}
+ 
+ 	      if (x > 512 * 2 || x < -511 * 2 || 1)
+ 		{
+ 		  /* now convert instruction */
+ 		  struct rcodes_s rc = msp430_rcodes[opcode->insn_opnumb];
+ 		  frag = frag_more (rc.llen * 2);
+ 
+ 		  /* anyway $ means skip next bytes after jump */
+ 		  if ((*l1 == '$' && x > 0) || x < 0)
+ 		    x -= rc.lpos * 2;
+ 		  else
+ 		    x += 2;
+ 
+ 		  bfd_putl16 ((bfd_vma) rc.lop0, frag);
+ 
+ 		  if (rc.llen > 2)
+ 		    {
+ 		      bfd_putl16 ((bfd_vma) rc.lop1, frag + 2);
+ 
+ 		      if (rc.llen > 3)
+ 			{
+ 			  bfd_putl16 ((bfd_vma) rc.lop2, frag + 4);
+ 			  bfd_putl16 ((bfd_vma) (x & 0xffff), frag + 6);
+ 			}
+ 		      else
+ 			bfd_putl16 ((bfd_vma) (x & 0xffff), frag + 4);
+ 		    }
+ 		  else
+ 		    {
+ 		      bfd_putl16 ((bfd_vma) (x & 0xffff), frag + 2);
+ 		    }
+ 		}
+ 	      else
+ 		{
+ 		  /* no conversion required */
+ 		  if ((*l1 == '$' && x > 0) || x < 0)
+ 		    x -= 2;
+ 		  x >>= 1;
+ 		  frag = frag_more (2);
+ 		  bin = msp430_rcodes[opcode->insn_opnumb].sop;
+ 		  bin |= x & 0x3ff;
+ 		  bfd_putl16 ((bfd_vma) bin, frag);
+ 		}
+ 	    }
+ 	  else if (exp.X_op == O_symbol)
+ 	    {
+ 	      /* relaxation required */
+ 	      struct rcodes_s rc = msp430_rcodes[opcode->insn_opnumb];
+ 	      frag = frag_more (8);
+ 	      bfd_putl16 ((bfd_vma) msp430_rcodes[opcode->insn_opnumb].sop,
+ 			  frag);
+ 	      frag = frag_variant (rs_machine_dependent, 8,	/* max_char */
+ 				   2,	/* var */
+ 				   ENCODE_RELAX (rc.lpos, STATE_BITS10),	/* wild guess */
+ 				   (exp.X_add_symbol),	/* symbol */
+ 				   0,	/* offset is zero if jump dist less than 1K */
+ 				   (char *) frag	/* opcode */
+ 		  );
+ 	    }
+ 	}
+       else
+ 	{
+ 	  as_bad (_("instruction requires label or absolute displacement"));
+ 	  break;
+ 	}
+       break;
+ 
      default:
        as_bad (_("Ilegal instruction or not implmented opcode."));
      }
*************** msp430_srcoperand (op, l, bin, imm_op)
*** 896,906 ****
        int rval = 0;
  
        /* Check if there is:
! 	 llo(x) - least significant 16 bits, x &= 0xffff
! 	 lhi(x) - x = (x >> 16) & 0xffff,
! 	 hlo(x) - x = (x >> 32) & 0xffff,
! 	 hhi(x) - x = (x >> 48) & 0xffff
! 	 The value _MUST_ be constant expression: #hlo(1231231231).  */
  
        *imm_op = 1;
  
--- 1258,1268 ----
        int rval = 0;
  
        /* Check if there is:
!          llo(x) - least significant 16 bits, x &= 0xffff
!          lhi(x) - x = (x >> 16) & 0xffff,
!          hlo(x) - x = (x >> 32) & 0xffff,
!          hhi(x) - x = (x >> 48) & 0xffff
!          The value _MUST_ be constant expression: #hlo(1231231231).  */
  
        *imm_op = 1;
  
*************** msp430_srcoperand (op, l, bin, imm_op)
*** 966,972 ****
  
  	  if (op->exp.X_add_number > 65535 || op->exp.X_add_number < -32768)
  	    {
! 	      as_bad (_("value %ld out of range. Use #lo() or #hi()"), x);
  	      return 1;
  	    }
  
--- 1328,1335 ----
  
  	  if (op->exp.X_add_number > 65535 || op->exp.X_add_number < -32768)
  	    {
! 	      as_bad (_("value %ld out of range. Use #lo() or #hi()"),
! 		      (long) x);
  	      return 1;
  	    }
  
*************** msp430_srcoperand (op, l, bin, imm_op)
*** 1102,1107 ****
--- 1465,1477 ----
  	      op->mode = OP_REG;
  	    }
  	}
+       /* redudant (yet) check */
+       else if (op->exp.X_op == O_register)
+ 	{
+ 	  as_bad (_
+ 		  ("Registers cannot be used within immediate expression [%s]"),
+ 		  l);
+ 	}
        else
  	{
  	  as_bad (_("unknown operand %s"), l);
*************** msp430_srcoperand (op, l, bin, imm_op)
*** 1132,1137 ****
--- 1502,1514 ----
        else if (op->exp.X_op == O_symbol)
  	{
  	}
+       /* redudant (yet) check */
+       else if (op->exp.X_op == O_register)
+ 	{
+ 	  as_bad (_
+ 		  ("Registers cannot be used within absolute expression [%s]"),
+ 		  l);
+ 	}
        else
  	{
  	  as_bad (_("unknown expression in operand %s"), l);
*************** msp430_srcoperand (op, l, bin, imm_op)
*** 1159,1165 ****
  	  return 1;
  	}
  
!       t++;	/* Points to the reg value.  */
  
        if (check_reg (t))
  	{
--- 1536,1542 ----
  	  return 1;
  	}
  
!       t++;			/* Points to the reg value.  */
  
        if (check_reg (t))
  	{
*************** msp430_srcoperand (op, l, bin, imm_op)
*** 1203,1209 ****
        op->am = 1;
        op->ol = 1;
        /* Extract a register.  */
!       t++;	/* Advance pointer.  */
  
        if (*t != 'r' && *t != 'R')
  	{
--- 1580,1586 ----
        op->am = 1;
        op->ol = 1;
        /* Extract a register.  */
!       t++;			/* Advance pointer.  */
  
        if (*t != 'r' && *t != 'R')
  	{
*************** msp430_srcoperand (op, l, bin, imm_op)
*** 1271,1276 ****
--- 1648,1660 ----
        else if (op->exp.X_op == O_symbol)
  	{
  	}
+       /* redudant (yet) check */
+       else if (op->exp.X_op == O_register)
+ 	{
+ 	  as_bad (_
+ 		  ("Registers cannot be used as a prefix of indexed expression [%s]"),
+ 		  l);
+ 	}
        else
  	{
  	  as_bad (_("unknown expression in operand %s"), l);
*************** msp430_srcoperand (op, l, bin, imm_op)
*** 1309,1329 ****
    /* Symbolic mode 'mov a, b' == 'mov x(pc), y(pc)'.  */
    do
      {
        char *t = l;
- 
        __tl = l;
- 
        while (*t)
  	{
  	  /* alpha/number    underline     dot for labels.  */
! 	  if (! ISALNUM (*t) && *t != '_' && *t != '.')
  	    {
  	      as_bad (_("unknown operand %s"), l);
  	      return 1;
  	    }
  	  t++;
  	}
! 
        op->mode = OP_EXP;
        op->reg = 0;		/* PC relative... be careful.  */
        op->am = 1;
--- 1693,1713 ----
    /* Symbolic mode 'mov a, b' == 'mov x(pc), y(pc)'.  */
    do
      {
+       /* allow expression in operand like 'a+123*(1|2)' */
+ #if 0
        char *t = l;
        __tl = l;
        while (*t)
  	{
  	  /* alpha/number    underline     dot for labels.  */
! 	  if (!ISALNUM (*t) && *t != '_' && *t != '.')
  	    {
  	      as_bad (_("unknown operand %s"), l);
  	      return 1;
  	    }
  	  t++;
  	}
! #endif
        op->mode = OP_EXP;
        op->reg = 0;		/* PC relative... be careful.  */
        op->am = 1;
*************** md_apply_fix3 (fixp, valuep, seg)
*** 1434,1440 ****
    if (fixp->fx_done)
      {
        /* Fetch the instruction, insert the fully resolved operand
! 	 value, and stuff the instruction back again.  */
  
        where = fixp->fx_frag->fr_literal + fixp->fx_where;
  
--- 1818,1824 ----
    if (fixp->fx_done)
      {
        /* Fetch the instruction, insert the fully resolved operand
!          value, and stuff the instruction back again.  */
  
        where = fixp->fx_frag->fr_literal + fixp->fx_where;
  
*************** parse_exp (s, op)
*** 1563,1572 ****
  
  
  int
! md_estimate_size_before_relax (fragp, seg)
!      fragS *fragp ATTRIBUTE_UNUSED;
!      asection *seg ATTRIBUTE_UNUSED;
  {
!   abort ();
!   return 0;
  }
--- 1947,2117 ----
  
  
  int
! md_estimate_size_before_relax (fragP, segment_type)
!      fragS *fragP;
!      asection *segment_type;
! {
!   if (fragP->fr_symbol && S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
!     {
!       /* this is a jump -> pcrel mode. Nothing to do here */
!       fragP->fr_subtype =
! 	  ENCODE_RELAX (RELAX_LEN (fragP->fr_subtype), STATE_BITS10);
!     }
!   else if (fragP->fr_symbol)
!     {
!       /* Its got a segment, but its not ours, so it will always be long. 
!          Liker may relax it to short jump */
!       fragP->fr_subtype =
! 	  ENCODE_RELAX (RELAX_LEN (fragP->fr_subtype), STATE_UNDEF);
!     }
!   else
!     {
!       /* We know the abs value. may be it is a jump to fixed address. */
!       fragP->fr_subtype =
! 	ENCODE_RELAX (RELAX_LEN (fragP->fr_subtype), STATE_UNDEF);
!     }
! 
!   return md_relax_table[fragP->fr_subtype].rlx_length;
! }
! 
! void
! md_convert_frag (abfd, sec, fragP)
!      bfd *abfd ATTRIBUTE_UNUSED;
!      asection *sec ATTRIBUTE_UNUSED;
!      fragS *fragP;
  {
!   char *where = 0;
!   switch (fragP->fr_subtype)
!     {
!     case ENCODE_RELAX (STATE_UNCOND_BRANCH, STATE_BITS10):
!     case ENCODE_RELAX (STATE_SIMPLE_BRANCH, STATE_BITS10):
!     case ENCODE_RELAX (STATE_NOOV_BRANCH, STATE_BITS10):
!       /* we do not have to convert anything here.
!          Just apply a fix */
!       fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset,
! 	       TRUE, BFD_RELOC_MSP430_10_PCREL);
!       fragP->fr_fix += 2;
!       break;
! 
!     case ENCODE_RELAX (STATE_UNCOND_BRANCH, STATE_WORD):
!     case ENCODE_RELAX (STATE_UNCOND_BRANCH, STATE_UNDEF):
!       {
! 	/* convert uncond branch jmp lab -> br lab */
! 	struct rcodes_s cc = msp430_rcodes[7];
! 	where = fragP->fr_literal + fragP->fr_fix;
! 	bfd_putl16 (cc.lop0, where);
! 	fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol,
! 		 fragP->fr_offset, TRUE, BFD_RELOC_MSP430_16_PCREL);
! 	fragP->fr_fix += 4;
!       }
!       break;
!       
!     case ENCODE_RELAX (STATE_SIMPLE_BRANCH, STATE_WORD):
!     case ENCODE_RELAX (STATE_SIMPLE_BRANCH, STATE_UNDEF):
!       {
! 	/* other simple branches */
! 	struct rcodes_s *cc = NULL;
! 	int i;
! 	int insn = bfd_getl16 (fragP->fr_opcode);
! 	insn &= 0xffff;
! 	for (i = 0; i < 7; i++)
! 	  if (msp430_rcodes[i].sop == insn)
! 	    cc = &msp430_rcodes[i];
! 	if (!cc)
! 	  as_fatal (_("internal inconsistency problem in %s: insn %04lx"),
! 		    __FUNCTION__, (long) insn);
! 	where = fragP->fr_literal + fragP->fr_fix;
! 	bfd_putl16 (cc->lop0, where);
! 	bfd_putl16 (cc->lop1, where + 2);
! 	fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
! 		 fragP->fr_offset, TRUE, BFD_RELOC_MSP430_16_PCREL);
! 	fragP->fr_fix += 6;
!       }
!       break;
!     
!     case ENCODE_RELAX (STATE_NOOV_BRANCH, STATE_WORD):
!     case ENCODE_RELAX (STATE_NOOV_BRANCH, STATE_UNDEF):
!       {
! 	struct rcodes_s cc = msp430_rcodes[6];
! 	where = fragP->fr_literal + fragP->fr_fix;
! 	bfd_putl16 (cc.lop0, where);
! 	bfd_putl16 (cc.lop1, where + 2);
! 	bfd_putl16 (cc.lop2, where + 4);
! 	fix_new (fragP, fragP->fr_fix + 6, 2, fragP->fr_symbol,
! 		 fragP->fr_offset, TRUE, BFD_RELOC_MSP430_16_PCREL);
! 	fragP->fr_fix += 8;
!       }
!       break;
! 
!     default:
!       as_fatal (_("internal inconsistency problem in %s:  %lx"),
! 		__FUNCTION__, (long) fragP->fr_subtype);
!       break;
!     }
! }
! 
! /* relax fragment. mostly stolen from hc11 and mcore 
!    which arches I think I know */
! long
! msp430_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS * fragP,
! 		   long stretch ATTRIBUTE_UNUSED)
! {
!   long growth;
!   offsetT aim = 0;
!   symbolS *symbolP;
!   const relax_typeS *this_type;
!   const relax_typeS *start_type;
!   relax_substateT next_state;
!   relax_substateT this_state;
!   const relax_typeS *table = md_relax_table;
! 
!   /* nothing to be done if the frag has a max size */
!   if (RELAX_STATE (fragP->fr_subtype) == (STATE_UNDEF))
!     return 0;
! 
!   if (RELAX_STATE (fragP->fr_subtype) == (STATE_BITS10))
!     {
!       symbolP = fragP->fr_symbol;
!       if (symbol_resolved_p (symbolP))
! 	as_fatal (_("internal inconsistency problem in %s: resolved symbol"),
! 		  __FUNCTION__);
!       aim = S_GET_VALUE (symbolP) - fragP->fr_address - fragP->fr_fix;
!     }
! 
!   this_state = fragP->fr_subtype;
!   start_type = this_type = table + this_state;
! 
!   if (aim < 0)
!     {
!       /* Look backwards.  */
!       for (next_state = this_type->rlx_more; next_state;)
! 	if (aim >= this_type->rlx_backward)
! 	  next_state = 0;
! 	else
! 	  {
! 	    /* Grow to next state.  */
! 	    this_state = next_state;
! 	    this_type = table + this_state;
! 	    next_state = this_type->rlx_more;
! 	  }
!     }
!   else
!     {
!       /* Look forwards.  */
!       for (next_state = this_type->rlx_more; next_state;)
! 	if (aim <= this_type->rlx_forward)
! 	  next_state = 0;
! 	else
! 	  {
! 	    /* Grow to next state.  */
! 	    this_state = next_state;
! 	    this_type = table + this_state;
! 	    next_state = this_type->rlx_more;
! 	  }
!     }
! 
!   growth = this_type->rlx_length - start_type->rlx_length;
!   if (growth != 0)
!     fragP->fr_subtype = this_state;
!   return growth;
  }
Index: gas/config/tc-msp430.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-msp430.h,v
retrieving revision 1.1
diff -c -3 -p -r1.1 tc-msp430.h
*** gas/config/tc-msp430.h	30 Dec 2002 19:25:07 -0000	1.1
--- gas/config/tc-msp430.h	17 Aug 2004 16:32:10 -0000
*************** extern long md_pcrel_from_section PARAMS
*** 112,114 ****
--- 112,121 ----
       should do nothing.  Some targets define a `.bss' directive that is
       also affected by this macro.  The default definition will set
       P2VAR to the truncated power of two of sizes up to eight bytes.  */
+ 
+ 
+ #define md_relax_frag(SEG, FRAGP, STRETCH)             \
+   msp430_relax_frag (SEG, FRAGP, STRETCH)
+ extern long msp430_relax_frag (segT, fragS*, long);
+ 
+ 

Reply via email to