File: gasPseudoOps.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (146 lines) | stat: -rw-r--r-- 5,301 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
(* gasPseudoOps.sml
 *
 * COPYRIGHT (c) 2006 The Fellowship of SML/NJ (www.smlnj.org)
 * All rights reserved.
 *
 * Implements the string related functions to emit pseudo-ops
 * in the standard GAS syntax (see http://www.gnu.org/software/binutils/manual/gas-2.9.1/)
 *)

functor GasPseudoOps (
    structure T : MLTREE
    val labFmt : {gPrefix: string, aPrefix: string}
  ) : AS_PSEUDO_OPS =
  struct
    structure T = T
    structure PB = PseudoOpsBasisTyp
    structure Fmt = Format

    fun error msg = MLRiscErrorMsg.error ("GasPseudoOps.", msg)

    fun prIntInf i = if IntInf.sign i < 0 then "-"^IntInf.toString(IntInf.~ i) 
                     else IntInf.toString i

    fun prInt i = if i < 0 then "-"^Int.toString(~i) else Int.toString i

    (* operator precedences:
       Note: these differ from C's precedences
	    3 NEG, NOTB
	    2 MULS, DIVS, SLL, SRA
	    1 ANDB, ORB, XORB
	    0 PLUS, MINUS
    *)

  (* NOTE: we use ">=" here instead of ">" so that we don't have to worry about associativity *)
    fun parens (str, prec, op_prec) = 
	if prec >= op_prec then "(" ^ str ^ ")" else str

    fun lexpToString le = toStr(le, 0)

    and toStr(T.LABEL lab, _) = Label.fmt labFmt lab 
      | toStr(T.LABEXP le, p) = toStr(le, p)
      | toStr(T.NEG(_, T.CONST c), _) =
          (prInt(~(T.Constant.valueOf c)) handle _ => "-"^T.Constant.toString c)
      | toStr(T.NEG(_, T.LI i), _) = prIntInf(~i)
      | toStr(T.NEG(_, lexp), prec) = "-" ^ parens(toStr(lexp, 3), prec, 3)
      | toStr(T.NOTB(_, lexp), prec) = "~" ^ parens(toStr(lexp, 3), prec, 3)
      | toStr(T.CONST c, _) = 
          (prInt(T.Constant.valueOf c) handle _ => T.Constant.toString c)
      | toStr(T.LI i, _) = prIntInf i
      | toStr(T.MULS(_,lexp1, lexp2), prec) =
	  parens(toStr(lexp1, 2) ^ "*" ^ toStr(lexp2,2), prec, 2)
      | toStr(T.DIVS(T.DIV_TO_ZERO, _, lexp1, lexp2), prec) =
	  parens(toStr(lexp1, 2) ^ "/" ^ toStr(lexp2,2), prec, 2)
      | toStr(T.SLL(_,lexp, cnt), prec) =
	  parens(toStr(lexp,2) ^ "<<" ^ toStr(cnt,2), prec, 2)
      | toStr(T.SRA(_,lexp, cnt), prec) =
	  parens(toStr(lexp,2) ^ ">>" ^ toStr(cnt,2), prec, 2)
      | toStr(T.ANDB(_,lexp, mask), prec) = 
          parens(toStr(lexp,1) ^ "&" ^ toStr(mask, 1), prec, 1)
      | toStr(T.ORB(_,lexp, mask), prec) = 
          parens(toStr(lexp, 1) ^ "|" ^ toStr(mask, 1), prec, 1)
      | toStr(T.XORB(_,lexp, mask), prec) = 
          parens(toStr(lexp, 1) ^ "^" ^ toStr(mask, 1), prec, 1)
      | toStr(T.ADD(_,lexp1, lexp2), prec) = 
          parens(toStr(lexp1, 0) ^ "+" ^ toStr(lexp2, 0), prec, 0)
      | toStr(T.SUB(_,lexp1, lexp2), prec) = 
          parens(toStr(lexp1, 0) ^ "-" ^ toStr(lexp2, 0), prec, 0)
      | toStr _ = error "toStr"

    fun defineLabel lab = lexpToString (T.LABEL lab) ^ ":"

    fun decls (fmt, labs) =
	  String.concat 
	    (map (fn lab => (Fmt.format fmt [Fmt.STR (lexpToString(T.LABEL lab))])) labs)

    (* if i is a power of two, return the lg of i, otherwise return nothing *)
    fun lg i = let
        fun loop (0, k) = SOME k
	  | loop (i, k) = if i mod 2 = 0
            then loop (i div 2, k+1)
	    else NONE
        in
	   loop (i, 0)
        end

    fun toString(PB.ALIGN_SZ n)     = 
        (* always favor p2align because it is guaranteed to be consistent across assemblers *)
        (case lg n
         of NONE => Fmt.format "\t.align\t%d" [Fmt.INT n]
	  | SOME k => Fmt.format "\t.p2align\t%d" [Fmt.INT k]
        (* end case *))
      | toString(PB.ALIGN_ENTRY)    = "\t.align\t4"	(* 16 byte boundary *)
      | toString(PB.ALIGN_LABEL)    = "\t.p2align\t4,,7"

      | toString(PB.DATA_LABEL lab) = Label.fmt labFmt lab ^ ":"
      | toString(PB.DATA_READ_ONLY) = "\t.section\t.rodata"
      | toString(PB.DATA)	    = "\t.data"
      | toString(PB.BSS)	    = "\t.section\t.bss"
      | toString(PB.TEXT)	    = "\t.text"
      | toString(PB.SECTION at)     = "\t.section\t" ^ Atom.toString at

      | toString(PB.REORDER)        = ""
      | toString(PB.NOREORDER)      = ""

      | toString(PB.INT{sz, i})     = let
	  fun join [] = []
	    | join [lexp] = [lexpToString lexp]
	    | join (lexp::r) = lexpToString lexp :: "," :: join r
	  val pop = (case sz
		 of 8 => "\t.byte\t"
		  | 16 => "\t.short\t"
		  | 32 => "\t.long\t"
		  | 64 => "\t.quad\t"
		  | n => error ("unexpected INT size: " ^ Int.toString n)
		(* end case *))
	  in
	    String.concat (pop :: join i)
	  end

      | toString(PB.ASCII s)        =
	  Fmt.format "\t.ascii\t\"%s\"" [Fmt.STR(String.toCString s)]
      | toString(PB.ASCIIZ s)       = 
          Fmt.format "\t.asciz\t\"%s\"" [Fmt.STR(String.toCString s)]

      | toString(PB.SPACE sz)	  = Fmt.format "\t.space\t%d" [Fmt.INT sz]

      | toString(PB.FLOAT{sz, f})   = let
	  fun join [] = []
	    | join [f] = [f]
	    | join (f::r) = f :: "," :: join r
	  val pop = (case sz
		 of 32 => "\t.single "
		  | 64 => "\t.double "
		  | 128 => "\t.extended "
		  | n => error ("unexpected FLOAT size: " ^ Int.toString n)
		(* end case *))
	  in
	    String.concat (pop :: join f)
	  end

      | toString(PB.IMPORT labs) = decls("\t.extern\t%s", labs)
      | toString(PB.EXPORT labs) = decls("\t.global\t%s", labs)
      | toString(PB.COMMENT txt) = Fmt.format "/* %s */" [Fmt.STR txt]
      | toString(PB.EXT _) = error "EXT"

  end