File:  [Research Unix] / researchv10no / cmd / sml / src / vax / vaxmcode.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 VaxMCode : VAXMCODER = struct

structure Jumps = struct
    datatype JumpKind = MODE | WHICH of (int ref * int * int)
		        | BYTEDISPL
			| LABPTR of int
			| COND of (int ref * int * int) | JBR
fun sbyte i = chr(if i<0 then 256+i else i)
fun eword i =
	if i<0 then eword(65536+i)
	else [chr(i mod 256), chr(i div 256)]
fun elong i =
        if i<0 
	  then let val a = ~i;
		   val b = a mod 65536;
		   val c = a div 65536;
		in eword(~b) @ eword(~c + if b=0 then 0 else ~1)
	       end
	  else eword(i mod 65536) @ eword(i div 65536)
fun intsize(i) =
        if i >= ~128 andalso i < 128
	    then 1
	else if i >= ~32768 andalso i < 32768
	    then 2
	else 4;

  fun emitlong i = implode(elong i)

  fun sizejump(mode,oldsize,s,d) =
   let fun which (r,a,b) =
            case oldsize of 1 => r := a | _ => r := b
    in case (mode,intsize(d-(s+oldsize)))
	       of  (MODE,i) => i+1
	        | (LABPTR _, _) => 4
		| (BYTEDISPL, _) => 1
		| (WHICH _, _) => 1
		| (COND x, 1) => (which x; 1)
		| (COND x, 2) => (which x; 4)
		| (COND x, _) => (which x; 7)
		| (JBR,1) => 2
		| (JBR,2) => 3
		| (JBR,_) => 6
   end

  fun emitjump(MODE,2,s,d) = chr(10*16+15) ^ sbyte(d-s-2)
    | emitjump(MODE,3,s,d) = implode(chr(12*16+15) :: eword(d-s-3))
    | emitjump(MODE,5,s,d) = implode(chr(14*16+15) :: elong (d-s-5))
    | emitjump(BYTEDISPL,1,s,d) = sbyte(d-s-1)
    | emitjump(LABPTR i, _,s,d) = emitlong(d-s+i)
    | emitjump(WHICH(ref i,_,_), _,_,_) = chr i
    | emitjump(COND _, 1,s,d) = sbyte(d-s-1)
    | emitjump(COND _, 4,s,d) = implode(chr 3 :: chr(3*16+1) :: eword(d-s-4))
    | emitjump(COND _, 7,s,d) = implode(chr 6 :: chr(16+7) :: chr(14*16+15) 
					:: elong (d-s-7))
    | emitjump(JBR,2,s,d) = chr(16+1) ^ sbyte (d-s-2)
    | emitjump(JBR,3,s,d) = implode(chr(3*16+1) :: eword (d-s-3))
    | emitjump(JBR,6,s,d) = implode(chr(16+7):: chr(14*16+15) :: elong (d-s-6))
    | emitjump _ = ErrorMsg.impossible "emitjump"
  
end (* Jumps *)

structure Emitter : BACKPATCH = Backpatch(Jumps)

structure Coder : VAXCODER = struct

open Emitter Jumps

fun emitbyte i = emitstring(chr i)
fun signedbyte i = emitbyte(if i<0 then 256+i else i)
fun emitword i =
	if i<0 then emitword(65536+i)
	else (emitbyte(i mod 256); emitbyte(i div 256));
fun emitlong i =
        if i<0 
	  then let val a = ~i;
		   val b = a mod 65536;
		   val c = a div 65536;
		in emitword(~b);
		   emitword(~c + if b=0 then 0 else ~1)
	       end
	  else (emitword(i mod 65536); emitword(i div 65536))
fun intsize(i) =
        if i >= ~128 andalso i < 128
	    then 1
	else if i >= ~32768 andalso i < 32768
	    then 2
	else 4;

datatype Register = reg of int

val r0 = reg 0
val r1 = reg 1
val r2 = reg 2
val r3 = reg 3
val r4 = reg 4
val r5 = reg 5
val r6 = reg 6
val r7 = reg 7
val r8 = reg 8
val r9 = reg 9
val r10 = reg 10
val r11 = reg 11
val r12 = reg 12
val r13 = reg 13
val sp = reg 14
val pc = reg 15

datatype EA = direct of Register
	    | autoinc of Register
	    | autodec of Register
	    | displace of int * Register
	    | deferred of int * Register
	    | immed of int
	    | immedlab of Label
	    | address of Label
	    | index of EA * Register

(* This is identical to M68PrimReal except that emitword is different,
   and the bias is off by two. *)
