File:  [Research Unix] / researchv10no / cmd / sml / src / m68 / m68mcode.sml
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

(* Copyright 1989 by AT&T Bell Laboratories *)
structure M68MCode : M68MCODER = struct

(* DEBUG
fun diag (s : string) f x =
	f x handle e =>
		(print "?exception "; print (System.exn_name e);
		 print " in basicm68."; print s; print "\n";
		 raise e)
*)

structure Jumps = struct
    datatype JumpKind = Jcc of int | LEA of int | FJcc of int | LABPTR of int
			| MODE
  datatype Size = Byte | Word | Long
  
  fun sizeint i =
  	if i < 128 andalso i > ~129 then Byte
  	else if i < 32768 andalso i > ~32769 then Word
  	else Long
  
  exception TooBig (* pc relative addressing only has 16-bit displacement *)
  
  fun sizejump (LEA _, _,s,d) = (* pc relative addressing *)
  	(case sizeint (d - s - 2) of
  	      Byte => 4
  	    | Word => 4
  	    | Long => 8)
    | sizejump (LABPTR _, _, _, _) = 4
    | sizejump (Jcc _, _, s, d) =
  	(case sizeint (d - s - 2) of
  	      Byte => 2
  	    | Word => 4
  	    | Long => 6)
    | sizejump (FJcc _, _, s, d) =
  	(case sizeint (d - s - 2) of
  	      Byte => 4
  	    | Word => 4
  	    | Long => 6)
    | sizejump (MODE,_,_,_) = 2
  
  (* DEBUG val sizejump = diag "sizejump" sizejump *)

fun eword i =
	if i < 0 then eword(65536 + i)
	else chr(i div 256) ^ chr(i mod 256)

fun elong i =
	if i < 0 then
	    let val a = ~i
		val b = a mod 65536
		val c = a div 65536
	    in  eword(~c + (if b = 0 then 0 else ~1)) ^ eword(~b)
	    end
	else eword(i div 65536) ^ eword(i mod 65536)

val emitlong = elong

fun signedbyte i = if i < 0 then signedbyte (256 + i) else i
  
  exception Illegal
  
  fun emitjump (Jcc(opcode),2,s,d) =
  	(case (d-s-2) of
  	       0 => eword(20081) (* nop *)
  	     | _ => eword(opcode + signedbyte (d - s - 2)))
    | emitjump (Jcc(opcode),4,s,d) = eword(opcode) ^ eword(d-s-2)
    | emitjump(Jcc(opcode),6,s,d) = eword(opcode+255) ^ elong(d-s-2)
    | emitjump(LABPTR i, _,s,d) = elong(d-s+i)
    | emitjump (LEA(opcode),4,s,d) = (* pc relative *)
  	eword(opcode+58) ^ eword (d-s-2)
    | emitjump (LEA(opcode),8,s,d) = (* pc relative *)
  	eword(opcode+59) ^ eword 368 ^ elong (d-s-2)
    | emitjump (FJcc(cond),4,s,d) =
  	eword(62080+cond) ^ eword(d-s-2)
    | emitjump (FJcc(cond),6,s,d) =
  	eword(62144+cond) ^ elong(d-s-2)
    | emitjump (MODE,2,s,d) =
      let val x = Integer.-(d,s)
       in if x < 32768 andalso ~32768 <= x
         then eword(d-s) 
         else raise Illegal
      end

  (* DEBUG val emitjump = diag "emitjump" emitjump *)
end (* structure Jumps *)

structure Emitter : BACKPATCH = Backpatch(Jumps)

structure Coder : M68CODER = struct

open Emitter
open Jumps

val emitword = fn i => emitstring(eword i)
val emitlong = fn i => emitstring(elong i)

datatype Register = DataReg of int
		  | AddrReg of int
		  | FloatReg of int
		  | PC

datatype EA = Direct of Register
	    | PostInc of Register
	    | PreDec of Register
	    | Displace of Register * int
	    | Index of Register * int * Register * Size
	    | Immedlab of Label
	    | Immed of int
	    | Abs of int
	    | Address of Label

