This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
RFC: additions to the machine-definition language
- To: gcc at gcc dot gnu dot org
- Subject: RFC: additions to the machine-definition language
- From: Dan Nicolaescu <dann at godzilla dot ICS dot UCI dot EDU>
- Date: Mon, 07 May 2001 18:10:43 -0700
Hi!
I was looking for some bugs in a machine definition & associated files
and it occured to me that a lot of the #define gobbledygook needed to
described a processor could be moved to the .md file and be made
smaller and cleaner in the process.
So I did a proof-of-concept implementation of this in emacs-lisp.
(Why? Because it's really easy to do, and everybody
has emacs, and I was bored... :)
The implemented features are:
(define-register "REGNAME")
(define-register-class (REGISTER_LIST))
(define-pic-offset-table-reg "REGNAME")
(define-arg-pointer-reg "REGNAME")
(define-frame-pointer-reg "REGNAME")
(define-fixed-registers "REGNAME")
(define-call-used-registers "REGNAME")
(define-reg-alloc-order REGISTER_LIST OR REG_CLASS_LIST)
(define-leaf-reg-alloc-order REGISTER_LIST OR REG_CLASS_LIST)
The current implementation will output the following:
#define REGISTER_NAMES ...
#define FIRST_PSEUDO_REGISTER ...
#define FRAME_POINTER_REGNUM ...
#define ARG_POINTER_REGNUM ...
#define PIC_OFFSET_TABLE_REGNUM ...
enum regclass ...
#define N_REG_CLASSES ...
#define REG_CLASS_NAMES ...
#define REG_CLASS_CONTENTS ...
#define FIXED_REGISTERS ...
#define CALL_USED_REGISTERS ...
#define REG_ALLOC_ORDER ...
#define REG_LEAF_ALLOC_ORDER ...
The main advantage is that it's a lot easier and less error prone to
define these things in the .md file that to
To try it, save the attachments as def-reg.el (the actual
implementation) and sparc.el (shows how to use it for the SPARC
processor)
and in emacs do:
M-x load-file RET def-reg.el RET
M-x load-file RET sparc.el RET
Create an empty buffer and do:
M-x dr-output RET
What do you think?
Please ignore that the syntax is not always orthogonal, this was done
having minimum effort as a priorty (besides it's easily fixable). The
current elisp code is intended as a fast prototyping tool and as a
proof-of-concept to have all the warts figured out before actually
doing a C implementation.
Is this worthwile pursuing? Comments, ideas are always welcome.
--dan
;;; Package for prototyping enhancements for GCC's .md files
;;; Author: Dan Nicolaescu <dann@ics.uci.edu>
;;;
;;; The goal of this is to get rid of a lot of preprocessor
;;; gobbledygook from the machine definition header files and put
;;; something more intelligible in the .md files, where it belongs.
;;;
;;;
;;; Implemented features: (see sparc.el for usage examples)
;;; define-register
;;; define-register-class
;;; define-pic-offset-table-reg
;;; define-arg-pointer-reg
;;; define-frame-pointer-reg
;;; define-fixed-registers
;;; define-call-used-registers
;;; define-reg-alloc-order
;;; define-leaf-reg-alloc-order
;;; TODO:
;;; eazy:
;;; - allow conditionals in `define-fixed-registers' and
;;; `define-call-used-registers' to be able to generate
;;; "CONDITIONAL_REGISTER_USAGE"
;;; - make `define-register-class' also take register classes as
;;; parameters, not only registers
;;; - define data the type sizes
;;; harder:
;;; - there should be a way to define addressing modes
;;; - translate the whole thing to C? -- bleah
;;; - other suggestions and help are welcome
(require 'cl)
;; Emacsen befor 21.x don't have mapc
(unless (fboundp 'mapc) (fset 'mapc 'mapcar))
(defvar dr-regset nil)
(defvar dr-regset-const-name nil)
(defvar dr-regnum 0)
(defvar dr-regclassset nil)
(defvar dr-fixed-registers nil)
(defvar dr-call-used-registers nil)
(defvar dr-reg-alloc-order nil)
(defvar dr-leaf-reg-alloc-order nil)
(defvar dr-frame-pointer-reg nil)
(defvar dr-arg-pointer-reg nil)
(defvar dr-pic-offset-table-reg nil)
(defun define-register (regname &optional const-name)
(setq dr-regset (push (cons regname dr-regnum) dr-regset))
(when const-name
(setq dr-regset-const-name
(push (cons const-name dr-regnum) dr-regset-const-name)))
(setq dr-regnum (1+ dr-regnum)))
(defmacro define-registers (rlist)
`(mapc 'define-register (list ,@rlist)))
(defmacro define-register-class (classname letter reglist)
`(setq dr-regclassset
(push
(list ,classname ,letter
(list ,@reglist))
dr-regclassset)))
(defmacro dr-add-to-list (lst &rest reg-or-class-lst)
`(mapc
(lambda (elem)
(if (listp elem)
;; it's a regclass
(setq ,lst
(append
(reverse
(mapcar (lambda (cls-lst-elem)
(cdr (assoc cls-lst-elem dr-regset)))
(caddr (assoc (cadr elem) dr-regclassset))))
,lst))
;; it's a register
(setq ,lst
(push (cdr (assoc elem dr-regset))
,lst))))
(list ,@reg-or-class-lst)))
(defmacro define-fixed-registers (&rest reg-or-class-list)
`(dr-add-to-list dr-fixed-registers ,@reg-or-class-list))
(defmacro define-call-used-registers (&rest reg-or-class-list)
`(dr-add-to-list dr-call-used-registers ,@reg-or-class-list))
(defmacro define-reg-alloc-order (&rest reg-or-class-list)
`(dr-add-to-list dr-reg-alloc-order ,@reg-or-class-list))
(defmacro define-leaf-reg-alloc-order (&rest reg-or-class-list)
`(dr-add-to-list dr-leaf-reg-alloc-order ,@reg-or-class-list))
(defmacro define-frame-pointer-reg (regname)
(setq dr-frame-pointer-reg regname))
(defmacro define-arg-pointer-reg (regname)
(setq dr-arg-pointer-reg regname))
(defmacro define-pic-offset-table-reg (regname)
(setq dr-pic-offset-table-reg regname))
(defun dr-reset-internal-vars ()
(interactive)
(setq dr-regclassset nil)
(setq dr-regset-const-name nil)
(setq dr-regset nil)
(setq dr-regnum 0)
(setq dr-fixed-registers nil)
(setq dr-call-used-registers nil)
(setq dr-leaf-reg-alloc-order nil)
(setq dr-reg-alloc-order nil)
(setq dr-frame-pointer-reg nil)
(setq dr-arg-pointer-reg nil)
(setq dr-pic-offset-table-reg nil))
(defun dr-output ()
(interactive)
(dr-output-regset-const-name (current-buffer))
(dr-output-reg-names (current-buffer))
(dr-output-first-pseudo (current-buffer))
(dr-output-frame-pointer-reg (current-buffer))
(dr-output-arg-pointer-reg (current-buffer))
(dr-output-pic-offset-table-reg (current-buffer))
(dr-output-regclass-enum (current-buffer))
(dr-output-n-regclasses (current-buffer))
(dr-output-regclass-names (current-buffer))
(dr-output-regclass-contents (current-buffer))
(dr-output-fixed-registers (current-buffer))
(dr-output-call-used-registers (current-buffer))
(dr-output-reg-alloc-order (current-buffer))
(dr-output-leaf-reg-alloc-order (current-buffer)))
(defun dr-output-regset-const-name (buff)
(with-current-buffer buff
(insert "\n")
(mapc (lambda (elem) (insert
(format "#define %s %d\n"
(car elem) (cdr elem))))
(reverse dr-regset-const-name))
(insert "\n")))
(defun dr-output-reg-names (buff)
(with-current-buffer buff
(insert "#define REGISTER_NAMES \\\n{")
(mapc (lambda (elem) (insert (format "\"%s\", " (car elem))))
(reverse dr-regset))
;; delete the last space and comma
(delete-backward-char 2)
(insert "}\n")))
(defun dr-output-regclass-enum (buff)
(with-current-buffer buff
(insert "\nenum regclass { NO_REGS, ")
(mapc (lambda (elem) (insert (format "%s, " (car elem))))
(reverse dr-regclassset))
(insert "ALL_REGS };\n")))
(defun dr-output-regclass-names (buff)
(with-current-buffer buff
(insert "\n#define REG_CLASS_NAMES { \"NO_REGS\", \\\n")
(mapc (lambda (elem) (insert (format "\"%s\", " (car elem))))
(reverse dr-regclassset))
(insert "\\\n\"ALL_REGS\" }\n")))
(defun dr-output-n-regclasses (buff)
(with-current-buffer buff
(insert (format "\n#define N_REG_CLASSES %d\n"
(+ 2 (length dr-regclassset))))))
(defun dr-output-first-pseudo (buff)
(with-current-buffer buff
(insert (format "\n#define FIRST_PSEUDO_REGISTER %d\n"
dr-regnum))))
(defmacro dr-output-1-if-in-list (lst)
`(dotimes (cnt dr-regnum)
(if (member cnt ,lst)
(insert "1, ")
(insert "0, "))))
(defun dr-output-fixed-registers (buff)
(with-current-buffer buff
(insert "\n#define FIXED_REGISTERS \\\n{")
(dr-output-1-if-in-list dr-fixed-registers)
;; delete the last space and comma
(delete-backward-char 2)
(insert "}\n")))
(defun dr-output-call-used-registers (buff)
(with-current-buffer buff
(insert "\n#define CALL_USED_REGISTERS \\\n{")
(dr-output-1-if-in-list dr-call-used-registers)
;; delete the last space and comma
(delete-backward-char 2)
(insert "}\n")))
(defun dr-output-reg-alloc-order (buff)
(with-current-buffer buff
(insert "\n#define REG_ALLOC_ORDER \\\n{")
(mapc (lambda (elem)
(insert (format "%d, " elem)))
(reverse dr-reg-alloc-order))
;; delete the last space and comma
(delete-backward-char 2)
(insert "}\n")))
(defun dr-output-leaf-reg-alloc-order (buff)
(with-current-buffer buff
(insert "\n#define REG_LEAF_ALLOC_ORDER \\\n{")
(mapc (lambda (elem)
(insert (format "%d, " elem)))
(reverse dr-leaf-reg-alloc-order))
;; delete the last space and comma
(delete-backward-char 2)
(insert "}\n")))
(defun dr-output-one-regclass (regclasslist)
(insert (format "{/*%s*/ " (car regclasslist)))
(let ((num 0)
;; construct the register list as numbers
(rlist (mapcar (lambda (elem)
(cdr (assoc elem dr-regset)))
(caddr regclasslist))))
(dotimes (i words)
;; emacs' integers are 28 bits, so we go 16 bits at a time
(setq num 0)
(insert "0x")
(dotimes (j 16)
(when (member (+ (* i 32) j 16) rlist)
(setq num (logior num (lsh 1 j)))))
(insert (format "%x" num))
(setq num 0)
(dotimes (j 16)
(when (member (+ (* i 32) j) rlist)
(setq num (logior num (lsh 1 j)))))
(insert (format "%x" num))
(insert ", ")))
(delete-backward-char 2)
(insert "}, \\\n"))
(defun dr-output-regclass-contents (buff)
(with-current-buffer buff
(insert "\n#define REG_CLASS_CONTENTS {\\\n")
;; we need words words for the representation
(let ((words (1+ (/ dr-regnum 32))))
(dr-output-one-regclass (list "NOREGS" "N" '()))
(mapc 'dr-output-one-regclass
(reverse dr-regclassset))
(dr-output-one-regclass (list "ALL_REGS" "A"
(reverse (mapcar 'car dr-regset)))))
(delete-backward-char 4)
(insert "}\n")))
(defun dr-output-frame-pointer-reg (buff)
(with-current-buffer buff
(insert (format "\n#define FRAME_POINTER_REGNUM %d\n"
(cdr (assoc dr-frame-pointer-reg dr-regset))))))
(defun dr-output-arg-pointer-reg (buff)
(with-current-buffer buff
(insert (format "\n#define ARG_POINTER_REGNUM %d\n"
(cdr (assoc dr-arg-pointer-reg dr-regset))))))
(defun dr-output-pic-offset-table-reg (buff)
(with-current-buffer buff
(insert (format "\n#define PIC_OFFSET_TABLE_REGNUM %d\n"
(cdr (assoc dr-pic-offset-table-reg dr-regset))))))
(provide 'def-reg)
(require 'def-reg)
(dr-reset-internal-vars)
(define-registers ("%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"))
(define-registers ("%o0" "%o1" "%o2" "%o3" "%o4" "%o5"))
(define-register "%sp" "STACK_POINTER") ;; this one also generates a
;; #define STACK_POINTER
;; register_number
(define-register "%o7")
(define-registers ("%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"))
(define-registers ("%i0" "%i1" "%i2" "%i3" "%i4" "%i5"))
(define-register "%fp" "FRAME_POINTER")
(define-register "%i7")
(define-registers ("%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"))
(define-registers ("%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"))
(define-registers ("%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"))
(define-registers ("%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"))
(define-registers ("%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"))
(define-registers ("%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"))
(define-registers ("%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"))
(define-registers ("%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"))
(define-registers ("%fcc0" "%fcc1" "%fcc2" "%fcc3"))
(define-register "%icc")
(define-pic-offset-table-reg "%l7")
(define-arg-pointer-reg "%fp")
(define-frame-pointer-reg "%fp")
(define-register-class "FPCC_REGS" "c" ("%fcc0" "%fcc1" "%fcc2" "%fcc3"))
(define-register-class "I64_REGS" "h"
("%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
"%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7"))
(define-register-class "GENERAL_REGS" "r"
("%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
"%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
"%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
"%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7"))
(define-register-class "FP_REGS" "f"
("%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
"%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
"%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
"%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"))
(define-register-class "EXTRA_FP_REGS" "e"
("%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
"%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
"%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
"%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"
"%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"
"%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"
"%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"
"%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"))
;; the letter is wrong
(define-register-class "GENERAL_OR_FP_REGS" "g"
("%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
"%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
"%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
"%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7"
"%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
"%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
"%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
"%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"))
;; the letter is wrong
(define-register-class "GENERAL_OR_EXTRA_FP_REGS" "b"
("%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
"%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
"%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
"%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7"
"%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
"%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
"%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
"%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"
"%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"
"%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"
"%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"
"%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"))
(define-fixed-registers "%g0" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7")
(define-call-used-registers
"%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
"%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
"%fp" "%i7"
'(regclass "EXTRA_FP_REGS")
'(regclass "FPCC_REGS")
"%icc")
(define-reg-alloc-order
"%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%g2" "%g3"
'(regclass "I64_REGS")
"%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
"%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
"%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
"%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"
"%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"
"%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"
"%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"
"%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"
"%f0" "%f1"
'(regclass "FPCC_REGS")
"%icc"
"%g1" "%g4" "%g5" "%g6" "%g7" "%g0" "%sp" "%fp")
(define-leaf-reg-alloc-order
"%g2" "%g3" "%i0" "%i1" "%i2" "%i3" "%i4" "%i5"
"%g4" "%g5" "%g6" "%g7" "%g1"
"%o7" "%o0" "%o1" "%o2" "%o3" "%o4" "%o5"
"%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
"%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
"%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
"%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
"%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"
"%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"
"%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"
"%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"
"%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"
"%f0" "%f1"
'(regclass "FPCC_REGS")
"%icc"
"%g0" "%sp" "%fp" "%i7")