structure VaxPrimReal : PRIMREAL =
struct
val significant = 53 (* 52 + redundant 1/2 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 + 1024
	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 VaxRealConst = RealConst(VaxPrimReal)
open VaxRealConst

fun regmode(mode,r) = emitbyte(mode*16+r)

fun emitarg (direct(reg r)) = regmode(5,r)
  | emitarg (autoinc(reg r)) = regmode(8,r)
  | emitarg (autodec(reg r)) = regmode(7,r)
  | emitarg (immed i) = 
	if i>=0 andalso i<64 then emitbyte i
	    else (emitarg(autoinc pc); emitlong i)
  | emitarg (displace(i,reg r)) =
	 if i=0 then regmode(6,r)
	 else (case intsize i 
		 of  1 => (regmode(10,r); signedbyte i)
		   | 2 => (regmode(12,r); emitword i)
		   | 4 => (regmode(14,r); emitlong i))
  | emitarg (deferred(i,reg r)) =
	(case intsize i of
	     1 => (regmode(11,r); signedbyte i)
	   | 2 => (regmode(13,r); emitword i)
	   | 4 => (regmode(15,r); emitlong i))
  | emitarg (index(ea, reg r)) = (regmode(4,r); emitarg ea)
  | emitarg (address lab) = jump(MODE,lab) (* no good for branches *)

fun emit2arg (arg1,arg2) = (emitarg arg1; emitarg arg2)

fun emit3arg (arg1,arg2,arg3) = (emitarg arg1; emitarg arg2; emitarg arg3)

fun pure (autoinc _) = false
  | pure (autodec _) = false
  | pure _ = true

fun args23(f2,f3) (args as (a,b,c)) = 
	if b=c andalso pure b then (f2(a,b)) else f3 args

fun immedbyte(i) =
	if i>=0 andalso i<64 then emitbyte i
	    else (emitarg(autoinc pc); signedbyte i);

fun immedword(i) =
	if i>=0 andalso i<64 then emitbyte i
	    else (emitarg(autoinc pc); emitword i);

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

fun jbr (address lab) = jump(JBR,lab)
fun bbc (immed 0, arg, address lab) =
	    let val r = (ref 0, 14*16+9,14*16+8)
	     in jump(WHICH r, lab); emitarg arg; jump(COND r, lab)
	    end
  | bbc (arg1, arg2, address lab) =
	    let val r = (ref 0, 14*16+1,14*16+0)
	     in jump(WHICH r, lab); emitarg arg1; emitarg arg2; jump(COND r, lab)
	    end
fun bbs (immed 0, arg, address lab) =
	    let val r = (ref 0, 14*16+8,14*16+9)
	     in jump(WHICH r, lab); emitarg arg; jump(COND r, lab)
	    end
  | bbs (arg1, arg2, address lab) =
	    let val r = (ref 0, 14*16+0,14*16+1)
	     in jump(WHICH r, lab); emitarg arg1; emitarg arg2; jump(COND r, lab)
	    end

fun movb (immed i, arg2) = (emitbyte(9*16); immedbyte i; emitarg arg2)
  | movb args = (emitbyte (9*16); emit2arg args)

fun movzbl args = (emitbyte (9*16+10); emit2arg args)

fun pushal args = (emitbyte (13*16+15); emitarg args)

fun addl2 (immed 1, arg) = (emitbyte(13*16+6); emitarg arg)
  | addl2 args = (emitbyte (12*16); emit2arg args)

fun moval (arg, autodec(reg 14)) = pushal arg
  | moval (args as (displace(i, reg p),direct (reg q))) =
	    if p=q andalso i> ~128 andalso i < 128
		then addl2(immed i, direct(reg p))
	        else (emitbyte (13*16+14); emit2arg args)
  | moval args = (emitbyte (13*16+14); emit2arg args)

fun movl (immedlab l, arg) = moval(address l, arg)
  | movl (arg, autodec(reg 14)) = (emitbyte(13*16+13); emitarg arg)
  | movl (immed 0, arg) = (emitbyte(13*16+4); emitarg arg)
  | movl args = (emitbyte (13*16); emit2arg args)

fun movq args = (emitbyte (7*16+13); emit2arg args)

fun rsb () = emitbyte 5
fun cmpl args = (emitbyte (13*16+1); emit2arg args)
fun addl3 args = (emitbyte (12*16+1); emit3arg args)
val addl3 = args23 (addl2,addl3)
fun subl2 args = (emitbyte (12*16+2); emit2arg args)
fun subl3 args = (emitbyte (12*16+3); emit3arg args)
val subl3 = args23 (subl2,subl3)
fun bisl3 args = (emitbyte (12*16+9); emit3arg args)
fun bicl3 args = (emitbyte (12*16+11); emit3arg args)
fun xorl3 args = (emitbyte (12*16+13); emit3arg args)
fun ashl(immed i,arg2,arg3)=(emitbyte(7*16+8);immedbyte i;emitarg arg2;emitarg arg3)
  | ashl args = (emitbyte (7*16+8); emit3arg args)
fun mull2 args = (emitbyte (12*16+4); emit2arg args)
fun divl3 args = (emitbyte (12*16+7); emit3arg args)
fun divl2 args = (emitbyte (12*16+6); emit2arg args)
val divl3 = args23 (divl2,divl3)
fun jmp (arg as address lab) = jbr arg
  | jmp arg = (emitbyte (16+7); emitarg arg)
fun brb (displace(i,reg 15)) = (emitbyte (16+1); signedbyte i)
fun brw (displace(i,reg 15)) = (emitbyte (3*16+1); emitword i)

local fun condj(i,j) =
	fn (address lab) => let val r = (ref 0,16+i,16+j)
		             in jump(WHICH r, lab); jump(COND r, lab)
		            end
	 | displace(k, reg 15) => (emitbyte (16+i); signedbyte k)
 in val beql = condj(3,2)
    val bneq = condj(2,3)
    val jne = bneq
    val bgeq = condj(8,9)
    val bgtr = condj(4,5)
    val blss = condj(9,8)
    val bleq = condj(5,4)
end
fun sobgeq (arg,address lab) = (emitbyte (15*16+4); emitarg arg;
				jump(BYTEDISPL,lab))

fun movg args = (emitword(20733); emit2arg args)
fun mnegg args = (emitword(21245); emit2arg args)
fun addg3 args = (emitword(16893); emit3arg args)
fun subg3 args = (emitword(17405); emit3arg args)
fun mulg3 args = (emitword(17917); emit3arg args)
fun divg3 args = (emitword(18429); emit3arg args)
fun cmpg args = (emitword(20989); emit2arg args)

fun push arg = movl(arg,autodec sp)
fun pusha arg = pushal arg
fun pop arg = movl(autoinc sp,arg)

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.