val d0 = DataReg 0
and d1 = DataReg 1
and d2 = DataReg 2
and d3 = DataReg 3
and d4 = DataReg 4
and d5 = DataReg 5
and d6 = DataReg 6
and d7 = DataReg 7
and a0 = AddrReg 0
and a1 = AddrReg 1
and a2 = AddrReg 2
and a3 = AddrReg 3
and a4 = AddrReg 4
and a5 = AddrReg 5
and a6 = AddrReg 6
and sp = AddrReg 7
and fp0 = FloatReg 0
and fp1 = FloatReg 1
and fp2 = FloatReg 2
and fp3 = FloatReg 3
and fp4 = FloatReg 4
and fp5 = FloatReg 5
and fp6 = FloatReg 6
and fp7 = FloatReg 7

exception BadLabelUse

(* DEBUG
fun diag (s : string) f x =
	f x handle e =>
		(print "?exception "; print (System.exn_name e);
		 print " in m68mcode."; print s; print "\n";
		 raise e)
*)

fun reg (Direct(DataReg d)) = d
  | reg (Direct(AddrReg a)) = a
  | reg (PostInc(AddrReg a)) = a
  | reg (PreDec(AddrReg a)) = a
  | reg (Displace(AddrReg a,_)) = a
  | reg (Displace(DataReg a,_)) = 0
  | reg (Index(PC,_,_,_)) = 3
  | reg (Index(AddrReg a,_,_,_)) = a
  | reg (Abs i) = (case sizeint i of
			  Byte => 0
			| Word => 0
			| Long => 1)
  | reg (Immed _) = 4
  | reg (Address _) = 2

(* DEBUG val reg = diag "reg" reg *)

fun mode (Direct(DataReg _)) = 0
  | mode (Direct(AddrReg _)) = 1
  | mode (Displace(AddrReg _, 0)) = 2
  | mode (PostInc(AddrReg _)) = 3
  | mode (PreDec(AddrReg _)) = 4
  | mode (Displace(AddrReg _,_)) = 5
  | mode (Displace(DataReg _,_)) = 6
  | mode (Index(PC,_,_,_)) = 7
  | mode (Index(AddrReg _,_,_,_)) = 6
  | mode (Abs _) = 7
  | mode (Immed _) = 7
  | mode (Address _) = 7

(* DEBUG val mode = diag "mode" mode *)

(* Very similar to Vax G_float format, except that the byte order within words
   is different and the bias is different by 2. *)
structure M68PrimReal : PRIMREAL =
struct
val significant = 53 (* 52 + redundant 1 bit *)
fun outofrange s = ErrorMsg.complain("Real constant "^s^" out of range")
(* Convert a portion of a boolean array to the appropriate integer. *)
exception Bits
fun bits(a,start,width) =
    let fun b true = 1
	  | b false = 0
	fun f 0 = b (a sub start)
	  | f n = b (a sub (start+n)) + 2 * f(n-1)
    in  if Array.length a < start+width orelse start < 0 orelse width < 0
	then raise Bits
	else f (width-1)
    end
fun emitreal (sign,frac,exp) =
    let val exponent = exp + 1022
	fun emit () =
	    let val word0 =
	           case frac sub 0 of (* zero? *)
	             true => Bits.orb(Bits.lshift(sign,15),
			     	      Bits.orb(Bits.lshift(exponent,4),
				      	       bits(frac,1,4)))
		   | false => 0
		val word1 = bits(frac,5,16)
		val word2 = bits(frac,21,16)
		val word3 = bits(frac,37,16)
	    in  emitword word0;
		emitword word1;
		emitword word2;
		emitword word3
	    end
    in  if exponent < 1 orelse exponent > 2047
	then outofrange "" (* A hack *)
	else emit()
    end
end
structure M68RealConst = RealConst(M68PrimReal)
open M68RealConst

fun scale Byte = 0
  | scale Word = 512
  | scale Long = 1024

fun emitext (Immed i) = emitlong i
  | emitext (Abs i) =
	(case sizeint i of
	      Byte => emitword i
	    | Word => emitword i
	    | Long => emitlong i)
  | emitext (Direct _) = ()
  | emitext (PostInc _) = ()
  | emitext (PreDec _) = ()
  | emitext (Displace(AddrReg _, 0)) = ()
  | emitext (Displace (AddrReg _, i)) = emitword i
  | emitext (Displace (DataReg d, 0)) = emitword(d*4096+2448)
  | emitext (Displace (DataReg d, i)) = (emitword(d*4096+2464); emitword i)
  | emitext (Index (_,disp,DataReg d,s)) =
	emitword(d * 4096 + 2048 + scale s + signedbyte disp)
  | emitext (Index (_,disp,AddrReg d,s)) =
	emitword(32768 + d * 4096 + 2048 + scale s + signedbyte disp)
  | emitext (Address lab) = jump(MODE,lab)

