This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch] MIPS: Add mips16e save/restore instruction support.



> > + 	    case 'm':		/* register list for save insn */
> > + 	    case 'M':		/* register list for restore insn */
> 
> Comment formatting.

ok..  although I thought I was consistent with the 'l','L' cases from
above.
anyway, I have reformatted it.

> > + 			if (seen_framesz)
> > + 			  {
> > + 			    as_bad ("more than one frame size in list");
> 
> Should be i18n: as_bad (_("... , there are more such instances further
> down.

ok.

> > + 		/* Encode args/astatic combination.  */
> > + 		if (args & astatics)
> > + 		  as_bad ("arg/static registers overlap");
> > + 		else if (args == 0xf)
> > + 		  /* All $a0-$a3 are args.  */
> > + 		  opcode |= 0xe << 16;
> > + 		else if (astatics == 0xf)
> > + 		  /* All $a0-$a3 are a-statics.  */
> 
> Now, how is it called, "astatic", "static" or "a-static"? Consistent
> naming would be good. I also dislike the magic constants showing up
> here.

ok, only "statics" is used for both variable and comments now.
I've also now put the magic constants into opcodes/mips.h as
MIPS16_ALL_ARGS amd MIPS16_ALL_STATICS.
new patch below.  regressions ok.

David.

	* mips.h: Assign 'm'/'M' codes to MIPS16e save/restore
	instructions.  Define MIPS16_ALL_ARGS and MIPS16_ALL_STATICS for
	save/restore encoding of the args field.

        * mips16-opc.c: Add MIPS16e save/restore opcodes.
        * mips-dis.c (print_mips16_insn_arg): Handle printing of 'm'/'M'
        codes for save/restore.

        * config/tc-mips.c (mips16_ip): Add handling of 'm' and 'M' codes
        for the MIPS16e save/restore instructions.

        * gas/mips/mips.exp: Run new save/restore tests.
        * gas/testsuite/gas/mips/mips16e-save.s: New test for generating
        different styles of save/restore instructions.
        * gas/testsuite/gas/mips/mips16e-save.d: New.

Index: include/opcode/mips.h
===================================================================
RCS file: /cvs/src/src/include/opcode/mips.h,v
retrieving revision 1.45
diff -c -p -b -r1.45 mips.h
*** include/opcode/mips.h       6 Sep 2005 18:42:58 -0000       1.45
--- include/opcode/mips.h       20 Oct 2005 13:37:44 -0000
*************** extern int bfd_mips_num_opcodes;
*** 928,933 ****
--- 928,935 ----
     "A" 8 bit PC relative address * 4 (MIPS16OP_*_IMM8)
     "B" 5 bit PC relative address * 8 (MIPS16OP_*_IMM5)
     "E" 5 bit PC relative address * 4 (MIPS16OP_*_IMM5)
+    "m" 7 bit register list for save instruction (18 bit extended)
+    "M" 7 bit register list for restore instruction (18 bit extended)
     */
  
+ /* Save/restore encoding for the args field when all 4 registers are
+    either saved as arguments or saved/restored as statics.  */
+ #define MIPS16_ALL_ARGS    0xe
+ #define MIPS16_ALL_STATICS 0xb
+ 
  /* For the mips16, we use the same opcode table format and a few of
     the same flags.  However, most of the flags are different.  */

Index: opcodes/mips16-opc.c
===================================================================
RCS file: /cvs/src/src/opcodes/mips16-opc.c,v
retrieving revision 1.9
diff -c -p -b -r1.9 mips16-opc.c
*** opcodes/mips16-opc.c        23 Aug 2005 11:06:10 -0000      1.9
--- opcodes/mips16-opc.c        20 Oct 2005 13:42:42 -0000
*************** const struct mips_opcode mips16_opcodes[
*** 226,231 ****
--- 226,233 ----
  {"jalrc",   "R,x",    0xe8c0, 0xf8ff, WR_31|RD_x|TRAP, 0,     0 },
  {"jrc",     "x",      0xe880, 0xf8ff, RD_x|TRAP,      0,      0 },
  {"jrc",     "R",      0xe8a0, 0xffff, RD_31|TRAP,     0,      0 },
+ {"restore", "M",      0x6400, 0xff80, WR_31|RD_SP|WR_SP|TRAP, 0,    0 },
+ {"save",    "m",      0x6480, 0xff80, RD_31|RD_SP|WR_SP|TRAP, 0,    0 },
  {"seb",           "x",        0xe891, 0xf8ff, WR_x|RD_x,      0,      0 },
  {"seh",           "x",        0xe8b1, 0xf8ff, WR_x|RD_x,      0,      0 },
  {"sew",           "x",        0xe8d1, 0xf8ff, WR_x|RD_x,      0,      I3 },

Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.325
diff -c -p -b -r1.325 tc-mips.c
*** gas/config/tc-mips.c	1 Nov 2005 01:59:28 -0000	1.325
--- gas/config/tc-mips.c	3 Nov 2005 17:39:48 -0000
*************** mips16_ip (char *str, struct mips_cl_ins
*** 9836,9841 ****
--- 9836,10013 ----
  	      }
  	    continue;
  
+ 	    case 'm':		/* Register list for save insn.  */
+ 	    case 'M':		/* Register list for restore insn.  */
+ 	      {
+ 		int opcode = 0;
+ 		int framesz = 0, seen_framesz = 0;
+ 		int args = 0, statics = 0, sregs = 0;
+ 
+ 		while (*s != '\0')
+ 		  {
+ 		    unsigned int reg1, reg2;
+ 
+ 		    while (*s == ' ' || *s == ',')
+ 		      ++s;
+ 		    my_getExpression (&imm_expr, s);
+ 		    if (imm_expr.X_op == O_constant)
+ 		      {
+ 			/* Handle the frame size.  */
+ 			if (seen_framesz)
+ 			  {
+ 			    as_bad (_("more than one frame size in list"));
+ 			    break;
+ 			  }
+ 			seen_framesz = 1;
+ 			framesz = imm_expr.X_add_number;
+ 			imm_expr.X_op = O_absent;
+ 			s = expr_end;
+ 			continue;
+ 		      }
+ 
+ 		    if (*s != '$')
+ 		      {
+ 			as_bad (_("can't parse register list"));
+ 			break;
+ 		      }
+ 		    ++s;
+ 
+ 		    reg1 = 0;
+ 		    while (ISDIGIT (*s))
+ 		      {
+ 			reg1 *= 10;
+ 			reg1 += *s - '0';
+ 			++s;
+ 		      }
+ 		    if (*s == ' ')
+ 		      ++s;
+ 		    if (*s != '-')
+ 		      reg2 = reg1;
+ 		    else
+ 		      {
+ 			++s;
+ 			if (*s == '$')
+ 			  ++s;
+ 			reg2 = 0;
+ 			while (ISDIGIT (*s))
+ 			  {
+ 			    reg2 *= 10;
+ 			    reg2 += *s - '0';
+ 			    ++s;
+ 			  }
+ 		      }
+ 
+ 		    while (reg1 <= reg2)
+ 		      {
+ 			if (reg1 >= 4 && reg1 <= 7)
+ 			  {
+ 			    if (c == 'm' && !seen_framesz)
+ 				/* args $a0-$a3 */
+ 				args |= 1 << (reg1 - 4);
+ 			    else
+ 				/* statics $a0-$a3 */
+ 				statics |= 1 << (reg1 - 4);
+ 			  }
+ 			else if ((reg1 >= 16 && reg1 <= 23) || reg1 == 30)
+ 			  {
+ 			    /* $s0-$s8 */
+ 			    sregs |= 1 << ((reg1 == 30) ? 8 : (reg1 - 16));
+ 			  }
+ 			else if (reg1 == 31)
+ 			  {
+ 			    /* Add $ra to insn.  */
+ 			    opcode |= 0x40;
+ 			  }
+ 			else
+ 			  {
+ 			    as_bad (_("unexpected register in list"));
+ 			    break;
+ 			  }
+ 			if (++reg1 == 24)
+ 			  reg1 = 30;
+ 		      }
+ 		  }
+ 
+ 		/* Encode args/tatics combination.  */
+ 		if (args & statics)
+ 		  as_bad (_("arg/static registers overlap"));
+ 		else if (args == 0xf)
+ 		  /* All $a0-$a3 are args.  */
+ 		  opcode |= MIPS16_ALL_ARGS << 16;
+ 		else if (statics == 0xf)
+ 		  /* All $a0-$a3 are statics.  */
+ 		  opcode |= MIPS16_ALL_STATICS << 16;
+ 		else 
+ 		  {
+ 		    int narg = 0, nstat = 0;
+ 
+ 		    /* Count arg registers.  */
+ 		    while (args & 0x1)
+ 		      {
+ 			args >>= 1;
+ 			narg++;
+ 		      }
+ 		    if (args != 0)
+ 		      as_bad (_("invalid arg register list"));
+ 
+ 		    /* Count static registers.  */
+ 		    while (statics & 0x8)
+ 		      {
+ 			statics = (statics << 1) & 0xf;
+ 			nstat++;
+ 		      }
+ 		    if (statics != 0) 
+ 		      as_bad (_("invalid static register list"));
+ 
+ 		    /* Encode args/statics.  */
+ 		    opcode |= ((narg << 2) | nstat) << 16;
+ 		  }
+ 
+ 		/* Encode $s0/$s1.  */
+ 		if (sregs & (1 << 0))		/* $s0 */
+ 		  opcode |= 0x20;
+ 		if (sregs & (1 << 1))		/* $s1 */
+ 		  opcode |= 0x10;
+ 		sregs >>= 2;
+ 
+ 		if (sregs != 0)
+ 		  {
+ 		    /* Count regs $s2-$s8.  */
+ 		    int nsreg = 0;
+ 		    while (sregs & 1)
+ 		      {
+ 			sregs >>= 1;
+ 			nsreg++;
+ 		      }
+ 		    if (sregs != 0)
+ 		      as_bad (_("invalid static register list"));
+ 		    /* Encode $s2-$s8. */
+ 		    opcode |= nsreg << 24;
+ 		  }
+ 
+ 		/* Encode frame size.  */
+ 		if (!seen_framesz)
+ 		  as_bad (_("missing frame size"));
+ 		else if ((framesz & 7) != 0 || framesz < 0
+ 			 || framesz > 0xff * 8)
+ 		  as_bad (_("invalid frame size"));
+ 		else if (framesz != 128 || (opcode >> 16) != 0)
+ 		  {
+ 		    framesz /= 8;
+ 		    opcode |= (((framesz & 0xf0) << 16)
+ 			     | (framesz & 0x0f));
+ 		  }
+ 
+ 		/* Finally build the instruction.  */
+ 		if ((opcode >> 16) != 0 || framesz == 0)
+ 		  {
+ 		    ip->use_extend = TRUE;
+ 		    ip->extend = opcode >> 16;
+ 		  }
+ 		ip->insn_opcode |= opcode & 0x7f;
+ 	      }
+ 	    continue;
+ 
  	    case 'e':		/* extend code */
  	      my_getExpression (&imm_expr, s);
  	      check_absolute_expr (ip, &imm_expr);

Index: opcodes/mips-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/mips-dis.c,v
retrieving revision 1.54
diff -c -p -b -r1.54 mips-dis.c
*** opcodes/mips-dis.c	6 Sep 2005 18:46:57 -0000	1.54
--- opcodes/mips-dis.c	3 Nov 2005 17:42:27 -0000
*************** print_mips16_insn_arg (char type,
*** 1656,1661 ****
--- 1656,1747 ----
        }
        break;
  
+     case 'm':
+     case 'M':
+       /* MIPS16e save/restore.  */
+       {
+ 	int need_comma = 0;
+ 	int amask, args, statics;
+ 	int nsreg, smask;
+ 	int framesz;
+ 	int i, j;
+ 
+ 	l = l & 0x7f;
+ 	if (use_extend)
+ 	  l |= extend << 16;
+ 
+ 	amask = (l >> 16) & 0xf;
+ 	if (amask == MIPS16_ALL_ARGS)
+ 	  {
+ 	    args = 4;
+ 	    statics = 0;
+ 	  }
+ 	else if (amask == MIPS16_ALL_STATICS)
+ 	  {
+ 	    args = 0;
+ 	    statics = 4;
+ 	  }
+ 	else
+ 	  {
+ 	    args = amask >> 2;
+ 	    statics = amask & 3;
+ 	  }
+ 
+ 	if (args > 0) {
+ 	    (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
+ 	    if (args > 1)
+ 	      (*info->fprintf_func) (info->stream, "-%s",
+ 				     mips_gpr_names[4 + args - 1]);
+ 	    need_comma = 1;
+ 	}
+ 
+ 	framesz = (((l >> 16) & 0xf0) | (l & 0x0f)) * 8;
+ 	if (framesz == 0 && !use_extend)
+ 	  framesz = 128;
+ 
+ 	(*info->fprintf_func) (info->stream, "%s%d", 
+ 			       need_comma ? "," : "",
+ 			       framesz);
+ 
+ 	if (l & 0x40) 			/* $ra */
+ 	  (*info->fprintf_func) (info->stream, ",%s", mips_gpr_names[31]);
+ 
+ 	nsreg = (l >> 24) & 0x7;
+ 	smask = 0;
+ 	if (l & 0x20) 			/* $s0 */
+ 	  smask |= 1 << 0;
+ 	if (l & 0x10) 			/* $s1 */
+ 	  smask |= 1 << 1;
+ 	if (nsreg > 0) 			/* $s2-$s8 */
+ 	  smask |= ((1 << nsreg) - 1) << 2;
+ 
+ 	/* Find first set static reg bit.  */
+ 	for (i = 0; i < 9; i++)
+ 	  {
+ 	    if (smask & (1 << i))
+ 	      {
+ 		(*info->fprintf_func) (info->stream, ",%s",
+ 				       mips_gpr_names[i == 8 ? 30 : (16 + i)]);
+ 		/* Skip over string of set bits.  */
+ 		for (j = i; smask & (2 << j); j++)
+ 		  continue;
+ 		if (j > i)
+ 		  (*info->fprintf_func) (info->stream, "-%s",
+ 					 mips_gpr_names[j == 8 ? 30 : (16 + j)]);
+ 		i = j + 1;
+ 	      }
+ 	  }
+ 
+ 	/* Statics $ax - $a3.  */
+ 	if (statics == 1)
+ 	  (*info->fprintf_func) (info->stream, ",%s", mips_gpr_names[7]);
+ 	else if (statics > 0) 
+ 	  (*info->fprintf_func) (info->stream, ",%s-%s", 
+ 				 mips_gpr_names[7 - statics + 1],
+ 				 mips_gpr_names[7]);
+       }
+       break;
+ 
      default:
        /* xgettext:c-format */
        (*info->fprintf_func)

Index: gas/testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.110
diff -c -p -b -r1.110 mips.exp
*** gas/testsuite/gas/mips/mips.exp     19 Oct 2005 18:47:09 -0000      1.110
--- gas/testsuite/gas/mips/mips.exp     20 Oct 2005 13:39:56 -0000
*************** if { [istarget mips*-*-*] } then {
*** 771,775 ****
            run_dump_test "mips16-dwarf2-n32"
        }
      }
!     if { !$no_mips16 } { run_dump_test "mips16e-jrc" }
  }
--- 771,778 ----
            run_dump_test "mips16-dwarf2-n32"
        }
      }
!     if { !$no_mips16 } { 
!         run_dump_test "mips16e-jrc"
!         run_dump_test "mips16e-save"
!     }
  }

