Fix some printing-related bugs, and make the code of the example programs more legible and fix some minor bugs in them
This commit is contained in:
parent
17cd71f9ed
commit
c89db6c351
21
emulator.pas
21
emulator.pas
|
@ -12,7 +12,7 @@ var
|
||||||
Addr, IP, RP: word; //Address argument and instruction and return pointers
|
Addr, IP, RP: word; //Address argument and instruction and return pointers
|
||||||
R: array [0 .. 3] of byte; //General-purpose registers
|
R: array [0 .. 3] of byte; //General-purpose registers
|
||||||
Mem: array [0 .. $ffef] of byte; //Memory
|
Mem: array [0 .. $ffef] of byte; //Memory
|
||||||
Prog: file of byte; //Program file
|
Prog{$ifdef printer}, Ptr{$endif}: file of byte; //Program file and printer
|
||||||
Ch: ansichar; //Character for input and output
|
Ch: ansichar; //Character for input and output
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -22,14 +22,6 @@ begin
|
||||||
IP := 0;
|
IP := 0;
|
||||||
RP := $fff0;
|
RP := $fff0;
|
||||||
|
|
||||||
//Initialise the printer
|
|
||||||
{$ifdef printer}
|
|
||||||
AssignLst (Lst, '| lpr');
|
|
||||||
rewrite (Lst);
|
|
||||||
Ch := ansichar ($d);
|
|
||||||
write (Lst, Ch);
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
//Read a program file and check for errors
|
//Read a program file and check for errors
|
||||||
if ParamCount <> 1 then begin
|
if ParamCount <> 1 then begin
|
||||||
writeln ('Usage: emulator program');
|
writeln ('Usage: emulator program');
|
||||||
|
@ -146,8 +138,10 @@ begin
|
||||||
//Printer
|
//Printer
|
||||||
{$ifdef printer}
|
{$ifdef printer}
|
||||||
else if Addr = $fffe then begin
|
else if Addr = $fffe then begin
|
||||||
Ch := ansichar (R [X]);
|
assign (Ptr, '/dev/usb/lp0');
|
||||||
write (Lst, Ch);
|
rewrite (Ptr);
|
||||||
|
write (Ptr, R [X]);
|
||||||
|
close (Ptr);
|
||||||
end
|
end
|
||||||
{$endif}
|
{$endif}
|
||||||
//Regular store
|
//Regular store
|
||||||
|
@ -214,9 +208,4 @@ begin
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//Close the printer
|
|
||||||
{$ifdef printer}
|
|
||||||
close (Lst);
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -17,24 +17,24 @@
|
||||||
store ffff, r1
|
store ffff, r1
|
||||||
store ffff, r1
|
store ffff, r1
|
||||||
|
|
||||||
;Get the hexadecimal digit of the high nibble
|
;Convert and print the high nibble
|
||||||
|
;Convert
|
||||||
ror r0
|
ror r0
|
||||||
ror r0
|
ror r0
|
||||||
ror r0
|
ror r0
|
||||||
ror r0
|
ror r0
|
||||||
cleq r0, r0, n2hex
|
cleq r0, r0, n2hex
|
||||||
|
;Print
|
||||||
;Print the digit
|
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
|
||||||
;Re-load the character to r0
|
;Re-load the character to r0
|
||||||
xor r0, r0
|
xor r0, r0
|
||||||
xor r0, r2
|
xor r0, r2
|
||||||
|
|
||||||
;Get the hexadecimal digit of the low nibble
|
;Convert and print the low nibble
|
||||||
|
;Convert
|
||||||
cleq r0, r0, n2hex
|
cleq r0, r0, n2hex
|
||||||
|
;Print
|
||||||
;Print the digit
|
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
|
||||||
;Print a newline
|
;Print a newline
|
||||||
|
@ -43,6 +43,8 @@
|
||||||
;Halt
|
;Halt
|
||||||
halt
|
halt
|
||||||
|
|
||||||
|
;***
|
||||||
|
|
||||||
;Print a newline
|
;Print a newline
|
||||||
newln: load r1, cr
|
newln: load r1, cr
|
||||||
store ffff, r1
|
store ffff, r1
|
||||||
|
@ -50,79 +52,89 @@ newln: load r1, cr
|
||||||
store ffff, r1
|
store ffff, r1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;***
|
||||||
|
|
||||||
;Get the hexadecimal digit of a nibble
|
;Get the hexadecimal digit of a nibble
|
||||||
|
|
||||||
;Extract the low nibble
|
;Extract the low nibble
|
||||||
n2hex: load r1, mask
|
n2hex: load r1, mask
|
||||||
and r0, r1
|
and r0, r1
|
||||||
|
|
||||||
;Locate the nibble in the table
|
;Locate the nibble in the table
|
||||||
load r1, tbl00
|
load r1, nbl0
|
||||||
breq r0, r1, dgt0
|
breq r0, r1, dgt0
|
||||||
load r1, tbl02
|
load r1, nbl1
|
||||||
breq r0, r1, dgt1
|
breq r0, r1, dgt1
|
||||||
load r1, tbl04
|
load r1, nbl2
|
||||||
breq r0, r1, dgt2
|
breq r0, r1, dgt2
|
||||||
load r1, tbl06
|
load r1, nbl3
|
||||||
breq r0, r1, dgt3
|
breq r0, r1, dgt3
|
||||||
load r1, tbl08
|
load r1, nbl4
|
||||||
breq r0, r1, dgt4
|
breq r0, r1, dgt4
|
||||||
load r1, tbl0a
|
load r1, nbl5
|
||||||
breq r0, r1, dgt5
|
breq r0, r1, dgt5
|
||||||
load r1, tbl0c
|
load r1, nbl6
|
||||||
breq r0, r1, dgt6
|
breq r0, r1, dgt6
|
||||||
load r1, tbl0e
|
load r1, nbl7
|
||||||
breq r0, r1, dgt7
|
breq r0, r1, dgt7
|
||||||
load r1, tbl10
|
load r1, nbl8
|
||||||
breq r0, r1, dgt8
|
breq r0, r1, dgt8
|
||||||
load r1, tbl12
|
load r1, nbl9
|
||||||
breq r0, r1, dgt9
|
breq r0, r1, dgt9
|
||||||
load r1, tbl14
|
load r1, nbla
|
||||||
breq r0, r1, dgta
|
breq r0, r1, dgta
|
||||||
load r1, tbl16
|
load r1, nblb
|
||||||
breq r0, r1, dgtb
|
breq r0, r1, dgtb
|
||||||
load r1, tbl18
|
load r1, nblc
|
||||||
breq r0, r1, dgtc
|
breq r0, r1, dgtc
|
||||||
load r1, tbl1a
|
load r1, nbld
|
||||||
breq r0, r1, dgtd
|
breq r0, r1, dgtd
|
||||||
load r1, tbl1c
|
load r1, nble
|
||||||
breq r0, r1, dgte
|
breq r0, r1, dgte
|
||||||
load r1, tbl1e
|
load r1, nblf
|
||||||
breq r0, r1, dgtf
|
breq r0, r1, dgtf
|
||||||
|
|
||||||
;Load the hexadecimal digit of the nibble
|
;Load the hexadecimal digit of the nibble
|
||||||
dgt0: load r0, tbl01
|
dgt0: load r0, hex0
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt1: load r0, tbl03
|
dgt1: load r0, hex1
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt2: load r0, tbl05
|
dgt2: load r0, hex2
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt3: load r0, tbl07
|
dgt3: load r0, hex3
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt4: load r0, tbl09
|
dgt4: load r0, hex4
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt5: load r0, tbl0b
|
dgt5: load r0, hex5
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt6: load r0, tbl0d
|
dgt6: load r0, hex6
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt7: load r0, tbl0f
|
dgt7: load r0, hex7
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt8: load r0, tbl11
|
dgt8: load r0, hex8
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgt9: load r0, tbl13
|
dgt9: load r0, hex9
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgta: load r0, tbl15
|
dgta: load r0, hexa
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgtb: load r0, tbl17
|
dgtb: load r0, hexb
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgtc: load r0, tbl19
|
dgtc: load r0, hexc
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgtd: load r0, tbl1b
|
dgtd: load r0, hexd
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgte: load r0, tbl1d
|
dgte: load r0, hexe
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
dgtf: load r0, tbl1f
|
dgtf: load r0, hexf
|
||||||
breq r0, r0, n2hend
|
breq r0, r0, n2hend
|
||||||
|
|
||||||
;Return
|
;Return
|
||||||
n2hend: ret
|
n2hend: ret
|
||||||
|
|
||||||
|
;***
|
||||||
|
|
||||||
|
;Data
|
||||||
|
|
||||||
;Characters
|
;Characters
|
||||||
cr: data d
|
cr: data d
|
||||||
lf: data a
|
lf: data a
|
||||||
|
@ -132,36 +144,38 @@ prompt: data 3e
|
||||||
;Mask
|
;Mask
|
||||||
mask: data f
|
mask: data f
|
||||||
|
|
||||||
|
;Nibble table
|
||||||
|
nbl0: data 0
|
||||||
|
nbl1: data 1
|
||||||
|
nbl2: data 2
|
||||||
|
nbl3: data 3
|
||||||
|
nbl4: data 4
|
||||||
|
nbl5: data 5
|
||||||
|
nbl6: data 6
|
||||||
|
nbl7: data 7
|
||||||
|
nbl8: data 8
|
||||||
|
nbl9: data 9
|
||||||
|
nbla: data a
|
||||||
|
nblb: data b
|
||||||
|
nblc: data c
|
||||||
|
nbld: data d
|
||||||
|
nble: data e
|
||||||
|
nblf: data f
|
||||||
|
|
||||||
;Hexadecimal table
|
;Hexadecimal table
|
||||||
tbl00: data 0
|
hex0: data 30
|
||||||
tbl01: data 30
|
hex1: data 31
|
||||||
tbl02: data 1
|
hex2: data 32
|
||||||
tbl03: data 31
|
hex3: data 33
|
||||||
tbl04: data 2
|
hex4: data 34
|
||||||
tbl05: data 32
|
hex5: data 35
|
||||||
tbl06: data 3
|
hex6: data 36
|
||||||
tbl07: data 33
|
hex7: data 37
|
||||||
tbl08: data 4
|
hex8: data 38
|
||||||
tbl09: data 34
|
hex9: data 39
|
||||||
tbl0a: data 5
|
hexa: data 41
|
||||||
tbl0b: data 35
|
hexb: data 42
|
||||||
tbl0c: data 6
|
hexc: data 43
|
||||||
tbl0d: data 36
|
hexd: data 44
|
||||||
tbl0e: data 7
|
hexe: data 45
|
||||||
tbl0f: data 37
|
hexf: data 46
|
||||||
tbl10: data 8
|
|
||||||
tbl11: data 38
|
|
||||||
tbl12: data 9
|
|
||||||
tbl13: data 39
|
|
||||||
tbl14: data a
|
|
||||||
tbl15: data 41
|
|
||||||
tbl16: data b
|
|
||||||
tbl17: data 42
|
|
||||||
tbl18: data c
|
|
||||||
tbl19: data 43
|
|
||||||
tbl1a: data d
|
|
||||||
tbl1b: data 44
|
|
||||||
tbl1c: data e
|
|
||||||
tbl1d: data 45
|
|
||||||
tbl1e: data f
|
|
||||||
tbl1f: data 46
|
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
;String echo
|
;String echo
|
||||||
|
|
||||||
;Store the buffer start address in buffst
|
;***
|
||||||
|
|
||||||
|
;Input
|
||||||
|
|
||||||
|
;Restore the buffer start address
|
||||||
;High byte
|
;High byte
|
||||||
load r0, chstor + 1
|
input: load r0, bfstrt
|
||||||
store buffst, r0
|
store chstor + 1, r0
|
||||||
;Low byte
|
;Low byte
|
||||||
load r0, chstor + 2
|
load r0, bfstrt + 1
|
||||||
store buffst + 1, r0
|
store chstor + 2, r0
|
||||||
|
|
||||||
;Print a prompt
|
;Print a prompt
|
||||||
start: load r0, prompt
|
load r0, prompt
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
load r0, space
|
load r0, space
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
@ -20,19 +24,18 @@ start: load r0, prompt
|
||||||
;Read a character
|
;Read a character
|
||||||
inloop: load r1, ffff
|
inloop: load r1, ffff
|
||||||
|
|
||||||
;Check for an escape
|
;Check for control characters and the buffer end
|
||||||
|
;Escape
|
||||||
load r2, esc
|
load r2, esc
|
||||||
breq r1, r2, escbr
|
breq r1, r2, escbr
|
||||||
|
;Carriage return
|
||||||
;Check for a return
|
|
||||||
load r2, cr
|
load r2, cr
|
||||||
breq r1, r2, inend
|
breq r1, r2, crbr
|
||||||
|
;Buffer end
|
||||||
;Check for end of the buffer
|
load r2, bfsize
|
||||||
load r2, buffsz
|
|
||||||
brneq r0, r2, chstor
|
brneq r0, r2, chstor
|
||||||
|
|
||||||
;Backtrack if end of the buffer
|
;Backtrack if at the buffer end
|
||||||
load r2, bs
|
load r2, bs
|
||||||
store ffff, r2
|
store ffff, r2
|
||||||
breq r0, r0, inloop
|
breq r0, r0, inloop
|
||||||
|
@ -40,18 +43,15 @@ inloop: load r1, ffff
|
||||||
;Store the character in the buffer
|
;Store the character in the buffer
|
||||||
chstor: store buffer, r1
|
chstor: store buffer, r1
|
||||||
|
|
||||||
;Increment the character counter and load it in r3
|
;Increment the character counter and store it in r3
|
||||||
|
;Increment
|
||||||
load r2, one
|
load r2, one
|
||||||
cleq r0, r0, sum
|
cleq r0, r0, sum
|
||||||
|
;Store
|
||||||
xor r3, r3
|
xor r3, r3
|
||||||
xor r3, r0
|
xor r3, r0
|
||||||
|
|
||||||
;Increment the buffer address
|
;Increment the buffer address
|
||||||
;High byte
|
|
||||||
load r0, chstor + 1
|
|
||||||
load r2, one
|
|
||||||
cleq r0, r0, sum
|
|
||||||
store chstor + 1, r0
|
|
||||||
;Low byte
|
;Low byte
|
||||||
load r0, chstor + 2
|
load r0, chstor + 2
|
||||||
load r2, one
|
load r2, one
|
||||||
|
@ -72,74 +72,71 @@ chstor: store buffer, r1
|
||||||
breq r0, r0, inloop
|
breq r0, r0, inloop
|
||||||
|
|
||||||
;Print a backslash and a newline
|
;Print a backslash and a newline
|
||||||
|
;Backslash
|
||||||
escbr: load r0, space
|
escbr: load r0, space
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
load r0, bslash
|
load r0, bslash
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
;Newline
|
||||||
load r0, cr
|
load r0, cr
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
load r0, lf
|
load r0, lf
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
|
||||||
;Restore the buffer address to its start
|
|
||||||
;High byte
|
|
||||||
load r0, buffst
|
|
||||||
store chstor + 1, r0
|
|
||||||
;Low byte
|
|
||||||
load r0, buffst + 1
|
|
||||||
store chstor + 2, r0
|
|
||||||
|
|
||||||
;Start a new input line
|
;Start a new input line
|
||||||
breq r0, r0, start
|
breq r0, r0, input
|
||||||
|
|
||||||
;Store a string-terminating zero in the buffer
|
;Store a string-terminating zero in the buffer
|
||||||
inend: xor r0, r0
|
;Get the buffer address
|
||||||
load r1, chstor + 1
|
crbr: load r1, chstor + 1
|
||||||
store endsto + 1, r1
|
store endsto + 1, r1
|
||||||
load r1, chstor + 2
|
load r1, chstor + 2
|
||||||
store endsto + 2, r1
|
store endsto + 2, r1
|
||||||
|
;Store
|
||||||
|
xor r0, r0
|
||||||
endsto: store 0000, r0
|
endsto: store 0000, r0
|
||||||
|
|
||||||
|
;***
|
||||||
|
|
||||||
|
;Print
|
||||||
|
|
||||||
;Print a line feed and align with the input
|
;Print a line feed and align with the input
|
||||||
|
;Line feed
|
||||||
load r0, lf
|
load r0, lf
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
;Align
|
||||||
load r0, space
|
load r0, space
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
|
||||||
;Load a character from the buffer
|
;Load a character from the buffer
|
||||||
outlop: load r1, buffer
|
chprnt: load r1, buffer
|
||||||
|
|
||||||
;Check for string end
|
;Check for string end
|
||||||
xor r2, r2
|
xor r2, r2
|
||||||
breq r1, r2, outend
|
breq r1, r2, end
|
||||||
|
|
||||||
;Print the character
|
;Print the character
|
||||||
store ffff, r1
|
store ffff, r1
|
||||||
|
|
||||||
;Increment the buffer address
|
;Increment the buffer address
|
||||||
;High byte
|
|
||||||
load r0, outlop + 1
|
|
||||||
load r2, one
|
|
||||||
cleq r0, r0, sum
|
|
||||||
store outlop + 1, r0
|
|
||||||
;Low byte
|
;Low byte
|
||||||
load r0, outlop + 2
|
load r0, chprnt + 2
|
||||||
load r2, one
|
load r2, one
|
||||||
cleq r0, r0, sum
|
cleq r0, r0, sum
|
||||||
store outlop + 2, r0
|
store chprnt + 2, r0
|
||||||
;Add the overflow to the high byte
|
;Add the overflow to the high byte
|
||||||
load r0, outlop + 1
|
load r0, chprnt + 1
|
||||||
xor r2, r2
|
xor r2, r2
|
||||||
xor r2, r1
|
xor r2, r1
|
||||||
cleq r0, r0, sum
|
cleq r0, r0, sum
|
||||||
store outlop + 1, r0
|
store chprnt + 1, r0
|
||||||
|
|
||||||
;Print the next character
|
;Print the next character
|
||||||
breq r0, r0, outlop
|
breq r0, r0, chprnt
|
||||||
|
|
||||||
;Print a newline
|
;Print a newline
|
||||||
outend: load r0, cr
|
end: load r0, cr
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
load r0, lf
|
load r0, lf
|
||||||
store ffff, r0
|
store ffff, r0
|
||||||
|
@ -147,34 +144,52 @@ outend: load r0, cr
|
||||||
;Halt
|
;Halt
|
||||||
halt
|
halt
|
||||||
|
|
||||||
|
;***
|
||||||
|
|
||||||
;Add r2 to r0 with the overflow stored in r1
|
;Add r2 to r0 with the overflow stored in r1
|
||||||
|
|
||||||
;Reset overflow
|
;Reset overflow
|
||||||
sum: xor r1, r1
|
sum: xor r1, r1
|
||||||
store ovrflw, r1
|
store ovrflw, r1
|
||||||
|
|
||||||
;Copy the first argument to r1
|
;Copy the first argument to r1
|
||||||
sumlop: xor r1, r1
|
sumlop: xor r1, r1
|
||||||
xor r1, r0
|
xor r1, r0
|
||||||
|
|
||||||
;Calculate the sum and carry and copy the pre-shift carry to r1
|
;Calculate the sum and carry and copy the pre-shift carry to r1
|
||||||
|
;Sum
|
||||||
xor r0, r2
|
xor r0, r2
|
||||||
|
;Carry
|
||||||
and r2, r1
|
and r2, r1
|
||||||
|
;Copy the pre-shift carry
|
||||||
xor r1, r1
|
xor r1, r1
|
||||||
xor r1, r2
|
xor r1, r2
|
||||||
|
;Shift the carry
|
||||||
shl r2
|
shl r2
|
||||||
;Check for overflow
|
|
||||||
|
;Check for and store overflow if any
|
||||||
|
;Check
|
||||||
rol r1
|
rol r1
|
||||||
breq r1, r2, nvrflw
|
breq r1, r2, nvrflw
|
||||||
;Store overflow
|
;Store
|
||||||
load r1, one
|
load r1, one
|
||||||
store ovrflw, r1
|
store ovrflw, r1
|
||||||
|
|
||||||
;Check for no carry
|
;Check for no carry
|
||||||
nvrflw: xor r1, r1
|
nvrflw: xor r1, r1
|
||||||
breq r1, r2, sumend
|
breq r1, r2, sumend
|
||||||
|
|
||||||
;Loop
|
;Loop
|
||||||
breq r0, r0, sumlop
|
breq r0, r0, sumlop
|
||||||
|
|
||||||
;Load overflow and return
|
;Load overflow and return
|
||||||
sumend: load r1, ovrflw
|
sumend: load r1, ovrflw
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;***
|
||||||
|
|
||||||
|
;Data
|
||||||
|
|
||||||
;Constants
|
;Constants
|
||||||
one: data 1
|
one: data 1
|
||||||
|
|
||||||
|
@ -191,7 +206,7 @@ bslash: data 5c
|
||||||
ovrflw: data 0
|
ovrflw: data 0
|
||||||
|
|
||||||
;Buffer
|
;Buffer
|
||||||
buffst: data 0
|
bfstrt: addr buffer
|
||||||
data 0
|
bfsize: data ff
|
||||||
buffsz: data f
|
|
||||||
buffer:
|
buffer:
|
||||||
|
|
|
@ -91,8 +91,8 @@ address FFFF. The emulator emulates a dumb terminal for this.
|
||||||
Arbitrary devices can be mapped to the other reserved addresses.
|
Arbitrary devices can be mapped to the other reserved addresses.
|
||||||
|
|
||||||
The emulator can be compiled in Linux with support for a dot matrix
|
The emulator can be compiled in Linux with support for a dot matrix
|
||||||
printer with the argument -dprinter. The printer must be set as the
|
printer at /dev/usb/lp0 with the argument -dprinter. The printer is
|
||||||
default in CUPS and will be mapped to address FFFE in the emulator.
|
mapped to address FFFE in the emulator.
|
||||||
|
|
||||||
Initial Program Loader
|
Initial Program Loader
|
||||||
----------------------
|
----------------------
|
||||||
|
|
Loading…
Reference in New Issue