(* DEBUG val emitext = diag "emitext" emitext *)

fun emitF (opcode,Direct(FloatReg a),Direct(FloatReg b)) =
	(emitword(61952); emitword(opcode+128*b+1024*a))
  | emitF (opcode,src,Direct(FloatReg f)) =
	(emitword(61952 + 8 * mode src + reg src);
	 emitword(opcode+21504+128*f);
	 emitext src)
  | emitF (opcode,Direct(FloatReg f),dest) =
	(emitword(61952 + 8 * mode dest + reg dest);
	 emitword(opcode+21504+128*f);
	 emitext dest)

(* DEBUG val emitF = diag "emitF" emitF *)

fun rts() = emitword 20085

fun exg (Direct(AddrReg a),Direct(AddrReg b)) =
	if a = b then () else emitword(49480 + 512 * a + b)
  | exg (Direct(DataReg a),Direct(DataReg b)) =
	if a = b then () else emitword(49472 + 512 * a + b)
  | exg (Direct(AddrReg b),Direct(DataReg a)) =
	emitword(49544 + 512 * a + b)
  | exg (Direct(DataReg a),Direct(AddrReg b)) =
	emitword(49544 + 512 * a + b)

(* DEBUG val exg = diag "exg" exg *)

fun pea (Direct _) = raise Illegal
  | pea (PreDec _) = raise Illegal
  | pea (PostInc _) = raise Illegal
  | pea (Immed _) = raise Illegal
  | pea (Address lab) = (jump(LEA(18496),lab))
  | pea src = (emitword(18496 + 8 * mode src + reg src); emitext src)

(* DEBUG val pea = diag "pea" pea *)

fun movl (_,Immed _) = raise Illegal
  (* labels not implemented *)
  (* CLR *)
  | movl(Immed 0,dest) =
    (emitword(17024 + reg dest + 8 * mode dest); emitext dest)
  (* MOVEQ/MOVE *)
  | movl (src as (Immed i),dest as (Direct(DataReg d))) =
    (case sizeint i of
       Byte => emitword(28672 + 512 * d + signedbyte i)
     | _ => (emitword(8192+512*reg dest+64*mode dest+8*mode src+reg src);
	     emitext src))
  (* MOVEA *)
  | movl (Address lab,Direct(AddrReg a)) = jump(LEA(8256+512*a),lab)
  | movl (src,Direct(AddrReg a)) =
    (emitword(8256 + a * 512 + mode src * 8 + reg src); emitext src)
  (* general MOVE *)
  | movl (src,dest) =
    (emitword(8192 + 512 * reg dest + 64 * mode dest + 8 * mode src + reg src);
     emitext src;
     emitext dest)

fun exg (Direct (DataReg a), Direct(DataReg b)) = emitword(49472+a*512+b)
  | exg (Direct (AddrReg a), Direct(AddrReg b)) = emitword(49480+a*512+b)
  | exg (Direct (DataReg a), Direct(AddrReg b)) = emitword(49544+a*512+b)
  | exg (Direct (AddrReg a), Direct(DataReg b)) = emitword(49544+b*512+a)

(* DEBUG val movl = diag "movl" movl *)

fun addl (_,Immed _) = raise Illegal
  (* ADDQ/ADDA *)
  | addl (src as (Immed i),dest as (Direct(AddrReg a))) =
    if i <= 8 andalso i >= 1
    then emitword(20608 + 512 * (i mod 8) + 8 * mode dest + reg dest)
    else (emitword(53696 + 512 * a + 8 * mode src + reg src); emitext src)
  | addl (src,Direct(AddrReg a)) =
    (emitword(53696 + 512 * a + 8 * mode src + reg src); emitext src)
  (* ADDQ/ADDI *)
  | addl (src as (Immed i),dest) =
    if i <= 8 andalso i >= 1
    then (emitword(20608+512*(i mod 8)+8*mode dest+reg dest); emitext dest)
    else (emitword(1664 + 8 * mode dest + reg dest); emitext src; emitext dest)
  (* general ADD *)
  | addl (src,Direct(DataReg d)) = 
    (emitword(53376 + 512 * d + reg src + 8 * mode src); emitext src)
  | addl (Direct(DataReg d),dest) =
    (emitword(53632 + 512 * d  + reg dest + 8 * mode dest); emitext dest)

(* DEBUG val addl = diag "addl" addl *)