Index: gas/testsuite/gas/mips/mips16e-save.s
===================================================================
# Test the generation of the mips16e save instruction

        .set    mips16
        .text
func:
# Un-extended version
        save    8
        save    $31,16
        save    $16,24
        save    $17,32
        save    $16-17,40
        save    $31,$16,48
        save    $31,$17,56
        save    $31,$16,$17,64
        save    $31,$16-17,72
        save    80,$31,$16-17
        save    $31,88,$16,$17
        save    $31,$17,128,$16

# Extended version
        save    136
        save    $31,144
        save    $16-17,152

        # sreg
        save    $18,64
        save    $18-23,72
        save    $18-23,$30,80
        save    $16-23,$30,88
        
        # static areg
        save    64,$7
        save    128,$7,$6
        save    256,$7,$6,$5,$4

        # areg
        save    $4,256
        save    $4,$5,128
        save    $4,$5,$6,$7,64

        # mix areg and static areg
        save    $4,128,$7
        save    $4,128,$7,$6,$5
        save    $4,$5,128,$7,$6
        save    $4,$5,$6,128,$7

        save    $4-5,$16-23,$30-31,128,$6-7

        restore $16,$17,$31,128
        restore $31,136
        restore $18,64
        restore $4-5,$16-23,$30-31,128,$6-7
        
        .p2align 4