fun lea (Direct _,_) = raise Illegal
  | lea (PreDec _,_) = raise Illegal
  | lea (PostInc _,_) = raise Illegal
  | lea (Immed _,_) = raise Illegal
  | lea (Address lab,Direct(AddrReg a)) = jump(LEA(16832+512*a),lab)
  | lea (src,Direct(AddrReg a)) =
        (emitword(16832 + 512 * a + 8 * mode src + reg src); emitext src)
  | lea (Displace(a, i), dest as (Direct(DataReg _))) =
	(movl(Immed(i), dest); addl(Direct(a), dest))
  | lea _ = raise Illegal

(* DEBUG val lea = diag "lea" lea *)

fun subl (_,Immed _) = raise Illegal
  (* SUBQ/SUBA *)
  | subl (src  as (Immed i),dest as (Direct(AddrReg a))) =
    if i <= 8 andalso i >= 1
    then emitword(20864 + 512 * (i mod 8) + 8 * mode dest + reg dest)
    else (emitword(37312 + 512 * a + 8 * mode src + reg src); emitext src)
  (* SUBA *)
  | subl (src,Direct(AddrReg a)) =
    (emitword(37312 + 512 * a + 8 * mode src + reg src); emitext src)
  (* SUBQ/SUBI *)
  | subl (src as (Immed i),dest) =
    if i <= 8 andalso i >= 1
    then (emitword(20864+512*(i mod 8)+8 * mode dest + reg dest); emitext dest)
    else (emitword(1152 + reg dest + 8 * mode dest); emitext src; emitext dest)
  (* general SUB *)
  | subl (src,Direct(DataReg d)) = 
    (emitword(36992 + 512 * d + reg src + 8 * mode src); emitext src)
  | subl (Direct(DataReg d),dest) = 
    (emitword(37248 + 512 * d + reg dest + 8 * mode dest); emitext dest)

(* DEBUG val subl = diag "subl" subl *)

fun eorl (_, Direct(AddrReg _)) = raise Illegal
  | eorl (Immed i, dest) =
    if i<65536
    then (emitword(2624 + reg dest + 8*mode dest); emitword i)
    else raise Match
  | eorl (Direct(DataReg d), dest) =
	(emitword(45440 + 512*d + 8*mode dest + reg dest); emitext dest)
  | eorl _ = raise Illegal

(* DEBUG val eorl = diag "eorl" eorl *)

fun orl (_, Direct(AddrReg _)) = raise Illegal
  | orl (Immed i, dest) =
    if i<65536
    then (emitword(64 + reg dest + 8*mode dest); emitword i)
    else raise Match
  | orl (src, Direct(DataReg d)) =
	(emitword(32896 + 512*d + 8*mode src + reg src); emitext src)
  | orl (Direct(DataReg d), dest) =
	(emitword(33152 + 512*d + 8*mode dest + reg dest); emitext dest)
  | orl _ = raise Illegal

(* DEBUG val orl = diag "orl" orl *)

fun andl (_, Direct(AddrReg _)) = raise Illegal
  | andl (Immed i, dest) =
	if i<65536
	then (emitword(576 + reg dest + 8*mode dest); emitword i)
	else raise Match
  | andl (src, Direct(DataReg d)) =
	(emitword(49280 + 512*d + 8*mode src + reg src); emitext src)
  | andl (Direct(DataReg d), dest) =
	(emitword(49536 + 512*d + 8*mode dest + reg dest); emitext dest)
  | andl _ = raise Illegal

(* DEBUG val andl = diag "andl" andl *)

fun mull (src,Direct(DataReg d)) =
	(emitword(19456 + reg src + 8 * mode src);
	 emitword(2048+4096*d);
	 emitext src)

(* DEBUG val mull = diag "mull" mull *)

fun divl (src,Direct(DataReg d)) =
	(emitword(19520 + reg src + 8 * mode src);
         emitword(2048 + 4097 (*yes, 4097!*) * d);
	 emitext src)

(* DEBUG val divl = diag "divl" divl *)

fun movb (_,Immed _) = raise Illegal
  (* labels not implemented *)
  | movb (Address _,_) = raise Illegal
  | movb (_,Address _) = raise Illegal
  (* CLR *)
  | movb (Immed 0, dest) =
    (emitword(16896 + reg dest + 8 * mode dest); emitext dest)
  (* general MOVE *)
  | movb (src,dest) =
    (emitword(4096 + 512 * reg dest + 64 * mode dest + 8 * mode src + reg src);
     emitext src;
     emitext dest)