Index: gas/testsuite/gas/mips/mips16e-save.s
===================================================================
#objdump: -dr -mmips:isa32 -mmips:16
#as: -march=mips32 -mips16
#name: mips16e save/restore
.*:     file format .*
Disassembly of section .text:
00000000 <func>:
   0:   6481            save    8
   2:   64c2            save    16,ra
   4:   64a3            save    24,s0
   6:   6494            save    32,s1
   8:   64b5            save    40,s0-s1
   a:   64e6            save    48,ra,s0
   c:   64d7            save    56,ra,s1
   e:   64f8            save    64,ra,s0-s1
  10:   64f9            save    72,ra,s0-s1
  12:   64fa            save    80,ra,s0-s1
  14:   64fb            save    88,ra,s0-s1
  16:   64f0            save    128,ra,s0-s1
  18:   f010 6481       save    136
  1c:   f010 64c2       save    144,ra
  20:   f010 64b3       save    152,s0-s1
  24:   f100 6488       save    64,s2
  28:   f600 6489       save    72,s2-s7
  2c:   f700 648a       save    80,s2-s8
  30:   f700 64bb       save    88,s0-s8
  34:   f001 6488       save    64,a3
  38:   f012 6480       save    128,a2-a3
  3c:   f02b 6480       save    256,a0-a3
  40:   f024 6480       save    a0,256
  44:   f018 6480       save    a0-a1,128
  48:   f00e 6488       save    a0-a3,64
  4c:   f015 6480       save    a0,128,a3
  50:   f017 6480       save    a0,128,a1-a3
  54:   f01a 6480       save    a0-a1,128,a2-a3
  58:   f01d 6480       save    a0-a2,128,a3
  5c:   f71a 64f0       save    a0-a1,128,ra,s0-s8,a2-a3
  60:   6470            restore 128,ra,s0-s1
  62:   f010 6441       restore 136,ra
  66:   f100 6408       restore 64,s2
  6a:   f71b 6470       restore 128,ra,s0-s8,a0-a3
  6e:   6500            nop


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]