(* DEBUG val movb = diag "movb" movb *)

fun shift dir =
 let val dr = dir * 256
     fun f (Immed 0, _) = ()
       | f (Immed 8, Direct(DataReg d)) = emitword(57472+dr+d)
       | f (Immed i, Direct(DataReg d)) =
	 if  i<1 orelse i>7 then raise Illegal else emitword(57472+dr + 512*i + d)
       | f (Immed 1, Direct _) = raise Illegal
       | f (Immed 1, dest) =
	   (emitword(57536 + dr + 8*mode dest + reg dest); emitext dest)
       | f (Direct(DataReg s), Direct(DataReg d)) = (emitword(57504+dr + 512*s + d))
       | f _ = raise Illegal
 in f
 end

val asll = shift 1
val asrl = shift 0

fun cmpl (_,Immed _) = raise Illegal
  (* CMP *)
  | cmpl (src,Direct(DataReg d)) =
    (emitword(45184 + 512 * d + 8 * mode src + reg src); emitext src)
  (* CMPA *)
  | cmpl (src,Direct(AddrReg a)) =
    (emitword(45504 + 512 * a + 8 * mode src + reg src); emitext src)
  (* CMPI *)
  | cmpl (Immed i,dest) =
    (emitword(3200 + 8 * mode dest + reg dest); emitext dest)
  (* CMPM *)
  | cmpl (PostInc(AddrReg y),PostInc(AddrReg x)) = emitword(45448 + 512 * x + y)

(* DEBUG val cmpl = diag "cmpl" cmpl *)

fun btst (_,Direct(AddrReg _)) = raise Illegal
  | btst (_,Immed _) = raise Illegal
  | btst (Direct(DataReg d),dest) =
    (emitword(256 + 512 * d + 8 * mode dest + reg dest); emitext dest)
  | btst (Immed i,dest) =
    (emitword(2048 + 8 * mode dest + reg dest); emitword i; emitext dest)

(* DEBUG val btst = diag "btst" btst *)

fun emitlab (i,lab) = jump(LABPTR i, lab)

fun jne (Address lab) = jump (Jcc(26112),lab)
fun jeq (Address lab) = jump (Jcc(26368),lab)
fun jgt (Address lab) = jump (Jcc(28160),lab)
fun jge (Address lab) = jump (Jcc(27648),lab)
fun jlt (Address lab) = jump (Jcc(27904),lab)
fun jle (Address lab) = jump (Jcc(28416),lab)

fun jra (Address lab) = jump (Jcc(24576),lab)
  | jra (arg as (Displace(AddrReg _,_))) = 
	    (emitword (20160 + 8 * mode arg + reg arg); emitext arg)
  | jra (arg as Index _) =
	    (emitword (20160 + 8 * mode arg + reg arg); emitext arg)

fun jbsr (Address lab) = jump (Jcc(24832),lab)
  | jbsr (dest as (Displace(AddrReg _,_))) =
    (emitword(20096 + 8 * mode dest + reg dest); emitext dest)
    	    (* doesn't handle >16bit displacement *)

(* 68881 float operations *)
(* Some src/dest combinations are illegal, but not caught here. *)
fun fjne (Address lab) = jump (FJcc(14),lab)
fun fjeq (Address lab) = jump (FJcc(1),lab)
fun fjgt (Address lab) = jump (FJcc(18),lab)
fun fjge (Address lab) = jump (FJcc(19),lab)
fun fjlt (Address lab) = jump (FJcc(20),lab)
fun fjle (Address lab) = jump (FJcc(21),lab)

fun fcmpd (src,dest) = emitF(56,src,dest)
fun faddd (src,dest) = emitF(34,src,dest)
fun fsubd (src,dest) = emitF(40,src,dest)
fun fmuld (src,dest) = emitF(35,src,dest)
fun fdivd (src,dest) = emitF(32,src,dest)
fun fnegd (src,dest) = emitF(26,src,dest)
fun fmoved (src,dest as Direct(FloatReg f)) = emitF(0,src,dest)
  | fmoved (src as Direct(FloatReg f),dest) = emitF(8192,src,dest)

fun trapv() = emitword(20086)
fun trapmi() = emitword 23548

fun push ea = movl(ea,PreDec sp)

fun pop ea = movl(PostInc sp,ea)

val pusha = pea

fun comment _ = ()

end (* Coder *)

val finish = Emitter.finish

end (* structure MCode *)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.